@seeka-labs/cli-apps 2.0.13-alpha.0 → 2.0.19-alpha.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (36) hide show
  1. package/LICENSE +19 -19
  2. package/dist/index.js +1 -1
  3. package/dist/index.js.map +2 -2
  4. package/dist/init-template/.gitlab-ci.yml +46 -46
  5. package/dist/init-template/.yarnrc.yml +8 -0
  6. package/dist/init-template/README.md +6 -6
  7. package/dist/init-template/app/browser/jest.config.js +11 -11
  8. package/dist/init-template/app/browser/package.json +40 -40
  9. package/dist/init-template/app/browser/scripts/esbuild/build-browser-plugin.mjs +110 -110
  10. package/dist/init-template/app/browser/scripts/esbuild/plugins/importAsGlobals.mjs +38 -38
  11. package/dist/init-template/app/browser/src/browser.ts +12 -12
  12. package/dist/init-template/app/browser/src/plugin/index.test.ts +6 -6
  13. package/dist/init-template/app/browser/src/plugin/index.ts +47 -47
  14. package/dist/init-template/app/browser/tsconfig.json +34 -34
  15. package/dist/init-template/app/server-azure-function/.eslintrc.cjs +10 -10
  16. package/dist/init-template/app/server-azure-function/.funcignore +21 -21
  17. package/dist/init-template/app/server-azure-function/README.md +104 -104
  18. package/dist/init-template/app/server-azure-function/host.json +19 -19
  19. package/dist/init-template/app/server-azure-function/local.settings.example.json +25 -25
  20. package/dist/init-template/app/server-azure-function/package.json +52 -52
  21. package/dist/init-template/app/server-azure-function/scripts/ngrok.js +27 -27
  22. package/dist/init-template/app/server-azure-function/src/functions/healthCheck.ts +13 -13
  23. package/dist/init-template/app/server-azure-function/src/functions/pollingExample.ts +39 -39
  24. package/dist/init-template/app/server-azure-function/src/functions/queueExample.ts +66 -66
  25. package/dist/init-template/app/server-azure-function/src/functions/seekaAppWebhook.ts +235 -235
  26. package/dist/init-template/app/server-azure-function/src/lib/browser/index.ts +54 -54
  27. package/dist/init-template/app/server-azure-function/src/lib/jobs/index.ts +95 -95
  28. package/dist/init-template/app/server-azure-function/src/lib/logging/index.ts +92 -92
  29. package/dist/init-template/app/server-azure-function/src/lib/models/index.ts +6 -6
  30. package/dist/init-template/app/server-azure-function/src/lib/services/index.ts +40 -40
  31. package/dist/init-template/app/server-azure-function/src/lib/state/redis/index.ts +96 -96
  32. package/dist/init-template/app/server-azure-function/src/lib/state/seeka/installations.ts +64 -64
  33. package/dist/init-template/app/server-azure-function/tsconfig.json +17 -17
  34. package/dist/init-template/package.json +1 -1
  35. package/dist/init-template/tsconfig.json +25 -25
  36. package/package.json +2 -2
