@soulcraft/sdk 1.6.2 → 1.7.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.
- package/dist/client/index.d.ts +4 -0
- package/dist/client/index.d.ts.map +1 -1
- package/dist/client/index.js +4 -0
- package/dist/client/index.js.map +1 -1
- package/dist/index.d.ts +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js.map +1 -1
- package/dist/modules/app-context/index.d.ts +214 -0
- package/dist/modules/app-context/index.d.ts.map +1 -0
- package/dist/modules/app-context/index.js +569 -0
- package/dist/modules/app-context/index.js.map +1 -0
- package/dist/modules/auth/products.d.ts +208 -0
- package/dist/modules/auth/products.d.ts.map +1 -0
- package/dist/modules/auth/products.js +165 -0
- package/dist/modules/auth/products.js.map +1 -0
- package/dist/server/index.d.ts +2 -0
- package/dist/server/index.d.ts.map +1 -1
- package/dist/server/index.js +2 -0
- package/dist/server/index.js.map +1 -1
- package/dist/transports/workshop.d.ts +173 -0
- package/dist/transports/workshop.d.ts.map +1 -0
- package/dist/transports/workshop.js +307 -0
- package/dist/transports/workshop.js.map +1 -0
- package/dist/types.d.ts +6 -2
- package/dist/types.d.ts.map +1 -1
- package/docs/ADR-004-product-registry.md +108 -0
- package/package.json +1 -1
|
@@ -0,0 +1,208 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @module modules/auth/products
|
|
3
|
+
* @description Centralized registry of all Soulcraft platform products and their
|
|
4
|
+
* auth configuration. This is the single source of truth for:
|
|
5
|
+
*
|
|
6
|
+
* - Which products exist on the platform
|
|
7
|
+
* - Their production domains and local dev ports
|
|
8
|
+
* - Their OIDC client IDs and redirect callback paths
|
|
9
|
+
* - Whether they require backchannel logout support
|
|
10
|
+
* - Which env var holds their OIDC client secret
|
|
11
|
+
*
|
|
12
|
+
* The auth server (`auth.soulcraft.com`) consumes this registry to derive all
|
|
13
|
+
* its registration arrays — trusted origins, CORS, OIDC trusted clients, and
|
|
14
|
+
* backchannel logout recipients — instead of maintaining five parallel hardcoded lists.
|
|
15
|
+
*
|
|
16
|
+
* ## Adding a new product
|
|
17
|
+
*
|
|
18
|
+
* 1. Add an entry to `SOULCRAFT_PRODUCTS` below (TypeScript enforces completeness).
|
|
19
|
+
* 2. Add `{PRODUCT}_OIDC_CLIENT_SECRET` (or equivalent) to the auth server's
|
|
20
|
+
* `.env.production`. Generate with: `openssl rand -hex 32`
|
|
21
|
+
* 3. Publish a new version of `@soulcraft/sdk`.
|
|
22
|
+
* 4. Deploy the auth server — it will pick up the new product automatically.
|
|
23
|
+
* 5. Set `SOULCRAFT_IDP_URL` in the product's own `.env.production`.
|
|
24
|
+
*
|
|
25
|
+
* @see ADR-002-product-registry.md for design rationale.
|
|
26
|
+
*/
|
|
27
|
+
/**
|
|
28
|
+
* Full auth configuration for a single Soulcraft platform product.
|
|
29
|
+
*
|
|
30
|
+
* Consumed by the auth server to derive trusted origins, CORS origins, OIDC
|
|
31
|
+
* client registrations, and backchannel logout recipients.
|
|
32
|
+
*/
|
|
33
|
+
export interface ProductRegistration {
|
|
34
|
+
/** Human-readable display name, e.g. `"Soulcraft Workshop"`. */
|
|
35
|
+
name: string;
|
|
36
|
+
/**
|
|
37
|
+
* Production domain without scheme or trailing slash.
|
|
38
|
+
* e.g. `"workshop.soulcraft.com"`, `"soulcraft.com"`
|
|
39
|
+
*/
|
|
40
|
+
domain: string;
|
|
41
|
+
/** Local development port. Used to derive `http://localhost:{devPort}` origins. */
|
|
42
|
+
devPort: number;
|
|
43
|
+
/**
|
|
44
|
+
* OIDC client ID registered on the auth server.
|
|
45
|
+
* Must be unique across all products. e.g. `"workshop"`.
|
|
46
|
+
*/
|
|
47
|
+
clientId: string;
|
|
48
|
+
/**
|
|
49
|
+
* Name of the environment variable that holds this product's OIDC client secret
|
|
50
|
+
* (or backchannel secret for cookie-proxy products). e.g. `"WORKSHOP_OIDC_CLIENT_SECRET"`.
|
|
51
|
+
*/
|
|
52
|
+
secretEnvVar: string;
|
|
53
|
+
/**
|
|
54
|
+
* How this product authenticates users:
|
|
55
|
+
* - `'oidc-redirect'` — full OIDC authorization code flow with redirect callbacks
|
|
56
|
+
* - `'cookie-proxy'` — validates the shared `.soulcraft.com` session cookie directly
|
|
57
|
+
* against `GET /api/auth/get-session`; no OIDC redirect involved
|
|
58
|
+
*/
|
|
59
|
+
authMode: 'oidc-redirect' | 'cookie-proxy';
|
|
60
|
+
/**
|
|
61
|
+
* Paths on this product's origin that the auth server should register as OIDC
|
|
62
|
+
* redirect URIs. Empty array for cookie-proxy products. Both production and dev
|
|
63
|
+
* variants are derived automatically via `deriveRedirectUrls`.
|
|
64
|
+
*/
|
|
65
|
+
callbackPaths: string[];
|
|
66
|
+
/**
|
|
67
|
+
* Additional paths to include as OIDC redirect URIs beyond the callback paths.
|
|
68
|
+
* Typically the homepage (`"/"`) which is used as `post_logout_redirect_uri`.
|
|
69
|
+
* Defaults to `["/"]` when omitted.
|
|
70
|
+
*/
|
|
71
|
+
extraRedirectPaths?: string[];
|
|
72
|
+
/**
|
|
73
|
+
* When `true`, the auth server includes this product in its OIDC backchannel
|
|
74
|
+
* logout registry. The product's `{domain}/api/auth/backchannel-logout` endpoint
|
|
75
|
+
* will be notified on every sign-out so it can terminate local sessions immediately.
|
|
76
|
+
*
|
|
77
|
+
* Set to `false` only for products that do not implement a backchannel endpoint
|
|
78
|
+
* (e.g. read-only dashboards, analytics tools).
|
|
79
|
+
*/
|
|
80
|
+
backchannelRequired: boolean;
|
|
81
|
+
}
|
|
82
|
+
/**
|
|
83
|
+
* Central registry of all Soulcraft platform products.
|
|
84
|
+
*
|
|
85
|
+
* `as const satisfies Record<string, ProductRegistration>` provides two guarantees:
|
|
86
|
+
* - TypeScript enforces that every entry has all required `ProductRegistration` fields
|
|
87
|
+
* - Literal types are preserved so `keyof typeof SOULCRAFT_PRODUCTS` yields
|
|
88
|
+
* `'workshop' | 'venue' | 'portal' | 'academy' | 'pulse'` (not just `string`)
|
|
89
|
+
*
|
|
90
|
+
* Adding a product here automatically:
|
|
91
|
+
* - Extends the `SoulcraftProduct` union type
|
|
92
|
+
* - Includes the product in all auth server derivations (origins, CORS, OIDC clients)
|
|
93
|
+
*/
|
|
94
|
+
export declare const SOULCRAFT_PRODUCTS: {
|
|
95
|
+
readonly workshop: {
|
|
96
|
+
readonly name: "Soulcraft Workshop";
|
|
97
|
+
readonly domain: "workshop.soulcraft.com";
|
|
98
|
+
readonly devPort: 5001;
|
|
99
|
+
readonly clientId: "workshop";
|
|
100
|
+
readonly secretEnvVar: "WORKSHOP_OIDC_CLIENT_SECRET";
|
|
101
|
+
readonly authMode: "oidc-redirect";
|
|
102
|
+
readonly callbackPaths: ["/api/auth/oauth2/callback/soulcraft-idp", "/api/auth/callback/soulcraft-idp"];
|
|
103
|
+
readonly extraRedirectPaths: ["/"];
|
|
104
|
+
readonly backchannelRequired: true;
|
|
105
|
+
};
|
|
106
|
+
readonly venue: {
|
|
107
|
+
readonly name: "Soulcraft Venue";
|
|
108
|
+
readonly domain: "venue.soulcraft.com";
|
|
109
|
+
readonly devPort: 5174;
|
|
110
|
+
readonly clientId: "venue";
|
|
111
|
+
readonly secretEnvVar: "VENUE_OIDC_CLIENT_SECRET";
|
|
112
|
+
readonly authMode: "oidc-redirect";
|
|
113
|
+
readonly callbackPaths: ["/api/auth/callback/soulcraft-idp"];
|
|
114
|
+
readonly extraRedirectPaths: ["/"];
|
|
115
|
+
readonly backchannelRequired: true;
|
|
116
|
+
};
|
|
117
|
+
readonly portal: {
|
|
118
|
+
readonly name: "Soulcraft Portal";
|
|
119
|
+
readonly domain: "soulcraft.com";
|
|
120
|
+
readonly devPort: 8080;
|
|
121
|
+
readonly clientId: "portal";
|
|
122
|
+
readonly secretEnvVar: "PORTAL_OIDC_CLIENT_SECRET";
|
|
123
|
+
readonly authMode: "oidc-redirect";
|
|
124
|
+
readonly callbackPaths: ["/api/auth/callback/soulcraft-idp", "/auth/callback"];
|
|
125
|
+
readonly extraRedirectPaths: ["/"];
|
|
126
|
+
readonly backchannelRequired: true;
|
|
127
|
+
};
|
|
128
|
+
readonly academy: {
|
|
129
|
+
readonly name: "Soulcraft Academy";
|
|
130
|
+
readonly domain: "academy.soulcraft.com";
|
|
131
|
+
readonly devPort: 5002;
|
|
132
|
+
readonly clientId: "academy";
|
|
133
|
+
readonly secretEnvVar: "ACADEMY_OIDC_CLIENT_SECRET";
|
|
134
|
+
readonly authMode: "oidc-redirect";
|
|
135
|
+
readonly callbackPaths: ["/api/auth/callback/soulcraft-idp"];
|
|
136
|
+
readonly extraRedirectPaths: ["/"];
|
|
137
|
+
readonly backchannelRequired: true;
|
|
138
|
+
};
|
|
139
|
+
readonly pulse: {
|
|
140
|
+
readonly name: "Soulcraft Pulse";
|
|
141
|
+
readonly domain: "pulse.soulcraft.com";
|
|
142
|
+
readonly devPort: 5004;
|
|
143
|
+
readonly clientId: "pulse";
|
|
144
|
+
readonly secretEnvVar: "PULSE_BACKCHANNEL_SECRET";
|
|
145
|
+
readonly authMode: "cookie-proxy";
|
|
146
|
+
readonly callbackPaths: [];
|
|
147
|
+
readonly extraRedirectPaths: ["/"];
|
|
148
|
+
readonly backchannelRequired: false;
|
|
149
|
+
};
|
|
150
|
+
};
|
|
151
|
+
/**
|
|
152
|
+
* Union of all registered Soulcraft product keys.
|
|
153
|
+
*
|
|
154
|
+
* Automatically derived from `SOULCRAFT_PRODUCTS` — adding a product to the
|
|
155
|
+
* registry extends this type without any manual update.
|
|
156
|
+
*
|
|
157
|
+
* @example
|
|
158
|
+
* function validateProduct(p: string): p is SoulcraftProduct {
|
|
159
|
+
* return p in SOULCRAFT_PRODUCTS
|
|
160
|
+
* }
|
|
161
|
+
*/
|
|
162
|
+
export type SoulcraftProduct = keyof typeof SOULCRAFT_PRODUCTS;
|
|
163
|
+
/**
|
|
164
|
+
* Derive the full list of trusted origins for all registered products.
|
|
165
|
+
*
|
|
166
|
+
* Returns both the production HTTPS origin and the `http://localhost:{devPort}`
|
|
167
|
+
* development origin for every product in `SOULCRAFT_PRODUCTS`.
|
|
168
|
+
*
|
|
169
|
+
* Used by the auth server for:
|
|
170
|
+
* - `betterAuth({ trustedOrigins: deriveOrigins() })` — callback URL validation
|
|
171
|
+
* - `cors({ origin: deriveOrigins() })` — CORS preflight on the Hono layer
|
|
172
|
+
*
|
|
173
|
+
* @returns Deduplicated list of origin strings (scheme + host, no trailing slash).
|
|
174
|
+
*
|
|
175
|
+
* @example
|
|
176
|
+
* deriveOrigins()
|
|
177
|
+
* // → [
|
|
178
|
+
* // 'https://workshop.soulcraft.com', 'http://localhost:5001',
|
|
179
|
+
* // 'https://venue.soulcraft.com', 'http://localhost:5174',
|
|
180
|
+
* // 'https://soulcraft.com', 'http://localhost:8080',
|
|
181
|
+
* // 'https://academy.soulcraft.com', 'http://localhost:5002',
|
|
182
|
+
* // 'https://pulse.soulcraft.com', 'http://localhost:5004',
|
|
183
|
+
* // ]
|
|
184
|
+
*/
|
|
185
|
+
export declare function deriveOrigins(): string[];
|
|
186
|
+
/**
|
|
187
|
+
* Derive all OIDC redirect URIs for a single product registration.
|
|
188
|
+
*
|
|
189
|
+
* Combines callback paths and extra redirect paths, generating both production
|
|
190
|
+
* and local development variants for each. Results are ordered: production paths
|
|
191
|
+
* first (all), then dev paths (all), matching the ordering in the auth server.
|
|
192
|
+
*
|
|
193
|
+
* @param p - A `ProductRegistration` from `SOULCRAFT_PRODUCTS`.
|
|
194
|
+
* @returns List of fully-qualified redirect URI strings.
|
|
195
|
+
*
|
|
196
|
+
* @example
|
|
197
|
+
* deriveRedirectUrls(SOULCRAFT_PRODUCTS.workshop)
|
|
198
|
+
* // → [
|
|
199
|
+
* // 'https://workshop.soulcraft.com/api/auth/oauth2/callback/soulcraft-idp',
|
|
200
|
+
* // 'https://workshop.soulcraft.com/api/auth/callback/soulcraft-idp',
|
|
201
|
+
* // 'https://workshop.soulcraft.com/',
|
|
202
|
+
* // 'http://localhost:5001/api/auth/oauth2/callback/soulcraft-idp',
|
|
203
|
+
* // 'http://localhost:5001/api/auth/callback/soulcraft-idp',
|
|
204
|
+
* // 'http://localhost:5001/',
|
|
205
|
+
* // ]
|
|
206
|
+
*/
|
|
207
|
+
export declare function deriveRedirectUrls(p: ProductRegistration): string[];
|
|
208
|
+
//# sourceMappingURL=products.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"products.d.ts","sourceRoot":"","sources":["../../../src/modules/auth/products.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AAMH;;;;;GAKG;AACH,MAAM,WAAW,mBAAmB;IAClC,gEAAgE;IAChE,IAAI,EAAE,MAAM,CAAA;IACZ;;;OAGG;IACH,MAAM,EAAE,MAAM,CAAA;IACd,mFAAmF;IACnF,OAAO,EAAE,MAAM,CAAA;IACf;;;OAGG;IACH,QAAQ,EAAE,MAAM,CAAA;IAChB;;;OAGG;IACH,YAAY,EAAE,MAAM,CAAA;IACpB;;;;;OAKG;IACH,QAAQ,EAAE,eAAe,GAAG,cAAc,CAAA;IAC1C;;;;OAIG;IACH,aAAa,EAAE,MAAM,EAAE,CAAA;IACvB;;;;OAIG;IACH,kBAAkB,CAAC,EAAE,MAAM,EAAE,CAAA;IAC7B;;;;;;;OAOG;IACH,mBAAmB,EAAE,OAAO,CAAA;CAC7B;AAMD;;;;;;;;;;;GAWG;AACH,eAAO,MAAM,kBAAkB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CA+DyB,CAAA;AAExD;;;;;;;;;;GAUG;AACH,MAAM,MAAM,gBAAgB,GAAG,MAAM,OAAO,kBAAkB,CAAA;AAM9D;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH,wBAAgB,aAAa,IAAI,MAAM,EAAE,CAKxC;AAED;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,wBAAgB,kBAAkB,CAAC,CAAC,EAAE,mBAAmB,GAAG,MAAM,EAAE,CAQnE"}
|
|
@@ -0,0 +1,165 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @module modules/auth/products
|
|
3
|
+
* @description Centralized registry of all Soulcraft platform products and their
|
|
4
|
+
* auth configuration. This is the single source of truth for:
|
|
5
|
+
*
|
|
6
|
+
* - Which products exist on the platform
|
|
7
|
+
* - Their production domains and local dev ports
|
|
8
|
+
* - Their OIDC client IDs and redirect callback paths
|
|
9
|
+
* - Whether they require backchannel logout support
|
|
10
|
+
* - Which env var holds their OIDC client secret
|
|
11
|
+
*
|
|
12
|
+
* The auth server (`auth.soulcraft.com`) consumes this registry to derive all
|
|
13
|
+
* its registration arrays — trusted origins, CORS, OIDC trusted clients, and
|
|
14
|
+
* backchannel logout recipients — instead of maintaining five parallel hardcoded lists.
|
|
15
|
+
*
|
|
16
|
+
* ## Adding a new product
|
|
17
|
+
*
|
|
18
|
+
* 1. Add an entry to `SOULCRAFT_PRODUCTS` below (TypeScript enforces completeness).
|
|
19
|
+
* 2. Add `{PRODUCT}_OIDC_CLIENT_SECRET` (or equivalent) to the auth server's
|
|
20
|
+
* `.env.production`. Generate with: `openssl rand -hex 32`
|
|
21
|
+
* 3. Publish a new version of `@soulcraft/sdk`.
|
|
22
|
+
* 4. Deploy the auth server — it will pick up the new product automatically.
|
|
23
|
+
* 5. Set `SOULCRAFT_IDP_URL` in the product's own `.env.production`.
|
|
24
|
+
*
|
|
25
|
+
* @see ADR-002-product-registry.md for design rationale.
|
|
26
|
+
*/
|
|
27
|
+
// ─────────────────────────────────────────────────────────────────────────────
|
|
28
|
+
// Registry
|
|
29
|
+
// ─────────────────────────────────────────────────────────────────────────────
|
|
30
|
+
/**
|
|
31
|
+
* Central registry of all Soulcraft platform products.
|
|
32
|
+
*
|
|
33
|
+
* `as const satisfies Record<string, ProductRegistration>` provides two guarantees:
|
|
34
|
+
* - TypeScript enforces that every entry has all required `ProductRegistration` fields
|
|
35
|
+
* - Literal types are preserved so `keyof typeof SOULCRAFT_PRODUCTS` yields
|
|
36
|
+
* `'workshop' | 'venue' | 'portal' | 'academy' | 'pulse'` (not just `string`)
|
|
37
|
+
*
|
|
38
|
+
* Adding a product here automatically:
|
|
39
|
+
* - Extends the `SoulcraftProduct` union type
|
|
40
|
+
* - Includes the product in all auth server derivations (origins, CORS, OIDC clients)
|
|
41
|
+
*/
|
|
42
|
+
export const SOULCRAFT_PRODUCTS = {
|
|
43
|
+
workshop: {
|
|
44
|
+
name: 'Soulcraft Workshop',
|
|
45
|
+
domain: 'workshop.soulcraft.com',
|
|
46
|
+
devPort: 5001,
|
|
47
|
+
clientId: 'workshop',
|
|
48
|
+
secretEnvVar: 'WORKSHOP_OIDC_CLIENT_SECRET',
|
|
49
|
+
authMode: 'oidc-redirect',
|
|
50
|
+
callbackPaths: [
|
|
51
|
+
'/api/auth/oauth2/callback/soulcraft-idp',
|
|
52
|
+
// Legacy path kept for in-flight sessions during transitions
|
|
53
|
+
'/api/auth/callback/soulcraft-idp',
|
|
54
|
+
],
|
|
55
|
+
extraRedirectPaths: ['/'],
|
|
56
|
+
backchannelRequired: true,
|
|
57
|
+
},
|
|
58
|
+
venue: {
|
|
59
|
+
name: 'Soulcraft Venue',
|
|
60
|
+
domain: 'venue.soulcraft.com',
|
|
61
|
+
devPort: 5174,
|
|
62
|
+
clientId: 'venue',
|
|
63
|
+
secretEnvVar: 'VENUE_OIDC_CLIENT_SECRET',
|
|
64
|
+
authMode: 'oidc-redirect',
|
|
65
|
+
callbackPaths: ['/api/auth/callback/soulcraft-idp'],
|
|
66
|
+
extraRedirectPaths: ['/'],
|
|
67
|
+
backchannelRequired: true,
|
|
68
|
+
},
|
|
69
|
+
portal: {
|
|
70
|
+
name: 'Soulcraft Portal',
|
|
71
|
+
domain: 'soulcraft.com',
|
|
72
|
+
devPort: 8080,
|
|
73
|
+
clientId: 'portal',
|
|
74
|
+
secretEnvVar: 'PORTAL_OIDC_CLIENT_SECRET',
|
|
75
|
+
authMode: 'oidc-redirect',
|
|
76
|
+
callbackPaths: ['/api/auth/callback/soulcraft-idp', '/auth/callback'],
|
|
77
|
+
extraRedirectPaths: ['/'],
|
|
78
|
+
backchannelRequired: true,
|
|
79
|
+
},
|
|
80
|
+
academy: {
|
|
81
|
+
name: 'Soulcraft Academy',
|
|
82
|
+
domain: 'academy.soulcraft.com',
|
|
83
|
+
devPort: 5002,
|
|
84
|
+
clientId: 'academy',
|
|
85
|
+
secretEnvVar: 'ACADEMY_OIDC_CLIENT_SECRET',
|
|
86
|
+
authMode: 'oidc-redirect',
|
|
87
|
+
callbackPaths: ['/api/auth/callback/soulcraft-idp'],
|
|
88
|
+
extraRedirectPaths: ['/'],
|
|
89
|
+
backchannelRequired: true,
|
|
90
|
+
},
|
|
91
|
+
pulse: {
|
|
92
|
+
name: 'Soulcraft Pulse',
|
|
93
|
+
domain: 'pulse.soulcraft.com',
|
|
94
|
+
devPort: 5004,
|
|
95
|
+
clientId: 'pulse',
|
|
96
|
+
// Pulse uses cookie-proxy; PULSE_BACKCHANNEL_SECRET doubles as the OIDC client
|
|
97
|
+
// secret for the minimal OIDC client entry that registers the homepage as a valid
|
|
98
|
+
// post_logout_redirect_uri. Backchannel is best-effort; no startup failure if absent.
|
|
99
|
+
secretEnvVar: 'PULSE_BACKCHANNEL_SECRET',
|
|
100
|
+
authMode: 'cookie-proxy',
|
|
101
|
+
callbackPaths: [],
|
|
102
|
+
extraRedirectPaths: ['/'],
|
|
103
|
+
backchannelRequired: false,
|
|
104
|
+
},
|
|
105
|
+
};
|
|
106
|
+
// ─────────────────────────────────────────────────────────────────────────────
|
|
107
|
+
// Derivation helpers
|
|
108
|
+
// ─────────────────────────────────────────────────────────────────────────────
|
|
109
|
+
/**
|
|
110
|
+
* Derive the full list of trusted origins for all registered products.
|
|
111
|
+
*
|
|
112
|
+
* Returns both the production HTTPS origin and the `http://localhost:{devPort}`
|
|
113
|
+
* development origin for every product in `SOULCRAFT_PRODUCTS`.
|
|
114
|
+
*
|
|
115
|
+
* Used by the auth server for:
|
|
116
|
+
* - `betterAuth({ trustedOrigins: deriveOrigins() })` — callback URL validation
|
|
117
|
+
* - `cors({ origin: deriveOrigins() })` — CORS preflight on the Hono layer
|
|
118
|
+
*
|
|
119
|
+
* @returns Deduplicated list of origin strings (scheme + host, no trailing slash).
|
|
120
|
+
*
|
|
121
|
+
* @example
|
|
122
|
+
* deriveOrigins()
|
|
123
|
+
* // → [
|
|
124
|
+
* // 'https://workshop.soulcraft.com', 'http://localhost:5001',
|
|
125
|
+
* // 'https://venue.soulcraft.com', 'http://localhost:5174',
|
|
126
|
+
* // 'https://soulcraft.com', 'http://localhost:8080',
|
|
127
|
+
* // 'https://academy.soulcraft.com', 'http://localhost:5002',
|
|
128
|
+
* // 'https://pulse.soulcraft.com', 'http://localhost:5004',
|
|
129
|
+
* // ]
|
|
130
|
+
*/
|
|
131
|
+
export function deriveOrigins() {
|
|
132
|
+
return Object.values(SOULCRAFT_PRODUCTS).flatMap((p) => [
|
|
133
|
+
`https://${p.domain}`,
|
|
134
|
+
`http://localhost:${p.devPort}`,
|
|
135
|
+
]);
|
|
136
|
+
}
|
|
137
|
+
/**
|
|
138
|
+
* Derive all OIDC redirect URIs for a single product registration.
|
|
139
|
+
*
|
|
140
|
+
* Combines callback paths and extra redirect paths, generating both production
|
|
141
|
+
* and local development variants for each. Results are ordered: production paths
|
|
142
|
+
* first (all), then dev paths (all), matching the ordering in the auth server.
|
|
143
|
+
*
|
|
144
|
+
* @param p - A `ProductRegistration` from `SOULCRAFT_PRODUCTS`.
|
|
145
|
+
* @returns List of fully-qualified redirect URI strings.
|
|
146
|
+
*
|
|
147
|
+
* @example
|
|
148
|
+
* deriveRedirectUrls(SOULCRAFT_PRODUCTS.workshop)
|
|
149
|
+
* // → [
|
|
150
|
+
* // 'https://workshop.soulcraft.com/api/auth/oauth2/callback/soulcraft-idp',
|
|
151
|
+
* // 'https://workshop.soulcraft.com/api/auth/callback/soulcraft-idp',
|
|
152
|
+
* // 'https://workshop.soulcraft.com/',
|
|
153
|
+
* // 'http://localhost:5001/api/auth/oauth2/callback/soulcraft-idp',
|
|
154
|
+
* // 'http://localhost:5001/api/auth/callback/soulcraft-idp',
|
|
155
|
+
* // 'http://localhost:5001/',
|
|
156
|
+
* // ]
|
|
157
|
+
*/
|
|
158
|
+
export function deriveRedirectUrls(p) {
|
|
159
|
+
const extraPaths = p.extraRedirectPaths ?? ['/'];
|
|
160
|
+
const allPaths = [...p.callbackPaths, ...extraPaths];
|
|
161
|
+
const prod = allPaths.map((path) => `https://${p.domain}${path}`);
|
|
162
|
+
const dev = allPaths.map((path) => `http://localhost:${p.devPort}${path}`);
|
|
163
|
+
return [...prod, ...dev];
|
|
164
|
+
}
|
|
165
|
+
//# sourceMappingURL=products.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"products.js","sourceRoot":"","sources":["../../../src/modules/auth/products.ts"],"names":[],"mappings":"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"}
|
package/dist/server/index.d.ts
CHANGED
|
@@ -47,6 +47,8 @@ export { createBackchannelLogoutHandler } from '../modules/auth/backchannel.js';
|
|
|
47
47
|
export type { BackchannelLogoutConfig, BackchannelAuthLike, } from '../modules/auth/backchannel.js';
|
|
48
48
|
export { verifyServiceToken, extractBearerToken, } from '../modules/auth/service-token.js';
|
|
49
49
|
export { SOULCRAFT_USER_FIELDS, SOULCRAFT_SESSION_CONFIG, getAuthMode, getOIDCClientConfig, } from '../modules/auth/config.js';
|
|
50
|
+
export { SOULCRAFT_PRODUCTS, deriveOrigins, deriveRedirectUrls, } from '../modules/auth/products.js';
|
|
51
|
+
export type { ProductRegistration, SoulcraftProduct, } from '../modules/auth/products.js';
|
|
50
52
|
export { createSDK } from './create-sdk.js';
|
|
51
53
|
export type { CreateSDKOptions } from './create-sdk.js';
|
|
52
54
|
export { createServerSDK } from './from-license.js';
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/server/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAgCG;AAGH,OAAO,EACL,kBAAkB,EAClB,gBAAgB,GACjB,MAAM,oBAAoB,CAAA;AAC3B,YAAY,EACV,kBAAkB,EAClB,iBAAiB,GAClB,MAAM,oBAAoB,CAAA;AAG3B,OAAO,EACL,mBAAmB,EACnB,qBAAqB,GACtB,MAAM,eAAe,CAAA;AACtB,YAAY,EACV,mBAAmB,EACnB,qBAAqB,EACrB,eAAe,EACf,SAAS,GACV,MAAM,eAAe,CAAA;AAGtB,OAAO,EAAE,WAAW,EAAE,MAAM,mCAAmC,CAAA;AAG/D,OAAO,EAAE,8BAA8B,EAAE,MAAM,0BAA0B,CAAA;AACzE,YAAY,EACV,8BAA8B,EAC9B,wBAAwB,GACzB,MAAM,0BAA0B,CAAA;AAGjC,OAAO,EACL,gBAAgB,EAChB,uBAAuB,EACvB,UAAU,GACX,MAAM,oBAAoB,CAAA;AAC3B,YAAY,EACV,qBAAqB,EACrB,UAAU,EACV,qBAAqB,EACrB,eAAe,GAChB,MAAM,oBAAoB,CAAA;AAC3B,YAAY,EACV,QAAQ,EACR,cAAc,EACd,WAAW,EACX,YAAY,EACZ,iBAAiB,EACjB,eAAe,EACf,mBAAmB,EACnB,qBAAqB,EACrB,mBAAmB,EACnB,eAAe,EACf,aAAa,GACd,MAAM,0BAA0B,CAAA;AAGjC,OAAO,EACL,oBAAoB,EACpB,2BAA2B,EAC3B,wBAAwB,EACxB,qBAAqB,EACrB,uBAAuB,EACvB,yBAAyB,EACzB,yBAAyB,EACzB,aAAa,GACd,MAAM,+BAA+B,CAAA;AACtC,YAAY,EACV,qBAAqB,EACrB,cAAc,EACd,WAAW,EACX,cAAc,EACd,eAAe,EACf,4BAA4B,EAC5B,yBAAyB,EACzB,sBAAsB,EACtB,0BAA0B,GAC3B,MAAM,+BAA+B,CAAA;AACtC,OAAO,EAAE,8BAA8B,EAAE,MAAM,gCAAgC,CAAA;AAC/E,YAAY,EACV,uBAAuB,EACvB,mBAAmB,GACpB,MAAM,gCAAgC,CAAA;AAGvC,OAAO,EACL,kBAAkB,EAClB,kBAAkB,GACnB,MAAM,kCAAkC,CAAA;AAGzC,OAAO,EACL,qBAAqB,EACrB,wBAAwB,EACxB,WAAW,EACX,mBAAmB,GACpB,MAAM,2BAA2B,CAAA;AAGlC,OAAO,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAA;AAC3C,YAAY,EAAE,gBAAgB,EAAE,MAAM,iBAAiB,CAAA;AAGvD,OAAO,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAA;AACnD,YAAY,EACV,SAAS,EACT,kBAAkB,EAClB,mBAAmB,EACnB,qBAAqB,GACtB,MAAM,mBAAmB,CAAA;AAG1B,OAAO,EAAE,mBAAmB,EAAE,MAAM,6BAA6B,CAAA;AACjE,YAAY,EAAE,0BAA0B,EAAE,MAAM,6BAA6B,CAAA;AAC7E,OAAO,EAAE,mBAAmB,EAAE,MAAM,6BAA6B,CAAA;AACjE,YAAY,EAAE,0BAA0B,EAAE,MAAM,6BAA6B,CAAA;AAC7E,OAAO,EAAE,gBAAgB,EAAE,MAAM,0BAA0B,CAAA;AAC3D,OAAO,EAAE,yBAAyB,EAAE,MAAM,mCAAmC,CAAA;AAG7E,YAAY,EAAE,gBAAgB,EAAE,MAAM,aAAa,CAAA;AACnD,OAAO,EAAE,qBAAqB,EAAE,qBAAqB,EAAE,MAAM,2BAA2B,CAAA;AACxF,YAAY,EAAE,4BAA4B,EAAE,qBAAqB,EAAE,MAAM,2BAA2B,CAAA;AACpG,OAAO,EAAE,cAAc,EAAE,MAAM,wBAAwB,CAAA"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/server/index.ts"],"names":[],"mappings":"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"}
|
package/dist/server/index.js
CHANGED
|
@@ -48,6 +48,8 @@ export { createBackchannelLogoutHandler } from '../modules/auth/backchannel.js';
|
|
|
48
48
|
export { verifyServiceToken, extractBearerToken, } from '../modules/auth/service-token.js';
|
|
49
49
|
// ── Auth config helpers (also on shared entry, duplicated here for convenience) ─
|
|
50
50
|
export { SOULCRAFT_USER_FIELDS, SOULCRAFT_SESSION_CONFIG, getAuthMode, getOIDCClientConfig, } from '../modules/auth/config.js';
|
|
51
|
+
// ── Product registry — single source of truth for all Soulcraft products ─────
|
|
52
|
+
export { SOULCRAFT_PRODUCTS, deriveOrigins, deriveRedirectUrls, } from '../modules/auth/products.js';
|
|
51
53
|
// ── createSDK factory ─────────────────────────────────────────────────────────
|
|
52
54
|
export { createSDK } from './create-sdk.js';
|
|
53
55
|
// ── createServerSDK.fromLicense() — license-driven server SDK ─────────────────
|
package/dist/server/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/server/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAgCG;AAEH,iFAAiF;AACjF,OAAO,EACL,kBAAkB,EAClB,gBAAgB,GACjB,MAAM,oBAAoB,CAAA;AAM3B,iFAAiF;AACjF,OAAO,EACL,mBAAmB,EACnB,qBAAqB,GACtB,MAAM,eAAe,CAAA;AAQtB,iFAAiF;AACjF,OAAO,EAAE,WAAW,EAAE,MAAM,mCAAmC,CAAA;AAE/D,iFAAiF;AACjF,OAAO,EAAE,8BAA8B,EAAE,MAAM,0BAA0B,CAAA;AAMzE,gFAAgF;AAChF,OAAO,EACL,gBAAgB,EAChB,uBAAuB,EACvB,UAAU,GACX,MAAM,oBAAoB,CAAA;AAqB3B,iFAAiF;AACjF,OAAO,EACL,oBAAoB,EACpB,2BAA2B,EAC3B,wBAAwB,EACxB,qBAAqB,EACrB,uBAAuB,EACvB,yBAAyB,EACzB,yBAAyB,EACzB,aAAa,GACd,MAAM,+BAA+B,CAAA;AAYtC,OAAO,EAAE,8BAA8B,EAAE,MAAM,gCAAgC,CAAA;AAM/E,iFAAiF;AACjF,OAAO,EACL,kBAAkB,EAClB,kBAAkB,GACnB,MAAM,kCAAkC,CAAA;AAEzC,mFAAmF;AACnF,OAAO,EACL,qBAAqB,EACrB,wBAAwB,EACxB,WAAW,EACX,mBAAmB,GACpB,MAAM,2BAA2B,CAAA;AAElC,iFAAiF;AACjF,OAAO,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAA;AAG3C,iFAAiF;AACjF,OAAO,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAA;AAQnD,qFAAqF;AACrF,OAAO,EAAE,mBAAmB,EAAE,MAAM,6BAA6B,CAAA;AAEjE,OAAO,EAAE,mBAAmB,EAAE,MAAM,6BAA6B,CAAA;AAEjE,OAAO,EAAE,gBAAgB,EAAE,MAAM,0BAA0B,CAAA;AAC3D,OAAO,EAAE,yBAAyB,EAAE,MAAM,mCAAmC,CAAA;AAI7E,OAAO,EAAE,qBAAqB,EAAE,qBAAqB,EAAE,MAAM,2BAA2B,CAAA;AAExF,OAAO,EAAE,cAAc,EAAE,MAAM,wBAAwB,CAAA"}
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/server/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAgCG;AAEH,iFAAiF;AACjF,OAAO,EACL,kBAAkB,EAClB,gBAAgB,GACjB,MAAM,oBAAoB,CAAA;AAM3B,iFAAiF;AACjF,OAAO,EACL,mBAAmB,EACnB,qBAAqB,GACtB,MAAM,eAAe,CAAA;AAQtB,iFAAiF;AACjF,OAAO,EAAE,WAAW,EAAE,MAAM,mCAAmC,CAAA;AAE/D,iFAAiF;AACjF,OAAO,EAAE,8BAA8B,EAAE,MAAM,0BAA0B,CAAA;AAMzE,gFAAgF;AAChF,OAAO,EACL,gBAAgB,EAChB,uBAAuB,EACvB,UAAU,GACX,MAAM,oBAAoB,CAAA;AAqB3B,iFAAiF;AACjF,OAAO,EACL,oBAAoB,EACpB,2BAA2B,EAC3B,wBAAwB,EACxB,qBAAqB,EACrB,uBAAuB,EACvB,yBAAyB,EACzB,yBAAyB,EACzB,aAAa,GACd,MAAM,+BAA+B,CAAA;AAYtC,OAAO,EAAE,8BAA8B,EAAE,MAAM,gCAAgC,CAAA;AAM/E,iFAAiF;AACjF,OAAO,EACL,kBAAkB,EAClB,kBAAkB,GACnB,MAAM,kCAAkC,CAAA;AAEzC,mFAAmF;AACnF,OAAO,EACL,qBAAqB,EACrB,wBAAwB,EACxB,WAAW,EACX,mBAAmB,GACpB,MAAM,2BAA2B,CAAA;AAElC,gFAAgF;AAChF,OAAO,EACL,kBAAkB,EAClB,aAAa,EACb,kBAAkB,GACnB,MAAM,6BAA6B,CAAA;AAMpC,iFAAiF;AACjF,OAAO,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAA;AAG3C,iFAAiF;AACjF,OAAO,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAA;AAQnD,qFAAqF;AACrF,OAAO,EAAE,mBAAmB,EAAE,MAAM,6BAA6B,CAAA;AAEjE,OAAO,EAAE,mBAAmB,EAAE,MAAM,6BAA6B,CAAA;AAEjE,OAAO,EAAE,gBAAgB,EAAE,MAAM,0BAA0B,CAAA;AAC3D,OAAO,EAAE,yBAAyB,EAAE,MAAM,mCAAmC,CAAA;AAI7E,OAAO,EAAE,qBAAqB,EAAE,qBAAqB,EAAE,MAAM,2BAA2B,CAAA;AAExF,OAAO,EAAE,cAAc,EAAE,MAAM,wBAAwB,CAAA"}
|
|
@@ -0,0 +1,173 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @module transports/workshop
|
|
3
|
+
* @description PostMessage transport for non-brainy API calls from kit iframes to
|
|
4
|
+
* the Workshop parent frame.
|
|
5
|
+
*
|
|
6
|
+
* While {@link PostMessageTransport} handles Brainy RPC (`brainy:request` /
|
|
7
|
+
* `brainy:response`), this transport handles generic HTTP-style API calls —
|
|
8
|
+
* AI chat streaming, Hall room joins, Pulse analytics, file operations, and
|
|
9
|
+
* notifications — using the `workshop:request` / `workshop:response` /
|
|
10
|
+
* `workshop:stream` wire protocol.
|
|
11
|
+
*
|
|
12
|
+
* The parent frame (PreviewFrame.svelte) receives `workshop:request` messages,
|
|
13
|
+
* forwards them as real HTTP requests to Workshop's backend, and relays the
|
|
14
|
+
* response back via `workshop:response` (JSON) or `workshop:stream` (SSE chunks).
|
|
15
|
+
*
|
|
16
|
+
* ## Wire protocol
|
|
17
|
+
*
|
|
18
|
+
* **Request** (kit iframe → parent):
|
|
19
|
+
* ```json
|
|
20
|
+
* { "type": "workshop:request", "id": "<uuid>", "path": "/api/ai/chat",
|
|
21
|
+
* "method": "POST", "body": "{...}", "stream": true, "headers": {} }
|
|
22
|
+
* ```
|
|
23
|
+
*
|
|
24
|
+
* **Response** (parent → kit iframe, non-streaming):
|
|
25
|
+
* ```json
|
|
26
|
+
* { "type": "workshop:response", "id": "<uuid>", "result": {...} }
|
|
27
|
+
* { "type": "workshop:response", "id": "<uuid>", "error": { "code": "...", "message": "..." } }
|
|
28
|
+
* ```
|
|
29
|
+
*
|
|
30
|
+
* **Stream chunk** (parent → kit iframe, streaming):
|
|
31
|
+
* ```json
|
|
32
|
+
* { "type": "workshop:stream", "id": "<uuid>", "chunk": "..." }
|
|
33
|
+
* { "type": "workshop:stream", "id": "<uuid>", "done": true }
|
|
34
|
+
* { "type": "workshop:stream", "id": "<uuid>", "error": "..." }
|
|
35
|
+
* ```
|
|
36
|
+
*
|
|
37
|
+
* ## Usage
|
|
38
|
+
*
|
|
39
|
+
* ```typescript
|
|
40
|
+
* import { WorkshopTransport } from '@soulcraft/sdk/client'
|
|
41
|
+
*
|
|
42
|
+
* const transport = new WorkshopTransport('https://workshop.soulcraft.com')
|
|
43
|
+
*
|
|
44
|
+
* // JSON call
|
|
45
|
+
* const result = await transport.call('/api/hall/rooms/my-room/join', 'POST', '{"audio":true}')
|
|
46
|
+
*
|
|
47
|
+
* // Streaming call (AI chat)
|
|
48
|
+
* for await (const chunk of transport.stream('/api/ai/chat', 'POST', body)) {
|
|
49
|
+
* process.stdout.write(chunk)
|
|
50
|
+
* }
|
|
51
|
+
* ```
|
|
52
|
+
*
|
|
53
|
+
* @see {@link PostMessageTransport} for Brainy-specific RPC transport.
|
|
54
|
+
*/
|
|
55
|
+
/** An API request posted from the kit iframe to the Workshop parent frame. */
|
|
56
|
+
export interface WorkshopRequest {
|
|
57
|
+
type: 'workshop:request';
|
|
58
|
+
id: string;
|
|
59
|
+
/** API path, e.g. '/api/ai/chat', '/api/pulse/track'. */
|
|
60
|
+
path: string;
|
|
61
|
+
/** HTTP method. */
|
|
62
|
+
method: 'GET' | 'POST' | 'PUT' | 'DELETE';
|
|
63
|
+
/** JSON-serialized body for POST/PUT. */
|
|
64
|
+
body?: string | undefined;
|
|
65
|
+
/** If true, the parent relays the response as `workshop:stream` chunks. */
|
|
66
|
+
stream?: boolean | undefined;
|
|
67
|
+
/** Extra headers (e.g. Content-Type for non-JSON bodies). */
|
|
68
|
+
headers?: Record<string, string> | undefined;
|
|
69
|
+
}
|
|
70
|
+
/** A JSON response posted from the parent to the kit iframe. */
|
|
71
|
+
export interface WorkshopResponse {
|
|
72
|
+
type: 'workshop:response';
|
|
73
|
+
id: string;
|
|
74
|
+
result?: unknown;
|
|
75
|
+
error?: {
|
|
76
|
+
code: string;
|
|
77
|
+
message: string;
|
|
78
|
+
};
|
|
79
|
+
}
|
|
80
|
+
/** A streaming chunk posted from the parent to the kit iframe. */
|
|
81
|
+
export interface WorkshopStreamChunk {
|
|
82
|
+
type: 'workshop:stream';
|
|
83
|
+
id: string;
|
|
84
|
+
/** SSE data line content (parsed JSON string from the `data:` line). */
|
|
85
|
+
chunk?: string;
|
|
86
|
+
/** True when the stream has ended. */
|
|
87
|
+
done?: boolean;
|
|
88
|
+
/** Error message if the stream failed. */
|
|
89
|
+
error?: string;
|
|
90
|
+
}
|
|
91
|
+
/** Minimal window interface for testability. */
|
|
92
|
+
export interface WorkshopTransportWindow {
|
|
93
|
+
addEventListener(type: 'message', listener: (event: MessageEvent) => void): void;
|
|
94
|
+
removeEventListener(type: 'message', listener: (event: MessageEvent) => void): void;
|
|
95
|
+
postMessage(message: unknown, targetOrigin: string): void;
|
|
96
|
+
readonly parent: WorkshopTransportWindow;
|
|
97
|
+
}
|
|
98
|
+
/**
|
|
99
|
+
* PostMessage transport for generic (non-brainy) API calls from kit iframes.
|
|
100
|
+
*
|
|
101
|
+
* Each `call()` posts a `workshop:request` message to `window.parent` and awaits
|
|
102
|
+
* a matching `workshop:response`. For streaming endpoints, `stream()` collects
|
|
103
|
+
* `workshop:stream` chunks and yields them as an `AsyncIterable<string>`.
|
|
104
|
+
*
|
|
105
|
+
* @example
|
|
106
|
+
* ```typescript
|
|
107
|
+
* const t = new WorkshopTransport(workshopOrigin)
|
|
108
|
+
*
|
|
109
|
+
* // Fire-and-forget analytics
|
|
110
|
+
* t.call('/api/pulse/track', 'POST', JSON.stringify({ event: 'page_view' }))
|
|
111
|
+
*
|
|
112
|
+
* // Stream AI tokens
|
|
113
|
+
* for await (const token of t.stream('/api/ai/chat', 'POST', body)) {
|
|
114
|
+
* output += token
|
|
115
|
+
* }
|
|
116
|
+
* ```
|
|
117
|
+
*/
|
|
118
|
+
export declare class WorkshopTransport {
|
|
119
|
+
private readonly _targetOrigin;
|
|
120
|
+
private readonly _timeoutMs;
|
|
121
|
+
private readonly _pendingCalls;
|
|
122
|
+
private readonly _pendingStreams;
|
|
123
|
+
private _closed;
|
|
124
|
+
private readonly _messageListener;
|
|
125
|
+
private readonly _listenerWindow;
|
|
126
|
+
private readonly _parentWindow;
|
|
127
|
+
/**
|
|
128
|
+
* @param targetOrigin - The Workshop parent frame's origin for postMessage security.
|
|
129
|
+
* Must be an explicit origin in production; `'*'` is acceptable only in dev.
|
|
130
|
+
* @param timeoutMs - Per-call timeout in milliseconds. Default: 60 000 (longer than
|
|
131
|
+
* brainy RPC because AI chat streams can take a while to start).
|
|
132
|
+
* @param listenerWindow - Window for message events. Defaults to `window`.
|
|
133
|
+
* @param parentWindow - Window to post messages to. Defaults to `window.parent`.
|
|
134
|
+
*/
|
|
135
|
+
constructor(targetOrigin: string, timeoutMs?: number, listenerWindow?: WorkshopTransportWindow, parentWindow?: WorkshopTransportWindow);
|
|
136
|
+
private _handleMessage;
|
|
137
|
+
private _streamTimeout;
|
|
138
|
+
private _generateId;
|
|
139
|
+
/**
|
|
140
|
+
* Send a JSON API call through the PostMessage relay.
|
|
141
|
+
*
|
|
142
|
+
* @param path - API endpoint path (e.g. '/api/hall/rooms/my-room/join').
|
|
143
|
+
* @param method - HTTP method.
|
|
144
|
+
* @param body - JSON-serialized request body.
|
|
145
|
+
* @param headers - Extra headers to forward.
|
|
146
|
+
* @returns The parsed JSON response body.
|
|
147
|
+
* @throws {Error} If the transport is closed, the request times out, or the
|
|
148
|
+
* parent responds with an error.
|
|
149
|
+
*/
|
|
150
|
+
call(path: string, method?: 'GET' | 'POST' | 'PUT' | 'DELETE', body?: string, headers?: Record<string, string>): Promise<unknown>;
|
|
151
|
+
/**
|
|
152
|
+
* Send a streaming API call through the PostMessage relay.
|
|
153
|
+
*
|
|
154
|
+
* The parent frame reads the HTTP response as SSE chunks and forwards each as
|
|
155
|
+
* a `workshop:stream` message. This method yields each chunk as it arrives.
|
|
156
|
+
*
|
|
157
|
+
* @param path - API endpoint path (e.g. '/api/ai/chat').
|
|
158
|
+
* @param method - HTTP method (typically 'POST').
|
|
159
|
+
* @param body - JSON-serialized request body.
|
|
160
|
+
* @param headers - Extra headers to forward.
|
|
161
|
+
* @returns An async iterable of string chunks.
|
|
162
|
+
*/
|
|
163
|
+
stream(path: string, method?: 'GET' | 'POST' | 'PUT' | 'DELETE', body?: string, headers?: Record<string, string>): AsyncIterable<string>;
|
|
164
|
+
/**
|
|
165
|
+
* Returns `true` if the transport is open and usable.
|
|
166
|
+
*/
|
|
167
|
+
isAlive(): boolean;
|
|
168
|
+
/**
|
|
169
|
+
* Close the transport, removing the message listener and rejecting all pending calls.
|
|
170
|
+
*/
|
|
171
|
+
close(): void;
|
|
172
|
+
}
|
|
173
|
+
//# sourceMappingURL=workshop.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"workshop.d.ts","sourceRoot":"","sources":["../../src/transports/workshop.ts"],"names":[],"mappings":"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"}
|