salesforce-integration-service
Svelte
salesforce-integration-service | Svelte | |
---|---|---|
3 | 637 | |
- | 76,733 | |
- | 0.9% | |
- | 9.9 | |
- | 2 days ago | |
JavaScript | ||
- | MIT License |
Stars - the number of stars that a project has on GitHub. Growth - month over month growth in stars.
Activity is a relative number indicating how actively a project is being developed. Recent commits have higher weight than older ones.
For example, an activity of 9.0 indicates that a project is amongst the top 10% of the most actively developed projects that we are tracking.
salesforce-integration-service
- Leveraging Salesforce Using a Client Written In Angular
-
Leveraging Salesforce Using a Client Written In Vue.js
Enter fullscreen mode Exit fullscreen mode axios Finding a solid HTTP client was also quick and easy. I simply added the axios dependency:npm install --save axiosOnce installed, I created a simple contact service in the ./src folder as defined below to retrieve a list of contacts from the Spring Boot RESTful service: import axios from 'axios' const SERVER_URL = 'http://localhost:9999'; const instance = axios.create({ baseURL: SERVER_URL, timeout: 1000 }); export default { getContacts: () => instance.get('/contacts', { transformResponse: [function (data) { return data ? JSON.parse(data) : data; }] }) } Enter fullscreen mode Exit fullscreen mode The core of the script portion of the contacts component is quite simple: establishing the SSE client, an array of contacts, and a loading boolean: import contactService from '../contact-service'; let sseClient; export default { name: "Contacts", data() { return { loading: true, contacts: [] }; }, Enter fullscreen mode Exit fullscreen mode With these changes in place, navigation to the localhost:8080 presented the updated Vue.js application:Next, using a simple cURL command, I updated the title of Sean Forbes from being the CFO to the CEO. This event updated the Vue.js application as shown below:Notice the title change in the list above and the toast message. Side-by-Side Demonstration Using everything created in this series so far, I created an animated GIF that shows the Svelte client on the left and the Vue.js client on the right.In the animated demonstration, a title is updated using the inline edit capabilities in Svelte. Shortly after the title is updated in the Svelte client, the Vue.js client receives the SSE with the updated contact information and dynamically updates the data for the updated contact. At the same time, the toast message is displayed, remaining on the screen until acknowledged by the end-user. Conclusion Starting in 2021, I have been trying to live the following mission statement, which I feel can apply to any IT professional: “Focus your time on delivering features/functionality which extends the value of your intellectual property. Leverage frameworks, products, and services for everything else.” J. Vester In this article, I leveraged an existing client framework and laser-focused dependencies to allow the creation of a component that meets the business needs provided in the example use case. Like my exercise using the Svelte client, the end-to-end time to complete this work was truly measured in minutes over hours.Of course, a production-ready scenario would require some additional work to prepare this application for “prime time” use.If you are interested in the source code used for the Vue.js client, simply navigate to the following repository on GitLab:https://gitlab.com/johnjvester/salesforce-integration-vueFuture articles are also planned for the following other JavaScript-based clients: React (React Native) Angular Lightning Web Components (outside the Salesforce ecosystem) Have a really great day! vue-sse The vue-sse dependency will handle the processing of SSEs and was added to the application using the following CLI command: npm install --save vue-sse Next, the main.js file was updated to include the following items: import VueSSE from 'vue-sse'; Vue.use(VueSSE) Enter fullscreen mode Exit fullscreen mode The vue-sse dependency is now ready for use and will be further documented later in this article. vue-toast-notification The vue-toast-notification dependency will be used for the required toast messages noted in the example use case. Adding toast notification functionality to the application required the following CLI command: npm install vue-toast-notification Next, the main.js file was updated to include the following items: import VueToast from 'vue-toast-notification'; import 'vue-toast-notification/dist/theme-sugar.css'; Vue.use(VueToast); Enter fullscreen mode Exit fullscreen mode At this point, the toast notifications logic is in place and ready for use. Updating the Spring Boot RESTful Service The Spring Boot RESTful service, originally created in the “Leveraging Salesforce Without Using Salesforce” article, needed to be modified in order to provide the Vue.js client a URI to connect to for SSE processing. Of course, the Spring Boot RESTful service also needed to be updated to actually create and broadcast the title changes of the contacts being stored in Salesforce. This section talks about the Java updates required to the Spring Boot repository. If you are not interested in the required service-tier updates and plan to simply pull down the latest service-tier code, simply scroll down to the “Creating the Contacts Component” section. As a reminder, the service-tier code can be found in the following repository on GitLab: https://gitlab.com/johnjvester/salesforce-integration-service Introducing the Contact Event Publisher Since the SSE message will contain the updated information from a Contact instance, I created a simple ContactEvent for the example use case: @NoArgsConstructor @AllArgsConstructor @Data public class ContactEvent { private Contact contact; } Enter fullscreen mode Exit fullscreen mode Leveraging the application event publisher which already exists in Spring Boot, a simple ContactEventPublisher was added to the service: @RequiredArgsConstructor @Component public class ContactEventPublisher { private final ApplicationEventPublisher applicationEventPublisher; public void publishContactEvent(Contact contact) { applicationEventPublisher.publishEvent(new ContactEvent(contact)); } } Enter fullscreen mode Exit fullscreen mode Finally, the updateContact() method for the PATCH event, was updated to publish the contact changes: Contact contact = getContact(id); contactEventPublisher.publishContactEvent(contact); return contact; Enter fullscreen mode Exit fullscreen mode Providing a Stream Controller With the Spring Boot service updated to publish events, the next step is to provide a controller that the Vue.js client can connect to in order to listen for the contact changes. In order to differentiate between different client sessions, I decided it would be best to include a session identifier to keep track of each listener. As a result, I create the following class to track each client listening for contact changes: @Data @RequiredArgsConstructor static class WebClient { private final String sessionId; private final SseEmitter emitter; } Enter fullscreen mode Exit fullscreen mode With such a design in place, it would be possible to direct an SSE message to a given client session. However, we won’t be performing that functionality at this part of the series. Next, the /stream/{sessionId} was created to provide a URI for the Vue.js client to subscribe to for contact-based updates: @GetMapping(value = "/stream/{sessionId}", produces = MediaType.TEXT_EVENT_STREAM_VALUE) public SseEmitter contactEvents(@PathVariable("sessionId") String sessionId, HttpServletResponse response) { response.setHeader("Cache-Control", "no-store"); log.info("Creating emitter for sessionId={}", sessionId); WebClient webClient = new WebClient(sessionId, new SseEmitter(ONE_HOUR)); Set webClientsForDocument = EMITTERS.computeIfAbsent(sessionId, key -> Collections.newSetFromMap(new ConcurrentReferenceHashMap<>())); webClientsForDocument.add(webClient); webClient.getEmitter().onCompletion(() -> { log.info("Removing completed emitter for sessionId={}", sessionId); removeWebClientEmitter(sessionId, webClient); }); webClient.getEmitter().onTimeout(() -> { log.warn("Removing timed out emitter for sessionId={}", sessionId); removeWebClientEmitter(sessionId, webClient); }); return webClient.getEmitter(); } Enter fullscreen mode Exit fullscreen mode At a very high level, the contactEvents() method accomplishes the following tasks: Establishes a new WebClient for the provided sessionId Adds to the list of emitters to broadcast to when contact events arrive Removes emitters on timeout or completion Finally, the event handling needs to be introduced. In Spring Boot, the @EventListener annotation can be added to a simple method: @EventListener public void onDocumentEvent(ContactEvent contactEvent) { processEvent(contactEvent); } Enter fullscreen mode Exit fullscreen mode When ContactEvents are published the processEvent() method simply broadcasts the changes to every listening client: protected void processEvent(ContactEvent contactEvent) { Collection matchingEmitters = EMITTERS.values().stream() .flatMap(Collection::stream) .collect(toCollection(HashSet::new)); matchingEmitters.parallelStream().forEach(webClient -> { if (webClient != null) { try { log.debug("Sending contact={} to WebClient sessionId={}", contactEvent.getContact(), webClient.getSessionId()); webClient.emitter.send(contactEvent.getContact()); } catch (IOException e) { e.printStackTrace(); } } }); } Enter fullscreen mode Exit fullscreen mode With the Spring Boot service updated and restarted, we can resume focus on the Vue.js client updates. Creating the Contacts Component Like Svelte, Vue.js allows for single-file components to exist. Using IntelliJ IDEA and the Vue.js plugin, I created the Contacts.vue component file and added a simple section for the view data—complete with standardized Bootstrap tags: Enter fullscreen mode Exit fullscreen mode The mounted() functionality was added to retrieve a list of contacts from the Spring Boot RESTful API and establish a listener for SSE functionality: mounted() { contactService.getContacts() .then(response => { console.log('contacts', response.data); this.contacts = response.data; }) .catch(error => { console.error(error) }) .finally(() => this.loading = false); sseClient = this.$sse.create({ url: 'http://localhost:9999/stream/' + uuidv4(), format: 'json', withCredentials: false, polyfill: true, }); sseClient.on('message', this.handleMessage); sseClient.connect() .then(sse => { console.log('Listening for SSEs on sse', sse); setTimeout(() => { sseClient.off('message', this.handleMessage); console.log('Stopped listening'); }, 60000); }) .catch((err) => { console.error('Failed to connect to server', err); }); } Enter fullscreen mode Exit fullscreen mode In order to generate a unique ID for every listener on the SSE URI, a simple function was added to the contacts component: function uuidv4() { return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function(c) { let r = Math.random() * 16 | 0, v = c === 'x' ? r : (r & 0x3 | 0x8); return v.toString(16); }); } Enter fullscreen mode Exit fullscreen mode Finally, methods were added to the component to handle creating the toast message and SSE client disconnecting: handleMessage(message) { console.info('Received message', message); if (message.id && this.contacts) { let foundIndex = this.contacts.findIndex(x => x.id === message.id); if (foundIndex >= 0) { let contact = this.contacts[foundIndex]; let toastMessage = 'Title updated for ' + contact.Name + ' from ' + contact.Title + ' to ' + message.Title; console.info(toastMessage); this.$toast.info(toastMessage, { position : "bottom", duration : 0 }); contact.Title = message.Title; } } } }, beforeDestroy() { sseClient.disconnect(); } Enter fullscreen mode Exit fullscreen mode To see the final version of the Contacts component, which includes an empty section, check out the following URL: https://gitlab.com/johnjvester/salesforce-integration-vue/-/blob/master/src/components/Contacts.vue Using the Vue.js Client The App.vue component was updated to remove the hello world aspects to yield the following design:
- Leveraging Salesforce Using a Client Written In Svelte
Svelte
-
Securing SvelteKit Apps with Keycloak
Svelte and specifically, SvelteKit is an open source web framework that makes developing web applications easier.
-
My opinion about opinionated Prettier: 👎
the technical decision how Svelte should treat self-closing html elements was hindered by Prettier:
-
Composable architecture example: Go headless (best practices)
Svelte
-
How to optimise React Apps?
React has introduced measures like batching state updates, background concurrent rendering and memoization to tackle this. My opinion is that the best way to solve the problem is by improving their reactivity model. The app needs to be able to track the code that should be re-run on updating a given state variable and specifically update the UI corresponding to this update. Tools like solid.js and svelte work in this manner. It also eliminates the need for a virtual DOM and diffing.
-
Episode 24/13: Native Signals, Details on Angular/Wiz, Alan Agius on the Angular CLI
Similarly to Promises/A+, this effort focuses on aligning the JavaScript ecosystem. If this alignment is successful, then a standard could emerge, based on that experience. Several framework authors are collaborating here on a common model which could back their reactivity core. The current draft is based on design input from the authors/maintainers of Angular, Bubble, Ember, FAST, MobX, Preact, Qwik, RxJS, Solid, Starbeam, Svelte, Vue, Wiz, and more…
- Rich Harris: Svelte parses HTML all wrong
- Mario meets Pareto: multi-objective optimization of Mario Kart builds
- Svelte parses HTML all wrong
-
Svelte for Beginners: Easy Guide
Svelte is a powerful web framework that offers a fresh approach to building web applications. Its simplicity, reactivity model, and built-in features make it an excellent choice for developers looking to create efficient and maintainable applications. By following this guide, you should now have a good understanding of how to get started with Svelte and build your first components, routes, and transitions. You can read more about svelte on the official Svelte website.
What are some alternatives?
salesforce-integration-svelte
Alpine.js - A rugged, minimal framework for composing JavaScript behavior in your markup.
Angular - Deliver web apps with confidence 🚀
lit - Lit is a simple library for building fast, lightweight web components.
sveltestrap - Bootstrap 4 & 5 components for Svelte
solid - A declarative, efficient, and flexible JavaScript library for building user interfaces. [Moved to: https://github.com/solidui/solid]
svelte-inline-edit
qwik - Instant-loading web apps, without effort
salesforce-integration-vue
awesome-blazor - Resources for Blazor, a .NET web framework using C#/Razor and HTML that runs in the browser with WebAssembly.
Next.js - The React Framework
lit-element - LEGACY REPO. This repository is for maintenance of the legacy LitElement library. The LitElement base class is now part of the Lit library, which is developed in the lit monorepo.