@@ -1,236 +1,236 @@
1
- import winston from 'winston';
2
-
3
- import { app, HttpRequest, HttpResponseInit, InvocationContext } from '@azure/functions';
4
- import {
5
- SeekaActivityAcceptedWebhookPayload, SeekaAppInstalledWebhookPayload,
6
- SeekaAppInstallSettingsUpdatedWebhookPayload, SeekaAppUninstalledWebhookPayload,
7
- SeekaIdentityChangedWebhookPayload, SeekaWebhookCallType, SeekaWebhookPayload,
8
- throwOnInvalidWebhookSignature
9
- } from '@seeka-labs/sdk-apps-server';
10
-
11
- import type { Headers as UndiciHeaders } from 'undici';
12
- import { getSeekaBrowserPlugin } from '../lib/browser';
13
- import { queueNames, triggerBackgroundJob } from '../lib/jobs';
14
-
15
- import { webhookLogger } from '../lib/logging';
16
- import { startServices } from '../lib/services';
17
- import {
18
- createOrUpdateInstallation, deleteInstallation, SampleAppInstallSettings, SeekaAppInstallState, tryGetInstallation
19
- } from '../lib/state/seeka/installations';
20
-
21
- import type { Logger } from 'winston';
22
- import { MyQueueItem } from './queueExample';
23
- app.http('seekaAppWebhook', {
24
- methods: ['POST'],
25
- authLevel: 'anonymous',
26
- route: 'webhook/seeka/app',
27
- handler: seekaAppWebhook
28
- });
29
-
30
- export async function seekaAppWebhook(req: HttpRequest, context: InvocationContext): Promise<HttpResponseInit> {
31
- const bodyStr = (await req.text()) as string;
32
- if (!bodyStr) {
33
- return {
34
- status: 400,
35
- jsonBody: { error: "Body missing. Ensure body is present and either specify the Content-Length request header OR set Transfer-Encoding request header to 'chunked'" }
36
- }
37
- }
38
- const body = JSON.parse(bodyStr) as SeekaWebhookPayload;
39
-
40
- const logger = webhookLogger(body, context);
41
- logger.profile('http.seeka.webhook.app')
42
- logger.verbose('Received webhook from Seeka', { body });
43
-
44
- // Handle probe
45
- if (body.type === SeekaWebhookCallType.Probe) {
46
- return {
47
- status: 204
48
- }
49
- }
50
-
51
- // Validate webhook
52
- try {
53
- throwOnInvalidWebhookSignature(process.env.SEEKA_APP_SECRET as string, req.headers as UndiciHeaders, bodyStr);
54
- logger.debug('Webhook signature validated', { body });
55
- }
56
- catch {
57
- logger.warn('Webhook signature invalid', { body });
58
- return {
59
- status: 401,
60
- jsonBody: { error: "Webhook call invalid" }
61
- }
62
- }
63
-
64
- if (body.isTest) {
65
- // This is a test webhook call
66
- return {
67
- status: 204
68
- }
69
- }
70
-
71
- await startServices(logger);
72
-
73
- // Check if the webhook is for an app we have installed
74
- let installation: SeekaAppInstallState | null = null;
75
- if (body.type != SeekaWebhookCallType.AppInstalled) {
76
- installation = await tryGetInstallation((body as SeekaAppInstalledWebhookPayload).context?.applicationInstallId as string, false, logger);
77
- if (installation == null) {
78
- logger.warn('Webhook call cannot be processed as the installation ID is not known by this app', { body });
79
-
80
- return {
81
- status: 422,
82
- jsonBody: { error: "App not installed" }
83
- }
84
- }
85
- }
86
-
87
- // Do something
88
- let errorMessage: string | null = null;
89
- try {
90
- switch (body.type) {
91
- case SeekaWebhookCallType.AppInstalled:
92
- {
93
- errorMessage = await onInstallation(body as SeekaAppInstalledWebhookPayload, logger);
94
- break;
95
- }
96
- case SeekaWebhookCallType.AppInstallSettingsUpdated:
97
- {
98
- errorMessage = await onInstallationSettingsUpdate(body as SeekaAppInstallSettingsUpdatedWebhookPayload, logger);
99
- break;
100
- }
101
- case SeekaWebhookCallType.AppUninstalled:
102
- {
103
- if (!body.isTest) {
104
- const payload = body as SeekaAppUninstalledWebhookPayload;
105
- await deleteInstallation(payload.context?.applicationInstallId as string, logger)
106
- }
107
- break;
108
- }
109
- case SeekaWebhookCallType.ActivityAccepted:
110
- {
111
- const payload = body as SeekaActivityAcceptedWebhookPayload;
112
- await handleSeekaActivity(payload, logger);
113
-
114
- break;
115
- }
116
- case SeekaWebhookCallType.IdentityChanged:
117
- {
118
- const payload = body as SeekaIdentityChangedWebhookPayload;
119
-
120
- break;
121
- }
122
- // START: component:browser
123
- case SeekaWebhookCallType.BrowserSdkPlugin: {
124
- const plugin = await getSeekaBrowserPlugin(installation as SeekaAppInstallState, logger);
125
-
126
- logger.profile('http.seeka.webhook.app')
127
- return {
128
- status: 200,
129
- body: JSON.stringify(plugin),
130
- headers: {
131
- 'Content-Type': 'application/json'
132
- }
133
- }
134
- }
135
- // END: component:browser
136
- }
137
- }
138
- catch (err) {
139
- logger.error('Failed to handle webhook', { ex: winston.exceptions.getAllInfo(err) });
140
- return {
141
- status: 500,
142
- jsonBody: { error: "Request failed" }
143
- }
144
- }
145
- finally {
146
- logger.profile('http.seeka.webhook.app')
147
- logger.verbose('Seeka webhook handled');
148
- }
149
-
150
- if (errorMessage) {
151
- logger.warn('Webhook call failed', { errorMessage });
152
- return {
153
- status: 400,
154
- jsonBody: { error: { message: errorMessage } }
155
- }
156
- }
157
-
158
- return {
159
- status: 204
160
- }
161
- }
162
-
163
- const validateInstallationSettings = async (installSettings: SampleAppInstallSettings, logger: Logger): Promise<string | null> => {
164
- // Returning an error message string here will block the installation request or settings update request by the user installing the app
165
-
166
-
167
- return null;
168
- }
169
-
170
- const onInstallation = async (payload: SeekaAppInstalledWebhookPayload, logger: Logger): Promise<string | null> => {
171
- if (payload.isTest) return null;
172
-
173
- const errorMessage = await validateInstallationSettings(payload.content?.installationSettings || {}, logger);
174
- if (errorMessage) return errorMessage;
175
-
176
- const installation = await createOrUpdateInstallation({
177
- ...payload.context,
178
- installationState: {
179
- grantedPermissions: payload.content?.grantedPermissions || []
180
- },
181
- applicationInstallId: payload.context?.applicationInstallId as string,
182
- organisationBrandId: payload.context?.organisationBrandId as string,
183
- organisationId: payload.context?.organisationId as string,
184
- installedAt: new Date().toISOString(),
185
- installationSettings: payload.content?.installationSettings || {}
186
- }, logger)
187
-
188
- try {
189
- await triggerBackgroundJob(queueNames.queueItemExampleQueueName, {
190
- ...payload.context,
191
- causationId: payload.causationId,
192
- correlationId: payload.requestId
193
- }, logger)
194
- }
195
- catch (err) {
196
- await deleteInstallation(installation.applicationInstallId, logger)
197
- return 'Failed to complete install';
198
- }
199
-
200
- return null;
201
- }
202
-
203
- const onInstallationSettingsUpdate = async (payload: SeekaAppInstallSettingsUpdatedWebhookPayload, logger: Logger): Promise<string | null> => {
204
- if (payload.isTest) return null;
205
-
206
- const errorMessage = await validateInstallationSettings(payload.content?.installationSettings || {}, logger);
207
- if (errorMessage) return errorMessage;
208
-
209
- const existingInstallation = await tryGetInstallation(payload.context?.applicationInstallId as string, true, logger) as SeekaAppInstallState;
210
- const installation = await createOrUpdateInstallation({
211
- ...existingInstallation,
212
- installationState: {
213
- ...existingInstallation.installationState,
214
- grantedPermissions: payload.content?.grantedPermissions || []
215
- },
216
- installationSettings: payload.content?.installationSettings || {},
217
- }, logger)
218
-
219
- await triggerBackgroundJob(queueNames.queueItemExampleQueueName, {
220
- ...payload.context,
221
- causationId: payload.causationId,
222
- correlationId: payload.requestId
223
- }, logger)
224
-
225
- return null;
226
- }
227
-
228
- const handleSeekaActivity = async (activity: SeekaActivityAcceptedWebhookPayload, logger: Logger) => {
229
- // Will be handled by queueExample
230
- await triggerBackgroundJob(queueNames.queueItemExampleQueueName, {
231
- ...activity.context,
232
- causationId: activity.causationId,
233
- correlationId: activity.requestId,
234
- items: [activity]
235
- } as MyQueueItem, logger)
1
+ import winston from 'winston';
2
+
3
+ import { app, HttpRequest, HttpResponseInit, InvocationContext } from '@azure/functions';
4
+ import {
5
+ SeekaActivityAcceptedWebhookPayload, SeekaAppInstalledWebhookPayload,
6
+ SeekaAppInstallSettingsUpdatedWebhookPayload, SeekaAppUninstalledWebhookPayload,
7
+ SeekaIdentityChangedWebhookPayload, SeekaWebhookCallType, SeekaWebhookPayload,
8
+ throwOnInvalidWebhookSignature
9
+ } from '@seeka-labs/sdk-apps-server';
10
+
11
+ import type { Headers as UndiciHeaders } from 'undici';
12
+ import { getSeekaBrowserPlugin } from '../lib/browser';
13
+ import { queueNames, triggerBackgroundJob } from '../lib/jobs';
14
+
15
+ import { webhookLogger } from '../lib/logging';
16
+ import { startServices } from '../lib/services';
17
+ import {
18
+ createOrUpdateInstallation, deleteInstallation, SampleAppInstallSettings, SeekaAppInstallState, tryGetInstallation
19
+ } from '../lib/state/seeka/installations';
20
+
21
+ import type { Logger } from 'winston';
22
+ import { MyQueueItem } from './queueExample';
23
+ app.http('seekaAppWebhook', {
24
+ methods: ['POST'],
25
+ authLevel: 'anonymous',
26
+ route: 'webhook/seeka/app',
27
+ handler: seekaAppWebhook
28
+ });
29
+
30
+ export async function seekaAppWebhook(req: HttpRequest, context: InvocationContext): Promise<HttpResponseInit> {
31
+ const bodyStr = (await req.text()) as string;
32
+ if (!bodyStr) {
33
+ return {
34
+ status: 400,
35
+ jsonBody: { error: "Body missing. Ensure body is present and either specify the Content-Length request header OR set Transfer-Encoding request header to 'chunked'" }
36
+ }
37
+ }
38
+ const body = JSON.parse(bodyStr) as SeekaWebhookPayload;
39
+
40
+ const logger = webhookLogger(body, context);
41
+ logger.profile('http.seeka.webhook.app')
42
+ logger.verbose('Received webhook from Seeka', { body });
43
+
44
+ // Handle probe
45
+ if (body.type === SeekaWebhookCallType.Probe) {
46
+ return {
47
+ status: 204
48
+ }
49
+ }
50
+
51
+ // Validate webhook
52
+ try {
53
+ throwOnInvalidWebhookSignature(process.env.SEEKA_APP_SECRET as string, req.headers as UndiciHeaders, bodyStr);
54
+ logger.debug('Webhook signature validated', { body });
55
+ }
56
+ catch {
57
+ logger.warn('Webhook signature invalid', { body });
58
+ return {
59
+ status: 401,
60
+ jsonBody: { error: "Webhook call invalid" }
61
+ }
62
+ }
63
+
64
+ if (body.isTest) {
65
+ // This is a test webhook call
66
+ return {
67
+ status: 204
68
+ }
69
+ }
70
+
71
+ await startServices(logger);
72
+
73
+ // Check if the webhook is for an app we have installed
74
+ let installation: SeekaAppInstallState | null = null;
75
+ if (body.type != SeekaWebhookCallType.AppInstalled) {
76
+ installation = await tryGetInstallation((body as SeekaAppInstalledWebhookPayload).context?.applicationInstallId as string, false, logger);
77
+ if (installation == null) {
78
+ logger.warn('Webhook call cannot be processed as the installation ID is not known by this app', { body });
79
+
80
+ return {
81
+ status: 422,
82
+ jsonBody: { error: "App not installed" }
83
+ }
84
+ }
85
+ }
86
+
87
+ // Do something
88
+ let errorMessage: string | null = null;
89
+ try {
90
+ switch (body.type) {
91
+ case SeekaWebhookCallType.AppInstalled:
92
+ {
93
+ errorMessage = await onInstallation(body as SeekaAppInstalledWebhookPayload, logger);
94
+ break;
95
+ }
96
+ case SeekaWebhookCallType.AppInstallSettingsUpdated:
97
+ {
98
+ errorMessage = await onInstallationSettingsUpdate(body as SeekaAppInstallSettingsUpdatedWebhookPayload, logger);
99
+ break;
100
+ }
101
+ case SeekaWebhookCallType.AppUninstalled:
102
+ {
103
+ if (!body.isTest) {
104
+ const payload = body as SeekaAppUninstalledWebhookPayload;
105
+ await deleteInstallation(payload.context?.applicationInstallId as string, logger)
106
+ }
107
+ break;
108
+ }
109
+ case SeekaWebhookCallType.ActivityAccepted:
110
+ {
111
+ const payload = body as SeekaActivityAcceptedWebhookPayload;
112
+ await handleSeekaActivity(payload, logger);
113
+
114
+ break;
115
+ }
116
+ case SeekaWebhookCallType.IdentityChanged:
117
+ {
118
+ const payload = body as SeekaIdentityChangedWebhookPayload;
119
+
120
+ break;
121
+ }
122
+ // START: component:browser
123
+ case SeekaWebhookCallType.BrowserSdkPlugin: {
124
+ const plugin = await getSeekaBrowserPlugin(installation as SeekaAppInstallState, logger);
125
+
126
+ logger.profile('http.seeka.webhook.app')
127
+ return {
128
+ status: 200,
129
+ body: JSON.stringify(plugin),
130
+ headers: {
131
+ 'Content-Type': 'application/json'
132
+ }
133
+ }
134
+ }
135
+ // END: component:browser
136
+ }
137
+ }
138
+ catch (err) {
139
+ logger.error('Failed to handle webhook', { ex: winston.exceptions.getAllInfo(err) });
140
+ return {
141
+ status: 500,
142
+ jsonBody: { error: "Request failed" }
143
+ }
144
+ }
145
+ finally {
146
+ logger.profile('http.seeka.webhook.app')
147
+ logger.verbose('Seeka webhook handled');
148
+ }
149
+
150
+ if (errorMessage) {
151
+ logger.warn('Webhook call failed', { errorMessage });
152
+ return {
153
+ status: 400,
154
+ jsonBody: { error: { message: errorMessage } }
155
+ }
156
+ }
157
+
158
+ return {
159
+ status: 204
160
+ }
161
+ }
162
+
163
+ const validateInstallationSettings = async (installSettings: SampleAppInstallSettings, logger: Logger): Promise<string | null> => {
164
+ // Returning an error message string here will block the installation request or settings update request by the user installing the app
165
+
166
+
167
+ return null;
168
+ }
169
+
170
+ const onInstallation = async (payload: SeekaAppInstalledWebhookPayload, logger: Logger): Promise<string | null> => {
171
+ if (payload.isTest) return null;
172
+
173
+ const errorMessage = await validateInstallationSettings(payload.content?.installationSettings || {}, logger);
174
+ if (errorMessage) return errorMessage;
175
+
176
+ const installation = await createOrUpdateInstallation({
177
+ ...payload.context,
178
+ installationState: {
179
+ grantedPermissions: payload.content?.grantedPermissions || []
180
+ },
181
+ applicationInstallId: payload.context?.applicationInstallId as string,
182
+ organisationBrandId: payload.context?.organisationBrandId as string,
183
+ organisationId: payload.context?.organisationId as string,
184
+ installedAt: new Date().toISOString(),
185
+ installationSettings: payload.content?.installationSettings || {}
186
+ }, logger)
187
+
188
+ try {
189
+ await triggerBackgroundJob(queueNames.queueItemExampleQueueName, {
190
+ ...payload.context,
191
+ causationId: payload.causationId,
192
+ correlationId: payload.requestId
193
+ }, logger)
194
+ }
195
+ catch (err) {
196
+ await deleteInstallation(installation.applicationInstallId, logger)
197
+ return 'Failed to complete install';
198
+ }
199
+
200
+ return null;
201
+ }
202
+
203
+ const onInstallationSettingsUpdate = async (payload: SeekaAppInstallSettingsUpdatedWebhookPayload, logger: Logger): Promise<string | null> => {
204
+ if (payload.isTest) return null;
205
+
206
+ const errorMessage = await validateInstallationSettings(payload.content?.installationSettings || {}, logger);
207
+ if (errorMessage) return errorMessage;
208
+
209
+ const existingInstallation = await tryGetInstallation(payload.context?.applicationInstallId as string, true, logger) as SeekaAppInstallState;
210
+ const installation = await createOrUpdateInstallation({
211
+ ...existingInstallation,
212
+ installationState: {
213
+ ...existingInstallation.installationState,
214
+ grantedPermissions: payload.content?.grantedPermissions || []
215
+ },
216
+ installationSettings: payload.content?.installationSettings || {},
217
+ }, logger)
218
+
219
+ await triggerBackgroundJob(queueNames.queueItemExampleQueueName, {
220
+ ...payload.context,
221
+ causationId: payload.causationId,
222
+ correlationId: payload.requestId
223
+ }, logger)
224
+
225
+ return null;
226
+ }
227
+
228
+ const handleSeekaActivity = async (activity: SeekaActivityAcceptedWebhookPayload, logger: Logger) => {
229
+ // Will be handled by queueExample
230
+ await triggerBackgroundJob(queueNames.queueItemExampleQueueName, {
231
+ ...activity.context,
232
+ causationId: activity.causationId,
233
+ correlationId: activity.requestId,
234
+ items: [activity]
235
+ } as MyQueueItem, logger)
236
236
  }
@@ -1,55 +1,55 @@
1
- import { SeekaBrowserSdkPluginWebhookResponse } from '@seeka-labs/sdk-apps-server';
2
- import fs from 'fs';
3
- import path from 'path';
4
- import util from 'util';
5
- import winston, { Logger } from 'winston';
6
- import type { ISampleAppBrowserSdkPluginConfig } from '../models';
7
- import {
8
- SeekaAppInstallState
9
- } from '../state/seeka/installations';
10
-
11
- const fileExistsAsync = util.promisify(fs.exists);
12
- const readFileAsync = util.promisify(fs.readFile);
13
-
14
- export async function getSeekaBrowserPlugin(installation: SeekaAppInstallState, logger: Logger): Promise<SeekaBrowserSdkPluginWebhookResponse> {
15
- logger.profile('http.seeka.browser.plugin')
16
-
17
- let content: string | undefined;
18
- let init: string | undefined;
19
-
20
- try {
21
- logger.verbose('Handling request for browser plugin content');
22
- const browserPluginPath = path.resolve('./dist/src/browser/seeka-app-example-name.min.js');
23
- if (await fileExistsAsync(browserPluginPath)) {
24
- // Content of the script. This should not change per installation it should be the same for all installations
25
- content = await readFileAsync(browserPluginPath, 'utf8');
26
-
27
- // Configuration for the plugin. This can be different per installation.
28
- // Configuration is sent to the browser so NO SENSITIVE CONFIG / SERVER SECRETS SHOULD BE SPECIFIED HERE.
29
- const pluginConfig = {
30
- myAppInstallSetting1: installation.installationSettings.myAppInstallSetting1,
31
- myAppInstallSetting2: installation.installationSettings.myAppInstallSetting2,
32
- appId: process.env.SEEKA_APP_ID,
33
- appInstallId: installation.applicationInstallId,
34
- appUrl: process.env.SELF_HOST_BASEURL
35
- } as ISampleAppBrowserSdkPluginConfig;
36
- init = `SampleAppConvergeSdkPlugin(${JSON.stringify(pluginConfig)})`;
37
- }
38
- else {
39
- logger.error('Browser plugin content not found', { path: browserPluginPath });
40
- }
41
- }
42
- catch (err) {
43
- logger.error('Failed to handle request for browser plugin content', { ex: winston.exceptions.getAllInfo(err) });
44
- }
45
- finally {
46
- logger.profile('http.seeka.browser.plugin')
47
- logger.verbose('Request for browser plugin content handled');
48
- }
49
-
50
- if (!content || !init) {
51
- throw new Error('Failed to handle request for browser plugin content')
52
- }
53
-
54
- return { content, init: init }
1
+ import { SeekaBrowserSdkPluginWebhookResponse } from '@seeka-labs/sdk-apps-server';
2
+ import fs from 'fs';
3
+ import path from 'path';
4
+ import util from 'util';
5
+ import winston, { Logger } from 'winston';
6
+ import type { ISampleAppBrowserSdkPluginConfig } from '../models';
7
+ import {
8
+ SeekaAppInstallState
9
+ } from '../state/seeka/installations';
10
+
11
+ const fileExistsAsync = util.promisify(fs.exists);
12
+ const readFileAsync = util.promisify(fs.readFile);
13
+
14
+ export async function getSeekaBrowserPlugin(installation: SeekaAppInstallState, logger: Logger): Promise<SeekaBrowserSdkPluginWebhookResponse> {
15
+ logger.profile('http.seeka.browser.plugin')
16
+
17
+ let content: string | undefined;
18
+ let init: string | undefined;
19
+
20
+ try {
21
+ logger.verbose('Handling request for browser plugin content');
22
+ const browserPluginPath = path.resolve('./dist/src/browser/seeka-app-example-name.min.js');
23
+ if (await fileExistsAsync(browserPluginPath)) {
24
+ // Content of the script. This should not change per installation it should be the same for all installations
25
+ content = await readFileAsync(browserPluginPath, 'utf8');
26
+
27
+ // Configuration for the plugin. This can be different per installation.
28
+ // Configuration is sent to the browser so NO SENSITIVE CONFIG / SERVER SECRETS SHOULD BE SPECIFIED HERE.
29
+ const pluginConfig = {
30
+ myAppInstallSetting1: installation.installationSettings.myAppInstallSetting1,
31
+ myAppInstallSetting2: installation.installationSettings.myAppInstallSetting2,
32
+ appId: process.env.SEEKA_APP_ID,
33
+ appInstallId: installation.applicationInstallId,
34
+ appUrl: process.env.SELF_HOST_BASEURL
35
+ } as ISampleAppBrowserSdkPluginConfig;
36
+ init = `SampleAppConvergeSdkPlugin(${JSON.stringify(pluginConfig)})`;
37
+ }
38
+ else {
39
+ logger.error('Browser plugin content not found', { path: browserPluginPath });
40
+ }
41
+ }
42
+ catch (err) {
43
+ logger.error('Failed to handle request for browser plugin content', { ex: winston.exceptions.getAllInfo(err) });
44
+ }
45
+ finally {
46
+ logger.profile('http.seeka.browser.plugin')
47
+ logger.verbose('Request for browser plugin content handled');
48
+ }
49
+
50
+ if (!content || !init) {
51
+ throw new Error('Failed to handle request for browser plugin content')
52
+ }
53
+
54
+ return { content, init: init }
55
55
  }