@wordrhyme/plugin 0.1.0-alpha.12 → 0.1.0-alpha.14
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/artifact.d.ts +1 -1
- package/dist/artifact.js +1 -1
- package/dist/build.d.ts +12 -0
- package/dist/build.js +31 -0
- package/dist/build.js.map +1 -0
- package/dist/{chunk-7EM22QYB.js → chunk-7U4PL5TX.js} +6 -2
- package/dist/chunk-7U4PL5TX.js.map +1 -0
- package/dist/{chunk-C7BZITSY.js → chunk-QUUDT6V5.js} +11 -59
- package/dist/chunk-QUUDT6V5.js.map +1 -0
- package/dist/{chunk-DNM4FUUP.js → chunk-V7IAPFUE.js} +7 -13
- package/dist/chunk-V7IAPFUE.js.map +1 -0
- package/dist/{client-DHu0337Q.d.ts → client-8lkI5njC.d.ts} +2 -2
- package/dist/client.d.ts +3 -3
- package/dist/client.js +1 -1
- package/dist/dev-utils.d.ts +13 -6
- package/dist/dev-utils.js +3 -1
- package/dist/{entity-extensions-CzaTt8bn.d.ts → entity-extensions-B6TmuDSK.d.ts} +2 -2
- package/dist/index.d.ts +18 -8
- package/dist/index.js +27 -19
- package/dist/index.js.map +1 -1
- package/dist/{manifest-DtNk_ILK.d.ts → manifest-DeCaPHoR.d.ts} +11 -45
- package/dist/react.d.ts +1 -1
- package/dist/server.d.ts +64 -14
- package/dist/server.js +161 -5
- package/dist/server.js.map +1 -1
- package/dist/trpc.d.ts +1 -1
- package/dist/trpc.js +1 -1
- package/dist/{types-BJo3_91V.d.ts → types-vMRNhnTU.d.ts} +61 -6
- package/package.json +9 -2
- package/dist/chunk-7EM22QYB.js.map +0 -1
- package/dist/chunk-C7BZITSY.js.map +0 -1
- package/dist/chunk-DNM4FUUP.js.map +0 -1
|
@@ -1327,6 +1327,12 @@ declare const pluginManifestSchema: z.ZodObject<{
|
|
|
1327
1327
|
storage: z.ZodOptional<z.ZodObject<{
|
|
1328
1328
|
provider: z.ZodOptional<z.ZodBoolean>;
|
|
1329
1329
|
}, z.core.$strip>>;
|
|
1330
|
+
sms: z.ZodOptional<z.ZodObject<{
|
|
1331
|
+
provider: z.ZodOptional<z.ZodBoolean>;
|
|
1332
|
+
}, z.core.$strip>>;
|
|
1333
|
+
organizations: z.ZodOptional<z.ZodObject<{
|
|
1334
|
+
provision: z.ZodOptional<z.ZodBoolean>;
|
|
1335
|
+
}, z.core.$strip>>;
|
|
1330
1336
|
artifacts: z.ZodOptional<z.ZodObject<{
|
|
1331
1337
|
write: z.ZodOptional<z.ZodBoolean>;
|
|
1332
1338
|
}, z.core.$strip>>;
|
|
@@ -1378,51 +1384,8 @@ declare const pluginManifestSchema: z.ZodObject<{
|
|
|
1378
1384
|
}, z.core.$strip>>>>;
|
|
1379
1385
|
}, z.core.$strip>>;
|
|
1380
1386
|
server: z.ZodOptional<z.ZodObject<{
|
|
1381
|
-
entry: z.ZodString
|
|
1382
|
-
|
|
1383
|
-
nestModule: z.ZodOptional<z.ZodString>;
|
|
1384
|
-
fastifyRoutes: z.ZodOptional<z.ZodUnion<readonly [z.ZodString, z.ZodObject<{
|
|
1385
|
-
entry: z.ZodString;
|
|
1386
|
-
grants: z.ZodOptional<z.ZodArray<z.ZodObject<{
|
|
1387
|
-
action: z.ZodString;
|
|
1388
|
-
subject: z.ZodString;
|
|
1389
|
-
targetPluginId: z.ZodOptional<z.ZodString>;
|
|
1390
|
-
}, z.core.$strip>>>;
|
|
1391
|
-
queueProcedures: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodArray<z.ZodObject<{
|
|
1392
|
-
action: z.ZodString;
|
|
1393
|
-
subject: z.ZodString;
|
|
1394
|
-
targetPluginId: z.ZodOptional<z.ZodString>;
|
|
1395
|
-
}, z.core.$strip>>>>;
|
|
1396
|
-
}, z.core.$strip>]>>;
|
|
1397
|
-
publicServices: z.ZodOptional<z.ZodArray<z.ZodObject<{
|
|
1398
|
-
name: z.ZodString;
|
|
1399
|
-
mountPath: z.ZodString;
|
|
1400
|
-
methods: z.ZodArray<z.ZodEnum<{
|
|
1401
|
-
GET: "GET";
|
|
1402
|
-
POST: "POST";
|
|
1403
|
-
PUT: "PUT";
|
|
1404
|
-
PATCH: "PATCH";
|
|
1405
|
-
DELETE: "DELETE";
|
|
1406
|
-
}>>;
|
|
1407
|
-
auth: z.ZodDefault<z.ZodEnum<{
|
|
1408
|
-
public: "public";
|
|
1409
|
-
bearer: "bearer";
|
|
1410
|
-
session: "session";
|
|
1411
|
-
user: "user";
|
|
1412
|
-
}>>;
|
|
1413
|
-
maxBodyBytes: z.ZodDefault<z.ZodNumber>;
|
|
1414
|
-
}, z.core.$strip>>>;
|
|
1415
|
-
trustedApiTokenProxy: z.ZodOptional<z.ZodObject<{
|
|
1416
|
-
invoker: z.ZodString;
|
|
1417
|
-
paths: z.ZodArray<z.ZodString>;
|
|
1418
|
-
}, z.core.$strip>>;
|
|
1419
|
-
hooks: z.ZodOptional<z.ZodArray<z.ZodEnum<{
|
|
1420
|
-
onUninstall: "onUninstall";
|
|
1421
|
-
onInstall: "onInstall";
|
|
1422
|
-
onEnable: "onEnable";
|
|
1423
|
-
onDisable: "onDisable";
|
|
1424
|
-
}>>>;
|
|
1425
|
-
}, z.core.$strip>>;
|
|
1387
|
+
entry: z.ZodOptional<z.ZodString>;
|
|
1388
|
+
}, z.core.$strict>>;
|
|
1426
1389
|
admin: z.ZodOptional<z.ZodObject<{
|
|
1427
1390
|
remoteEntry: z.ZodString;
|
|
1428
1391
|
devRemoteEntry: z.ZodOptional<z.ZodString>;
|
|
@@ -2060,6 +2023,9 @@ interface PluginCapabilities {
|
|
|
2060
2023
|
webDesigner?: boolean;
|
|
2061
2024
|
settingsTab?: boolean;
|
|
2062
2025
|
};
|
|
2026
|
+
organizations?: {
|
|
2027
|
+
provision?: boolean;
|
|
2028
|
+
};
|
|
2063
2029
|
}
|
|
2064
2030
|
|
|
2065
2031
|
export { webDesignActionSchema as $, type AdminTour as A, adminTourPlacementSchema as B, adminTourSchema as C, adminTourStepSchema as D, type EntityExtensionFieldType as E, autoCrudActionSchema as F, autoCrudActionZoneSchema as G, autoCrudActionsSchema as H, autoCrudDataSourceSchema as I, autoCrudFieldConfigSchema as J, autoCrudFieldOptionSchema as K, dashboardTargetSchema as L, entityExtensionCrudConfigSchema as M, entityExtensionFieldSchema as N, entityExtensionSchema as O, type PluginManifest as P, entityExtensionSlotSchema as Q, entityExtensionUseSchema as R, navGroupTargetSchema as S, navTargetSchema as T, pluginI18nSchema as U, pluginManifestSchema as V, type WebDesignAction as W, pluginUsesSchema as X, routeTargetSchema as Y, settingsTargetSchema as Z, targetSchema as _, type EntityExtensionField as a, webDesignBlockSchema as a0, webDesignDataSourceSchema as a1, webDesignSlotSchema as a2, webDesignSurfaceSchema as a3, webDesignTemplateSchema as a4, webExtensionQuerySchema as a5, webExtensionSchema as a6, webExtensionTargetSchema as a7, webPluginRouteSchema as a8, webSsrContractVersionSchema as a9, webSurfaceSchema as aa, type AdminTourPlacement as b, type AdminTourStep as c, type AggregationStrategy as d, type AutoCrudAction as e, type AutoCrudActionZone as f, type AutoCrudActions as g, type EntityExtension as h, type EntityExtensionCrudConfig as i, type EntityExtensionSlot as j, type EntityExtensionUse as k, type PluginCapabilities as l, type PluginNotificationType as m, type PluginStatus as n, type WebDesignBlock as o, type WebDesignDataSource as p, type WebDesignSlot as q, type WebDesignSurface as r, type WebDesignTemplate as s, type WebExtension as t, type WebExtensionQuery as u, type WebExtensionTarget as v, type WebPluginRoute as w, type WebSsrContractVersion as x, type WebSurface as y, adminExtensionSchema as z };
|
package/dist/react.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
|
-
import { W as WebSlotRemoteExtension, P as PluginMediaInfo } from './types-
|
|
2
|
+
import { W as WebSlotRemoteExtension, P as PluginMediaInfo } from './types-vMRNhnTU.js';
|
|
3
3
|
import { CurrencyInfo, FormatPriceOptions } from './globalization.js';
|
|
4
4
|
import './release-BDJeO54k.js';
|
|
5
5
|
import 'zod';
|
package/dist/server.d.ts
CHANGED
|
@@ -1,15 +1,15 @@
|
|
|
1
1
|
export { createPluginContext, pluginProcedure, pluginRouter } from './trpc.js';
|
|
2
|
-
import { a as PluginContext } from './types-
|
|
3
|
-
export { H as HookContext, c as HookTransaction } from './types-
|
|
2
|
+
import { a as PluginContext } from './types-vMRNhnTU.js';
|
|
3
|
+
export { H as HookContext, c as HookTransaction } from './types-vMRNhnTU.js';
|
|
4
4
|
import { DateRangeResolver } from './time.js';
|
|
5
5
|
export { inferRouterInputs, inferRouterOutputs } from '@trpc/server';
|
|
6
|
-
export { E as ENTITY_EXTENSION_VALUES_SAVE_HOOK_ID, a as EXTENSION_PROJECT_SAVE_HOOK_ID, b as EntityExtensionProjectionValue, c as EntityExtensionValueSaveHandler, d as EntityExtensionValueSavePayload, e as EntityExtensionValueSaveResult, f as entityExtensions, r as registerEntityExtensionValueSaver } from './entity-extensions-
|
|
6
|
+
export { E as ENTITY_EXTENSION_VALUES_SAVE_HOOK_ID, a as EXTENSION_PROJECT_SAVE_HOOK_ID, b as EntityExtensionProjectionValue, c as EntityExtensionValueSaveHandler, d as EntityExtensionValueSavePayload, e as EntityExtensionValueSaveResult, f as entityExtensions, r as registerEntityExtensionValueSaver } from './entity-extensions-B6TmuDSK.js';
|
|
7
7
|
import './globalization.js';
|
|
8
8
|
import 'decimal.js';
|
|
9
9
|
import './locale.js';
|
|
10
10
|
import './release-BDJeO54k.js';
|
|
11
11
|
import 'zod';
|
|
12
|
-
import './manifest-
|
|
12
|
+
import './manifest-DeCaPHoR.js';
|
|
13
13
|
|
|
14
14
|
interface PluginRuntimeRequestContext {
|
|
15
15
|
requestId?: string | undefined;
|
|
@@ -93,23 +93,73 @@ declare function createOAuthState<TPayload extends Record<string, unknown>>(ctx:
|
|
|
93
93
|
declare function consumeOAuthState<TPayload extends Record<string, unknown> = Record<string, unknown>>(ctx: OAuthSettings, options: ConsumeOAuthStateOptions): Promise<OAuthStateRecord<TPayload>>;
|
|
94
94
|
declare function verifyQueryHmacSha256(params: OAuthQueryParams, secret: string, options?: VerifyQueryHmacSha256Options): boolean;
|
|
95
95
|
|
|
96
|
-
|
|
97
|
-
|
|
96
|
+
declare const PLUGIN_HTTP_METHODS: readonly ["GET", "POST", "PUT", "PATCH", "DELETE", "OPTIONS", "HEAD"];
|
|
97
|
+
declare const MAX_PLUGIN_HTTP_BODY_BYTES: number;
|
|
98
|
+
type PluginHttpMethod = (typeof PLUGIN_HTTP_METHODS)[number];
|
|
99
|
+
type PluginHttpAuth = "public" | "session" | "user";
|
|
100
|
+
type PluginHttpScope = "platform" | "tenant";
|
|
101
|
+
interface PluginHttpSchema<T> {
|
|
102
|
+
parse(value: unknown): T;
|
|
103
|
+
}
|
|
104
|
+
interface PluginHttpRouteOptions<TParams = Record<string, string>, TQuery = Record<string, unknown>, TBody = unknown> {
|
|
105
|
+
auth?: PluginHttpAuth;
|
|
106
|
+
permission?: string;
|
|
107
|
+
/** API Token scope required in addition to the route's live RBAC permission. */
|
|
108
|
+
apiTokenScope?: string;
|
|
109
|
+
scope?: PluginHttpScope;
|
|
110
|
+
installation?: PluginHttpScope;
|
|
111
|
+
params?: PluginHttpSchema<TParams>;
|
|
112
|
+
query?: PluginHttpSchema<TQuery>;
|
|
113
|
+
body?: PluginHttpSchema<TBody>;
|
|
114
|
+
rawBody?: boolean;
|
|
115
|
+
maxBodyBytes?: number;
|
|
116
|
+
}
|
|
117
|
+
interface PluginHttpRequest<TParams = Record<string, string>, TQuery = Record<string, unknown>, TBody = unknown> {
|
|
118
|
+
method: PluginHttpMethod;
|
|
98
119
|
path: string;
|
|
99
|
-
|
|
120
|
+
params: TParams;
|
|
121
|
+
query: TQuery;
|
|
100
122
|
headers: Record<string, string | undefined>;
|
|
101
|
-
body:
|
|
123
|
+
body: TBody;
|
|
124
|
+
rawBody?: Uint8Array;
|
|
102
125
|
requestId: string;
|
|
126
|
+
remoteAddress?: string;
|
|
103
127
|
}
|
|
104
|
-
interface
|
|
128
|
+
interface PluginHttpResponse {
|
|
105
129
|
status?: number;
|
|
106
130
|
headers?: Record<string, string>;
|
|
107
131
|
body?: unknown;
|
|
108
132
|
}
|
|
109
|
-
interface
|
|
110
|
-
|
|
111
|
-
|
|
133
|
+
interface PluginHttpContext extends PluginContext {
|
|
134
|
+
readonly scope: PluginHttpScope;
|
|
135
|
+
runForOrganization<T>(organizationId: string, callback: (context: PluginContext) => Promise<T> | T): Promise<T>;
|
|
136
|
+
}
|
|
137
|
+
type PluginHttpResult = Response | PluginHttpResponse | undefined;
|
|
138
|
+
type PluginHttpHandler<TParams = Record<string, string>, TQuery = Record<string, unknown>, TBody = unknown> = (request: PluginHttpRequest<TParams, TQuery, TBody>, context: PluginHttpContext) => Promise<PluginHttpResult> | PluginHttpResult;
|
|
139
|
+
interface PluginHttpRouteDefinition {
|
|
140
|
+
readonly methods: readonly PluginHttpMethod[];
|
|
141
|
+
readonly path: string;
|
|
142
|
+
readonly options: Readonly<PluginHttpRouteOptions>;
|
|
143
|
+
readonly handler: PluginHttpHandler;
|
|
144
|
+
}
|
|
145
|
+
interface PluginHttpRouteRegistrar {
|
|
146
|
+
(path: string, handler: PluginHttpHandler): void;
|
|
147
|
+
<TParams = Record<string, string>, TQuery = Record<string, unknown>, TBody = unknown>(path: string, options: PluginHttpRouteOptions<TParams, TQuery, TBody>, handler: PluginHttpHandler<TParams, TQuery, TBody>): void;
|
|
148
|
+
}
|
|
149
|
+
interface PluginHttpRouter {
|
|
150
|
+
(handler: PluginHttpHandler): void;
|
|
151
|
+
(path: string, handler: PluginHttpHandler): void;
|
|
152
|
+
<TParams = Record<string, string>, TQuery = Record<string, unknown>, TBody = unknown>(path: string, options: PluginHttpRouteOptions<TParams, TQuery, TBody>, handler: PluginHttpHandler<TParams, TQuery, TBody>): void;
|
|
153
|
+
readonly routes: readonly PluginHttpRouteDefinition[];
|
|
154
|
+
readonly get: PluginHttpRouteRegistrar;
|
|
155
|
+
readonly post: PluginHttpRouteRegistrar;
|
|
156
|
+
readonly put: PluginHttpRouteRegistrar;
|
|
157
|
+
readonly patch: PluginHttpRouteRegistrar;
|
|
158
|
+
readonly delete: PluginHttpRouteRegistrar;
|
|
159
|
+
readonly options: PluginHttpRouteRegistrar;
|
|
160
|
+
readonly head: PluginHttpRouteRegistrar;
|
|
112
161
|
}
|
|
113
|
-
declare function
|
|
162
|
+
declare function createHttp(defaults?: PluginHttpRouteOptions): PluginHttpRouter;
|
|
163
|
+
declare function isPluginHttpRouter(value: unknown): value is PluginHttpRouter;
|
|
114
164
|
|
|
115
|
-
export { type CreatePluginRuntimeContextInput, type OAuthStateRecord, type
|
|
165
|
+
export { type CreatePluginRuntimeContextInput, MAX_PLUGIN_HTTP_BODY_BYTES, type OAuthStateRecord, PLUGIN_HTTP_METHODS, type PluginHttpAuth, type PluginHttpContext, type PluginHttpHandler, type PluginHttpMethod, type PluginHttpRequest, type PluginHttpResponse, type PluginHttpResult, type PluginHttpRouteDefinition, type PluginHttpRouteOptions, type PluginHttpRouter, type PluginHttpSchema, type PluginHttpScope, type PluginRuntimeBridge, type PluginRuntimeRequestContext, buildOAuthCallbackPath, buildOAuthCallbackUrl, buildOAuthResultRedirect, buildOAuthStateKey, consumeOAuthState, createHttp, createOAuthState, createPluginRuntimeContext, createPluginRuntimeRequestContext, isPluginHttpRouter, maskOAuthSecret, runWithPluginRuntimeContext, setPluginRuntimeBridge, verifyQueryHmacSha256 };
|
package/dist/server.js
CHANGED
|
@@ -2,7 +2,7 @@ import {
|
|
|
2
2
|
createPluginContext,
|
|
3
3
|
pluginProcedure,
|
|
4
4
|
pluginRouter
|
|
5
|
-
} from "./chunk-
|
|
5
|
+
} from "./chunk-V7IAPFUE.js";
|
|
6
6
|
import {
|
|
7
7
|
ENTITY_EXTENSION_VALUES_SAVE_HOOK_ID,
|
|
8
8
|
EXTENSION_PROJECT_SAVE_HOOK_ID,
|
|
@@ -165,24 +165,180 @@ function scopeOptions(options) {
|
|
|
165
165
|
return options.global !== void 0 ? { global: options.global } : void 0;
|
|
166
166
|
}
|
|
167
167
|
|
|
168
|
-
// src/
|
|
169
|
-
|
|
170
|
-
|
|
168
|
+
// src/http.ts
|
|
169
|
+
var PLUGIN_HTTP_METHODS = ["GET", "POST", "PUT", "PATCH", "DELETE", "OPTIONS", "HEAD"];
|
|
170
|
+
var MAX_PLUGIN_HTTP_BODY_BYTES = 100 * 1024 * 1024;
|
|
171
|
+
var HTTP_ROUTER_MARKER = /* @__PURE__ */ Symbol.for("wordrhyme.plugin.http-router");
|
|
172
|
+
function createHttp(defaults = {}) {
|
|
173
|
+
validateOptions(defaults);
|
|
174
|
+
const routes = [];
|
|
175
|
+
const routeKeys = /* @__PURE__ */ new Set();
|
|
176
|
+
const add = (methods, path, options, handler) => {
|
|
177
|
+
const normalizedPath = normalizePath(path);
|
|
178
|
+
const merged = Object.freeze({
|
|
179
|
+
...defaults,
|
|
180
|
+
...options,
|
|
181
|
+
auth: options.auth ?? defaults.auth ?? "user"
|
|
182
|
+
});
|
|
183
|
+
validateOptions(merged);
|
|
184
|
+
assertNoRouteConflict(routeKeys, methods, normalizedPath);
|
|
185
|
+
routes.push(
|
|
186
|
+
Object.freeze({
|
|
187
|
+
methods: Object.freeze([...methods]),
|
|
188
|
+
path: normalizedPath,
|
|
189
|
+
options: merged,
|
|
190
|
+
handler
|
|
191
|
+
})
|
|
192
|
+
);
|
|
193
|
+
};
|
|
194
|
+
const register = ((...args) => {
|
|
195
|
+
if (typeof args[0] === "function") {
|
|
196
|
+
add(PLUGIN_HTTP_METHODS, "*", {}, args[0]);
|
|
197
|
+
return;
|
|
198
|
+
}
|
|
199
|
+
registerRoute(add, PLUGIN_HTTP_METHODS, args);
|
|
200
|
+
});
|
|
201
|
+
for (const method of PLUGIN_HTTP_METHODS) {
|
|
202
|
+
const name = method.toLowerCase();
|
|
203
|
+
Object.defineProperty(register, name, {
|
|
204
|
+
enumerable: true,
|
|
205
|
+
value: (...args) => registerRoute(add, [method], args)
|
|
206
|
+
});
|
|
207
|
+
}
|
|
208
|
+
Object.defineProperties(register, {
|
|
209
|
+
routes: {
|
|
210
|
+
enumerable: true,
|
|
211
|
+
get: () => Object.freeze([...routes])
|
|
212
|
+
},
|
|
213
|
+
[HTTP_ROUTER_MARKER]: {
|
|
214
|
+
value: true
|
|
215
|
+
}
|
|
216
|
+
});
|
|
217
|
+
return register;
|
|
218
|
+
}
|
|
219
|
+
function isPluginHttpRouter(value) {
|
|
220
|
+
return typeof value === "function" && value[HTTP_ROUTER_MARKER] === true && Array.isArray(value.routes);
|
|
221
|
+
}
|
|
222
|
+
function registerRoute(add, methods, args) {
|
|
223
|
+
const [path, optionsOrHandler, possibleHandler] = args;
|
|
224
|
+
if (typeof path !== "string") {
|
|
225
|
+
throw new TypeError("Plugin HTTP route path must be a string");
|
|
226
|
+
}
|
|
227
|
+
if (typeof optionsOrHandler === "function") {
|
|
228
|
+
add(methods, path, {}, optionsOrHandler);
|
|
229
|
+
return;
|
|
230
|
+
}
|
|
231
|
+
if (!isRecord(optionsOrHandler) || typeof possibleHandler !== "function") {
|
|
232
|
+
throw new TypeError("Plugin HTTP route requires a handler");
|
|
233
|
+
}
|
|
234
|
+
add(methods, path, optionsOrHandler, possibleHandler);
|
|
235
|
+
}
|
|
236
|
+
function normalizePath(path) {
|
|
237
|
+
if (path === "*") return path;
|
|
238
|
+
if (!path.startsWith("/")) {
|
|
239
|
+
throw new TypeError("Plugin HTTP route path must start with /");
|
|
240
|
+
}
|
|
241
|
+
if (path.length > 1 && path.endsWith("/")) return path.slice(0, -1);
|
|
242
|
+
return path;
|
|
243
|
+
}
|
|
244
|
+
function validateOptions(options) {
|
|
245
|
+
if (!isRecord(options)) {
|
|
246
|
+
throw new TypeError("Plugin HTTP route options must be an object");
|
|
247
|
+
}
|
|
248
|
+
const allowedKeys = /* @__PURE__ */ new Set([
|
|
249
|
+
"auth",
|
|
250
|
+
"permission",
|
|
251
|
+
"apiTokenScope",
|
|
252
|
+
"scope",
|
|
253
|
+
"installation",
|
|
254
|
+
"params",
|
|
255
|
+
"query",
|
|
256
|
+
"body",
|
|
257
|
+
"rawBody",
|
|
258
|
+
"maxBodyBytes"
|
|
259
|
+
]);
|
|
260
|
+
const unknownKey = Object.keys(options).find((key) => !allowedKeys.has(key));
|
|
261
|
+
if (unknownKey) {
|
|
262
|
+
throw new TypeError(`Unknown Plugin HTTP route option: ${unknownKey}`);
|
|
263
|
+
}
|
|
264
|
+
if (options.auth !== void 0 && !["public", "session", "user"].includes(options.auth)) {
|
|
265
|
+
throw new TypeError("Plugin HTTP auth must be public, session, or user");
|
|
266
|
+
}
|
|
267
|
+
if (options.scope !== void 0 && !["platform", "tenant"].includes(options.scope)) {
|
|
268
|
+
throw new TypeError("Plugin HTTP scope must be platform or tenant");
|
|
269
|
+
}
|
|
270
|
+
if (options.installation !== void 0 && !["platform", "tenant"].includes(options.installation)) {
|
|
271
|
+
throw new TypeError("Plugin HTTP installation must be platform or tenant");
|
|
272
|
+
}
|
|
273
|
+
const effectiveScope = options.scope ?? (options.auth === "public" ? "platform" : "tenant");
|
|
274
|
+
if (effectiveScope === "platform" && options.installation === "tenant") {
|
|
275
|
+
throw new TypeError("Plugin HTTP platform scope cannot require a tenant installation");
|
|
276
|
+
}
|
|
277
|
+
if (options.permission !== void 0 && (typeof options.permission !== "string" || !options.permission.trim())) {
|
|
278
|
+
throw new TypeError("Plugin HTTP permission must be a non-empty string");
|
|
279
|
+
}
|
|
280
|
+
if (options.apiTokenScope !== void 0 && (typeof options.apiTokenScope !== "string" || !options.apiTokenScope.trim())) {
|
|
281
|
+
throw new TypeError("Plugin HTTP apiTokenScope must be a non-empty string");
|
|
282
|
+
}
|
|
283
|
+
if (options.apiTokenScope !== void 0 && options.permission === void 0) {
|
|
284
|
+
throw new TypeError("Plugin HTTP apiTokenScope requires permission");
|
|
285
|
+
}
|
|
286
|
+
const effectiveAuth = options.auth ?? "user";
|
|
287
|
+
if (options.apiTokenScope !== void 0 && effectiveAuth !== "user") {
|
|
288
|
+
throw new TypeError("Plugin HTTP apiTokenScope requires auth: user");
|
|
289
|
+
}
|
|
290
|
+
if (options.rawBody !== void 0 && typeof options.rawBody !== "boolean") {
|
|
291
|
+
throw new TypeError("Plugin HTTP rawBody must be a boolean");
|
|
292
|
+
}
|
|
293
|
+
for (const key of ["params", "query", "body"]) {
|
|
294
|
+
const schema = options[key];
|
|
295
|
+
if (schema !== void 0 && (!isRecord(schema) || typeof schema.parse !== "function")) {
|
|
296
|
+
throw new TypeError(`Plugin HTTP ${key} schema must provide parse()`);
|
|
297
|
+
}
|
|
298
|
+
}
|
|
299
|
+
if (options.maxBodyBytes !== void 0 && (!Number.isSafeInteger(options.maxBodyBytes) || options.maxBodyBytes <= 0 || options.maxBodyBytes > MAX_PLUGIN_HTTP_BODY_BYTES)) {
|
|
300
|
+
throw new TypeError(`Plugin HTTP maxBodyBytes must be a positive integer up to ${MAX_PLUGIN_HTTP_BODY_BYTES}`);
|
|
301
|
+
}
|
|
302
|
+
}
|
|
303
|
+
function assertNoRouteConflict(routeKeys, methods, path) {
|
|
304
|
+
const paths = path === "*" ? ["/", "/*"] : [path];
|
|
305
|
+
for (const method of methods) {
|
|
306
|
+
for (const routePath of paths) {
|
|
307
|
+
const key = `${method} ${canonicalRoutePath(routePath)}`;
|
|
308
|
+
if (routeKeys.has(key)) {
|
|
309
|
+
throw new TypeError(`Plugin HTTP route conflict: ${key}`);
|
|
310
|
+
}
|
|
311
|
+
}
|
|
312
|
+
}
|
|
313
|
+
for (const method of methods) {
|
|
314
|
+
for (const routePath of paths) {
|
|
315
|
+
routeKeys.add(`${method} ${canonicalRoutePath(routePath)}`);
|
|
316
|
+
}
|
|
317
|
+
}
|
|
318
|
+
}
|
|
319
|
+
function canonicalRoutePath(path) {
|
|
320
|
+
return path.replace(/:([A-Za-z0-9_]+)/g, ":");
|
|
321
|
+
}
|
|
322
|
+
function isRecord(value) {
|
|
323
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
171
324
|
}
|
|
172
325
|
export {
|
|
173
326
|
ENTITY_EXTENSION_VALUES_SAVE_HOOK_ID,
|
|
174
327
|
EXTENSION_PROJECT_SAVE_HOOK_ID,
|
|
328
|
+
MAX_PLUGIN_HTTP_BODY_BYTES,
|
|
329
|
+
PLUGIN_HTTP_METHODS,
|
|
175
330
|
buildOAuthCallbackPath,
|
|
176
331
|
buildOAuthCallbackUrl,
|
|
177
332
|
buildOAuthResultRedirect,
|
|
178
333
|
buildOAuthStateKey,
|
|
179
334
|
consumeOAuthState,
|
|
335
|
+
createHttp,
|
|
180
336
|
createOAuthState,
|
|
181
337
|
createPluginContext,
|
|
182
338
|
createPluginRuntimeContext,
|
|
183
339
|
createPluginRuntimeRequestContext,
|
|
184
|
-
definePublicService,
|
|
185
340
|
entityExtensions,
|
|
341
|
+
isPluginHttpRouter,
|
|
186
342
|
maskOAuthSecret,
|
|
187
343
|
pluginProcedure,
|
|
188
344
|
pluginRouter,
|
package/dist/server.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/runtime.ts","../src/oauth.ts","../src/public-service.ts"],"sourcesContent":["import type { PluginContext } from './types';\nimport type { DateRangeResolver } from './time';\n\nexport interface PluginRuntimeRequestContext {\n requestId?: string | undefined;\n organizationId?: string | undefined;\n originalOrganizationId?: string | undefined;\n userId?: string | undefined;\n user?: PluginContext['user'];\n userRole?: string | undefined;\n userRoles?: string[] | undefined;\n currentTeamId?: string | undefined;\n locale?: string | undefined;\n currency?: string | undefined;\n timezone?: string | undefined;\n clientTimeZone?: string | undefined;\n resolveDateRange?: DateRangeResolver | undefined;\n actorType?: PluginContext['actorType'] | 'api-token';\n isSystemContext?: boolean | undefined;\n principal?: PluginContext['principal'];\n invoker?: string | undefined;\n apiTokenId?: string | undefined;\n apiTokenScopes?: string[] | undefined;\n}\n\nexport interface CreatePluginRuntimeContextInput {\n pluginId: string;\n request?: unknown;\n response?: unknown;\n requestContext?: PluginRuntimeRequestContext | undefined;\n}\n\nexport interface PluginRuntimeBridge {\n createRequestContext(input: PluginRuntimeRequestContext): PluginRuntimeRequestContext;\n createContext(input: CreatePluginRuntimeContextInput): Promise<PluginContext>;\n runWithContext<T>(requestContext: PluginRuntimeRequestContext, callback: () => Promise<T> | T): Promise<T>;\n}\n\nlet runtimeBridge: PluginRuntimeBridge | undefined;\n\nexport function setPluginRuntimeBridge(bridge: PluginRuntimeBridge): void {\n runtimeBridge = bridge;\n}\n\nfunction getPluginRuntimeBridge(): PluginRuntimeBridge {\n if (!runtimeBridge) {\n throw new Error('Plugin runtime bridge is not available');\n }\n return runtimeBridge;\n}\n\nexport function createPluginRuntimeRequestContext(\n input: PluginRuntimeRequestContext,\n): PluginRuntimeRequestContext {\n return getPluginRuntimeBridge().createRequestContext(input);\n}\n\nexport function createPluginRuntimeContext(\n input: CreatePluginRuntimeContextInput,\n): Promise<PluginContext> {\n return getPluginRuntimeBridge().createContext(input);\n}\n\nexport function runWithPluginRuntimeContext<T>(\n requestContext: PluginRuntimeRequestContext,\n callback: () => Promise<T> | T,\n): Promise<T> {\n return getPluginRuntimeBridge().runWithContext(requestContext, callback);\n}\n","import crypto from 'node:crypto';\nimport type { PluginContext } from './types';\n\ntype OAuthSettingScope = {\n global?: boolean;\n};\n\ntype OAuthSettings = Pick<PluginContext, 'settings' | 'organizationId' | 'userId'>;\n\nexport type OAuthQueryValue =\n | string\n | number\n | boolean\n | null\n | undefined\n | readonly (string | number | boolean | null | undefined)[];\n\nexport type OAuthQueryParams = Record<string, OAuthQueryValue>;\n\nexport type OAuthStateRecord<TPayload extends Record<string, unknown> = Record<string, unknown>> =\n TPayload & {\n createdAt: string;\n expiresAt?: string;\n userId?: string;\n organizationId?: string;\n };\n\nexport interface CreateOAuthStateOptions<TPayload extends Record<string, unknown>> extends OAuthSettingScope {\n keyPrefix: string;\n payload: TPayload;\n bytes?: number;\n ttlSeconds?: number;\n encrypted?: boolean;\n includeContext?: boolean;\n now?: Date;\n}\n\nexport interface ConsumeOAuthStateOptions extends OAuthSettingScope {\n keyPrefix: string;\n state: string;\n deleteOnConsume?: boolean;\n now?: Date;\n}\n\nexport interface VerifyQueryHmacSha256Options {\n signatureKey?: string;\n excludeKeys?: string[];\n digest?: 'hex' | 'base64';\n}\n\nexport function buildOAuthCallbackPath(providerId: string): string {\n const normalized = providerId.trim();\n if (!/^[a-z0-9-]+$/i.test(normalized)) {\n throw new Error(`Invalid OAuth provider id: ${providerId}`);\n }\n return `/api/oauth/${normalized}/callback`;\n}\n\nexport function buildOAuthCallbackUrl(providerId: string, baseUrl: string): string {\n return new URL(buildOAuthCallbackPath(providerId), baseUrl).toString();\n}\n\nexport function buildOAuthResultRedirect(\n path: string,\n params: Record<string, string | number | boolean | null | undefined>,\n): string {\n const url = new URL(path, 'https://wordrhyme.local');\n for (const [key, value] of Object.entries(params)) {\n if (value !== null && value !== undefined) {\n url.searchParams.set(key, String(value));\n }\n }\n\n if (/^https?:\\/\\//i.test(path)) {\n return url.toString();\n }\n return `${url.pathname}${url.search}${url.hash}`;\n}\n\nexport function buildOAuthStateKey(keyPrefix: string, state: string): string {\n const prefix = keyPrefix.trim().replace(/\\.+$/, '');\n if (!prefix) throw new Error('OAuth state keyPrefix is required');\n if (!state) throw new Error('OAuth state is required');\n return `${prefix}.${state}`;\n}\n\nexport function maskOAuthSecret(value: string): string {\n if (value.length <= 8) return '********';\n return `${value.slice(0, 4)}****${value.slice(-4)}`;\n}\n\nexport async function createOAuthState<TPayload extends Record<string, unknown>>(\n ctx: OAuthSettings,\n options: CreateOAuthStateOptions<TPayload>,\n): Promise<{ state: string; key: string; payload: OAuthStateRecord<TPayload> }> {\n if (!ctx.settings) throw new Error('Settings not available');\n\n const state = crypto.randomBytes(options.bytes ?? 24).toString('hex');\n const key = buildOAuthStateKey(options.keyPrefix, state);\n const now = options.now ?? new Date();\n const payload = {\n ...options.payload,\n createdAt: now.toISOString(),\n } as OAuthStateRecord<TPayload>;\n\n if (options.ttlSeconds && options.ttlSeconds > 0) {\n payload.expiresAt = new Date(now.getTime() + options.ttlSeconds * 1000).toISOString();\n }\n\n if (options.includeContext !== false) {\n if (ctx.userId) payload.userId = ctx.userId;\n if (ctx.organizationId) payload.organizationId = ctx.organizationId;\n }\n\n await ctx.settings.set(key, payload, {\n encrypted: options.encrypted ?? true,\n ...(options.global !== undefined ? { global: options.global } : {}),\n });\n\n return { state, key, payload };\n}\n\nexport async function consumeOAuthState<TPayload extends Record<string, unknown> = Record<string, unknown>>(\n ctx: OAuthSettings,\n options: ConsumeOAuthStateOptions,\n): Promise<OAuthStateRecord<TPayload>> {\n if (!ctx.settings) throw new Error('Settings not available');\n\n const key = buildOAuthStateKey(options.keyPrefix, options.state);\n const raw = await ctx.settings.get<unknown>(key);\n const record = parseStateRecord<TPayload>(raw);\n if (!record) {\n throw new Error('Invalid or expired OAuth state');\n }\n\n const now = options.now ?? new Date();\n if (record.expiresAt && Date.parse(record.expiresAt) <= now.getTime()) {\n await ctx.settings.delete(key, scopeOptions(options)).catch(() => false);\n throw new Error('Invalid or expired OAuth state');\n }\n\n if (options.deleteOnConsume !== false) {\n await ctx.settings.delete(key, scopeOptions(options)).catch(() => false);\n }\n\n return record;\n}\n\nexport function createPkcePair(): {\n codeVerifier: string;\n codeChallenge: string;\n method: 'S256';\n} {\n const codeVerifier = base64Url(crypto.randomBytes(32));\n const codeChallenge = base64Url(crypto.createHash('sha256').update(codeVerifier).digest());\n return { codeVerifier, codeChallenge, method: 'S256' };\n}\n\nexport function buildCanonicalQueryString(\n params: OAuthQueryParams,\n excludeKeys: string[] = [],\n): string {\n const exclude = new Set(excludeKeys);\n const entries: Array<[string, string]> = [];\n\n for (const [key, value] of Object.entries(params)) {\n if (exclude.has(key)) continue;\n const values = Array.isArray(value) ? value : [value];\n for (const item of values) {\n if (item !== null && item !== undefined) {\n entries.push([key, String(item)]);\n }\n }\n }\n\n return entries\n .sort(([a], [b]) => a.localeCompare(b))\n .map(([key, value]) => `${key}=${value}`)\n .join('&');\n}\n\nexport function verifyQueryHmacSha256(\n params: OAuthQueryParams,\n secret: string,\n options: VerifyQueryHmacSha256Options = {},\n): boolean {\n if (!secret) return false;\n\n const signatureKey = options.signatureKey ?? 'hmac';\n const signature = firstQueryValue(params[signatureKey]);\n if (!signature) return false;\n\n const excludeKeys = options.excludeKeys ?? [signatureKey];\n const digest = options.digest ?? 'hex';\n const message = buildCanonicalQueryString(params, excludeKeys);\n const computed = crypto.createHmac('sha256', secret).update(message).digest(digest);\n\n return timingSafeEqualString(computed, signature);\n}\n\nexport function timingSafeEqualString(a: string, b: string): boolean {\n const left = Buffer.from(a, 'utf8');\n const right = Buffer.from(b, 'utf8');\n if (left.length !== right.length) return false;\n return crypto.timingSafeEqual(left, right);\n}\n\nfunction parseStateRecord<TPayload extends Record<string, unknown>>(\n value: unknown,\n): OAuthStateRecord<TPayload> | null {\n let parsed = value;\n if (typeof value === 'string') {\n try {\n parsed = JSON.parse(value) as unknown;\n } catch {\n return null;\n }\n }\n\n if (!parsed || typeof parsed !== 'object' || Array.isArray(parsed)) {\n return null;\n }\n\n const record = parsed as Record<string, unknown>;\n if (typeof record['createdAt'] !== 'string') {\n return null;\n }\n if ('expiresAt' in record && typeof record['expiresAt'] !== 'string') {\n return null;\n }\n\n return record as OAuthStateRecord<TPayload>;\n}\n\nfunction firstQueryValue(value: OAuthQueryValue): string | null {\n const candidate = Array.isArray(value) ? value.find((item) => item !== null && item !== undefined) : value;\n return candidate === null || candidate === undefined ? null : String(candidate);\n}\n\nfunction base64Url(input: Buffer): string {\n return input\n .toString('base64')\n .replace(/\\+/g, '-')\n .replace(/\\//g, '_')\n .replace(/=+$/g, '');\n}\n\nfunction scopeOptions(options: OAuthSettingScope): OAuthSettingScope | undefined {\n return options.global !== undefined ? { global: options.global } : undefined;\n}\n","import type { PluginContext } from \"./types\";\n\nexport interface PluginPublicServiceRequest {\n method: string;\n path: string;\n query: Record<string, string | string[]>;\n headers: Record<string, string | undefined>;\n body: unknown;\n requestId: string;\n}\n\nexport interface PluginPublicServiceResponse {\n status?: number;\n headers?: Record<string, string>;\n body?: unknown;\n}\n\nexport interface PluginPublicService {\n name: string;\n handle(request: PluginPublicServiceRequest, context: PluginContext): Promise<PluginPublicServiceResponse>;\n}\n\nexport function definePublicService(service: PluginPublicService): PluginPublicService {\n return service;\n}\n"],"mappings":"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","names":[]}
|
|
1
|
+
{"version":3,"sources":["../src/runtime.ts","../src/oauth.ts","../src/http.ts"],"sourcesContent":["import type { PluginContext } from './types';\nimport type { DateRangeResolver } from './time';\n\nexport interface PluginRuntimeRequestContext {\n requestId?: string | undefined;\n organizationId?: string | undefined;\n originalOrganizationId?: string | undefined;\n userId?: string | undefined;\n user?: PluginContext['user'];\n userRole?: string | undefined;\n userRoles?: string[] | undefined;\n currentTeamId?: string | undefined;\n locale?: string | undefined;\n currency?: string | undefined;\n timezone?: string | undefined;\n clientTimeZone?: string | undefined;\n resolveDateRange?: DateRangeResolver | undefined;\n actorType?: PluginContext['actorType'] | 'api-token';\n isSystemContext?: boolean | undefined;\n principal?: PluginContext['principal'];\n invoker?: string | undefined;\n apiTokenId?: string | undefined;\n apiTokenScopes?: string[] | undefined;\n}\n\nexport interface CreatePluginRuntimeContextInput {\n pluginId: string;\n request?: unknown;\n response?: unknown;\n requestContext?: PluginRuntimeRequestContext | undefined;\n}\n\nexport interface PluginRuntimeBridge {\n createRequestContext(input: PluginRuntimeRequestContext): PluginRuntimeRequestContext;\n createContext(input: CreatePluginRuntimeContextInput): Promise<PluginContext>;\n runWithContext<T>(requestContext: PluginRuntimeRequestContext, callback: () => Promise<T> | T): Promise<T>;\n}\n\nlet runtimeBridge: PluginRuntimeBridge | undefined;\n\nexport function setPluginRuntimeBridge(bridge: PluginRuntimeBridge): void {\n runtimeBridge = bridge;\n}\n\nfunction getPluginRuntimeBridge(): PluginRuntimeBridge {\n if (!runtimeBridge) {\n throw new Error('Plugin runtime bridge is not available');\n }\n return runtimeBridge;\n}\n\nexport function createPluginRuntimeRequestContext(\n input: PluginRuntimeRequestContext,\n): PluginRuntimeRequestContext {\n return getPluginRuntimeBridge().createRequestContext(input);\n}\n\nexport function createPluginRuntimeContext(\n input: CreatePluginRuntimeContextInput,\n): Promise<PluginContext> {\n return getPluginRuntimeBridge().createContext(input);\n}\n\nexport function runWithPluginRuntimeContext<T>(\n requestContext: PluginRuntimeRequestContext,\n callback: () => Promise<T> | T,\n): Promise<T> {\n return getPluginRuntimeBridge().runWithContext(requestContext, callback);\n}\n","import crypto from 'node:crypto';\nimport type { PluginContext } from './types';\n\ntype OAuthSettingScope = {\n global?: boolean;\n};\n\ntype OAuthSettings = Pick<PluginContext, 'settings' | 'organizationId' | 'userId'>;\n\nexport type OAuthQueryValue =\n | string\n | number\n | boolean\n | null\n | undefined\n | readonly (string | number | boolean | null | undefined)[];\n\nexport type OAuthQueryParams = Record<string, OAuthQueryValue>;\n\nexport type OAuthStateRecord<TPayload extends Record<string, unknown> = Record<string, unknown>> =\n TPayload & {\n createdAt: string;\n expiresAt?: string;\n userId?: string;\n organizationId?: string;\n };\n\nexport interface CreateOAuthStateOptions<TPayload extends Record<string, unknown>> extends OAuthSettingScope {\n keyPrefix: string;\n payload: TPayload;\n bytes?: number;\n ttlSeconds?: number;\n encrypted?: boolean;\n includeContext?: boolean;\n now?: Date;\n}\n\nexport interface ConsumeOAuthStateOptions extends OAuthSettingScope {\n keyPrefix: string;\n state: string;\n deleteOnConsume?: boolean;\n now?: Date;\n}\n\nexport interface VerifyQueryHmacSha256Options {\n signatureKey?: string;\n excludeKeys?: string[];\n digest?: 'hex' | 'base64';\n}\n\nexport function buildOAuthCallbackPath(providerId: string): string {\n const normalized = providerId.trim();\n if (!/^[a-z0-9-]+$/i.test(normalized)) {\n throw new Error(`Invalid OAuth provider id: ${providerId}`);\n }\n return `/api/oauth/${normalized}/callback`;\n}\n\nexport function buildOAuthCallbackUrl(providerId: string, baseUrl: string): string {\n return new URL(buildOAuthCallbackPath(providerId), baseUrl).toString();\n}\n\nexport function buildOAuthResultRedirect(\n path: string,\n params: Record<string, string | number | boolean | null | undefined>,\n): string {\n const url = new URL(path, 'https://wordrhyme.local');\n for (const [key, value] of Object.entries(params)) {\n if (value !== null && value !== undefined) {\n url.searchParams.set(key, String(value));\n }\n }\n\n if (/^https?:\\/\\//i.test(path)) {\n return url.toString();\n }\n return `${url.pathname}${url.search}${url.hash}`;\n}\n\nexport function buildOAuthStateKey(keyPrefix: string, state: string): string {\n const prefix = keyPrefix.trim().replace(/\\.+$/, '');\n if (!prefix) throw new Error('OAuth state keyPrefix is required');\n if (!state) throw new Error('OAuth state is required');\n return `${prefix}.${state}`;\n}\n\nexport function maskOAuthSecret(value: string): string {\n if (value.length <= 8) return '********';\n return `${value.slice(0, 4)}****${value.slice(-4)}`;\n}\n\nexport async function createOAuthState<TPayload extends Record<string, unknown>>(\n ctx: OAuthSettings,\n options: CreateOAuthStateOptions<TPayload>,\n): Promise<{ state: string; key: string; payload: OAuthStateRecord<TPayload> }> {\n if (!ctx.settings) throw new Error('Settings not available');\n\n const state = crypto.randomBytes(options.bytes ?? 24).toString('hex');\n const key = buildOAuthStateKey(options.keyPrefix, state);\n const now = options.now ?? new Date();\n const payload = {\n ...options.payload,\n createdAt: now.toISOString(),\n } as OAuthStateRecord<TPayload>;\n\n if (options.ttlSeconds && options.ttlSeconds > 0) {\n payload.expiresAt = new Date(now.getTime() + options.ttlSeconds * 1000).toISOString();\n }\n\n if (options.includeContext !== false) {\n if (ctx.userId) payload.userId = ctx.userId;\n if (ctx.organizationId) payload.organizationId = ctx.organizationId;\n }\n\n await ctx.settings.set(key, payload, {\n encrypted: options.encrypted ?? true,\n ...(options.global !== undefined ? { global: options.global } : {}),\n });\n\n return { state, key, payload };\n}\n\nexport async function consumeOAuthState<TPayload extends Record<string, unknown> = Record<string, unknown>>(\n ctx: OAuthSettings,\n options: ConsumeOAuthStateOptions,\n): Promise<OAuthStateRecord<TPayload>> {\n if (!ctx.settings) throw new Error('Settings not available');\n\n const key = buildOAuthStateKey(options.keyPrefix, options.state);\n const raw = await ctx.settings.get<unknown>(key);\n const record = parseStateRecord<TPayload>(raw);\n if (!record) {\n throw new Error('Invalid or expired OAuth state');\n }\n\n const now = options.now ?? new Date();\n if (record.expiresAt && Date.parse(record.expiresAt) <= now.getTime()) {\n await ctx.settings.delete(key, scopeOptions(options)).catch(() => false);\n throw new Error('Invalid or expired OAuth state');\n }\n\n if (options.deleteOnConsume !== false) {\n await ctx.settings.delete(key, scopeOptions(options)).catch(() => false);\n }\n\n return record;\n}\n\nexport function createPkcePair(): {\n codeVerifier: string;\n codeChallenge: string;\n method: 'S256';\n} {\n const codeVerifier = base64Url(crypto.randomBytes(32));\n const codeChallenge = base64Url(crypto.createHash('sha256').update(codeVerifier).digest());\n return { codeVerifier, codeChallenge, method: 'S256' };\n}\n\nexport function buildCanonicalQueryString(\n params: OAuthQueryParams,\n excludeKeys: string[] = [],\n): string {\n const exclude = new Set(excludeKeys);\n const entries: Array<[string, string]> = [];\n\n for (const [key, value] of Object.entries(params)) {\n if (exclude.has(key)) continue;\n const values = Array.isArray(value) ? value : [value];\n for (const item of values) {\n if (item !== null && item !== undefined) {\n entries.push([key, String(item)]);\n }\n }\n }\n\n return entries\n .sort(([a], [b]) => a.localeCompare(b))\n .map(([key, value]) => `${key}=${value}`)\n .join('&');\n}\n\nexport function verifyQueryHmacSha256(\n params: OAuthQueryParams,\n secret: string,\n options: VerifyQueryHmacSha256Options = {},\n): boolean {\n if (!secret) return false;\n\n const signatureKey = options.signatureKey ?? 'hmac';\n const signature = firstQueryValue(params[signatureKey]);\n if (!signature) return false;\n\n const excludeKeys = options.excludeKeys ?? [signatureKey];\n const digest = options.digest ?? 'hex';\n const message = buildCanonicalQueryString(params, excludeKeys);\n const computed = crypto.createHmac('sha256', secret).update(message).digest(digest);\n\n return timingSafeEqualString(computed, signature);\n}\n\nexport function timingSafeEqualString(a: string, b: string): boolean {\n const left = Buffer.from(a, 'utf8');\n const right = Buffer.from(b, 'utf8');\n if (left.length !== right.length) return false;\n return crypto.timingSafeEqual(left, right);\n}\n\nfunction parseStateRecord<TPayload extends Record<string, unknown>>(\n value: unknown,\n): OAuthStateRecord<TPayload> | null {\n let parsed = value;\n if (typeof value === 'string') {\n try {\n parsed = JSON.parse(value) as unknown;\n } catch {\n return null;\n }\n }\n\n if (!parsed || typeof parsed !== 'object' || Array.isArray(parsed)) {\n return null;\n }\n\n const record = parsed as Record<string, unknown>;\n if (typeof record['createdAt'] !== 'string') {\n return null;\n }\n if ('expiresAt' in record && typeof record['expiresAt'] !== 'string') {\n return null;\n }\n\n return record as OAuthStateRecord<TPayload>;\n}\n\nfunction firstQueryValue(value: OAuthQueryValue): string | null {\n const candidate = Array.isArray(value) ? value.find((item) => item !== null && item !== undefined) : value;\n return candidate === null || candidate === undefined ? null : String(candidate);\n}\n\nfunction base64Url(input: Buffer): string {\n return input\n .toString('base64')\n .replace(/\\+/g, '-')\n .replace(/\\//g, '_')\n .replace(/=+$/g, '');\n}\n\nfunction scopeOptions(options: OAuthSettingScope): OAuthSettingScope | undefined {\n return options.global !== undefined ? { global: options.global } : undefined;\n}\n","import type { PluginContext } from \"./types\";\n\nexport const PLUGIN_HTTP_METHODS = [\"GET\", \"POST\", \"PUT\", \"PATCH\", \"DELETE\", \"OPTIONS\", \"HEAD\"] as const;\nexport const MAX_PLUGIN_HTTP_BODY_BYTES = 100 * 1024 * 1024;\n\nexport type PluginHttpMethod = (typeof PLUGIN_HTTP_METHODS)[number];\nexport type PluginHttpAuth = \"public\" | \"session\" | \"user\";\nexport type PluginHttpScope = \"platform\" | \"tenant\";\n\nexport interface PluginHttpSchema<T> {\n parse(value: unknown): T;\n}\n\nexport interface PluginHttpRouteOptions<\n TParams = Record<string, string>,\n TQuery = Record<string, unknown>,\n TBody = unknown,\n> {\n auth?: PluginHttpAuth;\n permission?: string;\n /** API Token scope required in addition to the route's live RBAC permission. */\n apiTokenScope?: string;\n scope?: PluginHttpScope;\n installation?: PluginHttpScope;\n params?: PluginHttpSchema<TParams>;\n query?: PluginHttpSchema<TQuery>;\n body?: PluginHttpSchema<TBody>;\n rawBody?: boolean;\n maxBodyBytes?: number;\n}\n\nexport interface PluginHttpRequest<\n TParams = Record<string, string>,\n TQuery = Record<string, unknown>,\n TBody = unknown,\n> {\n method: PluginHttpMethod;\n path: string;\n params: TParams;\n query: TQuery;\n headers: Record<string, string | undefined>;\n body: TBody;\n rawBody?: Uint8Array;\n requestId: string;\n remoteAddress?: string;\n}\n\nexport interface PluginHttpResponse {\n status?: number;\n headers?: Record<string, string>;\n body?: unknown;\n}\n\nexport interface PluginHttpContext extends PluginContext {\n readonly scope: PluginHttpScope;\n runForOrganization<T>(organizationId: string, callback: (context: PluginContext) => Promise<T> | T): Promise<T>;\n}\n\nexport type PluginHttpResult = Response | PluginHttpResponse | undefined;\n\nexport type PluginHttpHandler<TParams = Record<string, string>, TQuery = Record<string, unknown>, TBody = unknown> = (\n request: PluginHttpRequest<TParams, TQuery, TBody>,\n context: PluginHttpContext,\n) => Promise<PluginHttpResult> | PluginHttpResult;\n\nexport interface PluginHttpRouteDefinition {\n readonly methods: readonly PluginHttpMethod[];\n readonly path: string;\n readonly options: Readonly<PluginHttpRouteOptions>;\n readonly handler: PluginHttpHandler;\n}\n\nexport interface PluginHttpRouteRegistrar {\n (path: string, handler: PluginHttpHandler): void;\n <TParams = Record<string, string>, TQuery = Record<string, unknown>, TBody = unknown>(\n path: string,\n options: PluginHttpRouteOptions<TParams, TQuery, TBody>,\n handler: PluginHttpHandler<TParams, TQuery, TBody>,\n ): void;\n}\n\nexport interface PluginHttpRouter {\n (handler: PluginHttpHandler): void;\n (path: string, handler: PluginHttpHandler): void;\n <TParams = Record<string, string>, TQuery = Record<string, unknown>, TBody = unknown>(\n path: string,\n options: PluginHttpRouteOptions<TParams, TQuery, TBody>,\n handler: PluginHttpHandler<TParams, TQuery, TBody>,\n ): void;\n readonly routes: readonly PluginHttpRouteDefinition[];\n readonly get: PluginHttpRouteRegistrar;\n readonly post: PluginHttpRouteRegistrar;\n readonly put: PluginHttpRouteRegistrar;\n readonly patch: PluginHttpRouteRegistrar;\n readonly delete: PluginHttpRouteRegistrar;\n readonly options: PluginHttpRouteRegistrar;\n readonly head: PluginHttpRouteRegistrar;\n}\n\nconst HTTP_ROUTER_MARKER = Symbol.for(\"wordrhyme.plugin.http-router\");\n\ntype MarkedPluginHttpRouter = PluginHttpRouter & {\n readonly [HTTP_ROUTER_MARKER]: true;\n};\n\nexport function createHttp(defaults: PluginHttpRouteOptions = {}): PluginHttpRouter {\n validateOptions(defaults);\n const routes: PluginHttpRouteDefinition[] = [];\n const routeKeys = new Set<string>();\n\n const add = (\n methods: readonly PluginHttpMethod[],\n path: string,\n options: PluginHttpRouteOptions,\n handler: PluginHttpHandler,\n ): void => {\n const normalizedPath = normalizePath(path);\n const merged = Object.freeze({\n ...defaults,\n ...options,\n auth: options.auth ?? defaults.auth ?? \"user\",\n });\n validateOptions(merged);\n assertNoRouteConflict(routeKeys, methods, normalizedPath);\n routes.push(\n Object.freeze({\n methods: Object.freeze([...methods]),\n path: normalizedPath,\n options: merged,\n handler,\n }),\n );\n };\n\n const register = ((...args: unknown[]) => {\n if (typeof args[0] === \"function\") {\n add(PLUGIN_HTTP_METHODS, \"*\", {}, args[0] as PluginHttpHandler);\n return;\n }\n registerRoute(add, PLUGIN_HTTP_METHODS, args);\n }) as MarkedPluginHttpRouter;\n\n for (const method of PLUGIN_HTTP_METHODS) {\n const name = method.toLowerCase() as Lowercase<PluginHttpMethod>;\n Object.defineProperty(register, name, {\n enumerable: true,\n value: (...args: unknown[]) => registerRoute(add, [method], args),\n });\n }\n\n Object.defineProperties(register, {\n routes: {\n enumerable: true,\n get: () => Object.freeze([...routes]),\n },\n [HTTP_ROUTER_MARKER]: {\n value: true,\n },\n });\n\n return register;\n}\n\nexport function isPluginHttpRouter(value: unknown): value is PluginHttpRouter {\n return (\n typeof value === \"function\" &&\n (value as Partial<MarkedPluginHttpRouter>)[HTTP_ROUTER_MARKER] === true &&\n Array.isArray((value as Partial<PluginHttpRouter>).routes)\n );\n}\n\nfunction registerRoute(\n add: (\n methods: readonly PluginHttpMethod[],\n path: string,\n options: PluginHttpRouteOptions,\n handler: PluginHttpHandler,\n ) => void,\n methods: readonly PluginHttpMethod[],\n args: unknown[],\n): void {\n const [path, optionsOrHandler, possibleHandler] = args;\n if (typeof path !== \"string\") {\n throw new TypeError(\"Plugin HTTP route path must be a string\");\n }\n if (typeof optionsOrHandler === \"function\") {\n add(methods, path, {}, optionsOrHandler as PluginHttpHandler);\n return;\n }\n if (!isRecord(optionsOrHandler) || typeof possibleHandler !== \"function\") {\n throw new TypeError(\"Plugin HTTP route requires a handler\");\n }\n add(methods, path, optionsOrHandler as PluginHttpRouteOptions, possibleHandler as PluginHttpHandler);\n}\n\nfunction normalizePath(path: string): string {\n if (path === \"*\") return path;\n if (!path.startsWith(\"/\")) {\n throw new TypeError(\"Plugin HTTP route path must start with /\");\n }\n if (path.length > 1 && path.endsWith(\"/\")) return path.slice(0, -1);\n return path;\n}\n\nfunction validateOptions(options: PluginHttpRouteOptions): void {\n if (!isRecord(options)) {\n throw new TypeError(\"Plugin HTTP route options must be an object\");\n }\n const allowedKeys = new Set([\n \"auth\",\n \"permission\",\n \"apiTokenScope\",\n \"scope\",\n \"installation\",\n \"params\",\n \"query\",\n \"body\",\n \"rawBody\",\n \"maxBodyBytes\",\n ]);\n const unknownKey = Object.keys(options).find((key) => !allowedKeys.has(key));\n if (unknownKey) {\n throw new TypeError(`Unknown Plugin HTTP route option: ${unknownKey}`);\n }\n if (options.auth !== undefined && ![\"public\", \"session\", \"user\"].includes(options.auth)) {\n throw new TypeError(\"Plugin HTTP auth must be public, session, or user\");\n }\n if (options.scope !== undefined && ![\"platform\", \"tenant\"].includes(options.scope)) {\n throw new TypeError(\"Plugin HTTP scope must be platform or tenant\");\n }\n if (options.installation !== undefined && ![\"platform\", \"tenant\"].includes(options.installation)) {\n throw new TypeError(\"Plugin HTTP installation must be platform or tenant\");\n }\n const effectiveScope = options.scope ?? (options.auth === \"public\" ? \"platform\" : \"tenant\");\n if (effectiveScope === \"platform\" && options.installation === \"tenant\") {\n throw new TypeError(\"Plugin HTTP platform scope cannot require a tenant installation\");\n }\n if (options.permission !== undefined && (typeof options.permission !== \"string\" || !options.permission.trim())) {\n throw new TypeError(\"Plugin HTTP permission must be a non-empty string\");\n }\n if (\n options.apiTokenScope !== undefined &&\n (typeof options.apiTokenScope !== \"string\" || !options.apiTokenScope.trim())\n ) {\n throw new TypeError(\"Plugin HTTP apiTokenScope must be a non-empty string\");\n }\n if (options.apiTokenScope !== undefined && options.permission === undefined) {\n throw new TypeError(\"Plugin HTTP apiTokenScope requires permission\");\n }\n const effectiveAuth = options.auth ?? \"user\";\n if (options.apiTokenScope !== undefined && effectiveAuth !== \"user\") {\n throw new TypeError(\"Plugin HTTP apiTokenScope requires auth: user\");\n }\n if (options.rawBody !== undefined && typeof options.rawBody !== \"boolean\") {\n throw new TypeError(\"Plugin HTTP rawBody must be a boolean\");\n }\n for (const key of [\"params\", \"query\", \"body\"] as const) {\n const schema = options[key];\n if (schema !== undefined && (!isRecord(schema) || typeof schema.parse !== \"function\")) {\n throw new TypeError(`Plugin HTTP ${key} schema must provide parse()`);\n }\n }\n if (\n options.maxBodyBytes !== undefined &&\n (!Number.isSafeInteger(options.maxBodyBytes) ||\n options.maxBodyBytes <= 0 ||\n options.maxBodyBytes > MAX_PLUGIN_HTTP_BODY_BYTES)\n ) {\n throw new TypeError(`Plugin HTTP maxBodyBytes must be a positive integer up to ${MAX_PLUGIN_HTTP_BODY_BYTES}`);\n }\n}\n\nfunction assertNoRouteConflict(routeKeys: Set<string>, methods: readonly PluginHttpMethod[], path: string): void {\n const paths = path === \"*\" ? [\"/\", \"/*\"] : [path];\n for (const method of methods) {\n for (const routePath of paths) {\n const key = `${method} ${canonicalRoutePath(routePath)}`;\n if (routeKeys.has(key)) {\n throw new TypeError(`Plugin HTTP route conflict: ${key}`);\n }\n }\n }\n for (const method of methods) {\n for (const routePath of paths) {\n routeKeys.add(`${method} ${canonicalRoutePath(routePath)}`);\n }\n }\n}\n\nfunction canonicalRoutePath(path: string): string {\n return path.replace(/:([A-Za-z0-9_]+)/g, \":\");\n}\n\nfunction isRecord(value: unknown): boolean {\n return typeof value === \"object\" && value !== null && !Array.isArray(value);\n}\n"],"mappings":"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","names":[]}
|
package/dist/trpc.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import * as _trpc_server from '@trpc/server';
|
|
2
2
|
export { inferRouterInputs, inferRouterOutputs } from '@trpc/server';
|
|
3
|
-
import { a as PluginContext } from './types-
|
|
3
|
+
import { a as PluginContext } from './types-vMRNhnTU.js';
|
|
4
4
|
import './globalization.js';
|
|
5
5
|
import 'decimal.js';
|
|
6
6
|
import './locale.js';
|