@ekairos/domain 1.22.34-beta.development.0 → 1.22.36-beta.development.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/README.md +123 -128
- package/dist/cli/bin.d.ts +9 -0
- package/dist/cli/bin.d.ts.map +1 -0
- package/dist/cli/bin.js +488 -0
- package/dist/cli/bin.js.map +1 -0
- package/dist/cli/client-runtime.d.ts +25 -0
- package/dist/cli/client-runtime.d.ts.map +1 -0
- package/dist/cli/client-runtime.js +60 -0
- package/dist/cli/client-runtime.js.map +1 -0
- package/dist/cli/config.d.ts +5 -0
- package/dist/cli/config.d.ts.map +1 -0
- package/dist/cli/config.js +44 -0
- package/dist/cli/config.js.map +1 -0
- package/dist/cli/create-app.d.ts +33 -0
- package/dist/cli/create-app.d.ts.map +1 -0
- package/dist/cli/create-app.js +1317 -0
- package/dist/cli/create-app.js.map +1 -0
- package/dist/cli/http.d.ts +28 -0
- package/dist/cli/http.d.ts.map +1 -0
- package/dist/cli/http.js +117 -0
- package/dist/cli/http.js.map +1 -0
- package/dist/cli/index.d.ts +8 -0
- package/dist/cli/index.d.ts.map +1 -0
- package/dist/cli/index.js +7 -0
- package/dist/cli/index.js.map +1 -0
- package/dist/cli/server.d.ts +3 -0
- package/dist/cli/server.d.ts.map +1 -0
- package/dist/cli/server.js +437 -0
- package/dist/cli/server.js.map +1 -0
- package/dist/cli/types.d.ts +60 -0
- package/dist/cli/types.d.ts.map +1 -0
- package/dist/cli/types.js +2 -0
- package/dist/cli/types.js.map +1 -0
- package/dist/cli/ui.d.ts +3 -0
- package/dist/cli/ui.d.ts.map +1 -0
- package/dist/cli/ui.js +136 -0
- package/dist/cli/ui.js.map +1 -0
- package/dist/index.d.ts +70 -11
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +121 -18
- package/dist/index.js.map +1 -1
- package/dist/next.d.ts +21 -21
- package/dist/next.d.ts.map +1 -1
- package/dist/next.js +212 -345
- package/dist/next.js.map +1 -1
- package/dist/polyfills/dom-events.d.ts +2 -0
- package/dist/polyfills/dom-events.d.ts.map +1 -0
- package/dist/polyfills/dom-events.js +92 -0
- package/dist/polyfills/dom-events.js.map +1 -0
- package/dist/runtime-handle.d.ts +34 -0
- package/dist/runtime-handle.d.ts.map +1 -0
- package/dist/runtime-handle.js +82 -0
- package/dist/runtime-handle.js.map +1 -0
- package/dist/runtime.d.ts +3 -2
- package/dist/runtime.d.ts.map +1 -1
- package/dist/runtime.js +72 -19
- package/dist/runtime.js.map +1 -1
- package/package.json +37 -4
package/dist/next.d.ts
CHANGED
|
@@ -1,25 +1,25 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
1
|
+
import { type RuntimeDomainSource, type RuntimeResolveOptions } from "./runtime.js";
|
|
2
|
+
type RuntimeLike = {
|
|
3
|
+
env?: Record<string, unknown>;
|
|
4
|
+
db(options?: RuntimeResolveOptions): Promise<any>;
|
|
5
|
+
meta(): {
|
|
6
|
+
domain?: RuntimeDomainSource | null;
|
|
7
|
+
schema?: unknown;
|
|
8
|
+
context?: unknown;
|
|
9
|
+
contextString?: string;
|
|
10
|
+
};
|
|
4
11
|
};
|
|
5
|
-
type
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
*/
|
|
12
|
-
bootstrapModule?: string;
|
|
12
|
+
export type CreateRuntimeRouteHandlerOptions<Env extends Record<string, unknown> = Record<string, unknown>, Runtime extends RuntimeLike = RuntimeLike> = {
|
|
13
|
+
createRuntime: (env: Env) => Runtime | Promise<Runtime>;
|
|
14
|
+
resolveEnv?: (input: {
|
|
15
|
+
req: Request;
|
|
16
|
+
body: unknown;
|
|
17
|
+
}) => Env | Promise<Env>;
|
|
13
18
|
};
|
|
14
|
-
type
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
* - No per-route/workflow imports
|
|
20
|
-
* - No "magic" root bootstrap file
|
|
21
|
-
* - Works for step runtimes because the server entry will always evaluate your bootstrap module
|
|
22
|
-
*/
|
|
23
|
-
export declare function withRuntime(nextConfigOrFn: NextConfigLike | NextConfigFnLike, opts?: WithRuntimeOptions): any;
|
|
19
|
+
export type RuntimeRouteHandlers = {
|
|
20
|
+
GET(req: Request): Promise<Response>;
|
|
21
|
+
POST(req: Request): Promise<Response>;
|
|
22
|
+
};
|
|
23
|
+
export declare function createRuntimeRouteHandler<Env extends Record<string, unknown> = Record<string, unknown>, Runtime extends RuntimeLike = RuntimeLike>(options: CreateRuntimeRouteHandlerOptions<Env, Runtime>): RuntimeRouteHandlers;
|
|
24
24
|
export {};
|
|
25
25
|
//# sourceMappingURL=next.d.ts.map
|
package/dist/next.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"next.d.ts","sourceRoot":"","sources":["../src/next.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"next.d.ts","sourceRoot":"","sources":["../src/next.ts"],"names":[],"mappings":"AAAA,OAAO,EAEL,KAAK,mBAAmB,EACxB,KAAK,qBAAqB,EAC3B,MAAM,cAAc,CAAA;AAGrB,KAAK,WAAW,GAAG;IACjB,GAAG,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;IAC7B,EAAE,CAAC,OAAO,CAAC,EAAE,qBAAqB,GAAG,OAAO,CAAC,GAAG,CAAC,CAAA;IACjD,IAAI,IAAI;QACN,MAAM,CAAC,EAAE,mBAAmB,GAAG,IAAI,CAAA;QACnC,MAAM,CAAC,EAAE,OAAO,CAAA;QAChB,OAAO,CAAC,EAAE,OAAO,CAAA;QACjB,aAAa,CAAC,EAAE,MAAM,CAAA;KACvB,CAAA;CACF,CAAA;AAED,MAAM,MAAM,gCAAgC,CAC1C,GAAG,SAAS,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAC7D,OAAO,SAAS,WAAW,GAAG,WAAW,IACvC;IACF,aAAa,EAAE,CAAC,GAAG,EAAE,GAAG,KAAK,OAAO,GAAG,OAAO,CAAC,OAAO,CAAC,CAAA;IACvD,UAAU,CAAC,EAAE,CAAC,KAAK,EAAE;QACnB,GAAG,EAAE,OAAO,CAAA;QACZ,IAAI,EAAE,OAAO,CAAA;KACd,KAAK,GAAG,GAAG,OAAO,CAAC,GAAG,CAAC,CAAA;CACzB,CAAA;AAED,MAAM,MAAM,oBAAoB,GAAG;IACjC,GAAG,CAAC,GAAG,EAAE,OAAO,GAAG,OAAO,CAAC,QAAQ,CAAC,CAAA;IACpC,IAAI,CAAC,GAAG,EAAE,OAAO,GAAG,OAAO,CAAC,QAAQ,CAAC,CAAA;CACtC,CAAA;AA+ID,wBAAgB,yBAAyB,CACvC,GAAG,SAAS,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAC7D,OAAO,SAAS,WAAW,GAAG,WAAW,EACzC,OAAO,EAAE,gCAAgC,CAAC,GAAG,EAAE,OAAO,CAAC,GAAG,oBAAoB,CA4G/E"}
|
package/dist/next.js
CHANGED
|
@@ -1,358 +1,225 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
const cwd = process.cwd();
|
|
6
|
-
const candidates = [
|
|
7
|
-
// legacy app-dir without /src
|
|
8
|
-
resolve(cwd, "app/.well-known/workflow/v1/step/route.js"),
|
|
9
|
-
resolve(cwd, "app/.well-known/workflow/v1/step/route.ts"),
|
|
10
|
-
// app-dir under /src
|
|
11
|
-
resolve(cwd, "src/app/.well-known/workflow/v1/step/route.js"),
|
|
12
|
-
resolve(cwd, "src/app/.well-known/workflow/v1/step/route.ts"),
|
|
13
|
-
];
|
|
14
|
-
const bootstrapAbs = resolve(cwd, bootstrapModule);
|
|
15
|
-
for (const routeFile of candidates) {
|
|
16
|
-
let contents;
|
|
17
|
-
try {
|
|
18
|
-
contents = readFileSync(routeFile, "utf8");
|
|
19
|
-
}
|
|
20
|
-
catch {
|
|
21
|
-
continue;
|
|
22
|
-
}
|
|
23
|
-
const routeDir = dirname(routeFile);
|
|
24
|
-
let spec = relative(routeDir, bootstrapAbs).replace(/\\/g, "/");
|
|
25
|
-
if (!spec.startsWith("."))
|
|
26
|
-
spec = `./${spec}`;
|
|
27
|
-
const importLine = `import * as __ekairosBootstrap from "${spec}";`;
|
|
28
|
-
const touchLine = `__ekairosBootstrap?.runtimeConfig?.setup?.();`;
|
|
29
|
-
const hasImport = contents.includes(importLine);
|
|
30
|
-
const hasTouch = contents.includes(touchLine);
|
|
31
|
-
if (hasImport && hasTouch)
|
|
32
|
-
continue;
|
|
33
|
-
const lines = contents.split(/\r?\n/);
|
|
34
|
-
// Insert the import above the first real statement (skip comments/empty lines).
|
|
35
|
-
let insertAt = 0;
|
|
36
|
-
for (let i = 0; i < lines.length; i++) {
|
|
37
|
-
const t = lines[i].trim();
|
|
38
|
-
const isComment = t.startsWith("//") ||
|
|
39
|
-
t.startsWith("/*") ||
|
|
40
|
-
t.startsWith("*") ||
|
|
41
|
-
t.startsWith("*/");
|
|
42
|
-
if (t === "" || isComment)
|
|
43
|
-
continue;
|
|
44
|
-
insertAt = i;
|
|
45
|
-
break;
|
|
46
|
-
}
|
|
47
|
-
if (!hasImport) {
|
|
48
|
-
lines.splice(insertAt, 0, importLine);
|
|
49
|
-
}
|
|
50
|
-
if (!hasTouch) {
|
|
51
|
-
let lastImport = -1;
|
|
52
|
-
for (let i = 0; i < lines.length; i++) {
|
|
53
|
-
if (lines[i].trim().startsWith("import "))
|
|
54
|
-
lastImport = i;
|
|
55
|
-
}
|
|
56
|
-
const touchAt = lastImport >= 0 ? lastImport + 1 : insertAt + 1;
|
|
57
|
-
lines.splice(touchAt, 0, touchLine);
|
|
58
|
-
}
|
|
59
|
-
writeFileSync(routeFile, lines.join("\n"));
|
|
60
|
-
}
|
|
1
|
+
import { executeRuntimeAction, } from "./runtime.js";
|
|
2
|
+
import { getDomainActionBinding, getDomainActions } from "./index.js";
|
|
3
|
+
function json(data, init) {
|
|
4
|
+
return Response.json(data, init);
|
|
61
5
|
}
|
|
62
|
-
function
|
|
63
|
-
|
|
64
|
-
if (existsSync(srcAppDir))
|
|
65
|
-
return srcAppDir;
|
|
66
|
-
const appDir = resolve(cwd, "app");
|
|
67
|
-
if (existsSync(appDir))
|
|
68
|
-
return appDir;
|
|
69
|
-
const srcDir = resolve(cwd, "src");
|
|
70
|
-
if (existsSync(srcDir))
|
|
71
|
-
return resolve(srcDir, "app");
|
|
72
|
-
return appDir;
|
|
6
|
+
function asRecord(value) {
|
|
7
|
+
return value && typeof value === "object" ? value : {};
|
|
73
8
|
}
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
const appDir = resolveAppDir(cwd);
|
|
79
|
-
const routeDir = resolve(appDir, ".well-known/ekairos/v1/domain");
|
|
80
|
-
const routeTs = resolve(routeDir, "route.ts");
|
|
81
|
-
const routeJs = resolve(routeDir, "route.js");
|
|
82
|
-
if (existsSync(routeTs))
|
|
83
|
-
rmSync(routeTs, { force: true });
|
|
84
|
-
if (existsSync(routeJs))
|
|
85
|
-
rmSync(routeJs, { force: true });
|
|
86
|
-
const ext = existsSync(resolve(cwd, "tsconfig.json")) ? "ts" : "js";
|
|
87
|
-
const routeFile = resolve(routeDir, `route.${ext}`);
|
|
88
|
-
const bootstrapAbs = resolve(cwd, bootstrapModule);
|
|
89
|
-
let spec = relative(routeDir, bootstrapAbs).replace(/\\/g, "/");
|
|
90
|
-
if (!spec.startsWith("."))
|
|
91
|
-
spec = `./${spec}`;
|
|
92
|
-
mkdirSync(routeDir, { recursive: true });
|
|
93
|
-
const contents = [
|
|
94
|
-
`// ${domainRouteMarker}`,
|
|
95
|
-
`import * as __ekairosBootstrap from "${spec}"`,
|
|
96
|
-
`__ekairosBootstrap?.runtimeConfig?.setup?.()`,
|
|
97
|
-
`import { NextResponse } from "next/server"`,
|
|
98
|
-
`import { getRuntimeConfig, resolveRuntime } from "@ekairos/domain/runtime"`,
|
|
99
|
-
`import { verifyOidcToken } from "@ekairos/events/oidc"`,
|
|
100
|
-
``,
|
|
101
|
-
`function listKeys(value) {`,
|
|
102
|
-
` return value ? Object.keys(value) : []`,
|
|
103
|
-
`}`,
|
|
104
|
-
``,
|
|
105
|
-
`function resolveSource(config) {`,
|
|
106
|
-
` return config?.domain ?? null`,
|
|
107
|
-
`}`,
|
|
108
|
-
``,
|
|
109
|
-
`function buildSchema(source) {`,
|
|
110
|
-
` if (!source) return null`,
|
|
111
|
-
` if (typeof source.toInstantSchema === "function") return source.toInstantSchema()`,
|
|
112
|
-
` if (typeof source.schema === "function") return source.schema()`,
|
|
113
|
-
` return {`,
|
|
114
|
-
` entities: source.entities ?? {},`,
|
|
115
|
-
` links: source.links ?? {},`,
|
|
116
|
-
` rooms: source.rooms ?? {},`,
|
|
117
|
-
` }`,
|
|
118
|
-
`}`,
|
|
119
|
-
``,
|
|
120
|
-
`function buildSummary(config, source) {`,
|
|
121
|
-
` return {`,
|
|
122
|
-
` available: Boolean(source),`,
|
|
123
|
-
` entities: listKeys(source?.entities),`,
|
|
124
|
-
` links: listKeys(source?.links),`,
|
|
125
|
-
` rooms: listKeys(source?.rooms),`,
|
|
126
|
-
` meta: config?.meta ?? {},`,
|
|
127
|
-
` }`,
|
|
128
|
-
`}`,
|
|
129
|
-
``,
|
|
130
|
-
`function buildContext(config, source) {`,
|
|
131
|
-
` if (!source || typeof source.context !== "function") return null`,
|
|
132
|
-
` return source.context({`,
|
|
133
|
-
` meta: config?.meta,`,
|
|
134
|
-
` })`,
|
|
135
|
-
`}`,
|
|
136
|
-
``,
|
|
137
|
-
`function buildContextString(config, source) {`,
|
|
138
|
-
` if (!source || typeof source.contextString !== "function") return null`,
|
|
139
|
-
` return source.contextString({`,
|
|
140
|
-
` meta: config?.meta,`,
|
|
141
|
-
` })`,
|
|
142
|
-
`}`,
|
|
143
|
-
``,
|
|
144
|
-
`const DEFAULT_OIDC_JWKS = "https://oidc.vercel.com/.well-known/jwks.json"`,
|
|
145
|
-
`const DEFAULT_OIDC_ISSUER = "https://oidc.vercel.com"`,
|
|
146
|
-
``,
|
|
147
|
-
`function parseOptionalBoolean(value) {`,
|
|
148
|
-
` const normalized = String(value ?? "").trim().toLowerCase()`,
|
|
149
|
-
` if (!normalized) return undefined`,
|
|
150
|
-
` if (["1", "true", "yes", "y", "on"].includes(normalized)) return true`,
|
|
151
|
-
` if (["0", "false", "no", "n", "off"].includes(normalized)) return false`,
|
|
152
|
-
` return undefined`,
|
|
153
|
-
`}`,
|
|
154
|
-
``,
|
|
155
|
-
`function resolveBearerToken(req) {`,
|
|
156
|
-
` const header = req.headers.get("authorization") || ""`,
|
|
157
|
-
` if (!header.startsWith("Bearer ")) return null`,
|
|
158
|
-
` return header.slice("Bearer ".length).trim()`,
|
|
159
|
-
`}`,
|
|
160
|
-
``,
|
|
161
|
-
`function resolveOidcJwksUrl() {`,
|
|
162
|
-
` return String(process.env.EKAIROS_DOMAIN_JWKS_URL ?? "").trim() || DEFAULT_OIDC_JWKS`,
|
|
163
|
-
`}`,
|
|
164
|
-
``,
|
|
165
|
-
`function resolveOidcIssuer() {`,
|
|
166
|
-
` return String(process.env.EKAIROS_DOMAIN_ISSUER ?? "").trim() || DEFAULT_OIDC_ISSUER`,
|
|
167
|
-
`}`,
|
|
168
|
-
``,
|
|
169
|
-
`function resolveOidcAudience() {`,
|
|
170
|
-
` const explicit = String(process.env.EKAIROS_DOMAIN_AUDIENCE ?? "").trim()`,
|
|
171
|
-
` return explicit || null`,
|
|
172
|
-
`}`,
|
|
173
|
-
``,
|
|
174
|
-
`function isAuthRequired() {`,
|
|
175
|
-
` const explicit = parseOptionalBoolean(process.env.EKAIROS_DOMAIN_AUTH_REQUIRED)`,
|
|
176
|
-
` if (explicit !== undefined) return explicit`,
|
|
177
|
-
` return Boolean(`,
|
|
178
|
-
` process.env.EKAIROS_DOMAIN_TOKEN ||`,
|
|
179
|
-
` process.env.EKAIROS_DOMAIN_JWKS_URL ||`,
|
|
180
|
-
` process.env.EKAIROS_DOMAIN_ISSUER ||`,
|
|
181
|
-
` process.env.EKAIROS_DOMAIN_AUDIENCE`,
|
|
182
|
-
` )`,
|
|
183
|
-
`}`,
|
|
184
|
-
``,
|
|
185
|
-
`async function isAuthorized(req) {`,
|
|
186
|
-
` if (!isAuthRequired()) return true`,
|
|
187
|
-
` const token = resolveBearerToken(req)`,
|
|
188
|
-
` if (!token) return false`,
|
|
189
|
-
` const staticToken = process.env.EKAIROS_DOMAIN_TOKEN`,
|
|
190
|
-
` if (staticToken && token === staticToken) return true`,
|
|
191
|
-
` try {`,
|
|
192
|
-
` return await verifyOidcToken(token, {`,
|
|
193
|
-
` jwksUrl: resolveOidcJwksUrl(),`,
|
|
194
|
-
` issuer: resolveOidcIssuer(),`,
|
|
195
|
-
` audience: resolveOidcAudience(),`,
|
|
196
|
-
` })`,
|
|
197
|
-
` } catch {`,
|
|
198
|
-
` return false`,
|
|
199
|
-
` }`,
|
|
200
|
-
`}`,
|
|
201
|
-
``,
|
|
202
|
-
`export async function GET(req) {`,
|
|
203
|
-
` if (!(await isAuthorized(req))) {`,
|
|
204
|
-
` return new NextResponse("Unauthorized", { status: 401 })`,
|
|
205
|
-
` }`,
|
|
206
|
-
` const config = getRuntimeConfig()`,
|
|
207
|
-
` const source = resolveSource(config)`,
|
|
208
|
-
` const context = buildContext(config, source)`,
|
|
209
|
-
` const schema = context?.schema ?? buildSchema(source)`,
|
|
210
|
-
` const contextString = buildContextString(config, source)`,
|
|
211
|
-
` return NextResponse.json({`,
|
|
212
|
-
` mode: "full",`,
|
|
213
|
-
` domain: context ?? buildSummary(config, source),`,
|
|
214
|
-
` schema,`,
|
|
215
|
-
` contextString,`,
|
|
216
|
-
` })`,
|
|
217
|
-
`}`,
|
|
218
|
-
``,
|
|
219
|
-
`function truncateQueryResult(result) {`,
|
|
220
|
-
` const MAX_QUERY_ROWS = 50`,
|
|
221
|
-
` const output = {}`,
|
|
222
|
-
` const truncation = {}`,
|
|
223
|
-
``,
|
|
224
|
-
` for (const [key, value] of Object.entries(result ?? {})) {`,
|
|
225
|
-
` if (Array.isArray(value)) {`,
|
|
226
|
-
` const total = value.length`,
|
|
227
|
-
` const returned = Math.min(total, MAX_QUERY_ROWS)`,
|
|
228
|
-
` output[key] = value.slice(0, returned)`,
|
|
229
|
-
` if (total > returned) {`,
|
|
230
|
-
` truncation[key] = { returned, total }`,
|
|
231
|
-
` }`,
|
|
232
|
-
` continue`,
|
|
233
|
-
` }`,
|
|
234
|
-
` output[key] = value`,
|
|
235
|
-
` }`,
|
|
236
|
-
``,
|
|
237
|
-
` return {`,
|
|
238
|
-
` data: output,`,
|
|
239
|
-
` truncated: Object.keys(truncation).length > 0 ? truncation : null,`,
|
|
240
|
-
` }`,
|
|
241
|
-
`}`,
|
|
242
|
-
``,
|
|
243
|
-
`export async function POST(req) {`,
|
|
244
|
-
` if (!(await isAuthorized(req))) {`,
|
|
245
|
-
` return new NextResponse("Unauthorized", { status: 401 })`,
|
|
246
|
-
` }`,
|
|
247
|
-
` let body = null`,
|
|
248
|
-
` try {`,
|
|
249
|
-
` body = await req.json()`,
|
|
250
|
-
` } catch {`,
|
|
251
|
-
` body = null`,
|
|
252
|
-
` }`,
|
|
253
|
-
``,
|
|
254
|
-
` const orgId = String(body?.orgId ?? "").trim()`,
|
|
255
|
-
` const query = body?.query ?? null`,
|
|
256
|
-
``,
|
|
257
|
-
` if (!orgId || !query) {`,
|
|
258
|
-
` return new NextResponse("Missing orgId or query", { status: 400 })`,
|
|
259
|
-
` }`,
|
|
260
|
-
``,
|
|
261
|
-
` const config = getRuntimeConfig()`,
|
|
262
|
-
` const source = resolveSource(config)`,
|
|
263
|
-
` if (!source) {`,
|
|
264
|
-
` return new NextResponse("Runtime domain not configured", { status: 500 })`,
|
|
265
|
-
` }`,
|
|
266
|
-
` const runtime = await resolveRuntime(source, { orgId })`,
|
|
267
|
-
` const result = await runtime.db.query(query)`,
|
|
268
|
-
` return NextResponse.json({`,
|
|
269
|
-
` ok: true,`,
|
|
270
|
-
` ...truncateQueryResult(result),`,
|
|
271
|
-
` })`,
|
|
272
|
-
`}`,
|
|
273
|
-
``,
|
|
274
|
-
].join("\n");
|
|
275
|
-
writeFileSync(routeFile, contents);
|
|
276
|
-
generatedDomainRoutes.add(routeFile);
|
|
9
|
+
function listKeys(value) {
|
|
10
|
+
if (!value || typeof value !== "object")
|
|
11
|
+
return [];
|
|
12
|
+
return Object.keys(value);
|
|
277
13
|
}
|
|
278
|
-
function
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
14
|
+
async function readBody(req) {
|
|
15
|
+
try {
|
|
16
|
+
return await req.json();
|
|
17
|
+
}
|
|
18
|
+
catch {
|
|
19
|
+
return null;
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
function serializeActionInputSchema(value) {
|
|
23
|
+
if (value === undefined)
|
|
24
|
+
return undefined;
|
|
25
|
+
try {
|
|
26
|
+
return JSON.parse(JSON.stringify(value));
|
|
27
|
+
}
|
|
28
|
+
catch {
|
|
29
|
+
return undefined;
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
function resolveActionKey(domain, action) {
|
|
33
|
+
const binding = getDomainActionBinding(action);
|
|
34
|
+
if (typeof binding?.key === "string" && binding.key.trim()) {
|
|
35
|
+
return binding.key.trim();
|
|
36
|
+
}
|
|
37
|
+
if (!domain || typeof domain.getActions !== "function") {
|
|
38
|
+
return undefined;
|
|
39
|
+
}
|
|
40
|
+
const actionName = String(action?.name ?? "").trim();
|
|
41
|
+
const actions = domain.getActions();
|
|
42
|
+
for (const candidate of actions) {
|
|
43
|
+
if (String(candidate?.name ?? "").trim() !== actionName)
|
|
297
44
|
continue;
|
|
298
|
-
|
|
299
|
-
if (typeof
|
|
300
|
-
|
|
301
|
-
entries[key] = [bootstrap, entry];
|
|
45
|
+
const candidateBinding = getDomainActionBinding(candidate);
|
|
46
|
+
if (typeof candidateBinding?.key === "string" && candidateBinding.key.trim()) {
|
|
47
|
+
return candidateBinding.key.trim();
|
|
302
48
|
}
|
|
303
49
|
}
|
|
50
|
+
return undefined;
|
|
51
|
+
}
|
|
52
|
+
function listRuntimeActions(domain) {
|
|
53
|
+
return getDomainActions(domain).map((action) => ({
|
|
54
|
+
name: String(action.name ?? "").trim(),
|
|
55
|
+
key: resolveActionKey(domain, action),
|
|
56
|
+
description: typeof action.description === "string" ? action.description : null,
|
|
57
|
+
inputSchema: serializeActionInputSchema(action.inputSchema),
|
|
58
|
+
}));
|
|
304
59
|
}
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
60
|
+
function findRuntimeAction(domain, name) {
|
|
61
|
+
const normalized = String(name ?? "").trim();
|
|
62
|
+
if (!normalized)
|
|
63
|
+
return null;
|
|
64
|
+
return (getDomainActions(domain).find((action) => {
|
|
65
|
+
if (String(action.name ?? "").trim() === normalized)
|
|
66
|
+
return true;
|
|
67
|
+
const key = resolveActionKey(domain, action);
|
|
68
|
+
return typeof key === "string" && key === normalized;
|
|
69
|
+
}) ?? null);
|
|
70
|
+
}
|
|
71
|
+
function buildDomainSummary(domain) {
|
|
72
|
+
if (!domain) {
|
|
318
73
|
return {
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
// - But for Turbopack builds, this hook may never run, so we ALSO patch
|
|
325
|
-
// in the config-function wrapper below (after withWorkflow generates the file).
|
|
326
|
-
patchWorkflowStepRouteToImportBootstrap(bootstrapModule);
|
|
327
|
-
ensureDomainRouteFile(bootstrapModule);
|
|
328
|
-
if (!options?.isServer)
|
|
329
|
-
return out;
|
|
330
|
-
const req = createRequire(import.meta.url);
|
|
331
|
-
const contextDir = (out && out.context) || process.cwd();
|
|
332
|
-
// Resolve relative to the app project (webpack context), not to this package.
|
|
333
|
-
const resolvedBootstrap = req.resolve(bootstrapModule, { paths: [contextDir] });
|
|
334
|
-
const originalEntry = out.entry;
|
|
335
|
-
out.entry = async () => {
|
|
336
|
-
const entries = typeof originalEntry === "function" ? await originalEntry() : originalEntry;
|
|
337
|
-
injectBootstrapIntoEntries(entries, resolvedBootstrap);
|
|
338
|
-
return entries;
|
|
339
|
-
};
|
|
340
|
-
return out;
|
|
341
|
-
},
|
|
74
|
+
available: false,
|
|
75
|
+
entities: [],
|
|
76
|
+
links: [],
|
|
77
|
+
rooms: [],
|
|
78
|
+
meta: {},
|
|
342
79
|
};
|
|
80
|
+
}
|
|
81
|
+
if (typeof domain.context === "function") {
|
|
82
|
+
return domain.context();
|
|
83
|
+
}
|
|
84
|
+
return {
|
|
85
|
+
available: true,
|
|
86
|
+
entities: listKeys(domain.entities),
|
|
87
|
+
links: listKeys(domain.links),
|
|
88
|
+
rooms: listKeys(domain.rooms),
|
|
89
|
+
meta: domain.meta ?? {},
|
|
343
90
|
};
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
if (
|
|
348
|
-
return
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
91
|
+
}
|
|
92
|
+
function resolveBearerToken(req) {
|
|
93
|
+
const header = req.headers.get("authorization") || "";
|
|
94
|
+
if (!header.startsWith("Bearer "))
|
|
95
|
+
return null;
|
|
96
|
+
return header.slice("Bearer ".length).trim();
|
|
97
|
+
}
|
|
98
|
+
function resolveImpersonatedDb(db, req, body) {
|
|
99
|
+
if (typeof db?.asUser !== "function")
|
|
100
|
+
return db;
|
|
101
|
+
const token = resolveBearerToken(req);
|
|
102
|
+
if (token)
|
|
103
|
+
return db.asUser({ token });
|
|
104
|
+
const asEmail = String(body?.asEmail ?? "").trim();
|
|
105
|
+
if (asEmail)
|
|
106
|
+
return db.asUser({ email: asEmail });
|
|
107
|
+
if (Boolean(body?.asGuest))
|
|
108
|
+
return db.asUser({ guest: true });
|
|
109
|
+
return db;
|
|
110
|
+
}
|
|
111
|
+
function truncateQueryResult(result) {
|
|
112
|
+
const MAX_QUERY_ROWS = 50;
|
|
113
|
+
const output = {};
|
|
114
|
+
const truncation = {};
|
|
115
|
+
for (const [key, value] of Object.entries(result ?? {})) {
|
|
116
|
+
if (Array.isArray(value)) {
|
|
117
|
+
const total = value.length;
|
|
118
|
+
const returned = Math.min(total, MAX_QUERY_ROWS);
|
|
119
|
+
output[key] = value.slice(0, returned);
|
|
120
|
+
if (total > returned)
|
|
121
|
+
truncation[key] = { returned, total };
|
|
122
|
+
continue;
|
|
123
|
+
}
|
|
124
|
+
output[key] = value;
|
|
125
|
+
}
|
|
126
|
+
return {
|
|
127
|
+
data: output,
|
|
128
|
+
truncated: Object.keys(truncation).length > 0 ? truncation : null,
|
|
129
|
+
};
|
|
130
|
+
}
|
|
131
|
+
export function createRuntimeRouteHandler(options) {
|
|
132
|
+
async function createRuntimeFor(req, body) {
|
|
133
|
+
const env = options.resolveEnv
|
|
134
|
+
? await options.resolveEnv({ req, body })
|
|
135
|
+
: asRecord(body?.env);
|
|
136
|
+
return await options.createRuntime(env);
|
|
354
137
|
}
|
|
355
|
-
|
|
356
|
-
|
|
138
|
+
return {
|
|
139
|
+
async GET(req) {
|
|
140
|
+
const runtime = await createRuntimeFor(req, null);
|
|
141
|
+
const meta = runtime.meta();
|
|
142
|
+
const domain = (meta.domain ?? null);
|
|
143
|
+
return json({
|
|
144
|
+
ok: true,
|
|
145
|
+
mode: "full",
|
|
146
|
+
instant: {
|
|
147
|
+
appId: String(runtime.env?.appId ?? process.env.NEXT_PUBLIC_INSTANT_APP_ID ?? "") || null,
|
|
148
|
+
apiURI: String(process.env.EKAIROS_DOMAIN_API_URI ?? process.env.INSTANT_API_URI ?? "https://api.instantdb.com"),
|
|
149
|
+
projectId: String(process.env.EKAIROS_PROJECT_ID ?? "") || null,
|
|
150
|
+
},
|
|
151
|
+
auth: {
|
|
152
|
+
required: false,
|
|
153
|
+
supportsRefreshToken: true,
|
|
154
|
+
supportsBearerToken: true,
|
|
155
|
+
},
|
|
156
|
+
domain: buildDomainSummary(domain),
|
|
157
|
+
schema: meta.schema,
|
|
158
|
+
contextString: meta.contextString ?? (typeof domain?.contextString === "function" ? domain.contextString() : null),
|
|
159
|
+
actions: listRuntimeActions(domain),
|
|
160
|
+
});
|
|
161
|
+
},
|
|
162
|
+
async POST(req) {
|
|
163
|
+
const body = await readBody(req);
|
|
164
|
+
const runtime = await createRuntimeFor(req, body);
|
|
165
|
+
const meta = runtime.meta();
|
|
166
|
+
const domain = (meta.domain ?? null);
|
|
167
|
+
const op = String(body?.op ?? (body?.action ? "action" : "query")).trim();
|
|
168
|
+
const db = resolveImpersonatedDb(await runtime.db(), req, body);
|
|
169
|
+
if (op === "action") {
|
|
170
|
+
const actionName = String(body?.action ?? "");
|
|
171
|
+
const action = findRuntimeAction(domain, actionName);
|
|
172
|
+
if (!action) {
|
|
173
|
+
return json({
|
|
174
|
+
ok: false,
|
|
175
|
+
error: `runtime_action_not_found:${actionName}`,
|
|
176
|
+
}, { status: 404 });
|
|
177
|
+
}
|
|
178
|
+
try {
|
|
179
|
+
const output = await executeRuntimeAction({
|
|
180
|
+
action: action,
|
|
181
|
+
runtime: {
|
|
182
|
+
...runtime,
|
|
183
|
+
async db() {
|
|
184
|
+
return db;
|
|
185
|
+
},
|
|
186
|
+
},
|
|
187
|
+
input: body?.input ?? {},
|
|
188
|
+
});
|
|
189
|
+
return json({
|
|
190
|
+
ok: true,
|
|
191
|
+
action: action.name,
|
|
192
|
+
output,
|
|
193
|
+
source: "runtime-route",
|
|
194
|
+
});
|
|
195
|
+
}
|
|
196
|
+
catch (error) {
|
|
197
|
+
return json({
|
|
198
|
+
ok: false,
|
|
199
|
+
error: error instanceof Error ? error.message : String(error),
|
|
200
|
+
source: "runtime-route",
|
|
201
|
+
}, { status: 500 });
|
|
202
|
+
}
|
|
203
|
+
}
|
|
204
|
+
const query = body?.query ?? null;
|
|
205
|
+
if (!query)
|
|
206
|
+
return new Response("Missing query", { status: 400 });
|
|
207
|
+
try {
|
|
208
|
+
const result = await db.query(query);
|
|
209
|
+
return json({
|
|
210
|
+
ok: true,
|
|
211
|
+
source: "runtime-route",
|
|
212
|
+
...truncateQueryResult(asRecord(result)),
|
|
213
|
+
});
|
|
214
|
+
}
|
|
215
|
+
catch (error) {
|
|
216
|
+
return json({
|
|
217
|
+
ok: false,
|
|
218
|
+
error: error instanceof Error ? error.message : String(error),
|
|
219
|
+
source: "runtime-route",
|
|
220
|
+
}, { status: 500 });
|
|
221
|
+
}
|
|
222
|
+
},
|
|
223
|
+
};
|
|
357
224
|
}
|
|
358
225
|
//# sourceMappingURL=next.js.map
|