@objectstack/nuxt 4.0.4 → 4.1.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 CHANGED
@@ -1,20 +1,59 @@
1
1
  # @objectstack/nuxt
2
2
 
3
- The official Nuxt adapter for ObjectStack, built on h3.
3
+ > Nuxt adapter for ObjectStack Nitro/h3 server routes for the auto-generated REST API.
4
4
 
5
- ## Features
6
- - h3 router integration for Nuxt server routes
7
- - Full Auth/GraphQL/Metadata/Data/Storage routes
8
- - AuthPlugin service support
9
- - Works with standalone h3 apps too
5
+ [![npm](https://img.shields.io/npm/v/@objectstack/nuxt.svg)](https://www.npmjs.com/package/@objectstack/nuxt)
6
+ [![License: Apache-2.0](https://img.shields.io/badge/License-Apache--2.0-blue.svg)](https://opensource.org/licenses/Apache-2.0)
10
7
 
11
- ## Usage
8
+ ## Overview
9
+
10
+ Provides an h3 router factory that exposes all ObjectStack dispatcher routes, mountable inside `server/api/[...].ts` of any Nuxt 3 application (or directly in a standalone Nitro app).
11
+
12
+ ## Installation
13
+
14
+ ```bash
15
+ pnpm add @objectstack/nuxt
16
+ ```
17
+
18
+ ## Quick Start
12
19
 
13
20
  ```typescript
14
- // server/api/[...].ts
21
+ // server/api/[...objectstack].ts
15
22
  import { createH3Router } from '@objectstack/nuxt';
16
- import { kernel } from '../kernel';
23
+ import { kernel } from '~/server/kernel';
17
24
 
18
- const router = createH3Router({ kernel });
19
- export default defineEventHandler(router.handler);
25
+ export default createH3Router({ kernel, prefix: '/api' }).handler;
20
26
  ```
27
+
28
+ ## Key Exports
29
+
30
+ | Export | Kind | Description |
31
+ |:---|:---|:---|
32
+ | `createH3Router(options)` | function | h3 `Router` with dispatcher routes installed. |
33
+ | `NuxtAdapterOptions` | interface | `{ kernel, prefix? }`. |
34
+
35
+ ## Middleware order
36
+
37
+ Register Nuxt server middleware that rewrites or compresses responses **before** this router. Do not wrap ObjectStack routes with `defineEventHandler` validators.
38
+
39
+ ## When to use
40
+
41
+ - ✅ Nuxt 3 / Nitro applications.
42
+ - ✅ Any h3-based server (used directly via `createH3Router`).
43
+
44
+ ## When not to use
45
+
46
+ - ❌ Nuxt 2 is not supported.
47
+
48
+ ## Related Packages
49
+
50
+ - [`@objectstack/runtime`](../../runtime), [`@objectstack/rest`](../../rest).
51
+
52
+ ## Links
53
+
54
+ - 📖 Docs: <https://objectstack.ai/docs>
55
+ - 📚 API Reference: <https://objectstack.ai/docs/references>
56
+
57
+ ## License
58
+
59
+ Apache-2.0 © ObjectStack
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@objectstack/nuxt",
3
- "version": "4.0.4",
3
+ "version": "4.1.0",
4
4
  "license": "Apache-2.0",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",
@@ -13,13 +13,39 @@
13
13
  },
14
14
  "peerDependencies": {
15
15
  "h3": "^1.15.11",
16
- "@objectstack/runtime": "^4.0.4"
16
+ "@objectstack/runtime": "^4.1.0"
17
17
  },
18
18
  "devDependencies": {
19
19
  "h3": "^1.15.11",
20
- "typescript": "^6.0.2",
21
- "vitest": "^4.1.4",
22
- "@objectstack/runtime": "4.0.4"
20
+ "typescript": "^6.0.3",
21
+ "vitest": "^4.1.7",
22
+ "@objectstack/runtime": "4.1.0"
23
+ },
24
+ "description": "Nuxt adapter for ObjectStack — Nitro server routes for the ObjectStack REST API.",
25
+ "keywords": [
26
+ "objectstack",
27
+ "nuxt",
28
+ "adapter",
29
+ "nitro",
30
+ "rest"
31
+ ],
32
+ "author": "ObjectStack",
33
+ "repository": {
34
+ "type": "git",
35
+ "url": "https://github.com/objectstack-ai/framework.git",
36
+ "directory": "packages/adapters/nuxt"
37
+ },
38
+ "homepage": "https://objectstack.ai/docs",
39
+ "bugs": "https://github.com/objectstack-ai/framework/issues",
40
+ "publishConfig": {
41
+ "access": "public"
42
+ },
43
+ "files": [
44
+ "dist",
45
+ "README.md"
46
+ ],
47
+ "engines": {
48
+ "node": ">=18.0.0"
23
49
  },
24
50
  "scripts": {
25
51
  "build": "tsup --config ../../../tsup.config.ts",
@@ -1,22 +0,0 @@
1
-
2
- > @objectstack/nuxt@4.0.4 build /home/runner/work/framework/framework/packages/adapters/nuxt
3
- > tsup --config ../../../tsup.config.ts
4
-
5
- CLI Building entry: src/index.ts
6
- CLI Using tsconfig: tsconfig.json
7
- CLI tsup v8.5.1
8
- CLI Using tsup config: /home/runner/work/framework/framework/tsup.config.ts
9
- CLI Target: es2020
10
- CLI Cleaning output folder
11
- ESM Build start
12
- CJS Build start
13
- ESM dist/index.mjs 5.86 KB
14
- ESM dist/index.mjs.map 12.34 KB
15
- ESM ⚡️ Build success in 66ms
16
- CJS dist/index.js 7.07 KB
17
- CJS dist/index.js.map 12.31 KB
18
- CJS ⚡️ Build success in 66ms
19
- DTS Build start
20
- DTS ⚡️ Build success in 12490ms
21
- DTS dist/index.d.mts 1015.00 B
22
- DTS dist/index.d.ts 1015.00 B
package/CHANGELOG.md DELETED
@@ -1,194 +0,0 @@
1
- # @objectstack/nuxt
2
-
3
- ## 4.0.4
4
-
5
- ### Patch Changes
6
-
7
- - @objectstack/runtime@4.0.4
8
-
9
- ## 4.0.3
10
-
11
- ### Patch Changes
12
-
13
- - @objectstack/runtime@4.0.3
14
-
15
- ## 4.0.2
16
-
17
- ### Patch Changes
18
-
19
- - @objectstack/runtime@4.0.2
20
-
21
- ## 4.0.0
22
-
23
- ### Patch Changes
24
-
25
- - f08ffc3: Fix discovery API endpoint routing and protocol consistency.
26
-
27
- **Discovery route standardization:**
28
-
29
- - All adapters (Express, Fastify, Hono, NestJS, Next.js, Nuxt, SvelteKit) now mount the discovery endpoint at `{prefix}/discovery` instead of `{prefix}` root.
30
- - `.well-known/objectstack` redirects now point to `{prefix}/discovery`.
31
- - Client `connect()` fallback URL changed from `/api/v1` to `/api/v1/discovery`.
32
- - Runtime dispatcher handles both `/discovery` (standard) and `/` (legacy) for backward compatibility.
33
-
34
- **Schema & route alignment:**
35
-
36
- - Added `storage` (service: `file-storage`) and `feed` (service: `data`) routes to `DEFAULT_DISPATCHER_ROUTES`.
37
- - Added `feed` and `discovery` fields to `ApiRoutesSchema`.
38
- - Unified `GetDiscoveryResponseSchema` with `DiscoverySchema` as single source of truth.
39
- - Client `getRoute('feed')` fallback updated from `/api/v1/data` to `/api/v1/feed`.
40
-
41
- **Type safety:**
42
-
43
- - Extracted `ApiRouteType` from `ApiRoutes` keys for type-safe client route resolution.
44
- - Removed `as any` type casting in client route access.
45
-
46
- - Updated dependencies [f08ffc3]
47
- - Updated dependencies [e0b0a78]
48
- - @objectstack/runtime@4.0.0
49
-
50
- ## 3.3.1
51
-
52
- ### Patch Changes
53
-
54
- - @objectstack/runtime@3.3.1
55
-
56
- ## 3.3.0
57
-
58
- ### Patch Changes
59
-
60
- - @objectstack/runtime@3.3.0
61
-
62
- ## 3.2.9
63
-
64
- ### Patch Changes
65
-
66
- - @objectstack/runtime@3.2.9
67
-
68
- ## 3.2.8
69
-
70
- ### Patch Changes
71
-
72
- - @objectstack/runtime@3.2.8
73
-
74
- ## 3.2.8
75
-
76
- ### Patch Changes
77
-
78
- - fix: unified catch-all dispatch pattern — `createH3Router()` now delegates all non-framework-specific routes to `HttpDispatcher.dispatch()`, automatically supporting packages, analytics, automation, i18n, ui, openapi, custom endpoints, and any future routes
79
- - Only auth (service check), storage (multipart), GraphQL (raw result), and discovery (response wrapper) remain as explicit routes
80
-
81
- ## 3.2.7
82
-
83
- ### Patch Changes
84
-
85
- - @objectstack/runtime@3.2.7
86
-
87
- ## 3.2.6
88
-
89
- ### Patch Changes
90
-
91
- - @objectstack/runtime@3.2.6
92
-
93
- ## 3.2.5
94
-
95
- ### Patch Changes
96
-
97
- - @objectstack/runtime@3.2.5
98
-
99
- ## 3.2.4
100
-
101
- ### Patch Changes
102
-
103
- - @objectstack/runtime@3.2.4
104
-
105
- ## 3.2.3
106
-
107
- ### Patch Changes
108
-
109
- - @objectstack/runtime@3.2.3
110
-
111
- ## 3.2.2
112
-
113
- ### Patch Changes
114
-
115
- - @objectstack/runtime@3.2.2
116
-
117
- ## 3.2.1
118
-
119
- ### Patch Changes
120
-
121
- - @objectstack/runtime@3.2.1
122
-
123
- ## 3.2.0
124
-
125
- ### Patch Changes
126
-
127
- - @objectstack/runtime@3.2.0
128
-
129
- ## 3.1.1
130
-
131
- ### Patch Changes
132
-
133
- - @objectstack/runtime@3.1.1
134
-
135
- ## 3.1.0
136
-
137
- ### Patch Changes
138
-
139
- - @objectstack/runtime@3.1.0
140
-
141
- ## 3.0.11
142
-
143
- ### Patch Changes
144
-
145
- - @objectstack/runtime@3.0.11
146
-
147
- ## 3.0.10
148
-
149
- ### Patch Changes
150
-
151
- - @objectstack/runtime@3.0.10
152
-
153
- ## 3.0.9
154
-
155
- ### Patch Changes
156
-
157
- - @objectstack/runtime@3.0.9
158
-
159
- ## 3.0.8
160
-
161
- ### Patch Changes
162
-
163
- - @objectstack/runtime@3.0.8
164
-
165
- ## 3.0.7
166
-
167
- ### Patch Changes
168
-
169
- - @objectstack/runtime@3.0.7
170
-
171
- ## 3.0.6
172
-
173
- ### Patch Changes
174
-
175
- - @objectstack/runtime@3.0.6
176
-
177
- ## 3.0.5
178
-
179
- ### Patch Changes
180
-
181
- - @objectstack/runtime@3.0.5
182
-
183
- ## 3.0.4
184
-
185
- ### Patch Changes
186
-
187
- - @objectstack/runtime@3.0.4
188
-
189
- ## 3.0.3
190
-
191
- ### Patch Changes
192
-
193
- - Updated dependencies [c7267f6]
194
- - @objectstack/runtime@3.0.3
@@ -1,4 +0,0 @@
1
- // Stub for @objectstack/runtime - replaced by vi.mock in tests
2
- export const HttpDispatcher = class {};
3
- export type ObjectKernel = any;
4
- export type HttpDispatcherResult = any;
package/src/index.ts DELETED
@@ -1,229 +0,0 @@
1
- // Copyright (c) 2025 ObjectStack. Licensed under the Apache-2.0 license.
2
-
3
- import {
4
- createRouter,
5
- defineEventHandler,
6
- getQuery,
7
- readBody,
8
- sendRedirect,
9
- setResponseHeader,
10
- setResponseStatus,
11
- type H3Event,
12
- type Router,
13
- } from 'h3';
14
- import { type ObjectKernel, HttpDispatcher, HttpDispatcherResult } from '@objectstack/runtime';
15
-
16
- export interface NuxtAdapterOptions {
17
- kernel: ObjectKernel;
18
- prefix?: string;
19
- }
20
-
21
- /**
22
- * Auth service interface with handleRequest method
23
- */
24
- interface AuthService {
25
- handleRequest(request: Request): Promise<Response>;
26
- }
27
-
28
- /**
29
- * Creates an h3 router with all ObjectStack route dispatchers.
30
- * Designed for use in Nuxt server routes or standalone h3 apps.
31
- *
32
- * Only routes that need framework-specific handling (auth service, storage
33
- * file upload, GraphQL raw result, discovery wrapper) are registered explicitly.
34
- * All other routes are handled by a catch-all that delegates to
35
- * `HttpDispatcher.dispatch()`, making the adapter automatically support
36
- * new routes added to the dispatcher.
37
- *
38
- * @example
39
- * ```ts
40
- * // server/api/[...].ts
41
- * import { createH3Router } from '@objectstack/nuxt';
42
- * import { kernel } from '../kernel';
43
- *
44
- * const router = createH3Router({ kernel });
45
- * export default defineEventHandler(router.handler);
46
- * ```
47
- */
48
- export function createH3Router(options: NuxtAdapterOptions): Router {
49
- const router = createRouter();
50
- const dispatcher = new HttpDispatcher(options.kernel);
51
- const prefix = options.prefix || '/api';
52
-
53
- const errorJson = (event: H3Event, message: string, code: number = 500) => {
54
- setResponseStatus(event, code);
55
- return { success: false, error: { message, code } };
56
- };
57
-
58
- const toResponse = (event: H3Event, result: HttpDispatcherResult) => {
59
- if (result.handled) {
60
- if (result.response) {
61
- if (result.response.headers) {
62
- Object.entries(result.response.headers).forEach(([k, v]) =>
63
- setResponseHeader(event, k, v as string),
64
- );
65
- }
66
- setResponseStatus(event, result.response.status);
67
- return result.response.body;
68
- }
69
- if (result.result) {
70
- const res = result.result;
71
- if (res.type === 'redirect' && res.url) {
72
- return sendRedirect(event, res.url);
73
- }
74
- if (res.type === 'stream' && res.stream) {
75
- if (res.headers) {
76
- Object.entries(res.headers).forEach(([k, v]) =>
77
- setResponseHeader(event, k, v as string),
78
- );
79
- }
80
- return res.stream;
81
- }
82
- return res;
83
- }
84
- }
85
- return errorJson(event, 'Not Found', 404);
86
- };
87
-
88
- // ─── Explicit routes (framework-specific handling required) ────────────────
89
-
90
- // --- Discovery ---
91
- router.get(
92
- prefix,
93
- defineEventHandler(async () => {
94
- return { data: await dispatcher.getDiscoveryInfo(prefix) };
95
- }),
96
- );
97
-
98
- router.get(
99
- `${prefix}/discovery`,
100
- defineEventHandler(async () => {
101
- return { data: await dispatcher.getDiscoveryInfo(prefix) };
102
- }),
103
- );
104
-
105
- // --- .well-known ---
106
- router.get(
107
- '/.well-known/objectstack',
108
- defineEventHandler((event) => {
109
- return sendRedirect(event, prefix);
110
- }),
111
- );
112
-
113
- // --- Auth (needs auth service integration) ---
114
- router.use(
115
- `${prefix}/auth/**`,
116
- defineEventHandler(async (event) => {
117
- try {
118
- const urlPath = event.path || event.node.req.url || '';
119
- const path = urlPath.substring(`${prefix}/auth/`.length).split('?')[0];
120
- const method = event.method;
121
-
122
- // Try AuthPlugin service first (prefer async to support factory-based services)
123
- let authService: AuthService | null = null;
124
- try {
125
- if (typeof options.kernel.getServiceAsync === 'function') {
126
- authService = await options.kernel.getServiceAsync<AuthService>('auth');
127
- } else if (typeof options.kernel.getService === 'function') {
128
- authService = options.kernel.getService<AuthService>('auth');
129
- }
130
- } catch {
131
- // Service not registered — fall through to dispatcher
132
- authService = null;
133
- }
134
-
135
- if (authService && typeof authService.handleRequest === 'function') {
136
- const host = event.node.req.headers.host || 'localhost';
137
- const protocol = (event.node.req.socket as any)?.encrypted ? 'https' : 'http';
138
- const url = `${protocol}://${host}${urlPath}`;
139
- const headers = new Headers();
140
- if (event.node.req.headers) {
141
- Object.entries(event.node.req.headers).forEach(([k, v]) => {
142
- if (typeof v === 'string') headers.set(k, v);
143
- else if (Array.isArray(v)) headers.set(k, v.join(', '));
144
- });
145
- }
146
- const init: RequestInit = { method, headers };
147
- if (method !== 'GET' && method !== 'HEAD') {
148
- const body = await readBody(event);
149
- if (body) {
150
- init.body = typeof body === 'string' ? body : JSON.stringify(body);
151
- if (!headers.has('content-type')) {
152
- headers.set('content-type', 'application/json');
153
- }
154
- }
155
- }
156
- const webRequest = new Request(url, init);
157
- const response = await authService.handleRequest(webRequest);
158
- setResponseStatus(event, response.status);
159
- response.headers.forEach((v: string, k: string) => setResponseHeader(event, k, v));
160
- return await response.text();
161
- }
162
-
163
- // Fallback to dispatcher
164
- const body = method === 'GET' || method === 'HEAD'
165
- ? {}
166
- : await readBody(event).catch(() => ({}));
167
- const result = await dispatcher.handleAuth(path, method, body, { request: event.node.req });
168
- return toResponse(event, result);
169
- } catch (err: any) {
170
- return errorJson(event, err.message || 'Internal Server Error', err.statusCode || 500);
171
- }
172
- }),
173
- );
174
-
175
- // --- GraphQL (returns raw result, not HttpDispatcherResult) ---
176
- router.post(
177
- `${prefix}/graphql`,
178
- defineEventHandler(async (event) => {
179
- try {
180
- const body = await readBody(event);
181
- const result = await dispatcher.handleGraphQL(body, { request: event.node.req });
182
- return result;
183
- } catch (err: any) {
184
- return errorJson(event, err.message || 'Internal Server Error', err.statusCode || 500);
185
- }
186
- }),
187
- );
188
-
189
- // --- Storage (needs multipart form parsing) ---
190
- router.use(
191
- `${prefix}/storage/**`,
192
- defineEventHandler(async (event) => {
193
- try {
194
- const urlPath = (event.path || event.node.req.url || '').split('?')[0];
195
- const subPath = urlPath.substring(`${prefix}/storage`.length);
196
- const method = event.method;
197
- const file = undefined; // File upload requires multipart parsing (e.g., formidable)
198
- const result = await dispatcher.handleStorage(subPath, method, file, { request: event.node.req });
199
- return toResponse(event, result);
200
- } catch (err: any) {
201
- return errorJson(event, err.message || 'Internal Server Error', err.statusCode || 500);
202
- }
203
- }),
204
- );
205
-
206
- // ─── Catch-all: delegate to dispatcher.dispatch() ─────────────────────────
207
- // Handles meta, data, packages, analytics, automation, i18n, ui, openapi,
208
- // custom API endpoints, and any future routes added to HttpDispatcher.
209
- router.use(
210
- `${prefix}/**`,
211
- defineEventHandler(async (event) => {
212
- try {
213
- const urlPath = (event.path || event.node.req.url || '').split('?')[0];
214
- const subPath = urlPath.substring(prefix.length);
215
- const method = event.method;
216
- const body = (method === 'POST' || method === 'PUT' || method === 'PATCH')
217
- ? await readBody(event)
218
- : undefined;
219
- const query = getQuery(event);
220
- const result = await dispatcher.dispatch(method, subPath, body, query, { request: event.node.req }, prefix);
221
- return toResponse(event, result);
222
- } catch (err: any) {
223
- return errorJson(event, err.message || 'Internal Server Error', err.statusCode || 500);
224
- }
225
- }),
226
- );
227
-
228
- return router;
229
- }
package/src/nuxt.test.ts DELETED
@@ -1,144 +0,0 @@
1
- // Copyright (c) 2025 ObjectStack. Licensed under the Apache-2.0 license.
2
-
3
- import { describe, it, expect, vi, beforeEach } from 'vitest';
4
-
5
- // Mock dispatcher instance
6
- const mockDispatcher = {
7
- getDiscoveryInfo: vi.fn().mockReturnValue({ version: '1.0', endpoints: [] }),
8
- handleAuth: vi.fn().mockResolvedValue({ handled: true, response: { body: { ok: true }, status: 200 } }),
9
- handleGraphQL: vi.fn().mockResolvedValue({ data: {} }),
10
- handleStorage: vi.fn().mockResolvedValue({ handled: true, response: { body: {}, status: 200 } }),
11
- dispatch: vi.fn().mockResolvedValue({ handled: true, response: { body: { success: true }, status: 200 } }),
12
- };
13
-
14
- vi.mock('@objectstack/runtime', () => {
15
- return {
16
- HttpDispatcher: function HttpDispatcher() {
17
- return mockDispatcher;
18
- },
19
- };
20
- });
21
-
22
- import { createApp, toNodeListener, createEvent } from 'h3';
23
- import { createH3Router } from './index';
24
- import http from 'node:http';
25
-
26
- const mockKernel = { name: 'test-kernel' } as any;
27
-
28
- function createTestApp() {
29
- const app = createApp();
30
- const router = createH3Router({ kernel: mockKernel });
31
- app.use(router);
32
- return app;
33
- }
34
-
35
- async function makeRequest(app: any, url: string, method = 'GET', body?: any) {
36
- const listener = toNodeListener(app);
37
-
38
- return new Promise<{ status: number; body: any }>((resolve, reject) => {
39
- const server = http.createServer(listener);
40
- server.listen(0, () => {
41
- const addr = server.address() as any;
42
- const reqOpts: http.RequestOptions = {
43
- hostname: 'localhost',
44
- port: addr.port,
45
- path: url,
46
- method,
47
- headers: body ? { 'Content-Type': 'application/json' } : {},
48
- };
49
- const req = http.request(reqOpts, (res) => {
50
- let data = '';
51
- res.on('data', (chunk) => { data += chunk; });
52
- res.on('end', () => {
53
- server.close();
54
- try {
55
- resolve({ status: res.statusCode || 500, body: JSON.parse(data) });
56
- } catch {
57
- resolve({ status: res.statusCode || 500, body: data });
58
- }
59
- });
60
- });
61
- req.on('error', (err) => { server.close(); reject(err); });
62
- if (body) req.write(JSON.stringify(body));
63
- req.end();
64
- });
65
- });
66
- }
67
-
68
- describe('createH3Router', () => {
69
- beforeEach(() => {
70
- vi.clearAllMocks();
71
- });
72
-
73
- it('handles discovery endpoint', async () => {
74
- const app = createTestApp();
75
- const res = await makeRequest(app, '/api');
76
- expect(res.status).toBe(200);
77
- expect(res.body.data).toBeDefined();
78
- expect(res.body.data.version).toBe('1.0');
79
- expect(mockDispatcher.getDiscoveryInfo).toHaveBeenCalledWith('/api');
80
- });
81
-
82
- it('handles auth route', async () => {
83
- const app = createTestApp();
84
- const res = await makeRequest(app, '/api/auth/login', 'POST', { email: 'a@b.com' });
85
- expect(res.status).toBe(200);
86
- expect(res.body.ok).toBe(true);
87
- expect(mockDispatcher.handleAuth).toHaveBeenCalled();
88
- });
89
-
90
- it('handles graphql route', async () => {
91
- const app = createTestApp();
92
- const body = { query: '{ objects { name } }' };
93
- const res = await makeRequest(app, '/api/graphql', 'POST', body);
94
- expect(res.status).toBe(200);
95
- expect(res.body.data).toBeDefined();
96
- expect(mockDispatcher.handleGraphQL).toHaveBeenCalled();
97
- });
98
-
99
- it('handles metadata route', async () => {
100
- const app = createTestApp();
101
- const res = await makeRequest(app, '/api/meta/objects');
102
- expect(res.status).toBe(200);
103
- expect(mockDispatcher.dispatch).toHaveBeenCalledWith(
104
- 'GET',
105
- '/meta/objects',
106
- undefined,
107
- expect.any(Object),
108
- expect.objectContaining({ request: expect.anything() }),
109
- '/api',
110
- );
111
- });
112
-
113
- it('handles data route', async () => {
114
- const app = createTestApp();
115
- const res = await makeRequest(app, '/api/data/account');
116
- expect(res.status).toBe(200);
117
- expect(mockDispatcher.dispatch).toHaveBeenCalledWith(
118
- 'GET',
119
- '/data/account',
120
- undefined,
121
- expect.any(Object),
122
- expect.objectContaining({ request: expect.anything() }),
123
- '/api',
124
- );
125
- });
126
-
127
- it('handles storage route', async () => {
128
- const app = createTestApp();
129
- const res = await makeRequest(app, '/api/storage/files');
130
- expect(res.status).toBe(200);
131
- expect(mockDispatcher.handleStorage).toHaveBeenCalled();
132
- });
133
-
134
- it('handles errors', async () => {
135
- mockDispatcher.dispatch.mockRejectedValueOnce(
136
- Object.assign(new Error('Forbidden'), { statusCode: 403 }),
137
- );
138
- const app = createTestApp();
139
- const res = await makeRequest(app, '/api/data/account');
140
- expect(res.status).toBe(403);
141
- expect(res.body.success).toBe(false);
142
- expect(res.body.error.message).toBe('Forbidden');
143
- });
144
- });
package/tsconfig.json DELETED
@@ -1,26 +0,0 @@
1
- {
2
- "extends": "../../../tsconfig.json",
3
- "compilerOptions": {
4
- "outDir": "./dist",
5
- "rootDir": "./src",
6
- "module": "NodeNext",
7
- "moduleResolution": "NodeNext",
8
- "esModuleInterop": true,
9
- "skipLibCheck": true,
10
- "lib": [
11
- "ES2020",
12
- "DOM",
13
- "DOM.Iterable"
14
- ],
15
- "types": [
16
- "node"
17
- ]
18
- },
19
- "include": [
20
- "src/**/*"
21
- ],
22
- "exclude": [
23
- "node_modules",
24
- "dist"
25
- ]
26
- }
package/vitest.config.ts DELETED
@@ -1,16 +0,0 @@
1
- // Copyright (c) 2025 ObjectStack. Licensed under the Apache-2.0 license.
2
-
3
- import { defineConfig } from 'vitest/config';
4
- import path from 'node:path';
5
-
6
- export default defineConfig({
7
- test: {
8
- globals: true,
9
- environment: 'node',
10
- },
11
- resolve: {
12
- alias: {
13
- '@objectstack/runtime': path.resolve(__dirname, 'src/__mocks__/runtime.ts'),
14
- },
15
- },
16
- });