@wix/sdk 1.12.7 → 1.12.9
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.
- package/build/auth/AppStrategy.d.ts +1 -0
- package/build/auth/AppStrategy.js +13 -7
- package/build/event-handlers-modules.d.ts +46 -2
- package/build/event-handlers-modules.js +99 -1
- package/build/service-plugin-modules.d.ts +32 -7
- package/build/service-plugin-modules.js +71 -3
- package/build/wixClient.d.ts +5 -49
- package/build/wixClient.js +9 -147
- package/cjs/build/auth/AppStrategy.d.ts +1 -0
- package/cjs/build/auth/AppStrategy.js +13 -7
- package/cjs/build/event-handlers-modules.d.ts +46 -2
- package/cjs/build/event-handlers-modules.js +100 -2
- package/cjs/build/service-plugin-modules.d.ts +32 -7
- package/cjs/build/service-plugin-modules.js +73 -5
- package/cjs/build/wixClient.d.ts +5 -49
- package/cjs/build/wixClient.js +6 -144
- package/package.json +6 -5
|
@@ -40,6 +40,7 @@ import { parsePublicKeyIfEncoded } from '../helpers.js';
|
|
|
40
40
|
*/
|
|
41
41
|
// eslint-disable-next-line @typescript-eslint/no-redeclare
|
|
42
42
|
export function AppStrategy(opts) {
|
|
43
|
+
const authServerBaseUrl = opts.authServerBaseUrl ?? 'https://www.wixapis.com';
|
|
43
44
|
let refreshToken = 'refreshToken' in opts ? opts.refreshToken : undefined;
|
|
44
45
|
return {
|
|
45
46
|
getInstallUrl({ redirectUrl, token, state }) {
|
|
@@ -68,7 +69,8 @@ export function AppStrategy(opts) {
|
|
|
68
69
|
if (!code || !instanceId) {
|
|
69
70
|
throw new Error('Invalid OAuth callback URL. Make sure you pass the url including the code and instanceId query params.');
|
|
70
71
|
}
|
|
71
|
-
const
|
|
72
|
+
const tokenUrl = new URL('/oauth/access', authServerBaseUrl);
|
|
73
|
+
const tokensRes = await fetch(tokenUrl.href, {
|
|
72
74
|
method: 'POST',
|
|
73
75
|
headers: {
|
|
74
76
|
'Content-Type': 'application/json',
|
|
@@ -96,7 +98,8 @@ export function AppStrategy(opts) {
|
|
|
96
98
|
if (!opts.appSecret) {
|
|
97
99
|
throw new Error('App secret is required for retrieveing app-level access tokens. Make sure to pass it to the AppStrategy');
|
|
98
100
|
}
|
|
99
|
-
const
|
|
101
|
+
const tokenUrl = new URL('/oauth/access', authServerBaseUrl);
|
|
102
|
+
const tokensRes = await fetch(tokenUrl.href, {
|
|
100
103
|
method: 'POST',
|
|
101
104
|
headers: {
|
|
102
105
|
'Content-Type': 'application/json',
|
|
@@ -123,7 +126,8 @@ export function AppStrategy(opts) {
|
|
|
123
126
|
if (!opts.appSecret) {
|
|
124
127
|
throw new Error('App secret is required for retrieveing app-level access tokens. Make sure to pass it to the AppStrategy');
|
|
125
128
|
}
|
|
126
|
-
const
|
|
129
|
+
const tokenUrl = new URL('/oauth2/token', authServerBaseUrl);
|
|
130
|
+
const tokensRes = await fetch(tokenUrl.href, {
|
|
127
131
|
method: 'POST',
|
|
128
132
|
headers: {
|
|
129
133
|
'Content-Type': 'application/json',
|
|
@@ -158,7 +162,7 @@ export function AppStrategy(opts) {
|
|
|
158
162
|
},
|
|
159
163
|
async elevated() {
|
|
160
164
|
if ('accessToken' in opts && opts.accessToken) {
|
|
161
|
-
const tokenInfo = await getTokenInfo(opts.accessToken);
|
|
165
|
+
const tokenInfo = await getTokenInfo(opts.accessToken, authServerBaseUrl);
|
|
162
166
|
if (tokenInfo.clientId !== opts.appId) {
|
|
163
167
|
throw new Error(`Invalid access token. The token is not issued for the app with ID "${opts.appId}"`);
|
|
164
168
|
}
|
|
@@ -170,6 +174,7 @@ export function AppStrategy(opts) {
|
|
|
170
174
|
appSecret: opts.appSecret,
|
|
171
175
|
publicKey: opts.publicKey,
|
|
172
176
|
instanceId: tokenInfo.instanceId,
|
|
177
|
+
authServerBaseUrl: opts.authServerBaseUrl,
|
|
173
178
|
});
|
|
174
179
|
}
|
|
175
180
|
else {
|
|
@@ -200,12 +205,13 @@ export function AppStrategy(opts) {
|
|
|
200
205
|
if (!tokenToCheck) {
|
|
201
206
|
throw new Error('Missing token to get info for. Either pass the token as an argument or provide it when initializing the AppStrategy');
|
|
202
207
|
}
|
|
203
|
-
return getTokenInfo(tokenToCheck);
|
|
208
|
+
return getTokenInfo(tokenToCheck, authServerBaseUrl);
|
|
204
209
|
},
|
|
205
210
|
};
|
|
206
211
|
}
|
|
207
|
-
async function getTokenInfo(token) {
|
|
208
|
-
const
|
|
212
|
+
async function getTokenInfo(token, authServerBaseUrl) {
|
|
213
|
+
const tokenInfoUrl = new URL('/oauth2/token-info', authServerBaseUrl);
|
|
214
|
+
const tokenInfoRes = await fetch(tokenInfoUrl.href, {
|
|
209
215
|
method: 'POST',
|
|
210
216
|
headers: {
|
|
211
217
|
'Content-Type': 'application/json',
|
|
@@ -1,4 +1,48 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { AuthenticationStrategy, EventDefinition, EventHandler, EventIdentity } from '@wix/sdk-types';
|
|
2
|
+
import { Emitter } from 'nanoevents';
|
|
2
3
|
export declare const isEventHandlerModule: (val: any) => val is EventDefinition<unknown, string>;
|
|
3
4
|
export declare function buildEventDefinition<T extends EventDefinition<any, string>>(eventDefinition: T, registerHandler: (eventDefinition: T, handler: EventHandler<T>) => void): (handler: EventHandler<T>) => void;
|
|
4
|
-
|
|
5
|
+
type ResolvePossibleEvents<T extends EventDefinition<any>[]> = {
|
|
6
|
+
[K in keyof T]: T[K] extends EventDefinition<any> ? {
|
|
7
|
+
eventType: T[K]['type'];
|
|
8
|
+
payload: T[K]['__payload'];
|
|
9
|
+
} : never;
|
|
10
|
+
} extends (infer U)[] ? U : never;
|
|
11
|
+
export type ProcessedEvent<T extends EventDefinition<any>[] = []> = {
|
|
12
|
+
instanceId: string;
|
|
13
|
+
identity?: EventIdentity;
|
|
14
|
+
} & (T['length'] extends 0 ? {
|
|
15
|
+
eventType: string;
|
|
16
|
+
payload: unknown;
|
|
17
|
+
} : ResolvePossibleEvents<T>);
|
|
18
|
+
export type EventHandlersClient = Emitter<{
|
|
19
|
+
registered: (event: EventDefinition<any>) => void;
|
|
20
|
+
}> & {
|
|
21
|
+
getRegisteredEvents(): Map<string, {
|
|
22
|
+
eventDefinition: EventDefinition;
|
|
23
|
+
handler: EventHandler<EventDefinition>;
|
|
24
|
+
}[]>;
|
|
25
|
+
process<ExpectedEvents extends EventDefinition<any>[] = []>(jwt: string, opts?: {
|
|
26
|
+
expectedEvents: ExpectedEvents;
|
|
27
|
+
}): Promise<ProcessedEvent<ExpectedEvents>>;
|
|
28
|
+
processRequest<ExpectedEvents extends EventDefinition<any>[] = []>(request: Request, opts?: {
|
|
29
|
+
expectedEvents: ExpectedEvents;
|
|
30
|
+
}): Promise<ProcessedEvent<ExpectedEvents>>;
|
|
31
|
+
parseJWT(jwt: string): Promise<ProcessedEvent>;
|
|
32
|
+
parseRequest(request: Request): Promise<ProcessedEvent>;
|
|
33
|
+
executeHandlers(event: ProcessedEvent): Promise<void>;
|
|
34
|
+
apps: {
|
|
35
|
+
AppInstalled: EventDefinition<{
|
|
36
|
+
appId: string;
|
|
37
|
+
originInstanceId: string;
|
|
38
|
+
}, 'AppInstalled'>;
|
|
39
|
+
AppRemoved: EventDefinition<{
|
|
40
|
+
appId: string;
|
|
41
|
+
}, 'AppRemoved'>;
|
|
42
|
+
};
|
|
43
|
+
};
|
|
44
|
+
export declare function eventHandlersModules(authStrategy: AuthenticationStrategy<any>): {
|
|
45
|
+
initModule(eventDefinition: EventDefinition<any, string>): (handler: EventHandler<EventDefinition<any, string>>) => void;
|
|
46
|
+
client: EventHandlersClient;
|
|
47
|
+
};
|
|
48
|
+
export {};
|
|
@@ -1,10 +1,12 @@
|
|
|
1
|
+
import { EventDefinition, } from '@wix/sdk-types';
|
|
2
|
+
import { createNanoEvents } from 'nanoevents';
|
|
1
3
|
export const isEventHandlerModule = (val) => val.__type === 'event-definition';
|
|
2
4
|
export function buildEventDefinition(eventDefinition, registerHandler) {
|
|
3
5
|
return (handler) => {
|
|
4
6
|
registerHandler(eventDefinition, handler);
|
|
5
7
|
};
|
|
6
8
|
}
|
|
7
|
-
|
|
9
|
+
function runHandler(eventDefinition, handler, payload, baseEventMetadata) {
|
|
8
10
|
let envelope;
|
|
9
11
|
if (eventDefinition.isDomainEvent) {
|
|
10
12
|
const domainEventPayload = payload;
|
|
@@ -46,3 +48,99 @@ export function runHandler(eventDefinition, handler, payload, baseEventMetadata)
|
|
|
46
48
|
const transformFromRESTFn = eventDefinition.transformations ?? ((x) => x);
|
|
47
49
|
return handler(transformFromRESTFn(envelope));
|
|
48
50
|
}
|
|
51
|
+
export function eventHandlersModules(authStrategy) {
|
|
52
|
+
const eventHandlers = new Map();
|
|
53
|
+
const webhooksEmitter = createNanoEvents();
|
|
54
|
+
const client = {
|
|
55
|
+
...webhooksEmitter,
|
|
56
|
+
getRegisteredEvents: () => eventHandlers,
|
|
57
|
+
async process(jwt, opts = {
|
|
58
|
+
expectedEvents: [],
|
|
59
|
+
}) {
|
|
60
|
+
const { eventType, identity, instanceId, payload } = await this.parseJWT(jwt);
|
|
61
|
+
const allExpectedEvents = [
|
|
62
|
+
...opts.expectedEvents,
|
|
63
|
+
...Array.from(eventHandlers.keys()).map((type) => ({ type })),
|
|
64
|
+
];
|
|
65
|
+
if (allExpectedEvents.length > 0 &&
|
|
66
|
+
!allExpectedEvents.some(({ type }) => type === eventType)) {
|
|
67
|
+
throw new Error(`Unexpected event type: ${eventType}. Expected one of: ${allExpectedEvents
|
|
68
|
+
.map((x) => x.type)
|
|
69
|
+
.join(', ')}`);
|
|
70
|
+
}
|
|
71
|
+
const handlers = eventHandlers.get(eventType) ?? [];
|
|
72
|
+
await Promise.all(handlers.map(({ eventDefinition, handler }) => runHandler(eventDefinition, handler, payload, {
|
|
73
|
+
instanceId,
|
|
74
|
+
identity,
|
|
75
|
+
})));
|
|
76
|
+
return {
|
|
77
|
+
instanceId,
|
|
78
|
+
eventType,
|
|
79
|
+
payload,
|
|
80
|
+
identity,
|
|
81
|
+
};
|
|
82
|
+
},
|
|
83
|
+
async processRequest(request, opts) {
|
|
84
|
+
const body = await request.text();
|
|
85
|
+
return this.process(body, opts);
|
|
86
|
+
},
|
|
87
|
+
async parseJWT(jwt) {
|
|
88
|
+
if (!authStrategy.decodeJWT) {
|
|
89
|
+
throw new Error('decodeJWT is not supported by the authentication strategy');
|
|
90
|
+
}
|
|
91
|
+
const { decoded, valid } = await authStrategy.decodeJWT(jwt);
|
|
92
|
+
if (!valid) {
|
|
93
|
+
throw new Error('JWT is not valid');
|
|
94
|
+
}
|
|
95
|
+
if (typeof decoded.data !== 'string') {
|
|
96
|
+
throw new Error(`Unexpected type of JWT data: expected string, got ${typeof decoded.data}`);
|
|
97
|
+
}
|
|
98
|
+
const parsedDecoded = JSON.parse(decoded.data);
|
|
99
|
+
const eventType = parsedDecoded.eventType;
|
|
100
|
+
const instanceId = parsedDecoded.instanceId;
|
|
101
|
+
const identity = parsedDecoded.identity
|
|
102
|
+
? JSON.parse(parsedDecoded.identity)
|
|
103
|
+
: undefined;
|
|
104
|
+
const payload = JSON.parse(parsedDecoded.data);
|
|
105
|
+
return {
|
|
106
|
+
instanceId,
|
|
107
|
+
eventType,
|
|
108
|
+
payload,
|
|
109
|
+
identity,
|
|
110
|
+
};
|
|
111
|
+
},
|
|
112
|
+
async parseRequest(request) {
|
|
113
|
+
const jwt = await request.text();
|
|
114
|
+
return this.parseJWT(jwt);
|
|
115
|
+
},
|
|
116
|
+
async executeHandlers(event) {
|
|
117
|
+
const allExpectedEvents = Array.from(eventHandlers.keys()).map((type) => ({ type }));
|
|
118
|
+
if (allExpectedEvents.length > 0 &&
|
|
119
|
+
!allExpectedEvents.some(({ type }) => type === event.eventType)) {
|
|
120
|
+
throw new Error(`Unexpected event type: ${event.eventType}. Expected one of: ${allExpectedEvents
|
|
121
|
+
.map((x) => x.type)
|
|
122
|
+
.join(', ')}`);
|
|
123
|
+
}
|
|
124
|
+
const handlers = eventHandlers.get(event.eventType) ?? [];
|
|
125
|
+
await Promise.all(handlers.map(({ eventDefinition, handler }) => runHandler(eventDefinition, handler, event.payload, {
|
|
126
|
+
instanceId: event.instanceId,
|
|
127
|
+
identity: event.identity,
|
|
128
|
+
})));
|
|
129
|
+
},
|
|
130
|
+
apps: {
|
|
131
|
+
AppInstalled: EventDefinition('AppInstalled')(),
|
|
132
|
+
AppRemoved: EventDefinition('AppRemoved')(),
|
|
133
|
+
},
|
|
134
|
+
};
|
|
135
|
+
return {
|
|
136
|
+
initModule(eventDefinition) {
|
|
137
|
+
return (handler) => {
|
|
138
|
+
const handlers = eventHandlers.get(eventDefinition.type) ?? [];
|
|
139
|
+
handlers.push({ eventDefinition, handler });
|
|
140
|
+
eventHandlers.set(eventDefinition.type, handlers);
|
|
141
|
+
webhooksEmitter.emit('registered', eventDefinition);
|
|
142
|
+
};
|
|
143
|
+
},
|
|
144
|
+
client,
|
|
145
|
+
};
|
|
146
|
+
}
|
|
@@ -1,8 +1,33 @@
|
|
|
1
|
-
import { ServicePluginContract, ServicePluginDefinition } from '@wix/sdk-types';
|
|
1
|
+
import { AuthenticationStrategy, ServicePluginContract, ServicePluginDefinition } from '@wix/sdk-types';
|
|
2
|
+
import { Emitter } from 'nanoevents';
|
|
2
3
|
export declare const isServicePluginModule: (val: any) => val is ServicePluginDefinition<ServicePluginContract>;
|
|
3
|
-
export
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
4
|
+
export type UnknownServicePluginResponse = unknown;
|
|
5
|
+
type ServicePluginRequestMetadata = {
|
|
6
|
+
instanceId: string;
|
|
7
|
+
appExtensionType: string;
|
|
8
|
+
};
|
|
9
|
+
type ServicePluginRequest = {
|
|
10
|
+
metadata: ServicePluginRequestMetadata;
|
|
11
|
+
request: unknown;
|
|
12
|
+
};
|
|
13
|
+
export type ServicePluginsClient = Emitter<{
|
|
14
|
+
registered: (servicePluginDefinition: ServicePluginDefinition<ServicePluginContract>) => void;
|
|
15
|
+
}> & {
|
|
16
|
+
getRegisteredServicePlugins(): Map<string, {
|
|
17
|
+
servicePluginDefinition: ServicePluginDefinition<any>;
|
|
18
|
+
implementation: ServicePluginContract;
|
|
19
|
+
}[]>;
|
|
20
|
+
process(request: {
|
|
21
|
+
url: string;
|
|
22
|
+
body: string;
|
|
23
|
+
}): Promise<unknown>;
|
|
24
|
+
processRequest(request: Request): Promise<Response>;
|
|
25
|
+
parseJWT(jwt: string): Promise<ServicePluginRequest>;
|
|
26
|
+
parseRequest(request: Request): Promise<ServicePluginRequest>;
|
|
27
|
+
executeHandler(servicePluginRequest: ServicePluginRequest, url: string): Promise<UnknownServicePluginResponse>;
|
|
28
|
+
};
|
|
29
|
+
export declare function servicePluginsModules(authStrategy: AuthenticationStrategy<any>): {
|
|
30
|
+
initModule<T extends ServicePluginDefinition<any>>(servicePluginDefinition: T): (implementation: T["__contract"]) => void;
|
|
31
|
+
client: ServicePluginsClient;
|
|
32
|
+
};
|
|
33
|
+
export {};
|
|
@@ -1,6 +1,74 @@
|
|
|
1
|
+
import { createNanoEvents } from 'nanoevents';
|
|
1
2
|
export const isServicePluginModule = (val) => val.__type === 'service-plugin-definition';
|
|
2
|
-
export function
|
|
3
|
-
|
|
4
|
-
|
|
3
|
+
export function servicePluginsModules(authStrategy) {
|
|
4
|
+
const servicePluginsImplementations = new Map();
|
|
5
|
+
const servicePluginsEmitter = createNanoEvents();
|
|
6
|
+
const client = {
|
|
7
|
+
...servicePluginsEmitter,
|
|
8
|
+
getRegisteredServicePlugins: () => servicePluginsImplementations,
|
|
9
|
+
async parseJWT(jwt) {
|
|
10
|
+
if (!authStrategy.decodeJWT) {
|
|
11
|
+
throw new Error('decodeJWT is not supported by the authentication strategy');
|
|
12
|
+
}
|
|
13
|
+
const { decoded, valid } = await authStrategy.decodeJWT(jwt, true);
|
|
14
|
+
if (!valid) {
|
|
15
|
+
throw new Error('JWT is not valid');
|
|
16
|
+
}
|
|
17
|
+
if (typeof decoded.data !== 'object' ||
|
|
18
|
+
decoded.data === null ||
|
|
19
|
+
!('metadata' in decoded.data) ||
|
|
20
|
+
typeof decoded.data.metadata !== 'object' ||
|
|
21
|
+
decoded.data.metadata === null ||
|
|
22
|
+
!('appExtensionType' in decoded.data.metadata) ||
|
|
23
|
+
typeof decoded.data.metadata.appExtensionType !== 'string') {
|
|
24
|
+
throw new Error('Unexpected JWT data: expected object with metadata.appExtensionType string');
|
|
25
|
+
}
|
|
26
|
+
return decoded.data;
|
|
27
|
+
},
|
|
28
|
+
async process(request) {
|
|
29
|
+
const servicePluginRequest = await this.parseJWT(request.body);
|
|
30
|
+
return this.executeHandler(servicePluginRequest, request.url);
|
|
31
|
+
},
|
|
32
|
+
async parseRequest(request) {
|
|
33
|
+
const body = await request.text();
|
|
34
|
+
return this.parseJWT(body);
|
|
35
|
+
},
|
|
36
|
+
async processRequest(request) {
|
|
37
|
+
const url = request.url;
|
|
38
|
+
const body = await request.text();
|
|
39
|
+
const implMethodResult = await this.process({ url, body });
|
|
40
|
+
return Response.json(implMethodResult);
|
|
41
|
+
},
|
|
42
|
+
async executeHandler(servicePluginRequest, url) {
|
|
43
|
+
const componentType = servicePluginRequest.metadata.appExtensionType.toLowerCase();
|
|
44
|
+
const implementations = servicePluginsImplementations.get(componentType) ?? [];
|
|
45
|
+
if (implementations.length === 0) {
|
|
46
|
+
throw new Error(`No service plugin implementations found for component type ${componentType}`);
|
|
47
|
+
}
|
|
48
|
+
else if (implementations.length > 1) {
|
|
49
|
+
throw new Error(`Multiple service plugin implementations found for component type ${componentType}. This is currently not supported`);
|
|
50
|
+
}
|
|
51
|
+
const { implementation: impl, servicePluginDefinition } = implementations[0];
|
|
52
|
+
const method = servicePluginDefinition.methods.find((m) => url.endsWith(m.primaryHttpMappingPath));
|
|
53
|
+
if (!method) {
|
|
54
|
+
throw new Error('Unexpect request: request url did not match any method: ' + url);
|
|
55
|
+
}
|
|
56
|
+
const implMethod = impl[method.name];
|
|
57
|
+
if (!implMethod) {
|
|
58
|
+
throw new Error(`Got request for service plugin method ${method.name} but no implementation was provided. Available methods: ${Object.keys(impl).join(', ')}`);
|
|
59
|
+
}
|
|
60
|
+
return method.transformations.toREST(await implMethod(method.transformations.fromREST(servicePluginRequest)));
|
|
61
|
+
},
|
|
62
|
+
};
|
|
63
|
+
return {
|
|
64
|
+
initModule(servicePluginDefinition) {
|
|
65
|
+
return (implementation) => {
|
|
66
|
+
const implementations = servicePluginsImplementations.get(servicePluginDefinition.componentType.toLowerCase()) ?? [];
|
|
67
|
+
implementations.push({ servicePluginDefinition, implementation });
|
|
68
|
+
servicePluginsImplementations.set(servicePluginDefinition.componentType.toLowerCase(), implementations);
|
|
69
|
+
servicePluginsEmitter.emit('registered', servicePluginDefinition);
|
|
70
|
+
};
|
|
71
|
+
},
|
|
72
|
+
client,
|
|
5
73
|
};
|
|
6
74
|
}
|
package/build/wixClient.d.ts
CHANGED
|
@@ -1,6 +1,8 @@
|
|
|
1
|
-
import { AuthenticationStrategy, BoundAuthenticationStrategy, BuildDescriptors, Descriptors,
|
|
1
|
+
import { AuthenticationStrategy, BoundAuthenticationStrategy, BuildDescriptors, Descriptors, Host, HostModule, RESTFunctionDescriptor } from '@wix/sdk-types';
|
|
2
2
|
import { EmptyObject } from 'type-fest/source/empty-object.js';
|
|
3
3
|
import type { GraphQLFormattedError } from 'graphql';
|
|
4
|
+
import { EventHandlersClient } from './event-handlers-modules.js';
|
|
5
|
+
import { ServicePluginsClient } from './service-plugin-modules.js';
|
|
4
6
|
export type ContextType = 'global' | 'module';
|
|
5
7
|
type Headers = Record<string, string>;
|
|
6
8
|
/**
|
|
@@ -42,55 +44,9 @@ export type WixClient<H extends Host<any> | undefined = undefined, Z extends Aut
|
|
|
42
44
|
data: Result;
|
|
43
45
|
errors?: GraphQLFormattedError[];
|
|
44
46
|
}>;
|
|
45
|
-
webhooks:
|
|
46
|
-
|
|
47
|
-
process<ExpectedEvents extends EventDefinition<any>[] = []>(jwt: string, opts?: {
|
|
48
|
-
expectedEvents: ExpectedEvents;
|
|
49
|
-
}): Promise<ProcessedEvent<ExpectedEvents>>;
|
|
50
|
-
processRequest<ExpectedEvents extends EventDefinition<any>[] = []>(request: Request, opts?: {
|
|
51
|
-
expectedEvents: ExpectedEvents;
|
|
52
|
-
}): Promise<ProcessedEvent<ExpectedEvents>>;
|
|
53
|
-
parseJWT(jwt: string): Promise<ProcessedEvent>;
|
|
54
|
-
parseRequest(request: Request): Promise<ProcessedEvent>;
|
|
55
|
-
executeHandlers(event: ProcessedEvent): Promise<void>;
|
|
56
|
-
apps: {
|
|
57
|
-
AppInstalled: EventDefinition<{
|
|
58
|
-
appId: string;
|
|
59
|
-
originInstanceId: string;
|
|
60
|
-
}, 'AppInstalled'>;
|
|
61
|
-
AppRemoved: EventDefinition<{
|
|
62
|
-
appId: string;
|
|
63
|
-
}, 'AppRemoved'>;
|
|
64
|
-
};
|
|
65
|
-
};
|
|
66
|
-
servicePlugins: {
|
|
67
|
-
getRegisteredServicePlugins(): Map<string, {
|
|
68
|
-
servicePluginDefinition: ServicePluginDefinition<any>;
|
|
69
|
-
implementation: ServicePluginContract;
|
|
70
|
-
}[]>;
|
|
71
|
-
process(request: {
|
|
72
|
-
url: string;
|
|
73
|
-
body: string;
|
|
74
|
-
}): Promise<unknown>;
|
|
75
|
-
processRequest(request: Request): Promise<Response>;
|
|
76
|
-
parseJWT(jwt: string): Promise<unknown>;
|
|
77
|
-
parseRequest(request: Request): Promise<unknown>;
|
|
78
|
-
executeHandler(servicePluginRequest: ProcessedEvent): Promise<void>;
|
|
79
|
-
};
|
|
47
|
+
webhooks: EventHandlersClient;
|
|
48
|
+
servicePlugins: ServicePluginsClient;
|
|
80
49
|
} & BuildDescriptors<T, H>;
|
|
81
|
-
type ResolvePossibleEvents<T extends EventDefinition<any>[]> = {
|
|
82
|
-
[K in keyof T]: T[K] extends EventDefinition<any> ? {
|
|
83
|
-
eventType: T[K]['type'];
|
|
84
|
-
payload: T[K]['__payload'];
|
|
85
|
-
} : never;
|
|
86
|
-
} extends (infer U)[] ? U : never;
|
|
87
|
-
export type ProcessedEvent<T extends EventDefinition<any>[] = []> = {
|
|
88
|
-
instanceId: string;
|
|
89
|
-
identity?: EventIdentity;
|
|
90
|
-
} & (T['length'] extends 0 ? {
|
|
91
|
-
eventType: string;
|
|
92
|
-
payload: unknown;
|
|
93
|
-
} : ResolvePossibleEvents<T>);
|
|
94
50
|
export declare function createClient<H extends Host<any> | undefined = undefined, Z extends AuthenticationStrategy<H> = AuthenticationStrategy<H>, T extends Descriptors = EmptyObject>(config: {
|
|
95
51
|
modules?: H extends Host<any> ? AssertHostMatches<T, H> : T;
|
|
96
52
|
auth?: Z;
|
package/build/wixClient.js
CHANGED
|
@@ -1,23 +1,23 @@
|
|
|
1
1
|
import { wixContext } from '@wix/sdk-context';
|
|
2
|
-
import {
|
|
2
|
+
import { SERVICE_PLUGIN_ERROR_TYPE, } from '@wix/sdk-types';
|
|
3
3
|
import { ambassadorModuleOptions, isAmbassadorModule, toHTTPModule, } from './ambassador-modules.js';
|
|
4
4
|
import { API_URL, PUBLIC_METADATA_KEY } from './common.js';
|
|
5
5
|
import { FetchErrorResponse } from './fetch-error.js';
|
|
6
6
|
import { getDefaultContentHeader, isObject } from './helpers.js';
|
|
7
7
|
import { buildHostModule, isHostModule } from './host-modules.js';
|
|
8
8
|
import { buildRESTDescriptor } from './rest-modules.js';
|
|
9
|
-
import {
|
|
10
|
-
import {
|
|
9
|
+
import { eventHandlersModules, isEventHandlerModule, } from './event-handlers-modules.js';
|
|
10
|
+
import { isServicePluginModule, servicePluginsModules, } from './service-plugin-modules.js';
|
|
11
11
|
export function createClient(config) {
|
|
12
12
|
const _headers = config.headers || { Authorization: '' };
|
|
13
|
-
const eventHandlers = new Map();
|
|
14
|
-
const servicePluginsImplementations = new Map();
|
|
15
13
|
const authStrategy = config.auth ||
|
|
16
14
|
{
|
|
17
15
|
getAuthHeaders: (_) => Promise.resolve({ headers: {} }),
|
|
18
16
|
};
|
|
19
17
|
const boundGetAuthHeaders = authStrategy.getAuthHeaders.bind(undefined, config.host);
|
|
20
18
|
authStrategy.getAuthHeaders = boundGetAuthHeaders;
|
|
19
|
+
const { client: servicePluginsClient, initModule: initServicePluginModule } = servicePluginsModules(authStrategy);
|
|
20
|
+
const { client: eventHandlersClient, initModule: initEventHandlerModule } = eventHandlersModules(authStrategy);
|
|
21
21
|
const boundFetch = async (url, options) => {
|
|
22
22
|
const authHeaders = await boundGetAuthHeaders();
|
|
23
23
|
const defaultContentTypeHeader = getDefaultContentHeader(options);
|
|
@@ -36,18 +36,10 @@ export function createClient(config) {
|
|
|
36
36
|
// excessively deep and possibly infinite.`
|
|
37
37
|
const use = (modules, metadata) => {
|
|
38
38
|
if (isEventHandlerModule(modules)) {
|
|
39
|
-
return
|
|
40
|
-
const handlers = eventHandlers.get(eventDefinition.type) ?? [];
|
|
41
|
-
handlers.push({ eventDefinition, handler });
|
|
42
|
-
eventHandlers.set(eventDefinition.type, handlers);
|
|
43
|
-
});
|
|
39
|
+
return initEventHandlerModule(modules);
|
|
44
40
|
}
|
|
45
41
|
else if (isServicePluginModule(modules)) {
|
|
46
|
-
return
|
|
47
|
-
const implementations = servicePluginsImplementations.get(servicePluginDefinition.componentType.toLowerCase()) ?? [];
|
|
48
|
-
implementations.push({ servicePluginDefinition, implementation });
|
|
49
|
-
servicePluginsImplementations.set(servicePluginDefinition.componentType.toLowerCase(), implementations);
|
|
50
|
-
});
|
|
42
|
+
return initServicePluginModule(modules);
|
|
51
43
|
}
|
|
52
44
|
else if (isHostModule(modules) && config.host) {
|
|
53
45
|
return buildHostModule(modules, config.host);
|
|
@@ -161,137 +153,7 @@ export function createClient(config) {
|
|
|
161
153
|
const { data, errors } = await res.json();
|
|
162
154
|
return { data: data ?? {}, errors };
|
|
163
155
|
},
|
|
164
|
-
webhooks:
|
|
165
|
-
|
|
166
|
-
async process(jwt, opts = {
|
|
167
|
-
expectedEvents: [],
|
|
168
|
-
}) {
|
|
169
|
-
const { eventType, identity, instanceId, payload } = await this.parseJWT(jwt);
|
|
170
|
-
const allExpectedEvents = [
|
|
171
|
-
...opts.expectedEvents,
|
|
172
|
-
...Array.from(eventHandlers.keys()).map((type) => ({ type })),
|
|
173
|
-
];
|
|
174
|
-
if (allExpectedEvents.length > 0 &&
|
|
175
|
-
!allExpectedEvents.some(({ type }) => type === eventType)) {
|
|
176
|
-
throw new Error(`Unexpected event type: ${eventType}. Expected one of: ${allExpectedEvents
|
|
177
|
-
.map((x) => x.type)
|
|
178
|
-
.join(', ')}`);
|
|
179
|
-
}
|
|
180
|
-
const handlers = eventHandlers.get(eventType) ?? [];
|
|
181
|
-
await Promise.all(handlers.map(({ eventDefinition, handler }) => runHandler(eventDefinition, handler, payload, {
|
|
182
|
-
instanceId,
|
|
183
|
-
identity,
|
|
184
|
-
})));
|
|
185
|
-
return {
|
|
186
|
-
instanceId,
|
|
187
|
-
eventType,
|
|
188
|
-
payload,
|
|
189
|
-
identity,
|
|
190
|
-
};
|
|
191
|
-
},
|
|
192
|
-
async processRequest(request, opts) {
|
|
193
|
-
const body = await request.text();
|
|
194
|
-
return this.process(body, opts);
|
|
195
|
-
},
|
|
196
|
-
async parseJWT(jwt) {
|
|
197
|
-
if (!authStrategy.decodeJWT) {
|
|
198
|
-
throw new Error('decodeJWT is not supported by the authentication strategy');
|
|
199
|
-
}
|
|
200
|
-
const { decoded, valid } = await authStrategy.decodeJWT(jwt);
|
|
201
|
-
if (!valid) {
|
|
202
|
-
throw new Error('JWT is not valid');
|
|
203
|
-
}
|
|
204
|
-
if (typeof decoded.data !== 'string') {
|
|
205
|
-
throw new Error(`Unexpected type of JWT data: expected string, got ${typeof decoded.data}`);
|
|
206
|
-
}
|
|
207
|
-
const parsedDecoded = JSON.parse(decoded.data);
|
|
208
|
-
const eventType = parsedDecoded.eventType;
|
|
209
|
-
const instanceId = parsedDecoded.instanceId;
|
|
210
|
-
const identity = parsedDecoded.identity
|
|
211
|
-
? JSON.parse(parsedDecoded.identity)
|
|
212
|
-
: undefined;
|
|
213
|
-
const payload = JSON.parse(parsedDecoded.data);
|
|
214
|
-
return {
|
|
215
|
-
instanceId,
|
|
216
|
-
eventType,
|
|
217
|
-
payload,
|
|
218
|
-
identity,
|
|
219
|
-
};
|
|
220
|
-
},
|
|
221
|
-
async parseRequest(request) {
|
|
222
|
-
const jwt = await request.text();
|
|
223
|
-
return this.parseJWT(jwt);
|
|
224
|
-
},
|
|
225
|
-
async executeHandlers(event) {
|
|
226
|
-
const allExpectedEvents = Array.from(eventHandlers.keys()).map((type) => ({ type }));
|
|
227
|
-
if (allExpectedEvents.length > 0 &&
|
|
228
|
-
!allExpectedEvents.some(({ type }) => type === event.eventType)) {
|
|
229
|
-
throw new Error(`Unexpected event type: ${event.eventType}. Expected one of: ${allExpectedEvents
|
|
230
|
-
.map((x) => x.type)
|
|
231
|
-
.join(', ')}`);
|
|
232
|
-
}
|
|
233
|
-
const handlers = eventHandlers.get(event.eventType) ?? [];
|
|
234
|
-
await Promise.all(handlers.map(({ eventDefinition, handler }) => runHandler(eventDefinition, handler, event.payload, {
|
|
235
|
-
instanceId: event.instanceId,
|
|
236
|
-
identity: event.identity,
|
|
237
|
-
})));
|
|
238
|
-
},
|
|
239
|
-
apps: {
|
|
240
|
-
AppInstalled: EventDefinition('AppInstalled')(),
|
|
241
|
-
AppRemoved: EventDefinition('AppRemoved')(),
|
|
242
|
-
},
|
|
243
|
-
},
|
|
244
|
-
servicePlugins: {
|
|
245
|
-
getRegisteredServicePlugins: () => servicePluginsImplementations,
|
|
246
|
-
async process(request) {
|
|
247
|
-
const servicePluginRequest = await this.parseJWT(request.body);
|
|
248
|
-
return this.executeHandler(servicePluginRequest, request.url);
|
|
249
|
-
},
|
|
250
|
-
async processRequest(request) {
|
|
251
|
-
const url = request.url;
|
|
252
|
-
const body = await request.text();
|
|
253
|
-
const implMethodResult = await this.process({ url, body });
|
|
254
|
-
return Response.json(implMethodResult);
|
|
255
|
-
},
|
|
256
|
-
async parseJWT(jwt) {
|
|
257
|
-
if (!authStrategy.decodeJWT) {
|
|
258
|
-
throw new Error('decodeJWT is not supported by the authentication strategy');
|
|
259
|
-
}
|
|
260
|
-
const { decoded, valid } = await authStrategy.decodeJWT(jwt, true);
|
|
261
|
-
if (!valid) {
|
|
262
|
-
throw new Error('JWT is not valid');
|
|
263
|
-
}
|
|
264
|
-
if (typeof decoded.data !== 'object' ||
|
|
265
|
-
decoded.data === null ||
|
|
266
|
-
!('metadata' in decoded.data) ||
|
|
267
|
-
typeof decoded.data.metadata !== 'object' ||
|
|
268
|
-
decoded.data.metadata === null ||
|
|
269
|
-
!('appExtensionType' in decoded.data.metadata) ||
|
|
270
|
-
typeof decoded.data.metadata.appExtensionType !== 'string') {
|
|
271
|
-
throw new Error('Unexpected JWT data: expected object with metadata.appExtensionType string');
|
|
272
|
-
}
|
|
273
|
-
return decoded.data;
|
|
274
|
-
},
|
|
275
|
-
async executeHandler(servicePluginRequest, url) {
|
|
276
|
-
const componentType = servicePluginRequest.metadata.appExtensionType.toLowerCase();
|
|
277
|
-
const implementations = servicePluginsImplementations.get(componentType) ?? [];
|
|
278
|
-
if (implementations.length === 0) {
|
|
279
|
-
throw new Error(`No service plugin implementations found for component type ${componentType}`);
|
|
280
|
-
}
|
|
281
|
-
else if (implementations.length > 1) {
|
|
282
|
-
throw new Error(`Multiple service plugin implementations found for component type ${componentType}. This is currently not supported`);
|
|
283
|
-
}
|
|
284
|
-
const { implementation: impl, servicePluginDefinition } = implementations[0];
|
|
285
|
-
const method = servicePluginDefinition.methods.find((m) => url.endsWith(m.primaryHttpMappingPath));
|
|
286
|
-
if (!method) {
|
|
287
|
-
throw new Error('Unexpect request: request url did not match any method: ' + url);
|
|
288
|
-
}
|
|
289
|
-
const implMethod = impl[method.name];
|
|
290
|
-
if (!implMethod) {
|
|
291
|
-
throw new Error(`Got request for service plugin method ${method.name} but no implementation was provided. Available methods: ${Object.keys(impl).join(', ')}`);
|
|
292
|
-
}
|
|
293
|
-
return method.transformations.toREST(await implMethod(method.transformations.fromREST(servicePluginRequest)));
|
|
294
|
-
},
|
|
295
|
-
},
|
|
156
|
+
webhooks: eventHandlersClient,
|
|
157
|
+
servicePlugins: servicePluginsClient,
|
|
296
158
|
};
|
|
297
159
|
}
|
|
@@ -66,6 +66,7 @@ const helpers_js_1 = require("../helpers.js");
|
|
|
66
66
|
*/
|
|
67
67
|
// eslint-disable-next-line @typescript-eslint/no-redeclare
|
|
68
68
|
function AppStrategy(opts) {
|
|
69
|
+
const authServerBaseUrl = opts.authServerBaseUrl ?? 'https://www.wixapis.com';
|
|
69
70
|
let refreshToken = 'refreshToken' in opts ? opts.refreshToken : undefined;
|
|
70
71
|
return {
|
|
71
72
|
getInstallUrl({ redirectUrl, token, state }) {
|
|
@@ -94,7 +95,8 @@ function AppStrategy(opts) {
|
|
|
94
95
|
if (!code || !instanceId) {
|
|
95
96
|
throw new Error('Invalid OAuth callback URL. Make sure you pass the url including the code and instanceId query params.');
|
|
96
97
|
}
|
|
97
|
-
const
|
|
98
|
+
const tokenUrl = new URL('/oauth/access', authServerBaseUrl);
|
|
99
|
+
const tokensRes = await fetch(tokenUrl.href, {
|
|
98
100
|
method: 'POST',
|
|
99
101
|
headers: {
|
|
100
102
|
'Content-Type': 'application/json',
|
|
@@ -122,7 +124,8 @@ function AppStrategy(opts) {
|
|
|
122
124
|
if (!opts.appSecret) {
|
|
123
125
|
throw new Error('App secret is required for retrieveing app-level access tokens. Make sure to pass it to the AppStrategy');
|
|
124
126
|
}
|
|
125
|
-
const
|
|
127
|
+
const tokenUrl = new URL('/oauth/access', authServerBaseUrl);
|
|
128
|
+
const tokensRes = await fetch(tokenUrl.href, {
|
|
126
129
|
method: 'POST',
|
|
127
130
|
headers: {
|
|
128
131
|
'Content-Type': 'application/json',
|
|
@@ -149,7 +152,8 @@ function AppStrategy(opts) {
|
|
|
149
152
|
if (!opts.appSecret) {
|
|
150
153
|
throw new Error('App secret is required for retrieveing app-level access tokens. Make sure to pass it to the AppStrategy');
|
|
151
154
|
}
|
|
152
|
-
const
|
|
155
|
+
const tokenUrl = new URL('/oauth2/token', authServerBaseUrl);
|
|
156
|
+
const tokensRes = await fetch(tokenUrl.href, {
|
|
153
157
|
method: 'POST',
|
|
154
158
|
headers: {
|
|
155
159
|
'Content-Type': 'application/json',
|
|
@@ -184,7 +188,7 @@ function AppStrategy(opts) {
|
|
|
184
188
|
},
|
|
185
189
|
async elevated() {
|
|
186
190
|
if ('accessToken' in opts && opts.accessToken) {
|
|
187
|
-
const tokenInfo = await getTokenInfo(opts.accessToken);
|
|
191
|
+
const tokenInfo = await getTokenInfo(opts.accessToken, authServerBaseUrl);
|
|
188
192
|
if (tokenInfo.clientId !== opts.appId) {
|
|
189
193
|
throw new Error(`Invalid access token. The token is not issued for the app with ID "${opts.appId}"`);
|
|
190
194
|
}
|
|
@@ -196,6 +200,7 @@ function AppStrategy(opts) {
|
|
|
196
200
|
appSecret: opts.appSecret,
|
|
197
201
|
publicKey: opts.publicKey,
|
|
198
202
|
instanceId: tokenInfo.instanceId,
|
|
203
|
+
authServerBaseUrl: opts.authServerBaseUrl,
|
|
199
204
|
});
|
|
200
205
|
}
|
|
201
206
|
else {
|
|
@@ -226,13 +231,14 @@ function AppStrategy(opts) {
|
|
|
226
231
|
if (!tokenToCheck) {
|
|
227
232
|
throw new Error('Missing token to get info for. Either pass the token as an argument or provide it when initializing the AppStrategy');
|
|
228
233
|
}
|
|
229
|
-
return getTokenInfo(tokenToCheck);
|
|
234
|
+
return getTokenInfo(tokenToCheck, authServerBaseUrl);
|
|
230
235
|
},
|
|
231
236
|
};
|
|
232
237
|
}
|
|
233
238
|
exports.AppStrategy = AppStrategy;
|
|
234
|
-
async function getTokenInfo(token) {
|
|
235
|
-
const
|
|
239
|
+
async function getTokenInfo(token, authServerBaseUrl) {
|
|
240
|
+
const tokenInfoUrl = new URL('/oauth2/token-info', authServerBaseUrl);
|
|
241
|
+
const tokenInfoRes = await fetch(tokenInfoUrl.href, {
|
|
236
242
|
method: 'POST',
|
|
237
243
|
headers: {
|
|
238
244
|
'Content-Type': 'application/json',
|
|
@@ -1,4 +1,48 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { AuthenticationStrategy, EventDefinition, EventHandler, EventIdentity } from '@wix/sdk-types';
|
|
2
|
+
import { Emitter } from 'nanoevents';
|
|
2
3
|
export declare const isEventHandlerModule: (val: any) => val is EventDefinition<unknown, string>;
|
|
3
4
|
export declare function buildEventDefinition<T extends EventDefinition<any, string>>(eventDefinition: T, registerHandler: (eventDefinition: T, handler: EventHandler<T>) => void): (handler: EventHandler<T>) => void;
|
|
4
|
-
|
|
5
|
+
type ResolvePossibleEvents<T extends EventDefinition<any>[]> = {
|
|
6
|
+
[K in keyof T]: T[K] extends EventDefinition<any> ? {
|
|
7
|
+
eventType: T[K]['type'];
|
|
8
|
+
payload: T[K]['__payload'];
|
|
9
|
+
} : never;
|
|
10
|
+
} extends (infer U)[] ? U : never;
|
|
11
|
+
export type ProcessedEvent<T extends EventDefinition<any>[] = []> = {
|
|
12
|
+
instanceId: string;
|
|
13
|
+
identity?: EventIdentity;
|
|
14
|
+
} & (T['length'] extends 0 ? {
|
|
15
|
+
eventType: string;
|
|
16
|
+
payload: unknown;
|
|
17
|
+
} : ResolvePossibleEvents<T>);
|
|
18
|
+
export type EventHandlersClient = Emitter<{
|
|
19
|
+
registered: (event: EventDefinition<any>) => void;
|
|
20
|
+
}> & {
|
|
21
|
+
getRegisteredEvents(): Map<string, {
|
|
22
|
+
eventDefinition: EventDefinition;
|
|
23
|
+
handler: EventHandler<EventDefinition>;
|
|
24
|
+
}[]>;
|
|
25
|
+
process<ExpectedEvents extends EventDefinition<any>[] = []>(jwt: string, opts?: {
|
|
26
|
+
expectedEvents: ExpectedEvents;
|
|
27
|
+
}): Promise<ProcessedEvent<ExpectedEvents>>;
|
|
28
|
+
processRequest<ExpectedEvents extends EventDefinition<any>[] = []>(request: Request, opts?: {
|
|
29
|
+
expectedEvents: ExpectedEvents;
|
|
30
|
+
}): Promise<ProcessedEvent<ExpectedEvents>>;
|
|
31
|
+
parseJWT(jwt: string): Promise<ProcessedEvent>;
|
|
32
|
+
parseRequest(request: Request): Promise<ProcessedEvent>;
|
|
33
|
+
executeHandlers(event: ProcessedEvent): Promise<void>;
|
|
34
|
+
apps: {
|
|
35
|
+
AppInstalled: EventDefinition<{
|
|
36
|
+
appId: string;
|
|
37
|
+
originInstanceId: string;
|
|
38
|
+
}, 'AppInstalled'>;
|
|
39
|
+
AppRemoved: EventDefinition<{
|
|
40
|
+
appId: string;
|
|
41
|
+
}, 'AppRemoved'>;
|
|
42
|
+
};
|
|
43
|
+
};
|
|
44
|
+
export declare function eventHandlersModules(authStrategy: AuthenticationStrategy<any>): {
|
|
45
|
+
initModule(eventDefinition: EventDefinition<any, string>): (handler: EventHandler<EventDefinition<any, string>>) => void;
|
|
46
|
+
client: EventHandlersClient;
|
|
47
|
+
};
|
|
48
|
+
export {};
|
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.
|
|
3
|
+
exports.eventHandlersModules = exports.buildEventDefinition = exports.isEventHandlerModule = void 0;
|
|
4
|
+
const sdk_types_1 = require("@wix/sdk-types");
|
|
5
|
+
const nanoevents_1 = require("nanoevents");
|
|
4
6
|
const isEventHandlerModule = (val) => val.__type === 'event-definition';
|
|
5
7
|
exports.isEventHandlerModule = isEventHandlerModule;
|
|
6
8
|
function buildEventDefinition(eventDefinition, registerHandler) {
|
|
@@ -51,4 +53,100 @@ function runHandler(eventDefinition, handler, payload, baseEventMetadata) {
|
|
|
51
53
|
const transformFromRESTFn = eventDefinition.transformations ?? ((x) => x);
|
|
52
54
|
return handler(transformFromRESTFn(envelope));
|
|
53
55
|
}
|
|
54
|
-
|
|
56
|
+
function eventHandlersModules(authStrategy) {
|
|
57
|
+
const eventHandlers = new Map();
|
|
58
|
+
const webhooksEmitter = (0, nanoevents_1.createNanoEvents)();
|
|
59
|
+
const client = {
|
|
60
|
+
...webhooksEmitter,
|
|
61
|
+
getRegisteredEvents: () => eventHandlers,
|
|
62
|
+
async process(jwt, opts = {
|
|
63
|
+
expectedEvents: [],
|
|
64
|
+
}) {
|
|
65
|
+
const { eventType, identity, instanceId, payload } = await this.parseJWT(jwt);
|
|
66
|
+
const allExpectedEvents = [
|
|
67
|
+
...opts.expectedEvents,
|
|
68
|
+
...Array.from(eventHandlers.keys()).map((type) => ({ type })),
|
|
69
|
+
];
|
|
70
|
+
if (allExpectedEvents.length > 0 &&
|
|
71
|
+
!allExpectedEvents.some(({ type }) => type === eventType)) {
|
|
72
|
+
throw new Error(`Unexpected event type: ${eventType}. Expected one of: ${allExpectedEvents
|
|
73
|
+
.map((x) => x.type)
|
|
74
|
+
.join(', ')}`);
|
|
75
|
+
}
|
|
76
|
+
const handlers = eventHandlers.get(eventType) ?? [];
|
|
77
|
+
await Promise.all(handlers.map(({ eventDefinition, handler }) => runHandler(eventDefinition, handler, payload, {
|
|
78
|
+
instanceId,
|
|
79
|
+
identity,
|
|
80
|
+
})));
|
|
81
|
+
return {
|
|
82
|
+
instanceId,
|
|
83
|
+
eventType,
|
|
84
|
+
payload,
|
|
85
|
+
identity,
|
|
86
|
+
};
|
|
87
|
+
},
|
|
88
|
+
async processRequest(request, opts) {
|
|
89
|
+
const body = await request.text();
|
|
90
|
+
return this.process(body, opts);
|
|
91
|
+
},
|
|
92
|
+
async parseJWT(jwt) {
|
|
93
|
+
if (!authStrategy.decodeJWT) {
|
|
94
|
+
throw new Error('decodeJWT is not supported by the authentication strategy');
|
|
95
|
+
}
|
|
96
|
+
const { decoded, valid } = await authStrategy.decodeJWT(jwt);
|
|
97
|
+
if (!valid) {
|
|
98
|
+
throw new Error('JWT is not valid');
|
|
99
|
+
}
|
|
100
|
+
if (typeof decoded.data !== 'string') {
|
|
101
|
+
throw new Error(`Unexpected type of JWT data: expected string, got ${typeof decoded.data}`);
|
|
102
|
+
}
|
|
103
|
+
const parsedDecoded = JSON.parse(decoded.data);
|
|
104
|
+
const eventType = parsedDecoded.eventType;
|
|
105
|
+
const instanceId = parsedDecoded.instanceId;
|
|
106
|
+
const identity = parsedDecoded.identity
|
|
107
|
+
? JSON.parse(parsedDecoded.identity)
|
|
108
|
+
: undefined;
|
|
109
|
+
const payload = JSON.parse(parsedDecoded.data);
|
|
110
|
+
return {
|
|
111
|
+
instanceId,
|
|
112
|
+
eventType,
|
|
113
|
+
payload,
|
|
114
|
+
identity,
|
|
115
|
+
};
|
|
116
|
+
},
|
|
117
|
+
async parseRequest(request) {
|
|
118
|
+
const jwt = await request.text();
|
|
119
|
+
return this.parseJWT(jwt);
|
|
120
|
+
},
|
|
121
|
+
async executeHandlers(event) {
|
|
122
|
+
const allExpectedEvents = Array.from(eventHandlers.keys()).map((type) => ({ type }));
|
|
123
|
+
if (allExpectedEvents.length > 0 &&
|
|
124
|
+
!allExpectedEvents.some(({ type }) => type === event.eventType)) {
|
|
125
|
+
throw new Error(`Unexpected event type: ${event.eventType}. Expected one of: ${allExpectedEvents
|
|
126
|
+
.map((x) => x.type)
|
|
127
|
+
.join(', ')}`);
|
|
128
|
+
}
|
|
129
|
+
const handlers = eventHandlers.get(event.eventType) ?? [];
|
|
130
|
+
await Promise.all(handlers.map(({ eventDefinition, handler }) => runHandler(eventDefinition, handler, event.payload, {
|
|
131
|
+
instanceId: event.instanceId,
|
|
132
|
+
identity: event.identity,
|
|
133
|
+
})));
|
|
134
|
+
},
|
|
135
|
+
apps: {
|
|
136
|
+
AppInstalled: (0, sdk_types_1.EventDefinition)('AppInstalled')(),
|
|
137
|
+
AppRemoved: (0, sdk_types_1.EventDefinition)('AppRemoved')(),
|
|
138
|
+
},
|
|
139
|
+
};
|
|
140
|
+
return {
|
|
141
|
+
initModule(eventDefinition) {
|
|
142
|
+
return (handler) => {
|
|
143
|
+
const handlers = eventHandlers.get(eventDefinition.type) ?? [];
|
|
144
|
+
handlers.push({ eventDefinition, handler });
|
|
145
|
+
eventHandlers.set(eventDefinition.type, handlers);
|
|
146
|
+
webhooksEmitter.emit('registered', eventDefinition);
|
|
147
|
+
};
|
|
148
|
+
},
|
|
149
|
+
client,
|
|
150
|
+
};
|
|
151
|
+
}
|
|
152
|
+
exports.eventHandlersModules = eventHandlersModules;
|
|
@@ -1,8 +1,33 @@
|
|
|
1
|
-
import { ServicePluginContract, ServicePluginDefinition } from '@wix/sdk-types';
|
|
1
|
+
import { AuthenticationStrategy, ServicePluginContract, ServicePluginDefinition } from '@wix/sdk-types';
|
|
2
|
+
import { Emitter } from 'nanoevents';
|
|
2
3
|
export declare const isServicePluginModule: (val: any) => val is ServicePluginDefinition<ServicePluginContract>;
|
|
3
|
-
export
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
4
|
+
export type UnknownServicePluginResponse = unknown;
|
|
5
|
+
type ServicePluginRequestMetadata = {
|
|
6
|
+
instanceId: string;
|
|
7
|
+
appExtensionType: string;
|
|
8
|
+
};
|
|
9
|
+
type ServicePluginRequest = {
|
|
10
|
+
metadata: ServicePluginRequestMetadata;
|
|
11
|
+
request: unknown;
|
|
12
|
+
};
|
|
13
|
+
export type ServicePluginsClient = Emitter<{
|
|
14
|
+
registered: (servicePluginDefinition: ServicePluginDefinition<ServicePluginContract>) => void;
|
|
15
|
+
}> & {
|
|
16
|
+
getRegisteredServicePlugins(): Map<string, {
|
|
17
|
+
servicePluginDefinition: ServicePluginDefinition<any>;
|
|
18
|
+
implementation: ServicePluginContract;
|
|
19
|
+
}[]>;
|
|
20
|
+
process(request: {
|
|
21
|
+
url: string;
|
|
22
|
+
body: string;
|
|
23
|
+
}): Promise<unknown>;
|
|
24
|
+
processRequest(request: Request): Promise<Response>;
|
|
25
|
+
parseJWT(jwt: string): Promise<ServicePluginRequest>;
|
|
26
|
+
parseRequest(request: Request): Promise<ServicePluginRequest>;
|
|
27
|
+
executeHandler(servicePluginRequest: ServicePluginRequest, url: string): Promise<UnknownServicePluginResponse>;
|
|
28
|
+
};
|
|
29
|
+
export declare function servicePluginsModules(authStrategy: AuthenticationStrategy<any>): {
|
|
30
|
+
initModule<T extends ServicePluginDefinition<any>>(servicePluginDefinition: T): (implementation: T["__contract"]) => void;
|
|
31
|
+
client: ServicePluginsClient;
|
|
32
|
+
};
|
|
33
|
+
export {};
|
|
@@ -1,11 +1,79 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.
|
|
3
|
+
exports.servicePluginsModules = exports.isServicePluginModule = void 0;
|
|
4
|
+
const nanoevents_1 = require("nanoevents");
|
|
4
5
|
const isServicePluginModule = (val) => val.__type === 'service-plugin-definition';
|
|
5
6
|
exports.isServicePluginModule = isServicePluginModule;
|
|
6
|
-
function
|
|
7
|
-
|
|
8
|
-
|
|
7
|
+
function servicePluginsModules(authStrategy) {
|
|
8
|
+
const servicePluginsImplementations = new Map();
|
|
9
|
+
const servicePluginsEmitter = (0, nanoevents_1.createNanoEvents)();
|
|
10
|
+
const client = {
|
|
11
|
+
...servicePluginsEmitter,
|
|
12
|
+
getRegisteredServicePlugins: () => servicePluginsImplementations,
|
|
13
|
+
async parseJWT(jwt) {
|
|
14
|
+
if (!authStrategy.decodeJWT) {
|
|
15
|
+
throw new Error('decodeJWT is not supported by the authentication strategy');
|
|
16
|
+
}
|
|
17
|
+
const { decoded, valid } = await authStrategy.decodeJWT(jwt, true);
|
|
18
|
+
if (!valid) {
|
|
19
|
+
throw new Error('JWT is not valid');
|
|
20
|
+
}
|
|
21
|
+
if (typeof decoded.data !== 'object' ||
|
|
22
|
+
decoded.data === null ||
|
|
23
|
+
!('metadata' in decoded.data) ||
|
|
24
|
+
typeof decoded.data.metadata !== 'object' ||
|
|
25
|
+
decoded.data.metadata === null ||
|
|
26
|
+
!('appExtensionType' in decoded.data.metadata) ||
|
|
27
|
+
typeof decoded.data.metadata.appExtensionType !== 'string') {
|
|
28
|
+
throw new Error('Unexpected JWT data: expected object with metadata.appExtensionType string');
|
|
29
|
+
}
|
|
30
|
+
return decoded.data;
|
|
31
|
+
},
|
|
32
|
+
async process(request) {
|
|
33
|
+
const servicePluginRequest = await this.parseJWT(request.body);
|
|
34
|
+
return this.executeHandler(servicePluginRequest, request.url);
|
|
35
|
+
},
|
|
36
|
+
async parseRequest(request) {
|
|
37
|
+
const body = await request.text();
|
|
38
|
+
return this.parseJWT(body);
|
|
39
|
+
},
|
|
40
|
+
async processRequest(request) {
|
|
41
|
+
const url = request.url;
|
|
42
|
+
const body = await request.text();
|
|
43
|
+
const implMethodResult = await this.process({ url, body });
|
|
44
|
+
return Response.json(implMethodResult);
|
|
45
|
+
},
|
|
46
|
+
async executeHandler(servicePluginRequest, url) {
|
|
47
|
+
const componentType = servicePluginRequest.metadata.appExtensionType.toLowerCase();
|
|
48
|
+
const implementations = servicePluginsImplementations.get(componentType) ?? [];
|
|
49
|
+
if (implementations.length === 0) {
|
|
50
|
+
throw new Error(`No service plugin implementations found for component type ${componentType}`);
|
|
51
|
+
}
|
|
52
|
+
else if (implementations.length > 1) {
|
|
53
|
+
throw new Error(`Multiple service plugin implementations found for component type ${componentType}. This is currently not supported`);
|
|
54
|
+
}
|
|
55
|
+
const { implementation: impl, servicePluginDefinition } = implementations[0];
|
|
56
|
+
const method = servicePluginDefinition.methods.find((m) => url.endsWith(m.primaryHttpMappingPath));
|
|
57
|
+
if (!method) {
|
|
58
|
+
throw new Error('Unexpect request: request url did not match any method: ' + url);
|
|
59
|
+
}
|
|
60
|
+
const implMethod = impl[method.name];
|
|
61
|
+
if (!implMethod) {
|
|
62
|
+
throw new Error(`Got request for service plugin method ${method.name} but no implementation was provided. Available methods: ${Object.keys(impl).join(', ')}`);
|
|
63
|
+
}
|
|
64
|
+
return method.transformations.toREST(await implMethod(method.transformations.fromREST(servicePluginRequest)));
|
|
65
|
+
},
|
|
66
|
+
};
|
|
67
|
+
return {
|
|
68
|
+
initModule(servicePluginDefinition) {
|
|
69
|
+
return (implementation) => {
|
|
70
|
+
const implementations = servicePluginsImplementations.get(servicePluginDefinition.componentType.toLowerCase()) ?? [];
|
|
71
|
+
implementations.push({ servicePluginDefinition, implementation });
|
|
72
|
+
servicePluginsImplementations.set(servicePluginDefinition.componentType.toLowerCase(), implementations);
|
|
73
|
+
servicePluginsEmitter.emit('registered', servicePluginDefinition);
|
|
74
|
+
};
|
|
75
|
+
},
|
|
76
|
+
client,
|
|
9
77
|
};
|
|
10
78
|
}
|
|
11
|
-
exports.
|
|
79
|
+
exports.servicePluginsModules = servicePluginsModules;
|
package/cjs/build/wixClient.d.ts
CHANGED
|
@@ -1,6 +1,8 @@
|
|
|
1
|
-
import { AuthenticationStrategy, BoundAuthenticationStrategy, BuildDescriptors, Descriptors,
|
|
1
|
+
import { AuthenticationStrategy, BoundAuthenticationStrategy, BuildDescriptors, Descriptors, Host, HostModule, RESTFunctionDescriptor } from '@wix/sdk-types';
|
|
2
2
|
import { EmptyObject } from 'type-fest/source/empty-object.js';
|
|
3
3
|
import type { GraphQLFormattedError } from 'graphql';
|
|
4
|
+
import { EventHandlersClient } from './event-handlers-modules.js';
|
|
5
|
+
import { ServicePluginsClient } from './service-plugin-modules.js';
|
|
4
6
|
export type ContextType = 'global' | 'module';
|
|
5
7
|
type Headers = Record<string, string>;
|
|
6
8
|
/**
|
|
@@ -42,55 +44,9 @@ export type WixClient<H extends Host<any> | undefined = undefined, Z extends Aut
|
|
|
42
44
|
data: Result;
|
|
43
45
|
errors?: GraphQLFormattedError[];
|
|
44
46
|
}>;
|
|
45
|
-
webhooks:
|
|
46
|
-
|
|
47
|
-
process<ExpectedEvents extends EventDefinition<any>[] = []>(jwt: string, opts?: {
|
|
48
|
-
expectedEvents: ExpectedEvents;
|
|
49
|
-
}): Promise<ProcessedEvent<ExpectedEvents>>;
|
|
50
|
-
processRequest<ExpectedEvents extends EventDefinition<any>[] = []>(request: Request, opts?: {
|
|
51
|
-
expectedEvents: ExpectedEvents;
|
|
52
|
-
}): Promise<ProcessedEvent<ExpectedEvents>>;
|
|
53
|
-
parseJWT(jwt: string): Promise<ProcessedEvent>;
|
|
54
|
-
parseRequest(request: Request): Promise<ProcessedEvent>;
|
|
55
|
-
executeHandlers(event: ProcessedEvent): Promise<void>;
|
|
56
|
-
apps: {
|
|
57
|
-
AppInstalled: EventDefinition<{
|
|
58
|
-
appId: string;
|
|
59
|
-
originInstanceId: string;
|
|
60
|
-
}, 'AppInstalled'>;
|
|
61
|
-
AppRemoved: EventDefinition<{
|
|
62
|
-
appId: string;
|
|
63
|
-
}, 'AppRemoved'>;
|
|
64
|
-
};
|
|
65
|
-
};
|
|
66
|
-
servicePlugins: {
|
|
67
|
-
getRegisteredServicePlugins(): Map<string, {
|
|
68
|
-
servicePluginDefinition: ServicePluginDefinition<any>;
|
|
69
|
-
implementation: ServicePluginContract;
|
|
70
|
-
}[]>;
|
|
71
|
-
process(request: {
|
|
72
|
-
url: string;
|
|
73
|
-
body: string;
|
|
74
|
-
}): Promise<unknown>;
|
|
75
|
-
processRequest(request: Request): Promise<Response>;
|
|
76
|
-
parseJWT(jwt: string): Promise<unknown>;
|
|
77
|
-
parseRequest(request: Request): Promise<unknown>;
|
|
78
|
-
executeHandler(servicePluginRequest: ProcessedEvent): Promise<void>;
|
|
79
|
-
};
|
|
47
|
+
webhooks: EventHandlersClient;
|
|
48
|
+
servicePlugins: ServicePluginsClient;
|
|
80
49
|
} & BuildDescriptors<T, H>;
|
|
81
|
-
type ResolvePossibleEvents<T extends EventDefinition<any>[]> = {
|
|
82
|
-
[K in keyof T]: T[K] extends EventDefinition<any> ? {
|
|
83
|
-
eventType: T[K]['type'];
|
|
84
|
-
payload: T[K]['__payload'];
|
|
85
|
-
} : never;
|
|
86
|
-
} extends (infer U)[] ? U : never;
|
|
87
|
-
export type ProcessedEvent<T extends EventDefinition<any>[] = []> = {
|
|
88
|
-
instanceId: string;
|
|
89
|
-
identity?: EventIdentity;
|
|
90
|
-
} & (T['length'] extends 0 ? {
|
|
91
|
-
eventType: string;
|
|
92
|
-
payload: unknown;
|
|
93
|
-
} : ResolvePossibleEvents<T>);
|
|
94
50
|
export declare function createClient<H extends Host<any> | undefined = undefined, Z extends AuthenticationStrategy<H> = AuthenticationStrategy<H>, T extends Descriptors = EmptyObject>(config: {
|
|
95
51
|
modules?: H extends Host<any> ? AssertHostMatches<T, H> : T;
|
|
96
52
|
auth?: Z;
|
package/cjs/build/wixClient.js
CHANGED
|
@@ -13,14 +13,14 @@ const event_handlers_modules_js_1 = require("./event-handlers-modules.js");
|
|
|
13
13
|
const service_plugin_modules_js_1 = require("./service-plugin-modules.js");
|
|
14
14
|
function createClient(config) {
|
|
15
15
|
const _headers = config.headers || { Authorization: '' };
|
|
16
|
-
const eventHandlers = new Map();
|
|
17
|
-
const servicePluginsImplementations = new Map();
|
|
18
16
|
const authStrategy = config.auth ||
|
|
19
17
|
{
|
|
20
18
|
getAuthHeaders: (_) => Promise.resolve({ headers: {} }),
|
|
21
19
|
};
|
|
22
20
|
const boundGetAuthHeaders = authStrategy.getAuthHeaders.bind(undefined, config.host);
|
|
23
21
|
authStrategy.getAuthHeaders = boundGetAuthHeaders;
|
|
22
|
+
const { client: servicePluginsClient, initModule: initServicePluginModule } = (0, service_plugin_modules_js_1.servicePluginsModules)(authStrategy);
|
|
23
|
+
const { client: eventHandlersClient, initModule: initEventHandlerModule } = (0, event_handlers_modules_js_1.eventHandlersModules)(authStrategy);
|
|
24
24
|
const boundFetch = async (url, options) => {
|
|
25
25
|
const authHeaders = await boundGetAuthHeaders();
|
|
26
26
|
const defaultContentTypeHeader = (0, helpers_js_1.getDefaultContentHeader)(options);
|
|
@@ -39,18 +39,10 @@ function createClient(config) {
|
|
|
39
39
|
// excessively deep and possibly infinite.`
|
|
40
40
|
const use = (modules, metadata) => {
|
|
41
41
|
if ((0, event_handlers_modules_js_1.isEventHandlerModule)(modules)) {
|
|
42
|
-
return (
|
|
43
|
-
const handlers = eventHandlers.get(eventDefinition.type) ?? [];
|
|
44
|
-
handlers.push({ eventDefinition, handler });
|
|
45
|
-
eventHandlers.set(eventDefinition.type, handlers);
|
|
46
|
-
});
|
|
42
|
+
return initEventHandlerModule(modules);
|
|
47
43
|
}
|
|
48
44
|
else if ((0, service_plugin_modules_js_1.isServicePluginModule)(modules)) {
|
|
49
|
-
return (
|
|
50
|
-
const implementations = servicePluginsImplementations.get(servicePluginDefinition.componentType.toLowerCase()) ?? [];
|
|
51
|
-
implementations.push({ servicePluginDefinition, implementation });
|
|
52
|
-
servicePluginsImplementations.set(servicePluginDefinition.componentType.toLowerCase(), implementations);
|
|
53
|
-
});
|
|
45
|
+
return initServicePluginModule(modules);
|
|
54
46
|
}
|
|
55
47
|
else if ((0, host_modules_js_1.isHostModule)(modules) && config.host) {
|
|
56
48
|
return (0, host_modules_js_1.buildHostModule)(modules, config.host);
|
|
@@ -164,138 +156,8 @@ function createClient(config) {
|
|
|
164
156
|
const { data, errors } = await res.json();
|
|
165
157
|
return { data: data ?? {}, errors };
|
|
166
158
|
},
|
|
167
|
-
webhooks:
|
|
168
|
-
|
|
169
|
-
async process(jwt, opts = {
|
|
170
|
-
expectedEvents: [],
|
|
171
|
-
}) {
|
|
172
|
-
const { eventType, identity, instanceId, payload } = await this.parseJWT(jwt);
|
|
173
|
-
const allExpectedEvents = [
|
|
174
|
-
...opts.expectedEvents,
|
|
175
|
-
...Array.from(eventHandlers.keys()).map((type) => ({ type })),
|
|
176
|
-
];
|
|
177
|
-
if (allExpectedEvents.length > 0 &&
|
|
178
|
-
!allExpectedEvents.some(({ type }) => type === eventType)) {
|
|
179
|
-
throw new Error(`Unexpected event type: ${eventType}. Expected one of: ${allExpectedEvents
|
|
180
|
-
.map((x) => x.type)
|
|
181
|
-
.join(', ')}`);
|
|
182
|
-
}
|
|
183
|
-
const handlers = eventHandlers.get(eventType) ?? [];
|
|
184
|
-
await Promise.all(handlers.map(({ eventDefinition, handler }) => (0, event_handlers_modules_js_1.runHandler)(eventDefinition, handler, payload, {
|
|
185
|
-
instanceId,
|
|
186
|
-
identity,
|
|
187
|
-
})));
|
|
188
|
-
return {
|
|
189
|
-
instanceId,
|
|
190
|
-
eventType,
|
|
191
|
-
payload,
|
|
192
|
-
identity,
|
|
193
|
-
};
|
|
194
|
-
},
|
|
195
|
-
async processRequest(request, opts) {
|
|
196
|
-
const body = await request.text();
|
|
197
|
-
return this.process(body, opts);
|
|
198
|
-
},
|
|
199
|
-
async parseJWT(jwt) {
|
|
200
|
-
if (!authStrategy.decodeJWT) {
|
|
201
|
-
throw new Error('decodeJWT is not supported by the authentication strategy');
|
|
202
|
-
}
|
|
203
|
-
const { decoded, valid } = await authStrategy.decodeJWT(jwt);
|
|
204
|
-
if (!valid) {
|
|
205
|
-
throw new Error('JWT is not valid');
|
|
206
|
-
}
|
|
207
|
-
if (typeof decoded.data !== 'string') {
|
|
208
|
-
throw new Error(`Unexpected type of JWT data: expected string, got ${typeof decoded.data}`);
|
|
209
|
-
}
|
|
210
|
-
const parsedDecoded = JSON.parse(decoded.data);
|
|
211
|
-
const eventType = parsedDecoded.eventType;
|
|
212
|
-
const instanceId = parsedDecoded.instanceId;
|
|
213
|
-
const identity = parsedDecoded.identity
|
|
214
|
-
? JSON.parse(parsedDecoded.identity)
|
|
215
|
-
: undefined;
|
|
216
|
-
const payload = JSON.parse(parsedDecoded.data);
|
|
217
|
-
return {
|
|
218
|
-
instanceId,
|
|
219
|
-
eventType,
|
|
220
|
-
payload,
|
|
221
|
-
identity,
|
|
222
|
-
};
|
|
223
|
-
},
|
|
224
|
-
async parseRequest(request) {
|
|
225
|
-
const jwt = await request.text();
|
|
226
|
-
return this.parseJWT(jwt);
|
|
227
|
-
},
|
|
228
|
-
async executeHandlers(event) {
|
|
229
|
-
const allExpectedEvents = Array.from(eventHandlers.keys()).map((type) => ({ type }));
|
|
230
|
-
if (allExpectedEvents.length > 0 &&
|
|
231
|
-
!allExpectedEvents.some(({ type }) => type === event.eventType)) {
|
|
232
|
-
throw new Error(`Unexpected event type: ${event.eventType}. Expected one of: ${allExpectedEvents
|
|
233
|
-
.map((x) => x.type)
|
|
234
|
-
.join(', ')}`);
|
|
235
|
-
}
|
|
236
|
-
const handlers = eventHandlers.get(event.eventType) ?? [];
|
|
237
|
-
await Promise.all(handlers.map(({ eventDefinition, handler }) => (0, event_handlers_modules_js_1.runHandler)(eventDefinition, handler, event.payload, {
|
|
238
|
-
instanceId: event.instanceId,
|
|
239
|
-
identity: event.identity,
|
|
240
|
-
})));
|
|
241
|
-
},
|
|
242
|
-
apps: {
|
|
243
|
-
AppInstalled: (0, sdk_types_1.EventDefinition)('AppInstalled')(),
|
|
244
|
-
AppRemoved: (0, sdk_types_1.EventDefinition)('AppRemoved')(),
|
|
245
|
-
},
|
|
246
|
-
},
|
|
247
|
-
servicePlugins: {
|
|
248
|
-
getRegisteredServicePlugins: () => servicePluginsImplementations,
|
|
249
|
-
async process(request) {
|
|
250
|
-
const servicePluginRequest = await this.parseJWT(request.body);
|
|
251
|
-
return this.executeHandler(servicePluginRequest, request.url);
|
|
252
|
-
},
|
|
253
|
-
async processRequest(request) {
|
|
254
|
-
const url = request.url;
|
|
255
|
-
const body = await request.text();
|
|
256
|
-
const implMethodResult = await this.process({ url, body });
|
|
257
|
-
return Response.json(implMethodResult);
|
|
258
|
-
},
|
|
259
|
-
async parseJWT(jwt) {
|
|
260
|
-
if (!authStrategy.decodeJWT) {
|
|
261
|
-
throw new Error('decodeJWT is not supported by the authentication strategy');
|
|
262
|
-
}
|
|
263
|
-
const { decoded, valid } = await authStrategy.decodeJWT(jwt, true);
|
|
264
|
-
if (!valid) {
|
|
265
|
-
throw new Error('JWT is not valid');
|
|
266
|
-
}
|
|
267
|
-
if (typeof decoded.data !== 'object' ||
|
|
268
|
-
decoded.data === null ||
|
|
269
|
-
!('metadata' in decoded.data) ||
|
|
270
|
-
typeof decoded.data.metadata !== 'object' ||
|
|
271
|
-
decoded.data.metadata === null ||
|
|
272
|
-
!('appExtensionType' in decoded.data.metadata) ||
|
|
273
|
-
typeof decoded.data.metadata.appExtensionType !== 'string') {
|
|
274
|
-
throw new Error('Unexpected JWT data: expected object with metadata.appExtensionType string');
|
|
275
|
-
}
|
|
276
|
-
return decoded.data;
|
|
277
|
-
},
|
|
278
|
-
async executeHandler(servicePluginRequest, url) {
|
|
279
|
-
const componentType = servicePluginRequest.metadata.appExtensionType.toLowerCase();
|
|
280
|
-
const implementations = servicePluginsImplementations.get(componentType) ?? [];
|
|
281
|
-
if (implementations.length === 0) {
|
|
282
|
-
throw new Error(`No service plugin implementations found for component type ${componentType}`);
|
|
283
|
-
}
|
|
284
|
-
else if (implementations.length > 1) {
|
|
285
|
-
throw new Error(`Multiple service plugin implementations found for component type ${componentType}. This is currently not supported`);
|
|
286
|
-
}
|
|
287
|
-
const { implementation: impl, servicePluginDefinition } = implementations[0];
|
|
288
|
-
const method = servicePluginDefinition.methods.find((m) => url.endsWith(m.primaryHttpMappingPath));
|
|
289
|
-
if (!method) {
|
|
290
|
-
throw new Error('Unexpect request: request url did not match any method: ' + url);
|
|
291
|
-
}
|
|
292
|
-
const implMethod = impl[method.name];
|
|
293
|
-
if (!implMethod) {
|
|
294
|
-
throw new Error(`Got request for service plugin method ${method.name} but no implementation was provided. Available methods: ${Object.keys(impl).join(', ')}`);
|
|
295
|
-
}
|
|
296
|
-
return method.transformations.toREST(await implMethod(method.transformations.fromREST(servicePluginRequest)));
|
|
297
|
-
},
|
|
298
|
-
},
|
|
159
|
+
webhooks: eventHandlersClient,
|
|
160
|
+
servicePlugins: servicePluginsClient,
|
|
299
161
|
};
|
|
300
162
|
}
|
|
301
163
|
exports.createClient = createClient;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@wix/sdk",
|
|
3
|
-
"version": "1.12.
|
|
3
|
+
"version": "1.12.9",
|
|
4
4
|
"license": "UNLICENSED",
|
|
5
5
|
"author": {
|
|
6
6
|
"name": "Ronny Ringel",
|
|
@@ -65,13 +65,14 @@
|
|
|
65
65
|
"dependencies": {
|
|
66
66
|
"@babel/runtime": "^7.23.2",
|
|
67
67
|
"@wix/identity": "^1.0.78",
|
|
68
|
-
"@wix/image-kit": "^1.
|
|
68
|
+
"@wix/image-kit": "^1.77.0",
|
|
69
69
|
"@wix/redirects": "^1.0.41",
|
|
70
70
|
"@wix/sdk-context": "^0.0.1",
|
|
71
|
-
"@wix/sdk-runtime": "0.3.
|
|
71
|
+
"@wix/sdk-runtime": "0.3.14",
|
|
72
72
|
"@wix/sdk-types": "^1.9.2",
|
|
73
73
|
"crypto-js": "^4.2.0",
|
|
74
74
|
"jose": "^5.2.1",
|
|
75
|
+
"nanoevents": "^9.0.0",
|
|
75
76
|
"pkce-challenge": "^3.1.0",
|
|
76
77
|
"querystring": "^0.2.1",
|
|
77
78
|
"type-fest": "^4.9.0"
|
|
@@ -88,7 +89,7 @@
|
|
|
88
89
|
"@wix/events": "^1.0.179",
|
|
89
90
|
"@wix/metro": "^1.0.73",
|
|
90
91
|
"@wix/metro-runtime": "^1.1677.0",
|
|
91
|
-
"@wix/sdk-runtime": "0.3.
|
|
92
|
+
"@wix/sdk-runtime": "0.3.14",
|
|
92
93
|
"eslint": "^8.56.0",
|
|
93
94
|
"eslint-config-sdk": "0.0.0",
|
|
94
95
|
"graphql": "^16.8.0",
|
|
@@ -122,5 +123,5 @@
|
|
|
122
123
|
"wallaby": {
|
|
123
124
|
"autoDetect": true
|
|
124
125
|
},
|
|
125
|
-
"falconPackageHash": "
|
|
126
|
+
"falconPackageHash": "fac4a20ec702fb1a9e081a3fe2eb9dc105d284baeb49281de73dbf0e"
|
|
126
127
|
}
|