@objectstack/sveltekit 3.2.7 → 3.2.9
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.turbo/turbo-build.log +10 -10
- package/CHANGELOG.md +19 -0
- package/dist/index.d.mts +3 -0
- package/dist/index.d.ts +3 -0
- package/dist/index.js +23 -46
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +23 -46
- package/dist/index.mjs.map +1 -1
- package/package.json +6 -6
- package/src/index.ts +21 -40
- package/src/sveltekit.test.ts +21 -17
package/.turbo/turbo-build.log
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
|
|
2
|
-
> @objectstack/sveltekit@3.2.
|
|
2
|
+
> @objectstack/sveltekit@3.2.9 build /home/runner/work/spec/spec/packages/adapters/sveltekit
|
|
3
3
|
> tsup --config ../../../tsup.config.ts
|
|
4
4
|
|
|
5
5
|
[34mCLI[39m Building entry: src/index.ts
|
|
@@ -10,13 +10,13 @@
|
|
|
10
10
|
[34mCLI[39m Cleaning output folder
|
|
11
11
|
[34mESM[39m Build start
|
|
12
12
|
[34mCJS[39m Build start
|
|
13
|
-
[32mESM[39m [1mdist/index.mjs [22m[
|
|
14
|
-
[32mESM[39m [1mdist/index.mjs.map [22m[
|
|
15
|
-
[32mESM[39m ⚡️ Build success in
|
|
16
|
-
[32mCJS[39m [1mdist/index.js [22m[
|
|
17
|
-
[32mCJS[39m [1mdist/index.js.map [22m[
|
|
18
|
-
[32mCJS[39m ⚡️ Build success in
|
|
13
|
+
[32mESM[39m [1mdist/index.mjs [22m[32m4.50 KB[39m
|
|
14
|
+
[32mESM[39m [1mdist/index.mjs.map [22m[32m10.35 KB[39m
|
|
15
|
+
[32mESM[39m ⚡️ Build success in 40ms
|
|
16
|
+
[32mCJS[39m [1mdist/index.js [22m[32m5.56 KB[39m
|
|
17
|
+
[32mCJS[39m [1mdist/index.js.map [22m[32m10.39 KB[39m
|
|
18
|
+
[32mCJS[39m ⚡️ Build success in 40ms
|
|
19
19
|
[34mDTS[39m Build start
|
|
20
|
-
[32mDTS[39m ⚡️ Build success in
|
|
21
|
-
[32mDTS[39m [1mdist/index.d.mts [22m[32m1.
|
|
22
|
-
[32mDTS[39m [1mdist/index.d.ts [22m[32m1.
|
|
20
|
+
[32mDTS[39m ⚡️ Build success in 12131ms
|
|
21
|
+
[32mDTS[39m [1mdist/index.d.mts [22m[32m1.65 KB[39m
|
|
22
|
+
[32mDTS[39m [1mdist/index.d.ts [22m[32m1.65 KB[39m
|
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,24 @@
|
|
|
1
1
|
# @objectstack/sveltekit
|
|
2
2
|
|
|
3
|
+
## 3.2.9
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- @objectstack/runtime@3.2.9
|
|
8
|
+
|
|
9
|
+
## 3.2.8
|
|
10
|
+
|
|
11
|
+
### Patch Changes
|
|
12
|
+
|
|
13
|
+
- @objectstack/runtime@3.2.8
|
|
14
|
+
|
|
15
|
+
## 3.2.8
|
|
16
|
+
|
|
17
|
+
### Patch Changes
|
|
18
|
+
|
|
19
|
+
- fix: unified catch-all dispatch pattern — `createRequestHandler()` now delegates all non-framework-specific routes to `HttpDispatcher.dispatch()`, automatically supporting packages, analytics, automation, i18n, ui, openapi, custom endpoints, and any future routes
|
|
20
|
+
- Only auth (service check), storage (formData), GraphQL (raw result), and discovery (response wrapper) remain as explicit routes
|
|
21
|
+
|
|
3
22
|
## 3.2.7
|
|
4
23
|
|
|
5
24
|
### Patch Changes
|
package/dist/index.d.mts
CHANGED
|
@@ -16,6 +16,9 @@ interface RequestEvent {
|
|
|
16
16
|
* Creates a SvelteKit request handler for ObjectStack API routes.
|
|
17
17
|
* Use in a catch-all `+server.ts` route like `src/routes/api/[...path]/+server.ts`.
|
|
18
18
|
*
|
|
19
|
+
* Only auth, GraphQL, storage, and discovery need explicit handling.
|
|
20
|
+
* All other routes delegate to `HttpDispatcher.dispatch()` automatically.
|
|
21
|
+
*
|
|
19
22
|
* @example
|
|
20
23
|
* ```ts
|
|
21
24
|
* // src/routes/api/[...path]/+server.ts
|
package/dist/index.d.ts
CHANGED
|
@@ -16,6 +16,9 @@ interface RequestEvent {
|
|
|
16
16
|
* Creates a SvelteKit request handler for ObjectStack API routes.
|
|
17
17
|
* Use in a catch-all `+server.ts` route like `src/routes/api/[...path]/+server.ts`.
|
|
18
18
|
*
|
|
19
|
+
* Only auth, GraphQL, storage, and discovery need explicit handling.
|
|
20
|
+
* All other routes delegate to `HttpDispatcher.dispatch()` automatically.
|
|
21
|
+
*
|
|
19
22
|
* @example
|
|
20
23
|
* ```ts
|
|
21
24
|
* // src/routes/api/[...path]/+server.ts
|
package/dist/index.js
CHANGED
|
@@ -82,7 +82,7 @@ function createRequestHandler(options) {
|
|
|
82
82
|
}
|
|
83
83
|
try {
|
|
84
84
|
if (segments[0] === "auth") {
|
|
85
|
-
const
|
|
85
|
+
const subPath2 = segments.slice(1).join("/");
|
|
86
86
|
let authService = null;
|
|
87
87
|
try {
|
|
88
88
|
if (typeof options.kernel.getServiceAsync === "function") {
|
|
@@ -96,67 +96,44 @@ function createRequestHandler(options) {
|
|
|
96
96
|
if (authService && typeof authService.handleRequest === "function") {
|
|
97
97
|
return await authService.handleRequest(request);
|
|
98
98
|
}
|
|
99
|
-
const
|
|
100
|
-
const
|
|
101
|
-
return toResponse(
|
|
99
|
+
const body2 = method === "GET" || method === "HEAD" ? {} : await request.json().catch(() => ({}));
|
|
100
|
+
const result2 = await dispatcher.handleAuth(subPath2, method, body2, { request });
|
|
101
|
+
return toResponse(result2);
|
|
102
102
|
}
|
|
103
103
|
if (segments[0] === "graphql" && method === "POST") {
|
|
104
|
-
const
|
|
105
|
-
const
|
|
106
|
-
return new Response(JSON.stringify(
|
|
104
|
+
const body2 = await request.json();
|
|
105
|
+
const result2 = await dispatcher.handleGraphQL(body2, { request });
|
|
106
|
+
return new Response(JSON.stringify(result2), {
|
|
107
107
|
status: 200,
|
|
108
108
|
headers: { "Content-Type": "application/json" }
|
|
109
109
|
});
|
|
110
110
|
}
|
|
111
|
-
if (segments[0] === "meta") {
|
|
112
|
-
const subPath = segments.slice(1).join("/");
|
|
113
|
-
let body = void 0;
|
|
114
|
-
if (method === "PUT" || method === "POST") {
|
|
115
|
-
body = await request.json().catch(() => ({}));
|
|
116
|
-
}
|
|
117
|
-
const result = await dispatcher.handleMetadata(
|
|
118
|
-
subPath ? `/${subPath}` : "",
|
|
119
|
-
{ request },
|
|
120
|
-
method,
|
|
121
|
-
body
|
|
122
|
-
);
|
|
123
|
-
return toResponse(result);
|
|
124
|
-
}
|
|
125
|
-
if (segments[0] === "data") {
|
|
126
|
-
const subPath = segments.slice(1).join("/");
|
|
127
|
-
let body = {};
|
|
128
|
-
if (method === "POST" || method === "PATCH") {
|
|
129
|
-
body = await request.json().catch(() => ({}));
|
|
130
|
-
}
|
|
131
|
-
const queryParams = {};
|
|
132
|
-
url.searchParams.forEach((val, key) => {
|
|
133
|
-
queryParams[key] = val;
|
|
134
|
-
});
|
|
135
|
-
const result = await dispatcher.handleData(
|
|
136
|
-
subPath ? `/${subPath}` : "",
|
|
137
|
-
method,
|
|
138
|
-
body,
|
|
139
|
-
queryParams,
|
|
140
|
-
{ request }
|
|
141
|
-
);
|
|
142
|
-
return toResponse(result);
|
|
143
|
-
}
|
|
144
111
|
if (segments[0] === "storage") {
|
|
145
|
-
const
|
|
112
|
+
const subPath2 = segments.slice(1).join("/");
|
|
146
113
|
let file = void 0;
|
|
147
|
-
if (method === "POST" &&
|
|
114
|
+
if (method === "POST" && subPath2 === "upload") {
|
|
148
115
|
const formData = await request.formData();
|
|
149
116
|
file = formData.get("file");
|
|
150
117
|
}
|
|
151
|
-
const
|
|
152
|
-
|
|
118
|
+
const result2 = await dispatcher.handleStorage(
|
|
119
|
+
subPath2 ? `/${subPath2}` : "",
|
|
153
120
|
method,
|
|
154
121
|
file,
|
|
155
122
|
{ request }
|
|
156
123
|
);
|
|
157
|
-
return toResponse(
|
|
124
|
+
return toResponse(result2);
|
|
125
|
+
}
|
|
126
|
+
const subPath = path || "";
|
|
127
|
+
let body = void 0;
|
|
128
|
+
if (method === "POST" || method === "PUT" || method === "PATCH") {
|
|
129
|
+
body = await request.json().catch(() => ({}));
|
|
158
130
|
}
|
|
159
|
-
|
|
131
|
+
const queryParams = {};
|
|
132
|
+
url.searchParams.forEach((val, key) => {
|
|
133
|
+
queryParams[key] = val;
|
|
134
|
+
});
|
|
135
|
+
const result = await dispatcher.dispatch(method, subPath, body, queryParams, { request });
|
|
136
|
+
return toResponse(result);
|
|
160
137
|
} catch (err) {
|
|
161
138
|
return errorJson(err.message || "Internal Server Error", err.statusCode || 500);
|
|
162
139
|
}
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/index.ts"],"sourcesContent":["// Copyright (c) 2025 ObjectStack. Licensed under the Apache-2.0 license.\n\nimport { type ObjectKernel, HttpDispatcher, HttpDispatcherResult } from '@objectstack/runtime';\n\nexport interface SvelteKitAdapterOptions {\n kernel: ObjectKernel;\n prefix?: string;\n}\n\n/**\n * Auth service interface with handleRequest method\n */\ninterface AuthService {\n handleRequest(request: Request): Promise<Response>;\n}\n\n/**\n * SvelteKit request event type (minimal interface to avoid hard dependency on @sveltejs/kit types at runtime)\n */\ninterface RequestEvent {\n request: Request;\n url: URL;\n params: Record<string, string>;\n}\n\n/**\n * Creates a SvelteKit request handler for ObjectStack API routes.\n * Use in a catch-all `+server.ts` route like `src/routes/api/[...path]/+server.ts`.\n *\n * @example\n * ```ts\n * // src/routes/api/[...path]/+server.ts\n * import { createRequestHandler } from '@objectstack/sveltekit';\n * import { kernel } from '$lib/kernel';\n *\n * const handler = createRequestHandler({ kernel });\n *\n * export const GET = handler;\n * export const POST = handler;\n * export const PUT = handler;\n * export const PATCH = handler;\n * export const DELETE = handler;\n * ```\n */\nexport function createRequestHandler(options: SvelteKitAdapterOptions) {\n const dispatcher = new HttpDispatcher(options.kernel);\n const prefix = options.prefix || '/api';\n\n const errorJson = (message: string, code: number = 500) => {\n return new Response(JSON.stringify({ success: false, error: { message, code } }), {\n status: code,\n headers: { 'Content-Type': 'application/json' },\n });\n };\n\n const toResponse = (result: HttpDispatcherResult): Response => {\n if (result.handled) {\n if (result.response) {\n const headers = new Headers({ 'Content-Type': 'application/json' });\n if (result.response.headers) {\n Object.entries(result.response.headers).forEach(([k, v]) => headers.set(k, v as string));\n }\n return new Response(JSON.stringify(result.response.body), {\n status: result.response.status,\n headers,\n });\n }\n if (result.result) {\n const res = result.result;\n if (res.type === 'redirect' && res.url) {\n return new Response(null, {\n status: 302,\n headers: { Location: res.url },\n });\n }\n if (res.type === 'stream' && res.stream) {\n const headers = new Headers();\n if (res.headers) {\n Object.entries(res.headers).forEach(([k, v]) => headers.set(k, v as string));\n }\n return new Response(res.stream, { status: 200, headers });\n }\n return new Response(JSON.stringify(res), {\n status: 200,\n headers: { 'Content-Type': 'application/json' },\n });\n }\n }\n return errorJson('Not Found', 404);\n };\n\n return async function handler(event: RequestEvent): Promise<Response> {\n const { request, url } = event;\n const method = request.method;\n const path = url.pathname.substring(prefix.length);\n const segments = path.split('/').filter(Boolean);\n\n // --- Discovery ---\n if (segments.length === 0 && method === 'GET') {\n return new Response(JSON.stringify({ data: await dispatcher.getDiscoveryInfo(prefix) }), {\n status: 200,\n headers: { 'Content-Type': 'application/json' },\n });\n }\n\n try {\n // --- Auth ---\n if (segments[0] === 'auth') {\n const subPath = segments.slice(1).join('/');\n\n // Try AuthPlugin service first (prefer async to support factory-based services)\n let authService: AuthService | null = null;\n try {\n if (typeof options.kernel.getServiceAsync === 'function') {\n authService = await options.kernel.getServiceAsync<AuthService>('auth');\n } else if (typeof options.kernel.getService === 'function') {\n authService = options.kernel.getService<AuthService>('auth');\n }\n } catch {\n // Service not registered — fall through to dispatcher\n authService = null;\n }\n\n if (authService && typeof authService.handleRequest === 'function') {\n return await authService.handleRequest(request);\n }\n\n // Fallback to dispatcher\n const body = method === 'GET' || method === 'HEAD'\n ? {}\n : await request.json().catch(() => ({}));\n const result = await dispatcher.handleAuth(subPath, method, body, { request });\n return toResponse(result);\n }\n\n // --- GraphQL ---\n if (segments[0] === 'graphql' && method === 'POST') {\n const body = await request.json() as { query: string; variables?: any };\n const result = await dispatcher.handleGraphQL(body, { request });\n return new Response(JSON.stringify(result), {\n status: 200,\n headers: { 'Content-Type': 'application/json' },\n });\n }\n\n // --- Metadata ---\n if (segments[0] === 'meta') {\n const subPath = segments.slice(1).join('/');\n let body: any = undefined;\n if (method === 'PUT' || method === 'POST') {\n body = await request.json().catch(() => ({}));\n }\n const result = await dispatcher.handleMetadata(\n subPath ? `/${subPath}` : '',\n { request },\n method,\n body,\n );\n return toResponse(result);\n }\n\n // --- Data ---\n if (segments[0] === 'data') {\n const subPath = segments.slice(1).join('/');\n let body: any = {};\n if (method === 'POST' || method === 'PATCH') {\n body = await request.json().catch(() => ({}));\n }\n const queryParams: Record<string, any> = {};\n url.searchParams.forEach((val, key) => { queryParams[key] = val; });\n\n const result = await dispatcher.handleData(\n subPath ? `/${subPath}` : '',\n method,\n body,\n queryParams,\n { request },\n );\n return toResponse(result);\n }\n\n // --- Storage ---\n if (segments[0] === 'storage') {\n const subPath = segments.slice(1).join('/');\n let file: any = undefined;\n if (method === 'POST' && subPath === 'upload') {\n const formData = await request.formData();\n file = formData.get('file');\n }\n const result = await dispatcher.handleStorage(\n subPath ? `/${subPath}` : '',\n method,\n file,\n { request },\n );\n return toResponse(result);\n }\n\n return errorJson('Not Found', 404);\n } catch (err: any) {\n return errorJson(err.message || 'Internal Server Error', err.statusCode || 500);\n }\n };\n}\n\n/**\n * Creates a SvelteKit handle hook that attaches the kernel to event.locals.\n *\n * @example\n * ```ts\n * // src/hooks.server.ts\n * import { createHandle } from '@objectstack/sveltekit';\n * export const handle = createHandle({ kernel });\n * ```\n */\nexport function createHandle(options: SvelteKitAdapterOptions) {\n return async function handle({ event, resolve }: { event: any; resolve: (event: any) => Promise<Response> }) {\n event.locals.objectStack = options.kernel;\n return resolve(event);\n };\n}\n"],"mappings":"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","names":[]}
|
|
1
|
+
{"version":3,"sources":["../src/index.ts"],"sourcesContent":["// Copyright (c) 2025 ObjectStack. Licensed under the Apache-2.0 license.\n\nimport { type ObjectKernel, HttpDispatcher, HttpDispatcherResult } from '@objectstack/runtime';\n\nexport interface SvelteKitAdapterOptions {\n kernel: ObjectKernel;\n prefix?: string;\n}\n\n/**\n * Auth service interface with handleRequest method\n */\ninterface AuthService {\n handleRequest(request: Request): Promise<Response>;\n}\n\n/**\n * SvelteKit request event type (minimal interface to avoid hard dependency on @sveltejs/kit types at runtime)\n */\ninterface RequestEvent {\n request: Request;\n url: URL;\n params: Record<string, string>;\n}\n\n/**\n * Creates a SvelteKit request handler for ObjectStack API routes.\n * Use in a catch-all `+server.ts` route like `src/routes/api/[...path]/+server.ts`.\n *\n * Only auth, GraphQL, storage, and discovery need explicit handling.\n * All other routes delegate to `HttpDispatcher.dispatch()` automatically.\n *\n * @example\n * ```ts\n * // src/routes/api/[...path]/+server.ts\n * import { createRequestHandler } from '@objectstack/sveltekit';\n * import { kernel } from '$lib/kernel';\n *\n * const handler = createRequestHandler({ kernel });\n *\n * export const GET = handler;\n * export const POST = handler;\n * export const PUT = handler;\n * export const PATCH = handler;\n * export const DELETE = handler;\n * ```\n */\nexport function createRequestHandler(options: SvelteKitAdapterOptions) {\n const dispatcher = new HttpDispatcher(options.kernel);\n const prefix = options.prefix || '/api';\n\n const errorJson = (message: string, code: number = 500) => {\n return new Response(JSON.stringify({ success: false, error: { message, code } }), {\n status: code,\n headers: { 'Content-Type': 'application/json' },\n });\n };\n\n const toResponse = (result: HttpDispatcherResult): Response => {\n if (result.handled) {\n if (result.response) {\n const headers = new Headers({ 'Content-Type': 'application/json' });\n if (result.response.headers) {\n Object.entries(result.response.headers).forEach(([k, v]) => headers.set(k, v as string));\n }\n return new Response(JSON.stringify(result.response.body), {\n status: result.response.status,\n headers,\n });\n }\n if (result.result) {\n const res = result.result;\n if (res.type === 'redirect' && res.url) {\n return new Response(null, {\n status: 302,\n headers: { Location: res.url },\n });\n }\n if (res.type === 'stream' && res.stream) {\n const headers = new Headers();\n if (res.headers) {\n Object.entries(res.headers).forEach(([k, v]) => headers.set(k, v as string));\n }\n return new Response(res.stream, { status: 200, headers });\n }\n return new Response(JSON.stringify(res), {\n status: 200,\n headers: { 'Content-Type': 'application/json' },\n });\n }\n }\n return errorJson('Not Found', 404);\n };\n\n return async function handler(event: RequestEvent): Promise<Response> {\n const { request, url } = event;\n const method = request.method;\n const path = url.pathname.substring(prefix.length);\n const segments = path.split('/').filter(Boolean);\n\n // --- Discovery ---\n if (segments.length === 0 && method === 'GET') {\n return new Response(JSON.stringify({ data: await dispatcher.getDiscoveryInfo(prefix) }), {\n status: 200,\n headers: { 'Content-Type': 'application/json' },\n });\n }\n\n try {\n // --- Auth (needs auth service integration) ---\n if (segments[0] === 'auth') {\n const subPath = segments.slice(1).join('/');\n\n // Try AuthPlugin service first (prefer async to support factory-based services)\n let authService: AuthService | null = null;\n try {\n if (typeof options.kernel.getServiceAsync === 'function') {\n authService = await options.kernel.getServiceAsync<AuthService>('auth');\n } else if (typeof options.kernel.getService === 'function') {\n authService = options.kernel.getService<AuthService>('auth');\n }\n } catch {\n // Service not registered — fall through to dispatcher\n authService = null;\n }\n\n if (authService && typeof authService.handleRequest === 'function') {\n return await authService.handleRequest(request);\n }\n\n // Fallback to dispatcher\n const body = method === 'GET' || method === 'HEAD'\n ? {}\n : await request.json().catch(() => ({}));\n const result = await dispatcher.handleAuth(subPath, method, body, { request });\n return toResponse(result);\n }\n\n // --- GraphQL (returns raw result, not HttpDispatcherResult) ---\n if (segments[0] === 'graphql' && method === 'POST') {\n const body = await request.json() as { query: string; variables?: any };\n const result = await dispatcher.handleGraphQL(body, { request });\n return new Response(JSON.stringify(result), {\n status: 200,\n headers: { 'Content-Type': 'application/json' },\n });\n }\n\n // --- Storage (needs formData parsing) ---\n if (segments[0] === 'storage') {\n const subPath = segments.slice(1).join('/');\n let file: any = undefined;\n if (method === 'POST' && subPath === 'upload') {\n const formData = await request.formData();\n file = formData.get('file');\n }\n const result = await dispatcher.handleStorage(\n subPath ? `/${subPath}` : '',\n method,\n file,\n { request },\n );\n return toResponse(result);\n }\n\n // --- Catch-all: delegate to dispatcher.dispatch() ---\n // Handles meta, data, packages, analytics, automation, i18n, ui,\n // openapi, custom API endpoints, and any future routes.\n const subPath = path || '';\n\n let body: any = undefined;\n if (method === 'POST' || method === 'PUT' || method === 'PATCH') {\n body = await request.json().catch(() => ({}));\n }\n\n const queryParams: Record<string, any> = {};\n url.searchParams.forEach((val, key) => { queryParams[key] = val; });\n\n const result = await dispatcher.dispatch(method, subPath, body, queryParams, { request });\n return toResponse(result);\n } catch (err: any) {\n return errorJson(err.message || 'Internal Server Error', err.statusCode || 500);\n }\n };\n}\n\n/**\n * Creates a SvelteKit handle hook that attaches the kernel to event.locals.\n *\n * @example\n * ```ts\n * // src/hooks.server.ts\n * import { createHandle } from '@objectstack/sveltekit';\n * export const handle = createHandle({ kernel });\n * ```\n */\nexport function createHandle(options: SvelteKitAdapterOptions) {\n return async function handle({ event, resolve }: { event: any; resolve: (event: any) => Promise<Response> }) {\n event.locals.objectStack = options.kernel;\n return resolve(event);\n };\n}\n"],"mappings":"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","names":["subPath","body","result"]}
|
package/dist/index.mjs
CHANGED
|
@@ -57,7 +57,7 @@ function createRequestHandler(options) {
|
|
|
57
57
|
}
|
|
58
58
|
try {
|
|
59
59
|
if (segments[0] === "auth") {
|
|
60
|
-
const
|
|
60
|
+
const subPath2 = segments.slice(1).join("/");
|
|
61
61
|
let authService = null;
|
|
62
62
|
try {
|
|
63
63
|
if (typeof options.kernel.getServiceAsync === "function") {
|
|
@@ -71,67 +71,44 @@ function createRequestHandler(options) {
|
|
|
71
71
|
if (authService && typeof authService.handleRequest === "function") {
|
|
72
72
|
return await authService.handleRequest(request);
|
|
73
73
|
}
|
|
74
|
-
const
|
|
75
|
-
const
|
|
76
|
-
return toResponse(
|
|
74
|
+
const body2 = method === "GET" || method === "HEAD" ? {} : await request.json().catch(() => ({}));
|
|
75
|
+
const result2 = await dispatcher.handleAuth(subPath2, method, body2, { request });
|
|
76
|
+
return toResponse(result2);
|
|
77
77
|
}
|
|
78
78
|
if (segments[0] === "graphql" && method === "POST") {
|
|
79
|
-
const
|
|
80
|
-
const
|
|
81
|
-
return new Response(JSON.stringify(
|
|
79
|
+
const body2 = await request.json();
|
|
80
|
+
const result2 = await dispatcher.handleGraphQL(body2, { request });
|
|
81
|
+
return new Response(JSON.stringify(result2), {
|
|
82
82
|
status: 200,
|
|
83
83
|
headers: { "Content-Type": "application/json" }
|
|
84
84
|
});
|
|
85
85
|
}
|
|
86
|
-
if (segments[0] === "meta") {
|
|
87
|
-
const subPath = segments.slice(1).join("/");
|
|
88
|
-
let body = void 0;
|
|
89
|
-
if (method === "PUT" || method === "POST") {
|
|
90
|
-
body = await request.json().catch(() => ({}));
|
|
91
|
-
}
|
|
92
|
-
const result = await dispatcher.handleMetadata(
|
|
93
|
-
subPath ? `/${subPath}` : "",
|
|
94
|
-
{ request },
|
|
95
|
-
method,
|
|
96
|
-
body
|
|
97
|
-
);
|
|
98
|
-
return toResponse(result);
|
|
99
|
-
}
|
|
100
|
-
if (segments[0] === "data") {
|
|
101
|
-
const subPath = segments.slice(1).join("/");
|
|
102
|
-
let body = {};
|
|
103
|
-
if (method === "POST" || method === "PATCH") {
|
|
104
|
-
body = await request.json().catch(() => ({}));
|
|
105
|
-
}
|
|
106
|
-
const queryParams = {};
|
|
107
|
-
url.searchParams.forEach((val, key) => {
|
|
108
|
-
queryParams[key] = val;
|
|
109
|
-
});
|
|
110
|
-
const result = await dispatcher.handleData(
|
|
111
|
-
subPath ? `/${subPath}` : "",
|
|
112
|
-
method,
|
|
113
|
-
body,
|
|
114
|
-
queryParams,
|
|
115
|
-
{ request }
|
|
116
|
-
);
|
|
117
|
-
return toResponse(result);
|
|
118
|
-
}
|
|
119
86
|
if (segments[0] === "storage") {
|
|
120
|
-
const
|
|
87
|
+
const subPath2 = segments.slice(1).join("/");
|
|
121
88
|
let file = void 0;
|
|
122
|
-
if (method === "POST" &&
|
|
89
|
+
if (method === "POST" && subPath2 === "upload") {
|
|
123
90
|
const formData = await request.formData();
|
|
124
91
|
file = formData.get("file");
|
|
125
92
|
}
|
|
126
|
-
const
|
|
127
|
-
|
|
93
|
+
const result2 = await dispatcher.handleStorage(
|
|
94
|
+
subPath2 ? `/${subPath2}` : "",
|
|
128
95
|
method,
|
|
129
96
|
file,
|
|
130
97
|
{ request }
|
|
131
98
|
);
|
|
132
|
-
return toResponse(
|
|
99
|
+
return toResponse(result2);
|
|
100
|
+
}
|
|
101
|
+
const subPath = path || "";
|
|
102
|
+
let body = void 0;
|
|
103
|
+
if (method === "POST" || method === "PUT" || method === "PATCH") {
|
|
104
|
+
body = await request.json().catch(() => ({}));
|
|
133
105
|
}
|
|
134
|
-
|
|
106
|
+
const queryParams = {};
|
|
107
|
+
url.searchParams.forEach((val, key) => {
|
|
108
|
+
queryParams[key] = val;
|
|
109
|
+
});
|
|
110
|
+
const result = await dispatcher.dispatch(method, subPath, body, queryParams, { request });
|
|
111
|
+
return toResponse(result);
|
|
135
112
|
} catch (err) {
|
|
136
113
|
return errorJson(err.message || "Internal Server Error", err.statusCode || 500);
|
|
137
114
|
}
|
package/dist/index.mjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/index.ts"],"sourcesContent":["// Copyright (c) 2025 ObjectStack. Licensed under the Apache-2.0 license.\n\nimport { type ObjectKernel, HttpDispatcher, HttpDispatcherResult } from '@objectstack/runtime';\n\nexport interface SvelteKitAdapterOptions {\n kernel: ObjectKernel;\n prefix?: string;\n}\n\n/**\n * Auth service interface with handleRequest method\n */\ninterface AuthService {\n handleRequest(request: Request): Promise<Response>;\n}\n\n/**\n * SvelteKit request event type (minimal interface to avoid hard dependency on @sveltejs/kit types at runtime)\n */\ninterface RequestEvent {\n request: Request;\n url: URL;\n params: Record<string, string>;\n}\n\n/**\n * Creates a SvelteKit request handler for ObjectStack API routes.\n * Use in a catch-all `+server.ts` route like `src/routes/api/[...path]/+server.ts`.\n *\n * @example\n * ```ts\n * // src/routes/api/[...path]/+server.ts\n * import { createRequestHandler } from '@objectstack/sveltekit';\n * import { kernel } from '$lib/kernel';\n *\n * const handler = createRequestHandler({ kernel });\n *\n * export const GET = handler;\n * export const POST = handler;\n * export const PUT = handler;\n * export const PATCH = handler;\n * export const DELETE = handler;\n * ```\n */\nexport function createRequestHandler(options: SvelteKitAdapterOptions) {\n const dispatcher = new HttpDispatcher(options.kernel);\n const prefix = options.prefix || '/api';\n\n const errorJson = (message: string, code: number = 500) => {\n return new Response(JSON.stringify({ success: false, error: { message, code } }), {\n status: code,\n headers: { 'Content-Type': 'application/json' },\n });\n };\n\n const toResponse = (result: HttpDispatcherResult): Response => {\n if (result.handled) {\n if (result.response) {\n const headers = new Headers({ 'Content-Type': 'application/json' });\n if (result.response.headers) {\n Object.entries(result.response.headers).forEach(([k, v]) => headers.set(k, v as string));\n }\n return new Response(JSON.stringify(result.response.body), {\n status: result.response.status,\n headers,\n });\n }\n if (result.result) {\n const res = result.result;\n if (res.type === 'redirect' && res.url) {\n return new Response(null, {\n status: 302,\n headers: { Location: res.url },\n });\n }\n if (res.type === 'stream' && res.stream) {\n const headers = new Headers();\n if (res.headers) {\n Object.entries(res.headers).forEach(([k, v]) => headers.set(k, v as string));\n }\n return new Response(res.stream, { status: 200, headers });\n }\n return new Response(JSON.stringify(res), {\n status: 200,\n headers: { 'Content-Type': 'application/json' },\n });\n }\n }\n return errorJson('Not Found', 404);\n };\n\n return async function handler(event: RequestEvent): Promise<Response> {\n const { request, url } = event;\n const method = request.method;\n const path = url.pathname.substring(prefix.length);\n const segments = path.split('/').filter(Boolean);\n\n // --- Discovery ---\n if (segments.length === 0 && method === 'GET') {\n return new Response(JSON.stringify({ data: await dispatcher.getDiscoveryInfo(prefix) }), {\n status: 200,\n headers: { 'Content-Type': 'application/json' },\n });\n }\n\n try {\n // --- Auth ---\n if (segments[0] === 'auth') {\n const subPath = segments.slice(1).join('/');\n\n // Try AuthPlugin service first (prefer async to support factory-based services)\n let authService: AuthService | null = null;\n try {\n if (typeof options.kernel.getServiceAsync === 'function') {\n authService = await options.kernel.getServiceAsync<AuthService>('auth');\n } else if (typeof options.kernel.getService === 'function') {\n authService = options.kernel.getService<AuthService>('auth');\n }\n } catch {\n // Service not registered — fall through to dispatcher\n authService = null;\n }\n\n if (authService && typeof authService.handleRequest === 'function') {\n return await authService.handleRequest(request);\n }\n\n // Fallback to dispatcher\n const body = method === 'GET' || method === 'HEAD'\n ? {}\n : await request.json().catch(() => ({}));\n const result = await dispatcher.handleAuth(subPath, method, body, { request });\n return toResponse(result);\n }\n\n // --- GraphQL ---\n if (segments[0] === 'graphql' && method === 'POST') {\n const body = await request.json() as { query: string; variables?: any };\n const result = await dispatcher.handleGraphQL(body, { request });\n return new Response(JSON.stringify(result), {\n status: 200,\n headers: { 'Content-Type': 'application/json' },\n });\n }\n\n // --- Metadata ---\n if (segments[0] === 'meta') {\n const subPath = segments.slice(1).join('/');\n let body: any = undefined;\n if (method === 'PUT' || method === 'POST') {\n body = await request.json().catch(() => ({}));\n }\n const result = await dispatcher.handleMetadata(\n subPath ? `/${subPath}` : '',\n { request },\n method,\n body,\n );\n return toResponse(result);\n }\n\n // --- Data ---\n if (segments[0] === 'data') {\n const subPath = segments.slice(1).join('/');\n let body: any = {};\n if (method === 'POST' || method === 'PATCH') {\n body = await request.json().catch(() => ({}));\n }\n const queryParams: Record<string, any> = {};\n url.searchParams.forEach((val, key) => { queryParams[key] = val; });\n\n const result = await dispatcher.handleData(\n subPath ? `/${subPath}` : '',\n method,\n body,\n queryParams,\n { request },\n );\n return toResponse(result);\n }\n\n // --- Storage ---\n if (segments[0] === 'storage') {\n const subPath = segments.slice(1).join('/');\n let file: any = undefined;\n if (method === 'POST' && subPath === 'upload') {\n const formData = await request.formData();\n file = formData.get('file');\n }\n const result = await dispatcher.handleStorage(\n subPath ? `/${subPath}` : '',\n method,\n file,\n { request },\n );\n return toResponse(result);\n }\n\n return errorJson('Not Found', 404);\n } catch (err: any) {\n return errorJson(err.message || 'Internal Server Error', err.statusCode || 500);\n }\n };\n}\n\n/**\n * Creates a SvelteKit handle hook that attaches the kernel to event.locals.\n *\n * @example\n * ```ts\n * // src/hooks.server.ts\n * import { createHandle } from '@objectstack/sveltekit';\n * export const handle = createHandle({ kernel });\n * ```\n */\nexport function createHandle(options: SvelteKitAdapterOptions) {\n return async function handle({ event, resolve }: { event: any; resolve: (event: any) => Promise<Response> }) {\n event.locals.objectStack = options.kernel;\n return resolve(event);\n };\n}\n"],"mappings":";AAEA,SAA4B,sBAA4C;AA0CjE,SAAS,qBAAqB,SAAkC;AACrE,QAAM,aAAa,IAAI,eAAe,QAAQ,MAAM;AACpD,QAAM,SAAS,QAAQ,UAAU;AAEjC,QAAM,YAAY,CAAC,SAAiB,OAAe,QAAQ;AACzD,WAAO,IAAI,SAAS,KAAK,UAAU,EAAE,SAAS,OAAO,OAAO,EAAE,SAAS,KAAK,EAAE,CAAC,GAAG;AAAA,MAChF,QAAQ;AAAA,MACR,SAAS,EAAE,gBAAgB,mBAAmB;AAAA,IAChD,CAAC;AAAA,EACH;AAEA,QAAM,aAAa,CAAC,WAA2C;AAC7D,QAAI,OAAO,SAAS;AAClB,UAAI,OAAO,UAAU;AACnB,cAAM,UAAU,IAAI,QAAQ,EAAE,gBAAgB,mBAAmB,CAAC;AAClE,YAAI,OAAO,SAAS,SAAS;AAC3B,iBAAO,QAAQ,OAAO,SAAS,OAAO,EAAE,QAAQ,CAAC,CAAC,GAAG,CAAC,MAAM,QAAQ,IAAI,GAAG,CAAW,CAAC;AAAA,QACzF;AACA,eAAO,IAAI,SAAS,KAAK,UAAU,OAAO,SAAS,IAAI,GAAG;AAAA,UACxD,QAAQ,OAAO,SAAS;AAAA,UACxB;AAAA,QACF,CAAC;AAAA,MACH;AACA,UAAI,OAAO,QAAQ;AACjB,cAAM,MAAM,OAAO;AACnB,YAAI,IAAI,SAAS,cAAc,IAAI,KAAK;AACtC,iBAAO,IAAI,SAAS,MAAM;AAAA,YACxB,QAAQ;AAAA,YACR,SAAS,EAAE,UAAU,IAAI,IAAI;AAAA,UAC/B,CAAC;AAAA,QACH;AACA,YAAI,IAAI,SAAS,YAAY,IAAI,QAAQ;AACvC,gBAAM,UAAU,IAAI,QAAQ;AAC5B,cAAI,IAAI,SAAS;AACf,mBAAO,QAAQ,IAAI,OAAO,EAAE,QAAQ,CAAC,CAAC,GAAG,CAAC,MAAM,QAAQ,IAAI,GAAG,CAAW,CAAC;AAAA,UAC7E;AACA,iBAAO,IAAI,SAAS,IAAI,QAAQ,EAAE,QAAQ,KAAK,QAAQ,CAAC;AAAA,QAC1D;AACA,eAAO,IAAI,SAAS,KAAK,UAAU,GAAG,GAAG;AAAA,UACvC,QAAQ;AAAA,UACR,SAAS,EAAE,gBAAgB,mBAAmB;AAAA,QAChD,CAAC;AAAA,MACH;AAAA,IACF;AACA,WAAO,UAAU,aAAa,GAAG;AAAA,EACnC;AAEA,SAAO,eAAe,QAAQ,OAAwC;AACpE,UAAM,EAAE,SAAS,IAAI,IAAI;AACzB,UAAM,SAAS,QAAQ;AACvB,UAAM,OAAO,IAAI,SAAS,UAAU,OAAO,MAAM;AACjD,UAAM,WAAW,KAAK,MAAM,GAAG,EAAE,OAAO,OAAO;AAG/C,QAAI,SAAS,WAAW,KAAK,WAAW,OAAO;AAC7C,aAAO,IAAI,SAAS,KAAK,UAAU,EAAE,MAAM,MAAM,WAAW,iBAAiB,MAAM,EAAE,CAAC,GAAG;AAAA,QACvF,QAAQ;AAAA,QACR,SAAS,EAAE,gBAAgB,mBAAmB;AAAA,MAChD,CAAC;AAAA,IACH;AAEA,QAAI;AAEF,UAAI,SAAS,CAAC,MAAM,QAAQ;AAC1B,cAAM,UAAU,SAAS,MAAM,CAAC,EAAE,KAAK,GAAG;AAG1C,YAAI,cAAkC;AACtC,YAAI;AACF,cAAI,OAAO,QAAQ,OAAO,oBAAoB,YAAY;AACxD,0BAAc,MAAM,QAAQ,OAAO,gBAA6B,MAAM;AAAA,UACxE,WAAW,OAAO,QAAQ,OAAO,eAAe,YAAY;AAC1D,0BAAc,QAAQ,OAAO,WAAwB,MAAM;AAAA,UAC7D;AAAA,QACF,QAAQ;AAEN,wBAAc;AAAA,QAChB;AAEA,YAAI,eAAe,OAAO,YAAY,kBAAkB,YAAY;AAClE,iBAAO,MAAM,YAAY,cAAc,OAAO;AAAA,QAChD;AAGA,cAAM,OAAO,WAAW,SAAS,WAAW,SACxC,CAAC,IACD,MAAM,QAAQ,KAAK,EAAE,MAAM,OAAO,CAAC,EAAE;AACzC,cAAM,SAAS,MAAM,WAAW,WAAW,SAAS,QAAQ,MAAM,EAAE,QAAQ,CAAC;AAC7E,eAAO,WAAW,MAAM;AAAA,MAC1B;AAGA,UAAI,SAAS,CAAC,MAAM,aAAa,WAAW,QAAQ;AAClD,cAAM,OAAO,MAAM,QAAQ,KAAK;AAChC,cAAM,SAAS,MAAM,WAAW,cAAc,MAAM,EAAE,QAAQ,CAAC;AAC/D,eAAO,IAAI,SAAS,KAAK,UAAU,MAAM,GAAG;AAAA,UAC1C,QAAQ;AAAA,UACR,SAAS,EAAE,gBAAgB,mBAAmB;AAAA,QAChD,CAAC;AAAA,MACH;AAGA,UAAI,SAAS,CAAC,MAAM,QAAQ;AAC1B,cAAM,UAAU,SAAS,MAAM,CAAC,EAAE,KAAK,GAAG;AAC1C,YAAI,OAAY;AAChB,YAAI,WAAW,SAAS,WAAW,QAAQ;AACzC,iBAAO,MAAM,QAAQ,KAAK,EAAE,MAAM,OAAO,CAAC,EAAE;AAAA,QAC9C;AACA,cAAM,SAAS,MAAM,WAAW;AAAA,UAC9B,UAAU,IAAI,OAAO,KAAK;AAAA,UAC1B,EAAE,QAAQ;AAAA,UACV;AAAA,UACA;AAAA,QACF;AACA,eAAO,WAAW,MAAM;AAAA,MAC1B;AAGA,UAAI,SAAS,CAAC,MAAM,QAAQ;AAC1B,cAAM,UAAU,SAAS,MAAM,CAAC,EAAE,KAAK,GAAG;AAC1C,YAAI,OAAY,CAAC;AACjB,YAAI,WAAW,UAAU,WAAW,SAAS;AAC3C,iBAAO,MAAM,QAAQ,KAAK,EAAE,MAAM,OAAO,CAAC,EAAE;AAAA,QAC9C;AACA,cAAM,cAAmC,CAAC;AAC1C,YAAI,aAAa,QAAQ,CAAC,KAAK,QAAQ;AAAE,sBAAY,GAAG,IAAI;AAAA,QAAK,CAAC;AAElE,cAAM,SAAS,MAAM,WAAW;AAAA,UAC9B,UAAU,IAAI,OAAO,KAAK;AAAA,UAC1B;AAAA,UACA;AAAA,UACA;AAAA,UACA,EAAE,QAAQ;AAAA,QACZ;AACA,eAAO,WAAW,MAAM;AAAA,MAC1B;AAGA,UAAI,SAAS,CAAC,MAAM,WAAW;AAC7B,cAAM,UAAU,SAAS,MAAM,CAAC,EAAE,KAAK,GAAG;AAC1C,YAAI,OAAY;AAChB,YAAI,WAAW,UAAU,YAAY,UAAU;AAC7C,gBAAM,WAAW,MAAM,QAAQ,SAAS;AACxC,iBAAO,SAAS,IAAI,MAAM;AAAA,QAC5B;AACA,cAAM,SAAS,MAAM,WAAW;AAAA,UAC9B,UAAU,IAAI,OAAO,KAAK;AAAA,UAC1B;AAAA,UACA;AAAA,UACA,EAAE,QAAQ;AAAA,QACZ;AACA,eAAO,WAAW,MAAM;AAAA,MAC1B;AAEA,aAAO,UAAU,aAAa,GAAG;AAAA,IACnC,SAAS,KAAU;AACjB,aAAO,UAAU,IAAI,WAAW,yBAAyB,IAAI,cAAc,GAAG;AAAA,IAChF;AAAA,EACF;AACF;AAYO,SAAS,aAAa,SAAkC;AAC7D,SAAO,eAAe,OAAO,EAAE,OAAO,QAAQ,GAA+D;AAC3G,UAAM,OAAO,cAAc,QAAQ;AACnC,WAAO,QAAQ,KAAK;AAAA,EACtB;AACF;","names":[]}
|
|
1
|
+
{"version":3,"sources":["../src/index.ts"],"sourcesContent":["// Copyright (c) 2025 ObjectStack. Licensed under the Apache-2.0 license.\n\nimport { type ObjectKernel, HttpDispatcher, HttpDispatcherResult } from '@objectstack/runtime';\n\nexport interface SvelteKitAdapterOptions {\n kernel: ObjectKernel;\n prefix?: string;\n}\n\n/**\n * Auth service interface with handleRequest method\n */\ninterface AuthService {\n handleRequest(request: Request): Promise<Response>;\n}\n\n/**\n * SvelteKit request event type (minimal interface to avoid hard dependency on @sveltejs/kit types at runtime)\n */\ninterface RequestEvent {\n request: Request;\n url: URL;\n params: Record<string, string>;\n}\n\n/**\n * Creates a SvelteKit request handler for ObjectStack API routes.\n * Use in a catch-all `+server.ts` route like `src/routes/api/[...path]/+server.ts`.\n *\n * Only auth, GraphQL, storage, and discovery need explicit handling.\n * All other routes delegate to `HttpDispatcher.dispatch()` automatically.\n *\n * @example\n * ```ts\n * // src/routes/api/[...path]/+server.ts\n * import { createRequestHandler } from '@objectstack/sveltekit';\n * import { kernel } from '$lib/kernel';\n *\n * const handler = createRequestHandler({ kernel });\n *\n * export const GET = handler;\n * export const POST = handler;\n * export const PUT = handler;\n * export const PATCH = handler;\n * export const DELETE = handler;\n * ```\n */\nexport function createRequestHandler(options: SvelteKitAdapterOptions) {\n const dispatcher = new HttpDispatcher(options.kernel);\n const prefix = options.prefix || '/api';\n\n const errorJson = (message: string, code: number = 500) => {\n return new Response(JSON.stringify({ success: false, error: { message, code } }), {\n status: code,\n headers: { 'Content-Type': 'application/json' },\n });\n };\n\n const toResponse = (result: HttpDispatcherResult): Response => {\n if (result.handled) {\n if (result.response) {\n const headers = new Headers({ 'Content-Type': 'application/json' });\n if (result.response.headers) {\n Object.entries(result.response.headers).forEach(([k, v]) => headers.set(k, v as string));\n }\n return new Response(JSON.stringify(result.response.body), {\n status: result.response.status,\n headers,\n });\n }\n if (result.result) {\n const res = result.result;\n if (res.type === 'redirect' && res.url) {\n return new Response(null, {\n status: 302,\n headers: { Location: res.url },\n });\n }\n if (res.type === 'stream' && res.stream) {\n const headers = new Headers();\n if (res.headers) {\n Object.entries(res.headers).forEach(([k, v]) => headers.set(k, v as string));\n }\n return new Response(res.stream, { status: 200, headers });\n }\n return new Response(JSON.stringify(res), {\n status: 200,\n headers: { 'Content-Type': 'application/json' },\n });\n }\n }\n return errorJson('Not Found', 404);\n };\n\n return async function handler(event: RequestEvent): Promise<Response> {\n const { request, url } = event;\n const method = request.method;\n const path = url.pathname.substring(prefix.length);\n const segments = path.split('/').filter(Boolean);\n\n // --- Discovery ---\n if (segments.length === 0 && method === 'GET') {\n return new Response(JSON.stringify({ data: await dispatcher.getDiscoveryInfo(prefix) }), {\n status: 200,\n headers: { 'Content-Type': 'application/json' },\n });\n }\n\n try {\n // --- Auth (needs auth service integration) ---\n if (segments[0] === 'auth') {\n const subPath = segments.slice(1).join('/');\n\n // Try AuthPlugin service first (prefer async to support factory-based services)\n let authService: AuthService | null = null;\n try {\n if (typeof options.kernel.getServiceAsync === 'function') {\n authService = await options.kernel.getServiceAsync<AuthService>('auth');\n } else if (typeof options.kernel.getService === 'function') {\n authService = options.kernel.getService<AuthService>('auth');\n }\n } catch {\n // Service not registered — fall through to dispatcher\n authService = null;\n }\n\n if (authService && typeof authService.handleRequest === 'function') {\n return await authService.handleRequest(request);\n }\n\n // Fallback to dispatcher\n const body = method === 'GET' || method === 'HEAD'\n ? {}\n : await request.json().catch(() => ({}));\n const result = await dispatcher.handleAuth(subPath, method, body, { request });\n return toResponse(result);\n }\n\n // --- GraphQL (returns raw result, not HttpDispatcherResult) ---\n if (segments[0] === 'graphql' && method === 'POST') {\n const body = await request.json() as { query: string; variables?: any };\n const result = await dispatcher.handleGraphQL(body, { request });\n return new Response(JSON.stringify(result), {\n status: 200,\n headers: { 'Content-Type': 'application/json' },\n });\n }\n\n // --- Storage (needs formData parsing) ---\n if (segments[0] === 'storage') {\n const subPath = segments.slice(1).join('/');\n let file: any = undefined;\n if (method === 'POST' && subPath === 'upload') {\n const formData = await request.formData();\n file = formData.get('file');\n }\n const result = await dispatcher.handleStorage(\n subPath ? `/${subPath}` : '',\n method,\n file,\n { request },\n );\n return toResponse(result);\n }\n\n // --- Catch-all: delegate to dispatcher.dispatch() ---\n // Handles meta, data, packages, analytics, automation, i18n, ui,\n // openapi, custom API endpoints, and any future routes.\n const subPath = path || '';\n\n let body: any = undefined;\n if (method === 'POST' || method === 'PUT' || method === 'PATCH') {\n body = await request.json().catch(() => ({}));\n }\n\n const queryParams: Record<string, any> = {};\n url.searchParams.forEach((val, key) => { queryParams[key] = val; });\n\n const result = await dispatcher.dispatch(method, subPath, body, queryParams, { request });\n return toResponse(result);\n } catch (err: any) {\n return errorJson(err.message || 'Internal Server Error', err.statusCode || 500);\n }\n };\n}\n\n/**\n * Creates a SvelteKit handle hook that attaches the kernel to event.locals.\n *\n * @example\n * ```ts\n * // src/hooks.server.ts\n * import { createHandle } from '@objectstack/sveltekit';\n * export const handle = createHandle({ kernel });\n * ```\n */\nexport function createHandle(options: SvelteKitAdapterOptions) {\n return async function handle({ event, resolve }: { event: any; resolve: (event: any) => Promise<Response> }) {\n event.locals.objectStack = options.kernel;\n return resolve(event);\n };\n}\n"],"mappings":"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","names":["subPath","body","result"]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@objectstack/sveltekit",
|
|
3
|
-
"version": "3.2.
|
|
3
|
+
"version": "3.2.9",
|
|
4
4
|
"license": "Apache-2.0",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"types": "dist/index.d.ts",
|
|
@@ -12,14 +12,14 @@
|
|
|
12
12
|
}
|
|
13
13
|
},
|
|
14
14
|
"peerDependencies": {
|
|
15
|
-
"@sveltejs/kit": "^2.
|
|
16
|
-
"@objectstack/runtime": "^3.2.
|
|
15
|
+
"@sveltejs/kit": "^2.55.0",
|
|
16
|
+
"@objectstack/runtime": "^3.2.9"
|
|
17
17
|
},
|
|
18
18
|
"devDependencies": {
|
|
19
|
-
"@sveltejs/kit": "^2.
|
|
19
|
+
"@sveltejs/kit": "^2.55.0",
|
|
20
20
|
"typescript": "^5.0.0",
|
|
21
|
-
"vitest": "^4.0
|
|
22
|
-
"@objectstack/runtime": "3.2.
|
|
21
|
+
"vitest": "^4.1.0",
|
|
22
|
+
"@objectstack/runtime": "3.2.9"
|
|
23
23
|
},
|
|
24
24
|
"scripts": {
|
|
25
25
|
"build": "tsup --config ../../../tsup.config.ts",
|
package/src/index.ts
CHANGED
|
@@ -27,6 +27,9 @@ interface RequestEvent {
|
|
|
27
27
|
* Creates a SvelteKit request handler for ObjectStack API routes.
|
|
28
28
|
* Use in a catch-all `+server.ts` route like `src/routes/api/[...path]/+server.ts`.
|
|
29
29
|
*
|
|
30
|
+
* Only auth, GraphQL, storage, and discovery need explicit handling.
|
|
31
|
+
* All other routes delegate to `HttpDispatcher.dispatch()` automatically.
|
|
32
|
+
*
|
|
30
33
|
* @example
|
|
31
34
|
* ```ts
|
|
32
35
|
* // src/routes/api/[...path]/+server.ts
|
|
@@ -104,7 +107,7 @@ export function createRequestHandler(options: SvelteKitAdapterOptions) {
|
|
|
104
107
|
}
|
|
105
108
|
|
|
106
109
|
try {
|
|
107
|
-
// --- Auth ---
|
|
110
|
+
// --- Auth (needs auth service integration) ---
|
|
108
111
|
if (segments[0] === 'auth') {
|
|
109
112
|
const subPath = segments.slice(1).join('/');
|
|
110
113
|
|
|
@@ -133,7 +136,7 @@ export function createRequestHandler(options: SvelteKitAdapterOptions) {
|
|
|
133
136
|
return toResponse(result);
|
|
134
137
|
}
|
|
135
138
|
|
|
136
|
-
// --- GraphQL ---
|
|
139
|
+
// --- GraphQL (returns raw result, not HttpDispatcherResult) ---
|
|
137
140
|
if (segments[0] === 'graphql' && method === 'POST') {
|
|
138
141
|
const body = await request.json() as { query: string; variables?: any };
|
|
139
142
|
const result = await dispatcher.handleGraphQL(body, { request });
|
|
@@ -143,43 +146,7 @@ export function createRequestHandler(options: SvelteKitAdapterOptions) {
|
|
|
143
146
|
});
|
|
144
147
|
}
|
|
145
148
|
|
|
146
|
-
// ---
|
|
147
|
-
if (segments[0] === 'meta') {
|
|
148
|
-
const subPath = segments.slice(1).join('/');
|
|
149
|
-
let body: any = undefined;
|
|
150
|
-
if (method === 'PUT' || method === 'POST') {
|
|
151
|
-
body = await request.json().catch(() => ({}));
|
|
152
|
-
}
|
|
153
|
-
const result = await dispatcher.handleMetadata(
|
|
154
|
-
subPath ? `/${subPath}` : '',
|
|
155
|
-
{ request },
|
|
156
|
-
method,
|
|
157
|
-
body,
|
|
158
|
-
);
|
|
159
|
-
return toResponse(result);
|
|
160
|
-
}
|
|
161
|
-
|
|
162
|
-
// --- Data ---
|
|
163
|
-
if (segments[0] === 'data') {
|
|
164
|
-
const subPath = segments.slice(1).join('/');
|
|
165
|
-
let body: any = {};
|
|
166
|
-
if (method === 'POST' || method === 'PATCH') {
|
|
167
|
-
body = await request.json().catch(() => ({}));
|
|
168
|
-
}
|
|
169
|
-
const queryParams: Record<string, any> = {};
|
|
170
|
-
url.searchParams.forEach((val, key) => { queryParams[key] = val; });
|
|
171
|
-
|
|
172
|
-
const result = await dispatcher.handleData(
|
|
173
|
-
subPath ? `/${subPath}` : '',
|
|
174
|
-
method,
|
|
175
|
-
body,
|
|
176
|
-
queryParams,
|
|
177
|
-
{ request },
|
|
178
|
-
);
|
|
179
|
-
return toResponse(result);
|
|
180
|
-
}
|
|
181
|
-
|
|
182
|
-
// --- Storage ---
|
|
149
|
+
// --- Storage (needs formData parsing) ---
|
|
183
150
|
if (segments[0] === 'storage') {
|
|
184
151
|
const subPath = segments.slice(1).join('/');
|
|
185
152
|
let file: any = undefined;
|
|
@@ -196,7 +163,21 @@ export function createRequestHandler(options: SvelteKitAdapterOptions) {
|
|
|
196
163
|
return toResponse(result);
|
|
197
164
|
}
|
|
198
165
|
|
|
199
|
-
|
|
166
|
+
// --- Catch-all: delegate to dispatcher.dispatch() ---
|
|
167
|
+
// Handles meta, data, packages, analytics, automation, i18n, ui,
|
|
168
|
+
// openapi, custom API endpoints, and any future routes.
|
|
169
|
+
const subPath = path || '';
|
|
170
|
+
|
|
171
|
+
let body: any = undefined;
|
|
172
|
+
if (method === 'POST' || method === 'PUT' || method === 'PATCH') {
|
|
173
|
+
body = await request.json().catch(() => ({}));
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
const queryParams: Record<string, any> = {};
|
|
177
|
+
url.searchParams.forEach((val, key) => { queryParams[key] = val; });
|
|
178
|
+
|
|
179
|
+
const result = await dispatcher.dispatch(method, subPath, body, queryParams, { request });
|
|
180
|
+
return toResponse(result);
|
|
200
181
|
} catch (err: any) {
|
|
201
182
|
return errorJson(err.message || 'Internal Server Error', err.statusCode || 500);
|
|
202
183
|
}
|
package/src/sveltekit.test.ts
CHANGED
|
@@ -7,9 +7,8 @@ const mockDispatcher = {
|
|
|
7
7
|
getDiscoveryInfo: vi.fn().mockReturnValue({ version: '1.0', endpoints: [] }),
|
|
8
8
|
handleAuth: vi.fn().mockResolvedValue({ handled: true, response: { body: { ok: true }, status: 200 } }),
|
|
9
9
|
handleGraphQL: vi.fn().mockResolvedValue({ data: {} }),
|
|
10
|
-
handleMetadata: vi.fn().mockResolvedValue({ handled: true, response: { body: { objects: [] }, status: 200 } }),
|
|
11
|
-
handleData: vi.fn().mockResolvedValue({ handled: true, response: { body: { records: [] }, status: 200 } }),
|
|
12
10
|
handleStorage: vi.fn().mockResolvedValue({ handled: true, response: { body: {}, status: 200 } }),
|
|
11
|
+
dispatch: vi.fn().mockResolvedValue({ handled: true, response: { body: { success: true }, status: 200 } }),
|
|
13
12
|
};
|
|
14
13
|
|
|
15
14
|
vi.mock('@objectstack/runtime', () => {
|
|
@@ -167,27 +166,29 @@ describe('createRequestHandler', () => {
|
|
|
167
166
|
});
|
|
168
167
|
|
|
169
168
|
describe('Metadata', () => {
|
|
170
|
-
it('GET /api/meta/objects
|
|
169
|
+
it('GET /api/meta/objects delegates to dispatch()', async () => {
|
|
171
170
|
const event = makeEvent('http://localhost/api/meta/objects');
|
|
172
171
|
const res = await handler(event);
|
|
173
172
|
expect(res.status).toBe(200);
|
|
174
|
-
expect(mockDispatcher.
|
|
175
|
-
'
|
|
173
|
+
expect(mockDispatcher.dispatch).toHaveBeenCalledWith(
|
|
174
|
+
'GET',
|
|
175
|
+
'/meta/objects',
|
|
176
|
+
undefined,
|
|
177
|
+
expect.any(Object),
|
|
176
178
|
expect.objectContaining({ request: expect.anything() }),
|
|
177
|
-
'GET', undefined,
|
|
178
179
|
);
|
|
179
180
|
});
|
|
180
181
|
});
|
|
181
182
|
|
|
182
183
|
describe('Data', () => {
|
|
183
|
-
it('GET /api/data/account
|
|
184
|
+
it('GET /api/data/account delegates to dispatch()', async () => {
|
|
184
185
|
const event = makeEvent('http://localhost/api/data/account');
|
|
185
186
|
const res = await handler(event);
|
|
186
187
|
expect(res.status).toBe(200);
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
188
|
+
expect(mockDispatcher.dispatch).toHaveBeenCalledWith(
|
|
189
|
+
'GET',
|
|
190
|
+
'/data/account',
|
|
191
|
+
undefined,
|
|
191
192
|
expect.any(Object),
|
|
192
193
|
expect.objectContaining({ request: expect.anything() }),
|
|
193
194
|
);
|
|
@@ -198,15 +199,17 @@ describe('createRequestHandler', () => {
|
|
|
198
199
|
const event = makeEvent('http://localhost/api/data/account', 'POST', body);
|
|
199
200
|
const res = await handler(event);
|
|
200
201
|
expect(res.status).toBe(200);
|
|
201
|
-
expect(mockDispatcher.
|
|
202
|
-
'
|
|
202
|
+
expect(mockDispatcher.dispatch).toHaveBeenCalledWith(
|
|
203
|
+
'POST',
|
|
204
|
+
'/data/account',
|
|
205
|
+
body,
|
|
203
206
|
expect.any(Object),
|
|
204
207
|
expect.objectContaining({ request: expect.anything() }),
|
|
205
208
|
);
|
|
206
209
|
});
|
|
207
210
|
|
|
208
211
|
it('returns 404 when not handled', async () => {
|
|
209
|
-
mockDispatcher.
|
|
212
|
+
mockDispatcher.dispatch.mockResolvedValueOnce({ handled: false });
|
|
210
213
|
const event = makeEvent('http://localhost/api/data/missing');
|
|
211
214
|
const res = await handler(event);
|
|
212
215
|
expect(res.status).toBe(404);
|
|
@@ -227,13 +230,14 @@ describe('createRequestHandler', () => {
|
|
|
227
230
|
|
|
228
231
|
describe('Error handling', () => {
|
|
229
232
|
it('returns 404 for unknown routes', async () => {
|
|
233
|
+
mockDispatcher.dispatch.mockResolvedValueOnce({ handled: false });
|
|
230
234
|
const event = makeEvent('http://localhost/api/unknown');
|
|
231
235
|
const res = await handler(event);
|
|
232
236
|
expect(res.status).toBe(404);
|
|
233
237
|
});
|
|
234
238
|
|
|
235
239
|
it('returns 500 on generic error', async () => {
|
|
236
|
-
mockDispatcher.
|
|
240
|
+
mockDispatcher.dispatch.mockRejectedValueOnce(new Error());
|
|
237
241
|
const event = makeEvent('http://localhost/api/data/account');
|
|
238
242
|
const res = await handler(event);
|
|
239
243
|
expect(res.status).toBe(500);
|
|
@@ -242,7 +246,7 @@ describe('createRequestHandler', () => {
|
|
|
242
246
|
|
|
243
247
|
describe('toResponse', () => {
|
|
244
248
|
it('handles redirect result', async () => {
|
|
245
|
-
mockDispatcher.
|
|
249
|
+
mockDispatcher.dispatch.mockResolvedValueOnce({
|
|
246
250
|
handled: true,
|
|
247
251
|
result: { type: 'redirect', url: 'https://example.com' },
|
|
248
252
|
});
|
|
@@ -253,7 +257,7 @@ describe('createRequestHandler', () => {
|
|
|
253
257
|
});
|
|
254
258
|
|
|
255
259
|
it('handles generic result objects', async () => {
|
|
256
|
-
mockDispatcher.
|
|
260
|
+
mockDispatcher.dispatch.mockResolvedValueOnce({
|
|
257
261
|
handled: true,
|
|
258
262
|
result: { foo: 'bar' },
|
|
259
263
|
});
|