vitek-plugin 0.1.2-beta.5 → 0.2.0-beta
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 +35 -4
- package/dist/adapters/vite/dev-server-middleware.d.ts +8 -0
- package/dist/adapters/vite/dev-server-middleware.d.ts.map +1 -0
- package/dist/adapters/vite/dev-server-middleware.js +30 -0
- package/dist/adapters/vite/dev-server-state.d.ts +41 -0
- package/dist/adapters/vite/dev-server-state.d.ts.map +1 -0
- package/dist/adapters/vite/dev-server-state.js +191 -0
- package/dist/adapters/vite/dev-server.d.ts +2 -21
- package/dist/adapters/vite/dev-server.d.ts.map +1 -1
- package/dist/adapters/vite/dev-server.js +7 -379
- package/dist/adapters/vite/path-utils.d.ts +20 -0
- package/dist/adapters/vite/path-utils.d.ts.map +1 -0
- package/dist/adapters/vite/path-utils.js +46 -0
- package/dist/adapters/vite/path-utils.test.d.ts +2 -0
- package/dist/adapters/vite/path-utils.test.d.ts.map +1 -0
- package/dist/adapters/vite/path-utils.test.js +79 -0
- package/dist/build/build-api-bundle.d.ts +1 -0
- package/dist/build/build-api-bundle.d.ts.map +1 -1
- package/dist/build/build-api-bundle.js +38 -3
- package/dist/build/build-api-bundle.test.d.ts +2 -0
- package/dist/build/build-api-bundle.test.d.ts.map +1 -0
- package/dist/build/build-api-bundle.test.js +50 -0
- package/dist/build/build-sockets-bundle.test.d.ts +2 -0
- package/dist/build/build-sockets-bundle.test.d.ts.map +1 -0
- package/dist/build/build-sockets-bundle.test.js +49 -0
- package/dist/cli/cli.d.ts +8 -0
- package/dist/cli/cli.d.ts.map +1 -0
- package/dist/cli/cli.js +25 -0
- package/dist/cli/fixtures/serve-config/vitek.config.d.mts +6 -0
- package/dist/cli/fixtures/serve-config/vitek.config.d.mts.map +1 -0
- package/dist/cli/fixtures/serve-config/vitek.config.mjs +19 -0
- package/dist/cli/init.d.ts +15 -0
- package/dist/cli/init.d.ts.map +1 -0
- package/dist/cli/init.js +99 -0
- package/dist/cli/init.test.d.ts +2 -0
- package/dist/cli/init.test.d.ts.map +1 -0
- package/dist/cli/init.test.js +117 -0
- package/dist/cli/mcp-project-config.d.ts +8 -0
- package/dist/cli/mcp-project-config.d.ts.map +1 -0
- package/dist/cli/mcp-project-config.js +26 -0
- package/dist/cli/mcp-project.d.ts +2 -0
- package/dist/cli/mcp-project.d.ts.map +1 -0
- package/dist/cli/mcp-project.js +101 -0
- package/dist/cli/serve.d.ts +27 -1
- package/dist/cli/serve.d.ts.map +1 -1
- package/dist/cli/serve.js +85 -10
- package/dist/cli/serve.test.d.ts +2 -0
- package/dist/cli/serve.test.d.ts.map +1 -0
- package/dist/cli/serve.test.js +108 -0
- package/dist/core/asyncapi/generate.d.ts +5 -3
- package/dist/core/asyncapi/generate.d.ts.map +1 -1
- package/dist/core/asyncapi/generate.test.d.ts +2 -0
- package/dist/core/asyncapi/generate.test.d.ts.map +1 -0
- package/dist/core/asyncapi/generate.test.js +120 -0
- package/dist/core/context/create-context.d.ts +2 -0
- package/dist/core/context/create-context.d.ts.map +1 -1
- package/dist/core/file-system/extract-type-from-file.d.ts +4 -0
- package/dist/core/file-system/extract-type-from-file.d.ts.map +1 -0
- package/dist/core/file-system/extract-type-from-file.js +77 -0
- package/dist/core/file-system/extract-type-from-file.test.d.ts +2 -0
- package/dist/core/file-system/extract-type-from-file.test.d.ts.map +1 -0
- package/dist/core/file-system/extract-type-from-file.test.js +75 -0
- package/dist/core/file-system/watch-api-dir.d.ts +4 -1
- package/dist/core/file-system/watch-api-dir.d.ts.map +1 -1
- package/dist/core/file-system/watch-api-dir.js +31 -6
- package/dist/core/file-system/watch-api-dir.test.d.ts +2 -0
- package/dist/core/file-system/watch-api-dir.test.d.ts.map +1 -0
- package/dist/core/file-system/watch-api-dir.test.js +38 -0
- package/dist/core/generation/run-file-generation.d.ts +24 -0
- package/dist/core/generation/run-file-generation.d.ts.map +1 -0
- package/dist/core/generation/run-file-generation.js +90 -0
- package/dist/core/generation/run-file-generation.test.d.ts +2 -0
- package/dist/core/generation/run-file-generation.test.d.ts.map +1 -0
- package/dist/core/generation/run-file-generation.test.js +151 -0
- package/dist/core/introspection/manifest.d.ts +24 -0
- package/dist/core/introspection/manifest.d.ts.map +1 -0
- package/dist/core/introspection/manifest.js +41 -0
- package/dist/core/introspection/manifest.test.d.ts +2 -0
- package/dist/core/introspection/manifest.test.d.ts.map +1 -0
- package/dist/core/introspection/manifest.test.js +62 -0
- package/dist/core/middleware/get-applicable-middlewares.d.ts +7 -0
- package/dist/core/middleware/get-applicable-middlewares.d.ts.map +1 -1
- package/dist/core/middleware/get-applicable-middlewares.js +23 -15
- package/dist/core/middleware/get-applicable-middlewares.test.js +36 -1
- package/dist/core/openapi/generate.d.ts +5 -74
- package/dist/core/openapi/generate.d.ts.map +1 -1
- package/dist/core/openapi/generate.js +4 -419
- package/dist/core/openapi/generate.test.d.ts +2 -0
- package/dist/core/openapi/generate.test.d.ts.map +1 -0
- package/dist/core/openapi/generate.test.js +184 -0
- package/dist/core/openapi/jsdoc.d.ts +3 -0
- package/dist/core/openapi/jsdoc.d.ts.map +1 -0
- package/dist/core/openapi/jsdoc.js +68 -0
- package/dist/core/openapi/jsdoc.test.d.ts +2 -0
- package/dist/core/openapi/jsdoc.test.d.ts.map +1 -0
- package/dist/core/openapi/jsdoc.test.js +111 -0
- package/dist/core/openapi/spec-builder.d.ts +4 -0
- package/dist/core/openapi/spec-builder.d.ts.map +1 -0
- package/dist/core/openapi/spec-builder.js +257 -0
- package/dist/core/openapi/spec-builder.test.d.ts +2 -0
- package/dist/core/openapi/spec-builder.test.d.ts.map +1 -0
- package/dist/core/openapi/spec-builder.test.js +93 -0
- package/dist/core/openapi/types.d.ts +42 -0
- package/dist/core/openapi/types.d.ts.map +1 -0
- package/dist/core/openapi/types.js +5 -0
- package/dist/core/server/cors.d.ts +29 -0
- package/dist/core/server/cors.d.ts.map +1 -0
- package/dist/core/server/cors.js +55 -0
- package/dist/core/server/cors.test.d.ts +2 -0
- package/dist/core/server/cors.test.d.ts.map +1 -0
- package/dist/core/server/cors.test.js +49 -0
- package/dist/core/server/proxy.d.ts +16 -0
- package/dist/core/server/proxy.d.ts.map +1 -0
- package/dist/core/server/proxy.js +20 -0
- package/dist/core/server/proxy.test.d.ts +2 -0
- package/dist/core/server/proxy.test.d.ts.map +1 -0
- package/dist/core/server/proxy.test.js +53 -0
- package/dist/core/server/request-handler.d.ts +17 -3
- package/dist/core/server/request-handler.d.ts.map +1 -1
- package/dist/core/server/request-handler.js +192 -84
- package/dist/core/server/request-handler.test.js +287 -22
- package/dist/core/socket/socket-handler.test.d.ts +2 -0
- package/dist/core/socket/socket-handler.test.d.ts.map +1 -0
- package/dist/core/socket/socket-handler.test.js +107 -0
- package/dist/core/types/schema.test.d.ts +2 -0
- package/dist/core/types/schema.test.d.ts.map +1 -0
- package/dist/core/types/schema.test.js +41 -0
- package/dist/core/validation/types.d.ts +2 -1
- package/dist/core/validation/types.d.ts.map +1 -1
- package/dist/core/validation/validator.d.ts +4 -16
- package/dist/core/validation/validator.d.ts.map +1 -1
- package/dist/core/validation/validator.js +4 -16
- package/dist/index.d.ts +6 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +2 -1
- package/dist/plugin/context.d.ts +15 -0
- package/dist/plugin/context.d.ts.map +1 -0
- package/dist/plugin/context.js +12 -0
- package/dist/plugin/options.d.ts +46 -0
- package/dist/plugin/options.d.ts.map +1 -0
- package/dist/plugin/options.js +1 -0
- package/dist/plugin/plugin-api.d.ts +49 -0
- package/dist/plugin/plugin-api.d.ts.map +1 -0
- package/dist/plugin/plugin-api.js +5 -0
- package/dist/plugin/vitek-build.d.ts +7 -0
- package/dist/plugin/vitek-build.d.ts.map +1 -0
- package/dist/plugin/vitek-build.js +104 -0
- package/dist/plugin/vitek-config.d.ts +4 -0
- package/dist/plugin/vitek-config.d.ts.map +1 -0
- package/dist/plugin/vitek-config.js +51 -0
- package/dist/plugin/vitek-config.test.d.ts +2 -0
- package/dist/plugin/vitek-config.test.d.ts.map +1 -0
- package/dist/plugin/vitek-config.test.js +62 -0
- package/dist/plugin/vitek-dev.d.ts +7 -0
- package/dist/plugin/vitek-dev.d.ts.map +1 -0
- package/dist/plugin/vitek-dev.js +71 -0
- package/dist/plugin/vitek-preview.d.ts +7 -0
- package/dist/plugin/vitek-preview.d.ts.map +1 -0
- package/dist/plugin/vitek-preview.js +107 -0
- package/dist/plugin/vitek-resolve.d.ts +7 -0
- package/dist/plugin/vitek-resolve.d.ts.map +1 -0
- package/dist/plugin/vitek-resolve.js +25 -0
- package/dist/plugin/vitek-transform.d.ts +7 -0
- package/dist/plugin/vitek-transform.d.ts.map +1 -0
- package/dist/plugin/vitek-transform.js +55 -0
- package/dist/plugin/vitek.d.ts +10 -0
- package/dist/plugin/vitek.d.ts.map +1 -0
- package/dist/plugin/vitek.js +27 -0
- package/dist/plugin.d.ts +3 -32
- package/dist/plugin.d.ts.map +1 -1
- package/dist/plugin.js +2 -246
- package/dist/plugin.test.js +114 -28
- package/dist/shared/response-helpers.d.ts +21 -0
- package/dist/shared/response-helpers.d.ts.map +1 -1
- package/dist/shared/response-helpers.js +41 -0
- package/dist/shared/response-helpers.test.js +54 -1
- package/package.json +19 -4
package/dist/plugin.js
CHANGED
|
@@ -1,249 +1,5 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Main Vite plugin
|
|
3
|
-
*
|
|
3
|
+
* Exports VitekOptions and vitek() — aggregates sub-plugins
|
|
4
4
|
*/
|
|
5
|
-
|
|
6
|
-
import * as fs from 'fs';
|
|
7
|
-
import { pathToFileURL, fileURLToPath } from 'url';
|
|
8
|
-
import { createViteDevServerMiddleware } from './adapters/vite/dev-server.js';
|
|
9
|
-
import { createViteLogger } from './adapters/vite/logger.js';
|
|
10
|
-
import { createRequestHandler } from './core/server/request-handler.js';
|
|
11
|
-
import { buildApiBundle, getApiBundleFilename } from './build/build-api-bundle.js';
|
|
12
|
-
import { buildSocketsBundle, getSocketsBundleFilename } from './build/build-sockets-bundle.js';
|
|
13
|
-
import { createSocketHandler } from './core/socket/socket-handler.js';
|
|
14
|
-
import { API_BASE_PATH, API_DIR_NAME, getSocketBasePath } from './shared/constants.js';
|
|
15
|
-
/**
|
|
16
|
-
* Vite plugin for Vitek
|
|
17
|
-
*/
|
|
18
|
-
export function vitek(options = {}) {
|
|
19
|
-
const apiDirOption = options.apiDir || `src/${API_DIR_NAME}`;
|
|
20
|
-
const buildApi = options.buildApi !== false;
|
|
21
|
-
let root;
|
|
22
|
-
let buildOutDir;
|
|
23
|
-
let cleanupFn = null;
|
|
24
|
-
return {
|
|
25
|
-
name: 'vitek',
|
|
26
|
-
enforce: 'pre',
|
|
27
|
-
configResolved(config) {
|
|
28
|
-
root = config.root;
|
|
29
|
-
buildOutDir = path.resolve(root, config.build?.outDir ?? 'dist');
|
|
30
|
-
},
|
|
31
|
-
resolveId(id, importer) {
|
|
32
|
-
if (!id.startsWith('.') || !importer)
|
|
33
|
-
return null;
|
|
34
|
-
const fullApiDir = path.resolve(root, apiDirOption);
|
|
35
|
-
let importerPath;
|
|
36
|
-
if (importer.startsWith('file:')) {
|
|
37
|
-
importerPath = fileURLToPath(importer);
|
|
38
|
-
}
|
|
39
|
-
else if (importer.startsWith('/')) {
|
|
40
|
-
const virtualPath = path.join(root, importer.replace(/^\//, ''));
|
|
41
|
-
importerPath = fs.existsSync(virtualPath) ? virtualPath : path.resolve(importer);
|
|
42
|
-
}
|
|
43
|
-
else {
|
|
44
|
-
importerPath = path.resolve(importer);
|
|
45
|
-
}
|
|
46
|
-
const normalizedApiDir = path.resolve(fullApiDir);
|
|
47
|
-
const normalizedImporter = path.resolve(importerPath);
|
|
48
|
-
if (!normalizedImporter.startsWith(normalizedApiDir))
|
|
49
|
-
return null;
|
|
50
|
-
let resolved = path.resolve(path.dirname(normalizedImporter), id);
|
|
51
|
-
if (!fs.existsSync(resolved)) {
|
|
52
|
-
const ext = ['.ts', '.tsx', '.mts', '.js', '.jsx', '.mjs'].find((e) => fs.existsSync(resolved + e));
|
|
53
|
-
if (ext)
|
|
54
|
-
resolved += ext;
|
|
55
|
-
}
|
|
56
|
-
return fs.existsSync(resolved) ? pathToFileURL(resolved).href : null;
|
|
57
|
-
},
|
|
58
|
-
transform(code, id) {
|
|
59
|
-
const idPath = id.startsWith('file:') ? fileURLToPath(id) : id;
|
|
60
|
-
const srcDir = path.resolve(root, 'src');
|
|
61
|
-
const virtualCandidate = idPath.startsWith('/') ? path.join(root, idPath.replace(/^\//, '')) : null;
|
|
62
|
-
const normalizedId = virtualCandidate != null && fs.existsSync(virtualCandidate)
|
|
63
|
-
? virtualCandidate
|
|
64
|
-
: path.resolve(idPath);
|
|
65
|
-
if (!normalizedId.startsWith(srcDir))
|
|
66
|
-
return null;
|
|
67
|
-
const dir = path.dirname(normalizedId);
|
|
68
|
-
const rootSlash = path.resolve(root) + path.sep;
|
|
69
|
-
const rewritten = code.replace(/from\s+['"](\.\.?[^'"]+)['"]/g, (match, specifier) => {
|
|
70
|
-
const resolved = path.resolve(dir, specifier);
|
|
71
|
-
if (!resolved.startsWith(rootSlash))
|
|
72
|
-
return match;
|
|
73
|
-
let target = resolved;
|
|
74
|
-
if (!fs.existsSync(target)) {
|
|
75
|
-
const ext = ['.ts', '.tsx', '.mts', '.js', '.jsx', '.mjs'].find((e) => fs.existsSync(target + e));
|
|
76
|
-
if (ext)
|
|
77
|
-
target += ext;
|
|
78
|
-
}
|
|
79
|
-
if (!fs.existsSync(target))
|
|
80
|
-
return match;
|
|
81
|
-
const rootRelative = path.relative(root, target).replace(/\\/g, '/');
|
|
82
|
-
const newSpecifier = `/${rootRelative}`;
|
|
83
|
-
const quote = match.includes('"') ? '"' : "'";
|
|
84
|
-
return `from ${quote}${newSpecifier}${quote}`;
|
|
85
|
-
});
|
|
86
|
-
return rewritten !== code ? { code: rewritten, map: null } : null;
|
|
87
|
-
},
|
|
88
|
-
async configureServer(server) {
|
|
89
|
-
const fullApiDir = path.resolve(root, apiDirOption);
|
|
90
|
-
if (!fs.existsSync(fullApiDir)) {
|
|
91
|
-
server.config.logger.warn(`[vitek] API directory not found: ${fullApiDir}`);
|
|
92
|
-
return;
|
|
93
|
-
}
|
|
94
|
-
const logger = createViteLogger(server.config.logger, options.logging);
|
|
95
|
-
const socketsEnabled = options.sockets !== false;
|
|
96
|
-
const socketBasePath = getSocketBasePath(options.apiBasePath, typeof options.sockets === 'object' ? options.sockets?.path : undefined);
|
|
97
|
-
const { ready, middleware, cleanup, setupSockets } = createViteDevServerMiddleware({
|
|
98
|
-
root,
|
|
99
|
-
apiDir: fullApiDir,
|
|
100
|
-
logger,
|
|
101
|
-
viteServer: server,
|
|
102
|
-
enableValidation: options.enableValidation || false,
|
|
103
|
-
openApi: options.openApi,
|
|
104
|
-
sockets: socketsEnabled,
|
|
105
|
-
socketBasePath,
|
|
106
|
-
});
|
|
107
|
-
cleanupFn = cleanup;
|
|
108
|
-
server.middlewares.use(middleware);
|
|
109
|
-
await ready;
|
|
110
|
-
if (socketsEnabled && server.httpServer) {
|
|
111
|
-
setupSockets(server.httpServer);
|
|
112
|
-
}
|
|
113
|
-
logger.info('Vitek plugin initialized');
|
|
114
|
-
const port = server.config.server?.port ?? 5173;
|
|
115
|
-
const apiPath = options.apiBasePath ?? API_BASE_PATH;
|
|
116
|
-
const originalPrintUrls = server.printUrls?.bind(server);
|
|
117
|
-
if (typeof originalPrintUrls === 'function') {
|
|
118
|
-
server.printUrls = () => {
|
|
119
|
-
originalPrintUrls();
|
|
120
|
-
const host = 'localhost';
|
|
121
|
-
const apiUrl = `http://${host}:${port}${apiPath}`;
|
|
122
|
-
server.config.logger.info(` ➜ API: ${apiUrl}`);
|
|
123
|
-
if (socketsEnabled) {
|
|
124
|
-
const wsUrl = `ws://${host}:${port}${socketBasePath}`;
|
|
125
|
-
server.config.logger.info(` ➜ WS: ${wsUrl}`);
|
|
126
|
-
}
|
|
127
|
-
};
|
|
128
|
-
}
|
|
129
|
-
},
|
|
130
|
-
async configurePreviewServer(server) {
|
|
131
|
-
if (!buildApi) {
|
|
132
|
-
return;
|
|
133
|
-
}
|
|
134
|
-
const bundlePath = path.join(buildOutDir, getApiBundleFilename());
|
|
135
|
-
if (!fs.existsSync(bundlePath)) {
|
|
136
|
-
server.config.logger.warn('[vitek] API bundle not found; preview serving static assets only. Run `vite build` first.');
|
|
137
|
-
return;
|
|
138
|
-
}
|
|
139
|
-
const previewPort = server.config.preview?.port ?? 4173;
|
|
140
|
-
const apiBaseUrl = `http://127.0.0.1:${previewPort}${API_BASE_PATH}`;
|
|
141
|
-
const api = {
|
|
142
|
-
async fetch(path, fetchOptions) {
|
|
143
|
-
const url = `${apiBaseUrl}/${path.replace(/^\//, '')}`;
|
|
144
|
-
const res = await fetch(url, {
|
|
145
|
-
method: fetchOptions?.method ?? 'GET',
|
|
146
|
-
headers: fetchOptions?.body !== undefined
|
|
147
|
-
? { 'Content-Type': 'application/json' }
|
|
148
|
-
: undefined,
|
|
149
|
-
body: fetchOptions?.body !== undefined
|
|
150
|
-
? JSON.stringify(fetchOptions.body)
|
|
151
|
-
: undefined,
|
|
152
|
-
});
|
|
153
|
-
const text = await res.text();
|
|
154
|
-
if (!text)
|
|
155
|
-
return undefined;
|
|
156
|
-
try {
|
|
157
|
-
return JSON.parse(text);
|
|
158
|
-
}
|
|
159
|
-
catch {
|
|
160
|
-
return text;
|
|
161
|
-
}
|
|
162
|
-
},
|
|
163
|
-
};
|
|
164
|
-
const noopSockets = { emit() { } };
|
|
165
|
-
const shared = { sockets: noopSockets, api };
|
|
166
|
-
const bundleUrl = pathToFileURL(bundlePath).href;
|
|
167
|
-
const bundleLoadPromise = import(bundleUrl);
|
|
168
|
-
let apiHandler = null;
|
|
169
|
-
const apiMiddleware = (req, res, next) => {
|
|
170
|
-
const pathname = req.url?.split('?')[0] ?? '';
|
|
171
|
-
if (pathname !== API_BASE_PATH && !pathname.startsWith(API_BASE_PATH + '/')) {
|
|
172
|
-
return next();
|
|
173
|
-
}
|
|
174
|
-
bundleLoadPromise
|
|
175
|
-
.then((mod) => {
|
|
176
|
-
if (!apiHandler) {
|
|
177
|
-
apiHandler = createRequestHandler({
|
|
178
|
-
routes: mod.routes,
|
|
179
|
-
middlewares: mod.middlewares,
|
|
180
|
-
shared,
|
|
181
|
-
});
|
|
182
|
-
server.config.logger.info('[vitek] API middleware registered for preview');
|
|
183
|
-
}
|
|
184
|
-
apiHandler(req, res, next);
|
|
185
|
-
})
|
|
186
|
-
.catch((err) => {
|
|
187
|
-
server.config.logger.error(`[vitek] Failed to load API bundle: ${err instanceof Error ? err.message : String(err)}`);
|
|
188
|
-
res.statusCode = 500;
|
|
189
|
-
res.setHeader('Content-Type', 'application/json');
|
|
190
|
-
res.end(JSON.stringify({ error: 'Internal server error', message: 'Failed to load API bundle' }));
|
|
191
|
-
});
|
|
192
|
-
};
|
|
193
|
-
server.middlewares.use(apiMiddleware);
|
|
194
|
-
const socketsEnabled = options.sockets !== false;
|
|
195
|
-
const socketBasePath = getSocketBasePath(options.apiBasePath, typeof options.sockets === 'object' ? options.sockets?.path : undefined);
|
|
196
|
-
const socketsBundlePath = path.join(buildOutDir, getSocketsBundleFilename());
|
|
197
|
-
if (socketsEnabled && fs.existsSync(socketsBundlePath)) {
|
|
198
|
-
try {
|
|
199
|
-
const socketsUrl = pathToFileURL(socketsBundlePath).href;
|
|
200
|
-
const mod = await import(socketsUrl);
|
|
201
|
-
const handler = createSocketHandler({
|
|
202
|
-
sockets: mod.sockets,
|
|
203
|
-
socketBasePath,
|
|
204
|
-
shared,
|
|
205
|
-
});
|
|
206
|
-
server.httpServer?.on('upgrade', handler);
|
|
207
|
-
server.config.logger.info('[vitek] WebSocket sockets registered for preview');
|
|
208
|
-
}
|
|
209
|
-
catch (err) {
|
|
210
|
-
server.config.logger.warn(`[vitek] Failed to load sockets bundle: ${err instanceof Error ? err.message : String(err)}`);
|
|
211
|
-
}
|
|
212
|
-
}
|
|
213
|
-
},
|
|
214
|
-
async closeBundle() {
|
|
215
|
-
if (buildApi) {
|
|
216
|
-
const fullApiDir = path.resolve(root, apiDirOption);
|
|
217
|
-
try {
|
|
218
|
-
await buildApiBundle({
|
|
219
|
-
root,
|
|
220
|
-
apiDir: fullApiDir,
|
|
221
|
-
outDir: buildOutDir,
|
|
222
|
-
});
|
|
223
|
-
}
|
|
224
|
-
catch (err) {
|
|
225
|
-
console.error('[vitek] Failed to build API bundle:', err instanceof Error ? err.message : err);
|
|
226
|
-
}
|
|
227
|
-
const socketsEnabled = options.sockets !== false;
|
|
228
|
-
if (socketsEnabled && fs.existsSync(fullApiDir)) {
|
|
229
|
-
try {
|
|
230
|
-
await buildSocketsBundle({
|
|
231
|
-
root,
|
|
232
|
-
apiDir: fullApiDir,
|
|
233
|
-
outDir: buildOutDir,
|
|
234
|
-
});
|
|
235
|
-
}
|
|
236
|
-
catch (err) {
|
|
237
|
-
console.error('[vitek] Failed to build sockets bundle:', err instanceof Error ? err.message : err);
|
|
238
|
-
}
|
|
239
|
-
}
|
|
240
|
-
}
|
|
241
|
-
},
|
|
242
|
-
buildEnd() {
|
|
243
|
-
if (cleanupFn) {
|
|
244
|
-
cleanupFn();
|
|
245
|
-
cleanupFn = null;
|
|
246
|
-
}
|
|
247
|
-
},
|
|
248
|
-
};
|
|
249
|
-
}
|
|
5
|
+
export { vitek } from './plugin/vitek.js';
|
package/dist/plugin.test.js
CHANGED
|
@@ -3,7 +3,12 @@ import * as fs from 'fs';
|
|
|
3
3
|
import * as path from 'path';
|
|
4
4
|
import { pathToFileURL } from 'url';
|
|
5
5
|
import { vitek } from './plugin.js';
|
|
6
|
+
function findPlugin(plugins, name) {
|
|
7
|
+
return plugins.find((p) => p.name === name);
|
|
8
|
+
}
|
|
6
9
|
function callResolveId(plugin, id, importer) {
|
|
10
|
+
if (!plugin)
|
|
11
|
+
return null;
|
|
7
12
|
const hook = plugin.resolveId;
|
|
8
13
|
if (!hook)
|
|
9
14
|
return null;
|
|
@@ -12,6 +17,8 @@ function callResolveId(plugin, id, importer) {
|
|
|
12
17
|
return fn.call(null, id, importer, { attributes: {}, isEntry: false });
|
|
13
18
|
}
|
|
14
19
|
function callTransform(plugin, code, id) {
|
|
20
|
+
if (!plugin)
|
|
21
|
+
return null;
|
|
15
22
|
const hook = plugin.transform;
|
|
16
23
|
if (!hook)
|
|
17
24
|
return null;
|
|
@@ -20,9 +27,13 @@ function callTransform(plugin, code, id) {
|
|
|
20
27
|
return fn.call(null, code, id);
|
|
21
28
|
}
|
|
22
29
|
describe('vitek plugin resolveId and transform', () => {
|
|
23
|
-
let
|
|
30
|
+
let plugins;
|
|
24
31
|
let rootDir;
|
|
25
32
|
let apiDir;
|
|
33
|
+
let configPlugin;
|
|
34
|
+
let resolvePlugin;
|
|
35
|
+
let transformPlugin;
|
|
36
|
+
let buildPlugin;
|
|
26
37
|
beforeEach(() => {
|
|
27
38
|
rootDir = fs.mkdtempSync(path.join(process.cwd(), 'vitek-plugin-test-'));
|
|
28
39
|
apiDir = path.join(rootDir, 'src', 'api');
|
|
@@ -32,11 +43,16 @@ describe('vitek plugin resolveId and transform', () => {
|
|
|
32
43
|
fs.writeFileSync(path.join(rootDir, 'src', 'lib', 'greeting.ts'), "export function getGreeting() { return 'hi'; }\n", 'utf-8');
|
|
33
44
|
fs.mkdirSync(path.join(rootDir, 'src', 'api', 'nested'), { recursive: true });
|
|
34
45
|
fs.writeFileSync(path.join(rootDir, 'src', 'api', 'nested', 'deep.get.ts'), "import { getGreeting } from '../../lib/greeting';\nexport default function handler() { return {}; }\n", 'utf-8');
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
46
|
+
plugins = vitek({ apiDir: path.join('src', 'api') });
|
|
47
|
+
configPlugin = findPlugin(plugins, 'vitek:build');
|
|
48
|
+
resolvePlugin = findPlugin(plugins, 'vitek:resolve');
|
|
49
|
+
transformPlugin = findPlugin(plugins, 'vitek:transform');
|
|
50
|
+
buildPlugin = findPlugin(plugins, 'vitek:build');
|
|
51
|
+
const configResolvedHook = configPlugin.configResolved;
|
|
52
|
+
if (configResolvedHook) {
|
|
53
|
+
const fn = typeof configResolvedHook === 'function' ? configResolvedHook : configResolvedHook.handler;
|
|
54
|
+
fn.call(null, { root: rootDir, build: { outDir: 'dist' } });
|
|
55
|
+
}
|
|
40
56
|
});
|
|
41
57
|
afterEach(() => {
|
|
42
58
|
try {
|
|
@@ -49,19 +65,19 @@ describe('vitek plugin resolveId and transform', () => {
|
|
|
49
65
|
describe('resolveId', () => {
|
|
50
66
|
it('returns null when id does not start with .', () => {
|
|
51
67
|
const importer = pathToFileURL(path.join(apiDir, 'health.get.ts')).href;
|
|
52
|
-
expect(callResolveId(
|
|
53
|
-
expect(callResolveId(
|
|
68
|
+
expect(callResolveId(resolvePlugin, 'vue', importer)).toBeNull();
|
|
69
|
+
expect(callResolveId(resolvePlugin, '/absolute', importer)).toBeNull();
|
|
54
70
|
});
|
|
55
71
|
it('returns null when importer is undefined', () => {
|
|
56
|
-
expect(callResolveId(
|
|
72
|
+
expect(callResolveId(resolvePlugin, '../lib/greeting', undefined)).toBeNull();
|
|
57
73
|
});
|
|
58
74
|
it('returns null when importer is outside apiDir', () => {
|
|
59
75
|
const importerOutside = pathToFileURL(path.join(rootDir, 'src', 'main.ts')).href;
|
|
60
|
-
expect(callResolveId(
|
|
76
|
+
expect(callResolveId(resolvePlugin, '../lib/greeting', importerOutside)).toBeNull();
|
|
61
77
|
});
|
|
62
78
|
it('resolves relative import from api file to existing file and returns file URL', () => {
|
|
63
79
|
const importer = pathToFileURL(path.join(apiDir, 'health.get.ts')).href;
|
|
64
|
-
const result = callResolveId(
|
|
80
|
+
const result = callResolveId(resolvePlugin, '../lib/greeting', importer);
|
|
65
81
|
expect(result).not.toBeNull();
|
|
66
82
|
expect(typeof result).toBe('string');
|
|
67
83
|
expect(result).toContain('greeting');
|
|
@@ -69,19 +85,19 @@ describe('vitek plugin resolveId and transform', () => {
|
|
|
69
85
|
});
|
|
70
86
|
it('resolves with extension fallback when target has no extension', () => {
|
|
71
87
|
const importer = pathToFileURL(path.join(apiDir, 'health.get.ts')).href;
|
|
72
|
-
const result = callResolveId(
|
|
88
|
+
const result = callResolveId(resolvePlugin, '../lib/greeting', importer);
|
|
73
89
|
expect(result).not.toBeNull();
|
|
74
90
|
const filePath = result.replace(/^file:\/\//, '').replace(/%2F/g, '/').replace(/%3A/g, ':');
|
|
75
91
|
expect(fs.existsSync(filePath) || fs.existsSync(filePath + '.ts')).toBe(true);
|
|
76
92
|
});
|
|
77
93
|
it('returns null when relative target does not exist', () => {
|
|
78
94
|
const importer = pathToFileURL(path.join(apiDir, 'health.get.ts')).href;
|
|
79
|
-
expect(callResolveId(
|
|
95
|
+
expect(callResolveId(resolvePlugin, '../lib/nonexistent', importer)).toBeNull();
|
|
80
96
|
});
|
|
81
97
|
it('resolves nested api file relative import', () => {
|
|
82
98
|
const nestedDir = path.join(apiDir, 'nested');
|
|
83
99
|
const importer = pathToFileURL(path.join(nestedDir, 'deep.get.ts')).href;
|
|
84
|
-
const result = callResolveId(
|
|
100
|
+
const result = callResolveId(resolvePlugin, '../../lib/greeting', importer);
|
|
85
101
|
expect(result).not.toBeNull();
|
|
86
102
|
expect(result).toContain('greeting');
|
|
87
103
|
});
|
|
@@ -91,14 +107,14 @@ describe('vitek plugin resolveId and transform', () => {
|
|
|
91
107
|
const code = "import x from '../lib/greeting';";
|
|
92
108
|
fs.mkdirSync(path.join(rootDir, 'other'), { recursive: true });
|
|
93
109
|
const idOutside = pathToFileURL(path.join(rootDir, 'other', 'main.ts')).href;
|
|
94
|
-
const result = callTransform(
|
|
110
|
+
const result = callTransform(transformPlugin, code, idOutside);
|
|
95
111
|
expect(result).toBeNull();
|
|
96
112
|
});
|
|
97
113
|
it('rewrites relative import when id is under src/lib (not only api)', () => {
|
|
98
114
|
fs.writeFileSync(path.join(rootDir, 'src', 'lib', 'executor.ts'), "import { getGreeting } from './greeting';\nexport function run() { return getGreeting(); }\n", 'utf-8');
|
|
99
115
|
const code = "import { getGreeting } from './greeting';\nexport function run() { return getGreeting(); }\n";
|
|
100
116
|
const id = pathToFileURL(path.join(rootDir, 'src', 'lib', 'executor.ts')).href;
|
|
101
|
-
const result = callTransform(
|
|
117
|
+
const result = callTransform(transformPlugin, code, id);
|
|
102
118
|
expect(result).not.toBeNull();
|
|
103
119
|
expect(result.code).toContain("/src/lib/greeting");
|
|
104
120
|
expect(result.code).not.toContain("from './greeting'");
|
|
@@ -109,14 +125,14 @@ describe('vitek plugin resolveId and transform', () => {
|
|
|
109
125
|
fs.writeFileSync(path.join(rootDir, 'src', 'lib', 'nested', 'index.ts'), "export { getMessage } from './helper';\n", 'utf-8');
|
|
110
126
|
const code = "export { getMessage } from './helper';\n";
|
|
111
127
|
const id = pathToFileURL(path.join(rootDir, 'src', 'lib', 'nested', 'index.ts')).href;
|
|
112
|
-
const result = callTransform(
|
|
128
|
+
const result = callTransform(transformPlugin, code, id);
|
|
113
129
|
expect(result).not.toBeNull();
|
|
114
130
|
expect(result.code).toContain("/src/lib/nested/helper");
|
|
115
131
|
});
|
|
116
132
|
it('rewrites relative import to root-relative path when id is under apiDir', () => {
|
|
117
133
|
const code = "import { getGreeting } from '../lib/greeting';\nexport default function handler() {}";
|
|
118
134
|
const id = pathToFileURL(path.join(apiDir, 'health.get.ts')).href;
|
|
119
|
-
const result = callTransform(
|
|
135
|
+
const result = callTransform(transformPlugin, code, id);
|
|
120
136
|
expect(result).not.toBeNull();
|
|
121
137
|
expect(result.code).toContain("/src/lib/greeting");
|
|
122
138
|
expect(result.code).not.toContain("from '../lib/greeting'");
|
|
@@ -124,44 +140,114 @@ describe('vitek plugin resolveId and transform', () => {
|
|
|
124
140
|
it('preserves double quotes when original uses double quotes', () => {
|
|
125
141
|
const code = 'import { getGreeting } from "../lib/greeting";';
|
|
126
142
|
const id = pathToFileURL(path.join(apiDir, 'health.get.ts')).href;
|
|
127
|
-
const result = callTransform(
|
|
143
|
+
const result = callTransform(transformPlugin, code, id);
|
|
128
144
|
expect(result).not.toBeNull();
|
|
129
145
|
expect(result.code).toContain('/src/lib/greeting');
|
|
130
146
|
});
|
|
131
147
|
it('returns null when code has no relative imports', () => {
|
|
132
148
|
const code = "import vue from 'vue';\nexport default {}";
|
|
133
149
|
const id = pathToFileURL(path.join(apiDir, 'health.get.ts')).href;
|
|
134
|
-
const result = callTransform(
|
|
150
|
+
const result = callTransform(transformPlugin, code, id);
|
|
135
151
|
expect(result).toBeNull();
|
|
136
152
|
});
|
|
137
153
|
it('rewrites nested relative import (../../lib)', () => {
|
|
138
154
|
const code = "import { getGreeting } from '../../lib/greeting';";
|
|
139
155
|
const nestedPath = path.join(apiDir, 'nested', 'deep.get.ts');
|
|
140
156
|
const id = pathToFileURL(nestedPath).href;
|
|
141
|
-
const result = callTransform(
|
|
157
|
+
const result = callTransform(transformPlugin, code, id);
|
|
142
158
|
expect(result).not.toBeNull();
|
|
143
159
|
expect(result.code).toContain("/src/lib/greeting");
|
|
144
160
|
});
|
|
145
161
|
it('does not rewrite import when resolved target is outside root', () => {
|
|
146
162
|
const code = "import x from '../../../etc/passwd';";
|
|
147
163
|
const id = pathToFileURL(path.join(apiDir, 'health.get.ts')).href;
|
|
148
|
-
const result = callTransform(
|
|
164
|
+
const result = callTransform(transformPlugin, code, id);
|
|
149
165
|
expect(result).toBeNull();
|
|
150
166
|
});
|
|
151
167
|
it('returns null when relative target file does not exist', () => {
|
|
152
168
|
const code = "import x from '../lib/nonexistent';";
|
|
153
169
|
const id = pathToFileURL(path.join(apiDir, 'health.get.ts')).href;
|
|
154
|
-
const result = callTransform(
|
|
170
|
+
const result = callTransform(transformPlugin, code, id);
|
|
155
171
|
expect(result).toBeNull();
|
|
156
172
|
});
|
|
157
173
|
});
|
|
158
174
|
describe('plugin shape', () => {
|
|
159
|
-
it('
|
|
160
|
-
expect(
|
|
175
|
+
it('returns array of sub-plugins with enforce pre for resolve/transform/build', () => {
|
|
176
|
+
expect(resolvePlugin.enforce).toBe('pre');
|
|
177
|
+
expect(transformPlugin.enforce).toBe('pre');
|
|
178
|
+
expect(buildPlugin.enforce).toBe('pre');
|
|
179
|
+
});
|
|
180
|
+
it('exposes resolveId and transform on respective plugins', () => {
|
|
181
|
+
expect(resolvePlugin.resolveId).toBeDefined();
|
|
182
|
+
expect(transformPlugin.transform).toBeDefined();
|
|
161
183
|
});
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
184
|
+
});
|
|
185
|
+
describe('buildStart', () => {
|
|
186
|
+
it('generates api.services.ts and api.types.ts when buildStart runs', async () => {
|
|
187
|
+
fs.writeFileSync(path.join(rootDir, 'tsconfig.json'), '{}', 'utf-8');
|
|
188
|
+
const buildStart = buildPlugin.buildStart;
|
|
189
|
+
if (!buildStart) {
|
|
190
|
+
expect.fail('Plugin does not have buildStart hook');
|
|
191
|
+
}
|
|
192
|
+
await buildStart.call(null);
|
|
193
|
+
const servicesPath = path.join(rootDir, 'src', 'api.services.ts');
|
|
194
|
+
const typesPath = path.join(rootDir, 'src', 'api.types.ts');
|
|
195
|
+
expect(fs.existsSync(servicesPath)).toBe(true);
|
|
196
|
+
expect(fs.existsSync(typesPath)).toBe(true);
|
|
197
|
+
expect(fs.readFileSync(servicesPath, 'utf-8')).toContain('getHealth');
|
|
198
|
+
expect(fs.readFileSync(typesPath, 'utf-8')).toContain('VitekParams');
|
|
199
|
+
});
|
|
200
|
+
it('skips type generation and API bundle when buildApi is false', async () => {
|
|
201
|
+
fs.writeFileSync(path.join(rootDir, 'tsconfig.json'), '{}', 'utf-8');
|
|
202
|
+
const noApiPlugins = vitek({ apiDir: path.join('src', 'api'), buildApi: false });
|
|
203
|
+
const noApiBuild = findPlugin(noApiPlugins, 'vitek:build');
|
|
204
|
+
const configResolved = noApiBuild.configResolved;
|
|
205
|
+
if (configResolved) {
|
|
206
|
+
const fn = typeof configResolved === 'function' ? configResolved : configResolved.handler;
|
|
207
|
+
fn.call(null, { root: rootDir, build: { outDir: 'dist' } });
|
|
208
|
+
}
|
|
209
|
+
const buildStart = noApiBuild.buildStart;
|
|
210
|
+
const closeBundle = noApiBuild.closeBundle;
|
|
211
|
+
if (buildStart)
|
|
212
|
+
await buildStart.call(null);
|
|
213
|
+
fs.mkdirSync(path.join(rootDir, 'dist'), { recursive: true });
|
|
214
|
+
if (closeBundle)
|
|
215
|
+
await closeBundle.call(null);
|
|
216
|
+
expect(fs.existsSync(path.join(rootDir, 'src', 'api.types.ts'))).toBe(false);
|
|
217
|
+
expect(fs.existsSync(path.join(rootDir, 'src', 'api.services.ts'))).toBe(false);
|
|
218
|
+
expect(fs.existsSync(path.join(rootDir, 'dist', 'vitek-api.mjs'))).toBe(false);
|
|
165
219
|
});
|
|
166
220
|
});
|
|
221
|
+
describe('srcDir option', () => {
|
|
222
|
+
it('transform respects srcDir when custom srcDir is set', () => {
|
|
223
|
+
fs.mkdirSync(path.join(rootDir, 'lib', 'shared'), { recursive: true });
|
|
224
|
+
fs.writeFileSync(path.join(rootDir, 'lib', 'shared', 'helper.ts'), "export function help() { return 'ok'; }\n", 'utf-8');
|
|
225
|
+
fs.writeFileSync(path.join(rootDir, 'lib', 'entry.ts'), "import { help } from './shared/helper';\nexport default help;\n", 'utf-8');
|
|
226
|
+
const customPlugins = vitek({ apiDir: path.join('src', 'api'), srcDir: 'lib' });
|
|
227
|
+
const customTransform = findPlugin(customPlugins, 'vitek:transform');
|
|
228
|
+
const customBuild = findPlugin(customPlugins, 'vitek:build');
|
|
229
|
+
const configResolved = customBuild.configResolved;
|
|
230
|
+
if (configResolved) {
|
|
231
|
+
const fn = typeof configResolved === 'function' ? configResolved : configResolved.handler;
|
|
232
|
+
fn.call(null, { root: rootDir, build: { outDir: 'dist' } });
|
|
233
|
+
}
|
|
234
|
+
const code = "import { help } from './shared/helper';\nexport default help;\n";
|
|
235
|
+
const id = pathToFileURL(path.join(rootDir, 'lib', 'entry.ts')).href;
|
|
236
|
+
const result = callTransform(customTransform, code, id);
|
|
237
|
+
expect(result).not.toBeNull();
|
|
238
|
+
expect(result.code).toContain('/lib/shared/helper');
|
|
239
|
+
});
|
|
240
|
+
});
|
|
241
|
+
});
|
|
242
|
+
describe('vitek plugin options (cors, trustProxy, onError)', () => {
|
|
243
|
+
it('accepts cors and trustProxy and returns plugins', () => {
|
|
244
|
+
const plugins = vitek({ apiDir: 'src/api', cors: true, trustProxy: true });
|
|
245
|
+
expect(plugins.length).toBeGreaterThan(0);
|
|
246
|
+
expect(findPlugin(plugins, 'vitek:dev')).toBeDefined();
|
|
247
|
+
});
|
|
248
|
+
it('accepts onError option', () => {
|
|
249
|
+
const onError = () => { };
|
|
250
|
+
const plugins = vitek({ apiDir: 'src/api', onError });
|
|
251
|
+
expect(plugins.length).toBeGreaterThan(0);
|
|
252
|
+
});
|
|
167
253
|
});
|
|
@@ -58,4 +58,25 @@ export declare function internalServerError(body?: any, headers?: Record<string,
|
|
|
58
58
|
* Creates a redirect response (301, 302, 307, 308)
|
|
59
59
|
*/
|
|
60
60
|
export declare function redirect(url: string, permanent?: boolean, preserveMethod?: boolean): VitekResponse;
|
|
61
|
+
/**
|
|
62
|
+
* Creates a plain text response (Content-Type: text/plain).
|
|
63
|
+
*/
|
|
64
|
+
export declare function text(body: string, status?: number): VitekResponse;
|
|
65
|
+
/**
|
|
66
|
+
* Creates an HTML response (Content-Type: text/html).
|
|
67
|
+
*/
|
|
68
|
+
export declare function html(body: string, status?: number): VitekResponse;
|
|
69
|
+
/**
|
|
70
|
+
* Cache-Control header helpers. Merge returned headers into your response, e.g.:
|
|
71
|
+
* `{ ...ok(body), headers: { ...ok(body).headers, ...cacheControl(60) } }`
|
|
72
|
+
*/
|
|
73
|
+
export declare function cacheControl(maxAgeSeconds: number, options?: {
|
|
74
|
+
staleWhileRevalidate?: number;
|
|
75
|
+
private?: boolean;
|
|
76
|
+
}): Record<string, string>;
|
|
77
|
+
/**
|
|
78
|
+
* Returns headers to disable caching. Merge into response headers, e.g.:
|
|
79
|
+
* `{ ...ok(body), headers: { ...ok(body).headers, ...noStore() } }`
|
|
80
|
+
*/
|
|
81
|
+
export declare function noStore(): Record<string, string>;
|
|
61
82
|
//# sourceMappingURL=response-helpers.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"response-helpers.d.ts","sourceRoot":"","sources":["../../src/shared/response-helpers.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,mCAAmC,CAAC;AAEvE;;GAEG;AACH,wBAAgB,IAAI,CAClB,IAAI,EAAE,GAAG,EACT,OAAO,GAAE;IAAE,MAAM,CAAC,EAAE,MAAM,CAAC;IAAC,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;CAAO,GAClE,aAAa,CASf;AAED;;GAEG;AACH,wBAAgB,EAAE,CAAC,IAAI,EAAE,GAAG,EAAE,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GAAG,aAAa,CAE7E;AAED;;GAEG;AACH,wBAAgB,OAAO,CAAC,IAAI,EAAE,GAAG,EAAE,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GAAG,aAAa,CAElF;AAED;;GAEG;AACH,wBAAgB,SAAS,CAAC,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GAAG,aAAa,CAMzE;AAED;;GAEG;AACH,wBAAgB,UAAU,CAAC,IAAI,GAAE,GAA8B,EAAE,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GAAG,aAAa,CAEhH;AAED;;GAEG;AACH,wBAAgB,YAAY,CAAC,IAAI,GAAE,GAA+B,EAAE,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GAAG,aAAa,CAEnH;AAED;;GAEG;AACH,wBAAgB,SAAS,CAAC,IAAI,GAAE,GAA4B,EAAE,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GAAG,aAAa,CAE7G;AAED;;GAEG;AACH,wBAAgB,QAAQ,CAAC,IAAI,GAAE,GAA4B,EAAE,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GAAG,aAAa,CAE5G;AAED;;GAEG;AACH,wBAAgB,QAAQ,CAAC,IAAI,GAAE,GAA2B,EAAE,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GAAG,aAAa,CAE3G;AAED;;GAEG;AACH,wBAAgB,mBAAmB,CACjC,IAAI,GAAE,GAAmC,EACzC,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GAC/B,aAAa,CAEf;AAED;;GAEG;AACH,wBAAgB,eAAe,CAC7B,IAAI,GAAE,GAAoC,EAC1C,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GAC/B,aAAa,CAEf;AAED;;GAEG;AACH,wBAAgB,mBAAmB,CACjC,IAAI,GAAE,GAAwC,EAC9C,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GAC/B,aAAa,CAEf;AAED;;GAEG;AACH,wBAAgB,QAAQ,CACtB,GAAG,EAAE,MAAM,EACX,SAAS,GAAE,OAAe,EAC1B,cAAc,GAAE,OAAe,GAC9B,aAAa,CASf"}
|
|
1
|
+
{"version":3,"file":"response-helpers.d.ts","sourceRoot":"","sources":["../../src/shared/response-helpers.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,mCAAmC,CAAC;AAEvE;;GAEG;AACH,wBAAgB,IAAI,CAClB,IAAI,EAAE,GAAG,EACT,OAAO,GAAE;IAAE,MAAM,CAAC,EAAE,MAAM,CAAC;IAAC,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;CAAO,GAClE,aAAa,CASf;AAED;;GAEG;AACH,wBAAgB,EAAE,CAAC,IAAI,EAAE,GAAG,EAAE,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GAAG,aAAa,CAE7E;AAED;;GAEG;AACH,wBAAgB,OAAO,CAAC,IAAI,EAAE,GAAG,EAAE,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GAAG,aAAa,CAElF;AAED;;GAEG;AACH,wBAAgB,SAAS,CAAC,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GAAG,aAAa,CAMzE;AAED;;GAEG;AACH,wBAAgB,UAAU,CAAC,IAAI,GAAE,GAA8B,EAAE,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GAAG,aAAa,CAEhH;AAED;;GAEG;AACH,wBAAgB,YAAY,CAAC,IAAI,GAAE,GAA+B,EAAE,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GAAG,aAAa,CAEnH;AAED;;GAEG;AACH,wBAAgB,SAAS,CAAC,IAAI,GAAE,GAA4B,EAAE,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GAAG,aAAa,CAE7G;AAED;;GAEG;AACH,wBAAgB,QAAQ,CAAC,IAAI,GAAE,GAA4B,EAAE,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GAAG,aAAa,CAE5G;AAED;;GAEG;AACH,wBAAgB,QAAQ,CAAC,IAAI,GAAE,GAA2B,EAAE,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GAAG,aAAa,CAE3G;AAED;;GAEG;AACH,wBAAgB,mBAAmB,CACjC,IAAI,GAAE,GAAmC,EACzC,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GAC/B,aAAa,CAEf;AAED;;GAEG;AACH,wBAAgB,eAAe,CAC7B,IAAI,GAAE,GAAoC,EAC1C,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GAC/B,aAAa,CAEf;AAED;;GAEG;AACH,wBAAgB,mBAAmB,CACjC,IAAI,GAAE,GAAwC,EAC9C,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GAC/B,aAAa,CAEf;AAED;;GAEG;AACH,wBAAgB,QAAQ,CACtB,GAAG,EAAE,MAAM,EACX,SAAS,GAAE,OAAe,EAC1B,cAAc,GAAE,OAAe,GAC9B,aAAa,CASf;AAED;;GAEG;AACH,wBAAgB,IAAI,CAAC,IAAI,EAAE,MAAM,EAAE,MAAM,GAAE,MAAY,GAAG,aAAa,CAMtE;AAED;;GAEG;AACH,wBAAgB,IAAI,CAAC,IAAI,EAAE,MAAM,EAAE,MAAM,GAAE,MAAY,GAAG,aAAa,CAMtE;AAED;;;GAGG;AACH,wBAAgB,YAAY,CAC1B,aAAa,EAAE,MAAM,EACrB,OAAO,CAAC,EAAE;IAAE,oBAAoB,CAAC,EAAE,MAAM,CAAC;IAAC,OAAO,CAAC,EAAE,OAAO,CAAA;CAAE,GAC7D,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CASxB;AAED;;;GAGG;AACH,wBAAgB,OAAO,IAAI,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAEhD"}
|
|
@@ -98,3 +98,44 @@ export function redirect(url, permanent = false, preserveMethod = false) {
|
|
|
98
98
|
body: undefined,
|
|
99
99
|
};
|
|
100
100
|
}
|
|
101
|
+
/**
|
|
102
|
+
* Creates a plain text response (Content-Type: text/plain).
|
|
103
|
+
*/
|
|
104
|
+
export function text(body, status = 200) {
|
|
105
|
+
return {
|
|
106
|
+
status,
|
|
107
|
+
headers: { 'Content-Type': 'text/plain; charset=utf-8' },
|
|
108
|
+
body,
|
|
109
|
+
};
|
|
110
|
+
}
|
|
111
|
+
/**
|
|
112
|
+
* Creates an HTML response (Content-Type: text/html).
|
|
113
|
+
*/
|
|
114
|
+
export function html(body, status = 200) {
|
|
115
|
+
return {
|
|
116
|
+
status,
|
|
117
|
+
headers: { 'Content-Type': 'text/html; charset=utf-8' },
|
|
118
|
+
body,
|
|
119
|
+
};
|
|
120
|
+
}
|
|
121
|
+
/**
|
|
122
|
+
* Cache-Control header helpers. Merge returned headers into your response, e.g.:
|
|
123
|
+
* `{ ...ok(body), headers: { ...ok(body).headers, ...cacheControl(60) } }`
|
|
124
|
+
*/
|
|
125
|
+
export function cacheControl(maxAgeSeconds, options) {
|
|
126
|
+
const parts = [`max-age=${maxAgeSeconds}`];
|
|
127
|
+
if (options?.staleWhileRevalidate != null) {
|
|
128
|
+
parts.push(`stale-while-revalidate=${options.staleWhileRevalidate}`);
|
|
129
|
+
}
|
|
130
|
+
if (options?.private === true) {
|
|
131
|
+
parts.push('private');
|
|
132
|
+
}
|
|
133
|
+
return { 'Cache-Control': parts.join(', ') };
|
|
134
|
+
}
|
|
135
|
+
/**
|
|
136
|
+
* Returns headers to disable caching. Merge into response headers, e.g.:
|
|
137
|
+
* `{ ...ok(body), headers: { ...ok(body).headers, ...noStore() } }`
|
|
138
|
+
*/
|
|
139
|
+
export function noStore() {
|
|
140
|
+
return { 'Cache-Control': 'no-store' };
|
|
141
|
+
}
|