@wix/sdk
Advanced tools
Comparing version
import { IOAuthStrategy, Tokens } from './types.js'; | ||
export declare function OAuthStrategy(config: { | ||
clientId: string; | ||
publicKey?: string; | ||
tokens?: Tokens; | ||
@@ -5,0 +6,0 @@ }): IOAuthStrategy; |
@@ -9,2 +9,3 @@ import { createClient } from '../../wixClient.js'; | ||
import { EMAIL_EXISTS, INVALID_CAPTCHA, INVALID_PASSWORD, MISSING_CAPTCHA, RESET_PASSWORD, } from './constants.js'; | ||
import { verify } from 'jsonwebtoken'; | ||
import { biHeaderGenerator } from '../../bi/biHeaderGenerator.js'; | ||
@@ -338,2 +339,12 @@ import { pkceChallenge } from './pkce-challenge.js'; | ||
captchaVisibleSiteKey: '6Ld0J8IcAAAAANyrnxzrRlX1xrrdXsOmsepUYosy', | ||
decodeJWT(token) { | ||
if (!config.publicKey) { | ||
throw new Error('Missing public key. Make sure to pass it to the OAuthStrategy'); | ||
} | ||
const decoded = verify(token, config.publicKey); | ||
return { | ||
decoded, | ||
valid: true, | ||
}; | ||
}, | ||
}; | ||
@@ -340,0 +351,0 @@ } |
@@ -21,2 +21,3 @@ import { AuthenticationStrategy } from '@wix/sdk-types'; | ||
* @param opts.refreshToken An optional refresh token previously retrieved from Wix OAuth API | ||
* @param opts.publicKey An optional public key for validating webhook requests | ||
* @returns An authentication strategy that can be used with WixClient | ||
@@ -53,4 +54,5 @@ * @example | ||
appId: string; | ||
appSecret: string; | ||
appSecret?: string; | ||
publicKey?: string; | ||
refreshToken?: string; | ||
}): WixAppOAuthStrategy; |
@@ -0,1 +1,2 @@ | ||
import { verify } from 'jsonwebtoken'; | ||
/** | ||
@@ -8,2 +9,3 @@ * Creates an authentication strategy for Wix Apps OAuth installation process. | ||
* @param opts.refreshToken An optional refresh token previously retrieved from Wix OAuth API | ||
* @param opts.publicKey An optional public key for validating webhook requests | ||
* @returns An authentication strategy that can be used with WixClient | ||
@@ -46,2 +48,5 @@ * @example | ||
async handleOAuthCallback(url, oauthOpts) { | ||
if (!opts.appSecret) { | ||
throw new Error('App secret is required for handling OAuth callback. Make sure to pass it to the WixAppOAuthStrategy'); | ||
} | ||
const params = new URLSearchParams(new URL(url).search); | ||
@@ -84,2 +89,5 @@ const state = params.get('state'); | ||
} | ||
if (!opts.appSecret) { | ||
throw new Error('App secret is required for refreshing access tokens. Make sure to pass it to the WixAppOAuthStrategy'); | ||
} | ||
const tokensRes = await fetch('https://www.wixapis.com/oauth/access', { | ||
@@ -108,3 +116,13 @@ method: 'POST', | ||
}, | ||
decodeJWT(token) { | ||
if (!opts.publicKey) { | ||
throw new Error('Missing public key. Make sure to pass it to the WixAppOAuthStrategy'); | ||
} | ||
const decoded = verify(token, opts.publicKey); | ||
return { | ||
decoded, | ||
valid: true, | ||
}; | ||
}, | ||
}; | ||
} |
@@ -1,2 +0,2 @@ | ||
import { AuthenticationStrategy, BoundAuthenticationStrategy, BuildRESTFunction, Host, HostModule, HostModuleAPI, RESTFunctionDescriptor } from '@wix/sdk-types'; | ||
import { AuthenticationStrategy, BoundAuthenticationStrategy, BuildRESTFunction, Host, HostModule, HostModuleAPI, RESTFunctionDescriptor, EventDefinition } from '@wix/sdk-types'; | ||
import { ConditionalExcept, EmptyObject } from 'type-fest'; | ||
@@ -63,3 +63,23 @@ import { AmbassadorFunctionDescriptor, BuildAmbassadorFunction } from './ambassador-modules.js'; | ||
}>; | ||
webhooks: { | ||
process<ExpectedEvents extends EventDefinition[] = []>(jwt: string, opts?: { | ||
expectedEvents: ExpectedEvents; | ||
}): ProcessedEvent<ExpectedEvents>; | ||
processRequest<ExpectedEvents extends EventDefinition[] = []>(request: Request, opts?: { | ||
expectedEvents: ExpectedEvents; | ||
}): Promise<ProcessedEvent<ExpectedEvents>>; | ||
}; | ||
} & BuildDescriptors<T, H>; | ||
type ResolvePossibleEvents<T extends EventDefinition[]> = { | ||
[K in keyof T]: T[K] extends EventDefinition ? { | ||
eventType: T[K]['type']; | ||
payload: T[K]['__payload']; | ||
} : never; | ||
} extends (infer U)[] ? U : never; | ||
export type ProcessedEvent<T extends EventDefinition[] = []> = { | ||
instanceId: string; | ||
} & (T['length'] extends 0 ? { | ||
eventType: string; | ||
payload: unknown; | ||
} : ResolvePossibleEvents<T>); | ||
export declare function createClient<H extends Host<any> | undefined = undefined, Z extends AuthenticationStrategy<H> = AuthenticationStrategy<H>, T extends Descriptors = EmptyObject>(config: { | ||
@@ -66,0 +86,0 @@ modules?: H extends Host<any> ? AssertHostMatches<T, H> : T; |
@@ -9,5 +9,6 @@ import { toHTTPModule, isAmbassadorModule, ambassadorModuleOptions, } from './ambassador-modules.js'; | ||
const _headers = config.headers || { Authorization: '' }; | ||
const authStrategy = config.auth || { | ||
getAuthHeaders: () => Promise.resolve({ headers: {} }), | ||
}; | ||
const authStrategy = config.auth || | ||
{ | ||
getAuthHeaders: (_) => Promise.resolve({ headers: {} }), | ||
}; | ||
const boundGetAuthHeaders = authStrategy.getAuthHeaders.bind(undefined, config.host); | ||
@@ -58,3 +59,5 @@ authStrategy.getAuthHeaders = boundGetAuthHeaders; | ||
}; | ||
const wrappedModules = config.modules ? use(config.modules) : {}; | ||
const wrappedModules = config.modules | ||
? use(config.modules) | ||
: {}; | ||
return { | ||
@@ -87,3 +90,35 @@ ...wrappedModules, | ||
}, | ||
webhooks: { | ||
process: (jwt, opts = { | ||
expectedEvents: [], | ||
}) => { | ||
if (!authStrategy.decodeJWT) { | ||
throw new Error('decodeJWT is not supported by the authentication strategy'); | ||
} | ||
const { decoded, valid } = authStrategy.decodeJWT(jwt); | ||
if (!valid) { | ||
throw new Error('JWT is not valid'); | ||
} | ||
const parsedDecoded = JSON.parse(decoded.data); | ||
const eventType = parsedDecoded.eventType; | ||
const instanceId = parsedDecoded.instanceId; | ||
const payload = JSON.parse(parsedDecoded.data); | ||
if (opts.expectedEvents.length > 0 && | ||
!opts.expectedEvents.some(({ type }) => type === eventType)) { | ||
throw new Error(`Unexpected event type: ${eventType}. Expected one of: ${opts.expectedEvents | ||
.map((x) => x.type) | ||
.join(', ')}`); | ||
} | ||
return { | ||
instanceId, | ||
eventType, | ||
payload, | ||
}; | ||
}, | ||
async processRequest(request, opts) { | ||
const body = await request.text(); | ||
return this.process(body, opts); | ||
}, | ||
}, | ||
}; | ||
} |
import { IOAuthStrategy, Tokens } from './types.js'; | ||
export declare function OAuthStrategy(config: { | ||
clientId: string; | ||
publicKey?: string; | ||
tokens?: Tokens; | ||
@@ -5,0 +6,0 @@ }): IOAuthStrategy; |
@@ -12,2 +12,3 @@ "use strict"; | ||
const constants_js_1 = require("./constants.js"); | ||
const jsonwebtoken_1 = require("jsonwebtoken"); | ||
const biHeaderGenerator_js_1 = require("../../bi/biHeaderGenerator.js"); | ||
@@ -341,2 +342,12 @@ const pkce_challenge_js_1 = require("./pkce-challenge.js"); | ||
captchaVisibleSiteKey: '6Ld0J8IcAAAAANyrnxzrRlX1xrrdXsOmsepUYosy', | ||
decodeJWT(token) { | ||
if (!config.publicKey) { | ||
throw new Error('Missing public key. Make sure to pass it to the OAuthStrategy'); | ||
} | ||
const decoded = (0, jsonwebtoken_1.verify)(token, config.publicKey); | ||
return { | ||
decoded, | ||
valid: true, | ||
}; | ||
}, | ||
}; | ||
@@ -343,0 +354,0 @@ } |
@@ -21,2 +21,3 @@ import { AuthenticationStrategy } from '@wix/sdk-types'; | ||
* @param opts.refreshToken An optional refresh token previously retrieved from Wix OAuth API | ||
* @param opts.publicKey An optional public key for validating webhook requests | ||
* @returns An authentication strategy that can be used with WixClient | ||
@@ -53,4 +54,5 @@ * @example | ||
appId: string; | ||
appSecret: string; | ||
appSecret?: string; | ||
publicKey?: string; | ||
refreshToken?: string; | ||
}): WixAppOAuthStrategy; |
"use strict"; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
exports.WixAppOAuthStrategy = void 0; | ||
const jsonwebtoken_1 = require("jsonwebtoken"); | ||
/** | ||
@@ -11,2 +12,3 @@ * Creates an authentication strategy for Wix Apps OAuth installation process. | ||
* @param opts.refreshToken An optional refresh token previously retrieved from Wix OAuth API | ||
* @param opts.publicKey An optional public key for validating webhook requests | ||
* @returns An authentication strategy that can be used with WixClient | ||
@@ -49,2 +51,5 @@ * @example | ||
async handleOAuthCallback(url, oauthOpts) { | ||
if (!opts.appSecret) { | ||
throw new Error('App secret is required for handling OAuth callback. Make sure to pass it to the WixAppOAuthStrategy'); | ||
} | ||
const params = new URLSearchParams(new URL(url).search); | ||
@@ -87,2 +92,5 @@ const state = params.get('state'); | ||
} | ||
if (!opts.appSecret) { | ||
throw new Error('App secret is required for refreshing access tokens. Make sure to pass it to the WixAppOAuthStrategy'); | ||
} | ||
const tokensRes = await fetch('https://www.wixapis.com/oauth/access', { | ||
@@ -111,4 +119,14 @@ method: 'POST', | ||
}, | ||
decodeJWT(token) { | ||
if (!opts.publicKey) { | ||
throw new Error('Missing public key. Make sure to pass it to the WixAppOAuthStrategy'); | ||
} | ||
const decoded = (0, jsonwebtoken_1.verify)(token, opts.publicKey); | ||
return { | ||
decoded, | ||
valid: true, | ||
}; | ||
}, | ||
}; | ||
} | ||
exports.WixAppOAuthStrategy = WixAppOAuthStrategy; |
@@ -1,2 +0,2 @@ | ||
import { AuthenticationStrategy, BoundAuthenticationStrategy, BuildRESTFunction, Host, HostModule, HostModuleAPI, RESTFunctionDescriptor } from '@wix/sdk-types'; | ||
import { AuthenticationStrategy, BoundAuthenticationStrategy, BuildRESTFunction, Host, HostModule, HostModuleAPI, RESTFunctionDescriptor, EventDefinition } from '@wix/sdk-types'; | ||
import { ConditionalExcept, EmptyObject } from 'type-fest'; | ||
@@ -63,3 +63,23 @@ import { AmbassadorFunctionDescriptor, BuildAmbassadorFunction } from './ambassador-modules.js'; | ||
}>; | ||
webhooks: { | ||
process<ExpectedEvents extends EventDefinition[] = []>(jwt: string, opts?: { | ||
expectedEvents: ExpectedEvents; | ||
}): ProcessedEvent<ExpectedEvents>; | ||
processRequest<ExpectedEvents extends EventDefinition[] = []>(request: Request, opts?: { | ||
expectedEvents: ExpectedEvents; | ||
}): Promise<ProcessedEvent<ExpectedEvents>>; | ||
}; | ||
} & BuildDescriptors<T, H>; | ||
type ResolvePossibleEvents<T extends EventDefinition[]> = { | ||
[K in keyof T]: T[K] extends EventDefinition ? { | ||
eventType: T[K]['type']; | ||
payload: T[K]['__payload']; | ||
} : never; | ||
} extends (infer U)[] ? U : never; | ||
export type ProcessedEvent<T extends EventDefinition[] = []> = { | ||
instanceId: string; | ||
} & (T['length'] extends 0 ? { | ||
eventType: string; | ||
payload: unknown; | ||
} : ResolvePossibleEvents<T>); | ||
export declare function createClient<H extends Host<any> | undefined = undefined, Z extends AuthenticationStrategy<H> = AuthenticationStrategy<H>, T extends Descriptors = EmptyObject>(config: { | ||
@@ -66,0 +86,0 @@ modules?: H extends Host<any> ? AssertHostMatches<T, H> : T; |
@@ -12,5 +12,6 @@ "use strict"; | ||
const _headers = config.headers || { Authorization: '' }; | ||
const authStrategy = config.auth || { | ||
getAuthHeaders: () => Promise.resolve({ headers: {} }), | ||
}; | ||
const authStrategy = config.auth || | ||
{ | ||
getAuthHeaders: (_) => Promise.resolve({ headers: {} }), | ||
}; | ||
const boundGetAuthHeaders = authStrategy.getAuthHeaders.bind(undefined, config.host); | ||
@@ -61,3 +62,5 @@ authStrategy.getAuthHeaders = boundGetAuthHeaders; | ||
}; | ||
const wrappedModules = config.modules ? use(config.modules) : {}; | ||
const wrappedModules = config.modules | ||
? use(config.modules) | ||
: {}; | ||
return { | ||
@@ -90,4 +93,36 @@ ...wrappedModules, | ||
}, | ||
webhooks: { | ||
process: (jwt, opts = { | ||
expectedEvents: [], | ||
}) => { | ||
if (!authStrategy.decodeJWT) { | ||
throw new Error('decodeJWT is not supported by the authentication strategy'); | ||
} | ||
const { decoded, valid } = authStrategy.decodeJWT(jwt); | ||
if (!valid) { | ||
throw new Error('JWT is not valid'); | ||
} | ||
const parsedDecoded = JSON.parse(decoded.data); | ||
const eventType = parsedDecoded.eventType; | ||
const instanceId = parsedDecoded.instanceId; | ||
const payload = JSON.parse(parsedDecoded.data); | ||
if (opts.expectedEvents.length > 0 && | ||
!opts.expectedEvents.some(({ type }) => type === eventType)) { | ||
throw new Error(`Unexpected event type: ${eventType}. Expected one of: ${opts.expectedEvents | ||
.map((x) => x.type) | ||
.join(', ')}`); | ||
} | ||
return { | ||
instanceId, | ||
eventType, | ||
payload, | ||
}; | ||
}, | ||
async processRequest(request, opts) { | ||
const body = await request.text(); | ||
return this.process(body, opts); | ||
}, | ||
}, | ||
}; | ||
} | ||
exports.createClient = createClient; |
{ | ||
"name": "@wix/sdk", | ||
"version": "1.6.4", | ||
"version": "1.7.0", | ||
"license": "UNLICENSED", | ||
@@ -61,7 +61,11 @@ "author": { | ||
"dependencies": { | ||
"@babel/runtime": "^7.23.2", | ||
"@wix/identity": "^1.0.71", | ||
"@wix/image-kit": "^1.46.0", | ||
"@wix/image-kit": "^1.49.0", | ||
"@wix/redirects": "^1.0.31", | ||
"@wix/sdk-types": "^1.5.3", | ||
"@wix/sdk-types": "^1.5.4", | ||
"crypto-js": "^4.2.0", | ||
"jsonwebtoken": "^9.0.2", | ||
"pkce-challenge": "^3.1.0", | ||
"querystring": "^0.2.1", | ||
"type-fest": "^4.9.0" | ||
@@ -75,7 +79,9 @@ }, | ||
"@types/is-ci": "^3.0.4", | ||
"@types/jsonwebtoken": "^9.0.5", | ||
"@types/node": "^20.10.6", | ||
"@wix/ecom": "^1.0.440", | ||
"@wix/events": "^1.0.134", | ||
"@vitest/ui": "^1.1.3", | ||
"@wix/ecom": "^1.0.468", | ||
"@wix/events": "^1.0.141", | ||
"@wix/metro": "^1.0.73", | ||
"@wix/metro-runtime": "^1.1587.0", | ||
"@wix/metro-runtime": "^1.1611.0", | ||
"eslint": "^8.56.0", | ||
@@ -86,5 +92,5 @@ "eslint-config-sdk": "0.0.0", | ||
"jsdom": "^22.1.0", | ||
"msw": "^2.0.11", | ||
"msw": "^2.0.12", | ||
"typescript": "^5.3.3", | ||
"vitest": "^0.34.6", | ||
"vitest": "^1.1.3", | ||
"vitest-teamcity-reporter": "^0.2.2" | ||
@@ -115,3 +121,3 @@ }, | ||
}, | ||
"falconPackageHash": "16fe89900be2a97b0197aa9ae070fa9735a543d8affe31f1c1473037" | ||
"falconPackageHash": "d7def5d521cd246af737cbbae2bf6712ccfa33ace5a4aaacee8af1b5" | ||
} |
134367
5.84%3326
5.52%11
57.14%18
12.5%+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
Updated
Updated