@holo-js/adapter-nuxt 0.3.27 → 0.4.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/LICENSE +21 -0
- package/dist/.holo-build-fingerprint +1 -0
- package/dist/module.d.mts +7 -11
- package/dist/module.json +2 -2
- package/dist/module.mjs +106 -59
- package/dist/runtime/authorization-error.js +1 -1
- package/dist/runtime/composables/index.d.ts +2 -4
- package/dist/runtime/composables/index.js +34 -37
- package/dist/runtime/plugins/forms.js +1 -1
- package/dist/runtime/plugins/init.js +23 -7
- package/dist/runtime/server/connection-address.js +7 -0
- package/dist/runtime/server/error.js +6 -15
- package/dist/runtime/server/form-failure.js +19 -6
- package/dist/runtime/server/route-request.js +39 -0
- package/dist/runtime/server/routes/broadcast-auth.post.js +3 -13
- package/dist/runtime/server/routes/broadcast-config.get.js +1 -1
- package/dist/runtime/server/routes/realtime-mutation.post.js +6 -5
- package/dist/runtime/server/routes/realtime-query.post.js +6 -5
- package/dist/runtime/server/routes/storage.js +8 -2
- package/dist/runtime/shims.d.ts +3 -50
- package/package.json +31 -24
- package/dist/runtime/drivers/s3.js +0 -1
- package/dist/runtime/plugins/storage.js +0 -10
- package/dist/runtime/server/routes/realtime-request.d.ts +0 -0
- package/dist/runtime/server/routes/realtime-request.js +0 -14
- /package/dist/runtime/{drivers/s3.d.ts → server/connection-address.d.ts} +0 -0
- /package/dist/runtime/{plugins/storage.d.ts → server/route-request.d.ts} +0 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Holo-JS contributors
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
e7de7522096e85f09dffe635f153a2321b5d38f460190ac2164bb8db98bd3188
|
package/dist/module.d.mts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import
|
|
1
|
+
import { NuxtModule } from 'nuxt/schema';
|
|
2
2
|
import { LoadedHoloConfig, HoloConfigMap } from '@holo-js/config';
|
|
3
3
|
|
|
4
4
|
type ModuleOptions = Record<string, never>;
|
|
@@ -44,7 +44,6 @@ type HoloStorageRuntimeConfig = {
|
|
|
44
44
|
disks: Record<string, RuntimeDiskConfig>;
|
|
45
45
|
};
|
|
46
46
|
type StorageModule = {
|
|
47
|
-
applyNitroStorageConfig(nitro: NuxtOptionsWithNitro, config: HoloStorageRuntimeConfig, s3Driver: string): void;
|
|
48
47
|
hasPublicLocalDisk(config: HoloStorageRuntimeConfig): boolean;
|
|
49
48
|
mergeModuleOptions(base: StorageModuleOptions | undefined, overrides: StorageModuleOptions | undefined): StorageModuleOptions;
|
|
50
49
|
normalizeModuleOptions(options: StorageModuleOptions | undefined): HoloStorageRuntimeConfig;
|
|
@@ -65,7 +64,6 @@ type NuxtViteOptions = {
|
|
|
65
64
|
};
|
|
66
65
|
interface NuxtOptionsWithNitro {
|
|
67
66
|
nitro: {
|
|
68
|
-
storage: Record<string, unknown>;
|
|
69
67
|
moduleSideEffects?: string[];
|
|
70
68
|
errorHandler?: string | string[];
|
|
71
69
|
externals?: {
|
|
@@ -94,7 +92,6 @@ interface NuxtOptionsWithNitro {
|
|
|
94
92
|
};
|
|
95
93
|
[key: string]: unknown;
|
|
96
94
|
};
|
|
97
|
-
holoStorage?: HoloStorageRuntimeConfig;
|
|
98
95
|
[key: string]: unknown;
|
|
99
96
|
};
|
|
100
97
|
build: {
|
|
@@ -106,7 +103,6 @@ interface NuxtOptionsWithNitro {
|
|
|
106
103
|
rootDir?: string;
|
|
107
104
|
_holoStorageModuleOptions?: StorageModuleOptions;
|
|
108
105
|
_holoStorageFinalizeRegistered?: boolean;
|
|
109
|
-
_holoStorageRuntimeRegistered?: boolean;
|
|
110
106
|
_holoBroadcastAuthRouteRegistered?: boolean;
|
|
111
107
|
_holoRealtimeRouteRegistered?: boolean;
|
|
112
108
|
_holoClientTransformsRegistered?: boolean;
|
|
@@ -120,10 +116,11 @@ declare function isProjectPackageLinked(rootDir: string, packageRootName: string
|
|
|
120
116
|
declare function addNitroRuntimeTraceIncludes(opts: NuxtOptionsWithNitro, rootDir: string, pluginPackages?: readonly string[], resolvePackage?: (rootDir: string, packageName: string) => string | undefined): void;
|
|
121
117
|
declare function resolveClientOptimizeDeps(rootDir: string): string[];
|
|
122
118
|
declare function addViteOptimizeDeps(opts: NuxtOptionsWithNitro, deps: readonly string[]): void;
|
|
123
|
-
declare function isRealtimeDefinitionModule(
|
|
119
|
+
declare function isRealtimeDefinitionModule(rootDir: string, id: string, directories?: readonly string[]): boolean;
|
|
124
120
|
declare function resolveExistingRealtimeDefinitionFile(path: string): string | undefined;
|
|
125
121
|
declare function existsFile(path: string): boolean;
|
|
126
122
|
declare function resolveRealtimeDefinitionImport(source: string, importer: string | undefined): string | undefined;
|
|
123
|
+
declare function renderRealtimeDefinitionsModule(rootDir: string): string;
|
|
127
124
|
declare function createRealtimeDefinitionVitePlugin(rootDir: string): unknown;
|
|
128
125
|
declare function addVitePlugin(vite: NuxtViteOptions, plugin: unknown): void;
|
|
129
126
|
declare function addNitroErrorHandler(opts: NuxtOptionsWithNitro, handler: string): void;
|
|
@@ -136,9 +133,8 @@ declare function resolveStorageSetup(storageModule: StorageModule | undefined, l
|
|
|
136
133
|
};
|
|
137
134
|
declare function finalizeStorageSetup(storageModule: StorageModule, opts: NuxtOptionsWithNitro, resolver: {
|
|
138
135
|
resolve(path: string): string;
|
|
139
|
-
}
|
|
140
|
-
declare
|
|
141
|
-
declare const _default: nuxt_schema.NuxtModule<ModuleOptions, ModuleOptions, false>;
|
|
136
|
+
}): void;
|
|
137
|
+
declare const holoNuxtModule: NuxtModule<ModuleOptions>;
|
|
142
138
|
|
|
143
139
|
declare const moduleInternals: {
|
|
144
140
|
addViteOptimizeDeps: typeof addViteOptimizeDeps;
|
|
@@ -151,7 +147,6 @@ declare const moduleInternals: {
|
|
|
151
147
|
hasModuleNotFoundCode: typeof hasModuleNotFoundCode;
|
|
152
148
|
hasLoadedConfigFile: typeof hasLoadedConfigFile;
|
|
153
149
|
importOptionalStorageS3Module: typeof importOptionalStorageS3Module;
|
|
154
|
-
applyStorageRuntimeConfig: typeof applyStorageRuntimeConfig;
|
|
155
150
|
finalizeStorageSetup: typeof finalizeStorageSetup;
|
|
156
151
|
resolveStorageSetup: typeof resolveStorageSetup;
|
|
157
152
|
isModuleResolutionFailure: typeof isModuleResolutionFailure;
|
|
@@ -160,6 +155,7 @@ declare const moduleInternals: {
|
|
|
160
155
|
isProjectPackageLinked: typeof isProjectPackageLinked;
|
|
161
156
|
isRealtimeDefinitionModule: typeof isRealtimeDefinitionModule;
|
|
162
157
|
resolveClientOptimizeDeps: typeof resolveClientOptimizeDeps;
|
|
158
|
+
renderRealtimeDefinitionsModule: typeof renderRealtimeDefinitionsModule;
|
|
163
159
|
resolveExistingRealtimeDefinitionFile: typeof resolveExistingRealtimeDefinitionFile;
|
|
164
160
|
resolveRealtimeDefinitionImport: typeof resolveRealtimeDefinitionImport;
|
|
165
161
|
};
|
|
@@ -167,5 +163,5 @@ declare const adapterNuxtInternals: {
|
|
|
167
163
|
toStorageModuleOptions: typeof toStorageModuleOptions;
|
|
168
164
|
};
|
|
169
165
|
|
|
170
|
-
export { adapterNuxtInternals,
|
|
166
|
+
export { adapterNuxtInternals, holoNuxtModule as default, moduleInternals };
|
|
171
167
|
export type { ModuleOptions };
|
package/dist/module.json
CHANGED
package/dist/module.mjs
CHANGED
|
@@ -1,30 +1,33 @@
|
|
|
1
1
|
import { createRealtimeClientDefinitionTransform as createRealtimeClientDefinitionTransform$1, createRealtimeClientDefinitionModule as createRealtimeClientDefinitionModule$1, compileBrowserValidation } from '@holo-js/adapter-shared/build';
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
2
|
+
import { resolveRealtimeDefinitionDirectories, isInRealtimeDefinitionDirectory, assertRealtimeDefinitionTree } from '@holo-js/adapter-shared/realtime-directories';
|
|
3
|
+
import { existsSync, lstatSync, readFileSync, readdirSync } from 'node:fs';
|
|
4
|
+
import { readdir, readFile, mkdir, access } from 'node:fs/promises';
|
|
4
5
|
import { createRequire } from 'node:module';
|
|
5
6
|
import { resolve, extname, relative, basename, dirname, isAbsolute } from 'node:path';
|
|
6
7
|
import { defineNuxtModule, createResolver, addServerPlugin, addServerImportsDir, addServerHandler, addPlugin } from '@nuxt/kit';
|
|
7
8
|
import { loadConfigDirectory } from '@holo-js/config';
|
|
8
9
|
import '@holo-js/db/config';
|
|
9
10
|
|
|
10
|
-
function createRealtimeClientDefinitionModule(source) {
|
|
11
|
-
return createRealtimeClientDefinitionModule$1(source, "@holo-js/adapter-nuxt/realtime");
|
|
11
|
+
function createRealtimeClientDefinitionModule(source, filePath) {
|
|
12
|
+
return createRealtimeClientDefinitionModule$1({ source, importTarget: "@holo-js/adapter-nuxt/realtime", filePath });
|
|
12
13
|
}
|
|
13
|
-
function createRealtimeClientDefinitionTransform(source) {
|
|
14
|
-
return createRealtimeClientDefinitionTransform$1(source, "@holo-js/adapter-nuxt/realtime");
|
|
14
|
+
function createRealtimeClientDefinitionTransform(source, filePath) {
|
|
15
|
+
return createRealtimeClientDefinitionTransform$1({ source, importTarget: "@holo-js/adapter-nuxt/realtime", filePath });
|
|
15
16
|
}
|
|
16
17
|
|
|
17
18
|
const MODEL_FILE_EXTENSIONS = /* @__PURE__ */ new Set([".ts", ".tsx", ".mts", ".cts", ".js", ".jsx", ".mjs", ".cjs"]);
|
|
18
19
|
const HOLO_PACKAGE_SCOPE = "@holo-js/";
|
|
19
20
|
const realtimeClientDefinitionPrefix = "\0holo-realtime-client:";
|
|
21
|
+
const realtimeDefinitionsModuleId = "#holo/realtime-definitions";
|
|
22
|
+
const VALIDATION_CLIENT_DEPENDENCIES = ["valibot", "@holo-js/kernel > file-type"];
|
|
20
23
|
const CLIENT_OPTIMIZE_DEPS = [
|
|
21
24
|
{
|
|
22
25
|
packageName: `${HOLO_PACKAGE_SCOPE}forms`,
|
|
23
|
-
include: `${HOLO_PACKAGE_SCOPE}forms > ${HOLO_PACKAGE_SCOPE}validation >
|
|
26
|
+
include: VALIDATION_CLIENT_DEPENDENCIES.map((dependency) => `${HOLO_PACKAGE_SCOPE}forms > ${HOLO_PACKAGE_SCOPE}validation > ${dependency}`)
|
|
24
27
|
},
|
|
25
28
|
{
|
|
26
29
|
packageName: `${HOLO_PACKAGE_SCOPE}validation`,
|
|
27
|
-
include: `${HOLO_PACKAGE_SCOPE}validation >
|
|
30
|
+
include: VALIDATION_CLIENT_DEPENDENCIES.map((dependency) => `${HOLO_PACKAGE_SCOPE}validation > ${dependency}`)
|
|
28
31
|
}
|
|
29
32
|
];
|
|
30
33
|
const NITRO_RUNTIME_TRACE_IMPORTS = [
|
|
@@ -207,7 +210,7 @@ function resolveClientOptimizeDeps(rootDir) {
|
|
|
207
210
|
for (const { packageName, include } of CLIENT_OPTIMIZE_DEPS) {
|
|
208
211
|
try {
|
|
209
212
|
projectRequire.resolve(packageName);
|
|
210
|
-
deps.push(include);
|
|
213
|
+
deps.push(...include);
|
|
211
214
|
} catch (error) {
|
|
212
215
|
if (!isModuleResolutionFailure(error)) {
|
|
213
216
|
throw error;
|
|
@@ -229,10 +232,10 @@ function addViteOptimizeDeps(opts, deps) {
|
|
|
229
232
|
])
|
|
230
233
|
];
|
|
231
234
|
}
|
|
232
|
-
function isRealtimeDefinitionModule(
|
|
235
|
+
function isRealtimeDefinitionModule(rootDir, id, directories = resolveRealtimeDefinitionDirectories(rootDir)) {
|
|
233
236
|
const [sourcePath = ""] = id.split("?");
|
|
234
237
|
const normalizedId = sourcePath.replaceAll("\\", "/");
|
|
235
|
-
return normalizedId.includes("/server/realtime/") && MODEL_FILE_EXTENSIONS.has(extname(normalizedId));
|
|
238
|
+
return (normalizedId.includes("/server/realtime/") || isInRealtimeDefinitionDirectory(directories, normalizedId)) && MODEL_FILE_EXTENSIONS.has(extname(normalizedId));
|
|
236
239
|
}
|
|
237
240
|
function resolveExistingRealtimeDefinitionFile(path) {
|
|
238
241
|
if (MODEL_FILE_EXTENSIONS.has(extname(path)) && existsFile(path)) {
|
|
@@ -260,10 +263,39 @@ function resolveRealtimeDefinitionImport(source, importer) {
|
|
|
260
263
|
const basePath = source.startsWith(".") ? importer ? resolve(dirname(importer.split("?")[0]), source) : void 0 : resolve(source);
|
|
261
264
|
return basePath ? resolveExistingRealtimeDefinitionFile(basePath) : void 0;
|
|
262
265
|
}
|
|
266
|
+
function collectRealtimeDefinitionFiles(rootDir) {
|
|
267
|
+
const realtimeRoot = resolve(rootDir, "server/realtime");
|
|
268
|
+
if (!existsSync(realtimeRoot)) {
|
|
269
|
+
return [];
|
|
270
|
+
}
|
|
271
|
+
return readdirSync(realtimeRoot, { recursive: true, withFileTypes: true }).filter((entry) => entry.isFile() && MODEL_FILE_EXTENSIONS.has(extname(entry.name))).map((entry) => resolve(entry.parentPath, entry.name)).sort((left, right) => left.localeCompare(right));
|
|
272
|
+
}
|
|
273
|
+
function renderRealtimeDefinitionsModule(rootDir) {
|
|
274
|
+
const files = collectRealtimeDefinitionFiles(rootDir);
|
|
275
|
+
const imports = files.map((filePath, index) => `import * as realtimeModule${index} from ${JSON.stringify(filePath)}`);
|
|
276
|
+
const values = files.map((_filePath, index) => `...Object.values(realtimeModule${index})`);
|
|
277
|
+
return [
|
|
278
|
+
...imports,
|
|
279
|
+
"",
|
|
280
|
+
`export const realtimeDefinitions = [${values.join(", ")}]`,
|
|
281
|
+
""
|
|
282
|
+
].join("\n");
|
|
283
|
+
}
|
|
263
284
|
function createRealtimeDefinitionVitePlugin(rootDir) {
|
|
285
|
+
const directories = resolveRealtimeDefinitionDirectories(rootDir);
|
|
286
|
+
let realtimeTreeChanged = false;
|
|
287
|
+
const loadedDefinitionIds = /* @__PURE__ */ new Set();
|
|
264
288
|
return {
|
|
265
289
|
name: "holo-realtime-client-definitions",
|
|
266
290
|
enforce: "pre",
|
|
291
|
+
buildStart() {
|
|
292
|
+
assertRealtimeDefinitionTree(rootDir);
|
|
293
|
+
},
|
|
294
|
+
configureServer(server) {
|
|
295
|
+
server.watcher.on("all", (_event, path) => {
|
|
296
|
+
if (isInRealtimeDefinitionDirectory(directories, path)) realtimeTreeChanged = true;
|
|
297
|
+
});
|
|
298
|
+
},
|
|
267
299
|
resolveId(source, importer, options) {
|
|
268
300
|
if (options?.ssr) {
|
|
269
301
|
return null;
|
|
@@ -271,22 +303,32 @@ function createRealtimeDefinitionVitePlugin(rootDir) {
|
|
|
271
303
|
const resolved = resolveRealtimeDefinitionImport(source, importer);
|
|
272
304
|
return resolved ? `${realtimeClientDefinitionPrefix}${resolved}` : null;
|
|
273
305
|
},
|
|
274
|
-
load(id) {
|
|
275
|
-
if (!
|
|
306
|
+
load(id, options) {
|
|
307
|
+
if (!options?.ssr && realtimeTreeChanged) {
|
|
308
|
+
assertRealtimeDefinitionTree(rootDir);
|
|
309
|
+
realtimeTreeChanged = false;
|
|
310
|
+
}
|
|
311
|
+
if (id.startsWith(realtimeClientDefinitionPrefix)) {
|
|
312
|
+
const sourcePath2 = id.slice(realtimeClientDefinitionPrefix.length);
|
|
313
|
+
loadedDefinitionIds.add(id);
|
|
314
|
+
return createRealtimeClientDefinitionModule(readFileSync(sourcePath2, "utf8"), sourcePath2);
|
|
315
|
+
}
|
|
316
|
+
if (options?.ssr || !isRealtimeDefinitionModule(rootDir, id, directories)) {
|
|
276
317
|
return null;
|
|
277
318
|
}
|
|
278
|
-
const sourcePath = id.
|
|
279
|
-
|
|
319
|
+
const sourcePath = id.split("?")[0];
|
|
320
|
+
loadedDefinitionIds.add(id);
|
|
321
|
+
return createRealtimeClientDefinitionModule(readFileSync(sourcePath, "utf8"), sourcePath);
|
|
280
322
|
},
|
|
281
323
|
transform(code, id, options) {
|
|
282
324
|
if (!options?.ssr && !id.includes("node_modules") && /\.[cm]?[jt]sx?$/.test(id)) {
|
|
283
325
|
const compiled = compileBrowserValidation(code, id);
|
|
284
326
|
if (compiled) return { code: compiled, map: null };
|
|
285
327
|
}
|
|
286
|
-
if (options?.ssr || !isRealtimeDefinitionModule(rootDir, id)) {
|
|
328
|
+
if (options?.ssr || loadedDefinitionIds.has(id) || !isRealtimeDefinitionModule(rootDir, id, directories)) {
|
|
287
329
|
return null;
|
|
288
330
|
}
|
|
289
|
-
return createRealtimeClientDefinitionTransform(code);
|
|
331
|
+
return createRealtimeClientDefinitionTransform(code, id.split("?")[0]);
|
|
290
332
|
}
|
|
291
333
|
};
|
|
292
334
|
}
|
|
@@ -327,20 +369,28 @@ function hasLoadedConfigFile(loaded, configName) {
|
|
|
327
369
|
return normalizedPath.endsWith(`/config/${configName}.ts`) || normalizedPath.endsWith(`/config/${configName}.mts`) || normalizedPath.endsWith(`/config/${configName}.js`) || normalizedPath.endsWith(`/config/${configName}.mjs`) || normalizedPath.endsWith(`/config/${configName}.cts`) || normalizedPath.endsWith(`/config/${configName}.cjs`);
|
|
328
370
|
});
|
|
329
371
|
}
|
|
372
|
+
async function writeGeneratedFile(path, contents) {
|
|
373
|
+
const { atomicFileInternals } = await import('@holo-js/core');
|
|
374
|
+
await atomicFileInternals.writeTextFile(path, contents);
|
|
375
|
+
}
|
|
330
376
|
async function ensureModelRegistryTypesPlaceholder(path) {
|
|
331
377
|
try {
|
|
332
378
|
await access(path);
|
|
333
379
|
return;
|
|
334
380
|
} catch {
|
|
335
381
|
await mkdir(dirname(path), { recursive: true });
|
|
336
|
-
await
|
|
382
|
+
await writeGeneratedFile(path, "// Generated by holo prepare. Do not edit.\n\nexport {}\n");
|
|
337
383
|
}
|
|
338
384
|
}
|
|
385
|
+
const STORAGE_CREDENTIAL_KEYS = /* @__PURE__ */ new Set(["accessKeyId", "secretAccessKey", "sessionToken"]);
|
|
386
|
+
function withoutStorageCredentials(disk) {
|
|
387
|
+
return Object.fromEntries(Object.entries(disk).filter(([key]) => !STORAGE_CREDENTIAL_KEYS.has(key)));
|
|
388
|
+
}
|
|
339
389
|
function toStorageModuleOptions(loaded) {
|
|
340
390
|
return {
|
|
341
391
|
defaultDisk: loaded.storage.defaultDisk,
|
|
342
392
|
routePrefix: loaded.storage.routePrefix,
|
|
343
|
-
disks:
|
|
393
|
+
disks: Object.fromEntries(Object.entries(loaded.storage.disks).map(([name, disk]) => [name, withoutStorageCredentials(disk)]))
|
|
344
394
|
};
|
|
345
395
|
}
|
|
346
396
|
function resolveStorageSetup(storageModule, loaded) {
|
|
@@ -356,11 +406,8 @@ function resolveStorageSetup(storageModule, loaded) {
|
|
|
356
406
|
normalized: storageModule.normalizeModuleOptions(options)
|
|
357
407
|
};
|
|
358
408
|
}
|
|
359
|
-
function finalizeStorageSetup(storageModule, opts, resolver
|
|
409
|
+
function finalizeStorageSetup(storageModule, opts, resolver) {
|
|
360
410
|
const normalized = storageModule.normalizeModuleOptions(opts._holoStorageModuleOptions);
|
|
361
|
-
opts.runtimeConfig = opts.runtimeConfig || {};
|
|
362
|
-
opts.runtimeConfig.holoStorage = normalized;
|
|
363
|
-
storageModule.applyNitroStorageConfig(opts, normalized, s3Driver);
|
|
364
411
|
if (storageModule.hasPublicLocalDisk(normalized)) {
|
|
365
412
|
addServerHandler({
|
|
366
413
|
route: `${normalized.routePrefix}/**`,
|
|
@@ -368,11 +415,6 @@ function finalizeStorageSetup(storageModule, opts, resolver, s3Driver) {
|
|
|
368
415
|
});
|
|
369
416
|
}
|
|
370
417
|
}
|
|
371
|
-
function applyStorageRuntimeConfig(runtimeConfig, normalized) {
|
|
372
|
-
if (normalized) {
|
|
373
|
-
runtimeConfig.holoStorage = normalized;
|
|
374
|
-
}
|
|
375
|
-
}
|
|
376
418
|
async function createServerModelImports(projectRoot, modelsRelativePath, generatedSchemaRelativePath) {
|
|
377
419
|
const modelsDir = resolve(projectRoot, modelsRelativePath);
|
|
378
420
|
const generatedSchemaPath = resolve(projectRoot, generatedSchemaRelativePath);
|
|
@@ -408,16 +450,16 @@ async function createServerModelImports(projectRoot, modelsRelativePath, generat
|
|
|
408
450
|
"export default () => {}"
|
|
409
451
|
];
|
|
410
452
|
await mkdir(modelImportDir, { recursive: true });
|
|
411
|
-
await
|
|
412
|
-
|
|
413
|
-
await
|
|
414
|
-
|
|
453
|
+
await writeGeneratedFile(modelImportFile, `${lines.join("\n")}
|
|
454
|
+
`);
|
|
455
|
+
await writeGeneratedFile(modelPluginFile, `${pluginLines.join("\n")}
|
|
456
|
+
`);
|
|
415
457
|
return {
|
|
416
458
|
importDir: modelImportDir,
|
|
417
459
|
pluginFile: modelPluginFile
|
|
418
460
|
};
|
|
419
461
|
}
|
|
420
|
-
const
|
|
462
|
+
const holoNuxtModule = defineNuxtModule({
|
|
421
463
|
meta: {
|
|
422
464
|
name: "@holo-js/adapter-nuxt"
|
|
423
465
|
},
|
|
@@ -433,7 +475,6 @@ const module$1 = defineNuxtModule({
|
|
|
433
475
|
addViteOptimizeDeps(opts, resolveClientOptimizeDeps(rootDir));
|
|
434
476
|
const storageModule = await importOptionalStorageModule();
|
|
435
477
|
const loaded = await loadConfigDirectory(rootDir, {
|
|
436
|
-
preferCache: process.env.NODE_ENV === "production",
|
|
437
478
|
processEnv: process.env
|
|
438
479
|
});
|
|
439
480
|
if ((loaded.app.plugins ?? []).includes("@holo-js/panels")) {
|
|
@@ -443,9 +484,7 @@ const module$1 = defineNuxtModule({
|
|
|
443
484
|
}
|
|
444
485
|
}
|
|
445
486
|
const storageSetup = resolveStorageSetup(storageModule, loaded);
|
|
446
|
-
|
|
447
|
-
opts.nitro = opts.nitro || { storage: {} };
|
|
448
|
-
opts.nitro.storage = opts.nitro.storage || {};
|
|
487
|
+
opts.nitro = opts.nitro || {};
|
|
449
488
|
if (isProjectPackageLinked(rootDir, "@holo-js/core")) {
|
|
450
489
|
opts.nitro.rollupConfig = {
|
|
451
490
|
...opts.nitro.rollupConfig,
|
|
@@ -466,11 +505,8 @@ const module$1 = defineNuxtModule({
|
|
|
466
505
|
};
|
|
467
506
|
opts.runtimeConfig.holo = {
|
|
468
507
|
appUrl: loaded.app.url,
|
|
469
|
-
appEnv: loaded.app.env,
|
|
470
|
-
appDebug: loaded.app.debug,
|
|
471
508
|
projectRoot: rootDir
|
|
472
509
|
};
|
|
473
|
-
opts.runtimeConfig.db = loaded.database;
|
|
474
510
|
const mergedStorageOptions = storageSetup.options;
|
|
475
511
|
const normalizedStorage = storageSetup.normalized;
|
|
476
512
|
opts._holoStorageModuleOptions = mergedStorageOptions;
|
|
@@ -479,11 +515,10 @@ const module$1 = defineNuxtModule({
|
|
|
479
515
|
throw new Error("[@holo-js/adapter-nuxt] S3 storage disks require @holo-js/storage-s3 to be installed.");
|
|
480
516
|
}
|
|
481
517
|
}
|
|
482
|
-
applyStorageRuntimeConfig(opts.runtimeConfig, normalizedStorage);
|
|
483
518
|
if (!opts._holoCoreRuntimeRegistered) {
|
|
484
519
|
if (existsSync(resolve(rootDir, ".holo-js/generated/definition-importer.ts"))) {
|
|
485
520
|
const initPluginPath = resolve(rootDir, ".holo-js/generated/nuxt-init.ts");
|
|
486
|
-
await
|
|
521
|
+
await writeGeneratedFile(initPluginPath, [
|
|
487
522
|
`import init from ${JSON.stringify(resolver.resolve("./runtime/plugins/init"))}`,
|
|
488
523
|
"import { installProjectDefinitionImporter } from './definition-importer'",
|
|
489
524
|
"",
|
|
@@ -491,7 +526,7 @@ const module$1 = defineNuxtModule({
|
|
|
491
526
|
"",
|
|
492
527
|
"export default init",
|
|
493
528
|
""
|
|
494
|
-
].join("\n")
|
|
529
|
+
].join("\n"));
|
|
495
530
|
addServerPlugin(initPluginPath);
|
|
496
531
|
} else {
|
|
497
532
|
addServerPlugin(resolver.resolve("./runtime/plugins/init"));
|
|
@@ -510,10 +545,6 @@ const module$1 = defineNuxtModule({
|
|
|
510
545
|
}
|
|
511
546
|
opts._holoCoreRuntimeRegistered = true;
|
|
512
547
|
}
|
|
513
|
-
if (storageModule && !opts._holoStorageRuntimeRegistered) {
|
|
514
|
-
addServerPlugin(resolver.resolve("./runtime/plugins/storage"));
|
|
515
|
-
opts._holoStorageRuntimeRegistered = true;
|
|
516
|
-
}
|
|
517
548
|
if (hasProjectPackage(rootDir, "@holo-js/broadcast") && !opts._holoBroadcastAuthRouteRegistered) {
|
|
518
549
|
addServerHandler({
|
|
519
550
|
route: "/broadcasting/config",
|
|
@@ -550,11 +581,12 @@ const module$1 = defineNuxtModule({
|
|
|
550
581
|
route: "/holo/realtime/mutation",
|
|
551
582
|
handler: resolver.resolve("./runtime/server/routes/realtime-mutation.post")
|
|
552
583
|
});
|
|
584
|
+
opts.nitro.virtual = {
|
|
585
|
+
...opts.nitro.virtual,
|
|
586
|
+
[realtimeDefinitionsModuleId]: () => renderRealtimeDefinitionsModule(rootDir)
|
|
587
|
+
};
|
|
553
588
|
opts._holoRealtimeRouteRegistered = true;
|
|
554
589
|
}
|
|
555
|
-
if (storageModule && normalizedStorage && (!opts.nitro.storage || Object.keys(opts.nitro.storage).every((key) => !key.startsWith("holo:")))) {
|
|
556
|
-
storageModule.applyNitroStorageConfig(opts, normalizedStorage, s3Driver);
|
|
557
|
-
}
|
|
558
590
|
const runtimePath = resolver.resolve("./runtime");
|
|
559
591
|
for (const packageName of [runtimePath, "@holo-js/auth"]) {
|
|
560
592
|
if (!opts.build.transpile.includes(packageName)) {
|
|
@@ -564,7 +596,7 @@ const module$1 = defineNuxtModule({
|
|
|
564
596
|
if (storageModule && !opts._holoStorageFinalizeRegistered) {
|
|
565
597
|
opts._holoStorageFinalizeRegistered = true;
|
|
566
598
|
nuxt.hook("modules:done", () => {
|
|
567
|
-
finalizeStorageSetup(storageModule, opts, resolver
|
|
599
|
+
finalizeStorageSetup(storageModule, opts, resolver);
|
|
568
600
|
});
|
|
569
601
|
}
|
|
570
602
|
if (!opts._holoTypesRegistered) {
|
|
@@ -572,12 +604,27 @@ const module$1 = defineNuxtModule({
|
|
|
572
604
|
await ensureModelRegistryTypesPlaceholder(authTypesPath);
|
|
573
605
|
await ensureModelRegistryTypesPlaceholder(authorizationTypesPath);
|
|
574
606
|
await ensureModelRegistryTypesPlaceholder(modelRegistryTypesPath);
|
|
575
|
-
|
|
576
|
-
|
|
577
|
-
|
|
578
|
-
references.push(
|
|
579
|
-
|
|
580
|
-
|
|
607
|
+
const serverTypeReferences = [authTypesPath, authorizationTypesPath, modelRegistryTypesPath, ...pluginTypesPaths].map((path) => ({ path }));
|
|
608
|
+
const serverTypeIncludes = [resolve(rootDir, "config/**/*")];
|
|
609
|
+
nuxt.hook("nitro:prepare:types", ({ references }) => {
|
|
610
|
+
references.push(...serverTypeReferences);
|
|
611
|
+
});
|
|
612
|
+
nuxt.hook("nitro:config", (nitroConfig) => {
|
|
613
|
+
nitroConfig.typescript ??= {};
|
|
614
|
+
nitroConfig.typescript.tsConfig ??= {};
|
|
615
|
+
nitroConfig.typescript.tsConfig.include = [...nitroConfig.typescript.tsConfig.include ?? [], ...serverTypeIncludes];
|
|
616
|
+
});
|
|
617
|
+
nuxt.hook("prepare:types", async ({ references, serverReferences, tsConfig, serverTsConfig }) => {
|
|
618
|
+
references.push({ types: "@holo-js/adapter-nuxt" }, ...serverTypeReferences);
|
|
619
|
+
serverReferences?.push(...serverTypeReferences);
|
|
620
|
+
if (serverTsConfig) serverTsConfig.include = [...serverTsConfig.include ?? [], ...serverTypeIncludes];
|
|
621
|
+
const options = nuxt.options;
|
|
622
|
+
const { projectTsconfigInternals } = await import('@holo-js/core');
|
|
623
|
+
await projectTsconfigInternals.writeNuxtTsconfigSnapshot(
|
|
624
|
+
rootDir,
|
|
625
|
+
options.typesDir || options.buildDir || resolve(rootDir, ".nuxt"),
|
|
626
|
+
{ tsConfig, serverTsConfig }
|
|
627
|
+
);
|
|
581
628
|
});
|
|
582
629
|
}
|
|
583
630
|
}
|
|
@@ -593,7 +640,6 @@ const moduleInternals = {
|
|
|
593
640
|
hasModuleNotFoundCode,
|
|
594
641
|
hasLoadedConfigFile,
|
|
595
642
|
importOptionalStorageS3Module,
|
|
596
|
-
applyStorageRuntimeConfig,
|
|
597
643
|
finalizeStorageSetup,
|
|
598
644
|
resolveStorageSetup,
|
|
599
645
|
isModuleResolutionFailure,
|
|
@@ -602,6 +648,7 @@ const moduleInternals = {
|
|
|
602
648
|
isProjectPackageLinked,
|
|
603
649
|
isRealtimeDefinitionModule,
|
|
604
650
|
resolveClientOptimizeDeps,
|
|
651
|
+
renderRealtimeDefinitionsModule,
|
|
605
652
|
resolveExistingRealtimeDefinitionFile,
|
|
606
653
|
resolveRealtimeDefinitionImport
|
|
607
654
|
};
|
|
@@ -609,4 +656,4 @@ const adapterNuxtInternals = {
|
|
|
609
656
|
toStorageModuleOptions
|
|
610
657
|
};
|
|
611
658
|
|
|
612
|
-
export { adapterNuxtInternals,
|
|
659
|
+
export { adapterNuxtInternals, holoNuxtModule as default, moduleInternals };
|
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
import type { HoloAdapterProjectAccessors } from '@holo-js/core'
|
|
2
|
-
import type { RuntimeDatabaseConfig } from '@holo-js/db'
|
|
3
2
|
|
|
4
3
|
export interface HoloRuntimeConnection {
|
|
5
4
|
driver?: 'sqlite' | 'postgres' | 'mysql'
|
|
@@ -29,12 +28,9 @@ export interface HoloRuntimeDefaultConnection extends HoloRuntimeConnection {
|
|
|
29
28
|
export declare const holo: HoloAdapterProjectAccessors
|
|
30
29
|
export declare function configureHoloRuntimeConfig(config: {
|
|
31
30
|
holo: {
|
|
32
|
-
appEnv: 'production' | 'development' | 'test'
|
|
33
|
-
appDebug: boolean
|
|
34
31
|
appUrl?: string
|
|
35
32
|
projectRoot?: string
|
|
36
33
|
}
|
|
37
|
-
db?: RuntimeDatabaseConfig
|
|
38
34
|
}): void
|
|
39
35
|
export declare function resetHoloRuntimeConfig(): void
|
|
40
36
|
export type NuxtAuthRequestEvent = {
|
|
@@ -52,8 +48,10 @@ export type NuxtAuthRequestEvent = {
|
|
|
52
48
|
readonly headers?: Readonly<Record<string, string | readonly string[] | undefined>>
|
|
53
49
|
}
|
|
54
50
|
readonly res?: {
|
|
51
|
+
statusCode: number
|
|
55
52
|
getHeader(name: string): number | string | readonly string[] | undefined
|
|
56
53
|
setHeader(name: string, value: number | string | readonly string[]): void
|
|
54
|
+
end(): void
|
|
57
55
|
}
|
|
58
56
|
}
|
|
59
57
|
}
|
|
@@ -1,8 +1,10 @@
|
|
|
1
|
+
import { resolveProjectAppEnvironmentSync } from "@holo-js/config";
|
|
1
2
|
import {
|
|
2
3
|
createHoloProjectAccessors,
|
|
4
|
+
getHolo,
|
|
3
5
|
initializeHoloAdapterProject
|
|
4
6
|
} from "@holo-js/core";
|
|
5
|
-
import {
|
|
7
|
+
import { createCookieWriteUnavailableError } from "@holo-js/kernel";
|
|
6
8
|
export function configureHoloRuntimeConfig(config) {
|
|
7
9
|
const runtimeGlobals = globalThis;
|
|
8
10
|
runtimeGlobals.__holoRuntimeConfig = config;
|
|
@@ -21,14 +23,12 @@ function getRuntimeConfig() {
|
|
|
21
23
|
}
|
|
22
24
|
return runtimeGlobals.useRuntimeConfig();
|
|
23
25
|
}
|
|
24
|
-
function resolveRuntimeEnvName(env) {
|
|
25
|
-
return env;
|
|
26
|
-
}
|
|
27
26
|
function resolveRuntimeProjectRoot(config) {
|
|
28
27
|
return config.holo.projectRoot?.trim() || process.cwd();
|
|
29
28
|
}
|
|
30
|
-
async function
|
|
31
|
-
|
|
29
|
+
async function resolveNitroEvent() {
|
|
30
|
+
const { useEvent } = await import("#imports");
|
|
31
|
+
return useEvent();
|
|
32
32
|
}
|
|
33
33
|
export function createNuxtAuthRequestAccessors(requestEvent) {
|
|
34
34
|
function safeDecode(value) {
|
|
@@ -39,7 +39,7 @@ export function createNuxtAuthRequestAccessors(requestEvent) {
|
|
|
39
39
|
}
|
|
40
40
|
}
|
|
41
41
|
async function readHeader(name) {
|
|
42
|
-
const event = requestEvent ??
|
|
42
|
+
const event = requestEvent ?? await resolveNitroEvent();
|
|
43
43
|
if (!event) {
|
|
44
44
|
return void 0;
|
|
45
45
|
}
|
|
@@ -80,11 +80,14 @@ export function createNuxtAuthRequestAccessors(requestEvent) {
|
|
|
80
80
|
}
|
|
81
81
|
return void 0;
|
|
82
82
|
}
|
|
83
|
+
async function resolveResponse() {
|
|
84
|
+
const event = requestEvent ?? await resolveNitroEvent();
|
|
85
|
+
return event?.node?.res;
|
|
86
|
+
}
|
|
83
87
|
async function appendCookie(cookie) {
|
|
84
|
-
const
|
|
85
|
-
const response = event?.node?.res;
|
|
88
|
+
const response = await resolveResponse();
|
|
86
89
|
if (!response) {
|
|
87
|
-
|
|
90
|
+
throw createCookieWriteUnavailableError("Authentication cookies cannot be set outside an active Nitro request.");
|
|
88
91
|
}
|
|
89
92
|
const current = response.getHeader("set-cookie");
|
|
90
93
|
if (Array.isArray(current)) {
|
|
@@ -103,20 +106,26 @@ export function createNuxtAuthRequestAccessors(requestEvent) {
|
|
|
103
106
|
const getHeaderValue = async (name) => {
|
|
104
107
|
return await readHeader(name);
|
|
105
108
|
};
|
|
109
|
+
const canAppendResponseCookie = async () => {
|
|
110
|
+
return Boolean(await resolveResponse());
|
|
111
|
+
};
|
|
106
112
|
const appendResponseCookie = async (cookie) => {
|
|
107
113
|
await appendCookie(cookie);
|
|
108
114
|
};
|
|
109
115
|
const redirectResponse = async (url, status) => {
|
|
110
|
-
const event = requestEvent ??
|
|
111
|
-
|
|
116
|
+
const event = requestEvent ?? await resolveNitroEvent();
|
|
117
|
+
const response = event?.node?.res;
|
|
118
|
+
if (!response) {
|
|
112
119
|
throw new TypeError("Holo Nuxt auth redirect requires an active Nitro event.");
|
|
113
120
|
}
|
|
114
|
-
|
|
115
|
-
|
|
121
|
+
response.statusCode = status ?? 302;
|
|
122
|
+
response.setHeader("location", url);
|
|
123
|
+
response.end();
|
|
116
124
|
};
|
|
117
125
|
return {
|
|
118
126
|
getCookie: getCookieValue,
|
|
119
127
|
getHeader: getHeaderValue,
|
|
128
|
+
canAppendResponseCookie,
|
|
120
129
|
appendResponseCookie,
|
|
121
130
|
redirectResponse
|
|
122
131
|
};
|
|
@@ -130,9 +139,8 @@ export async function runWithNuxtRequest(event, callback) {
|
|
|
130
139
|
export const holo = createHoloProjectAccessors(async () => {
|
|
131
140
|
const config = getRuntimeConfig();
|
|
132
141
|
const authRequest = createNuxtAuthRequestAccessors();
|
|
142
|
+
const { createNuxtAuthorizationError } = await import("../authorization-error.js");
|
|
133
143
|
const project = await initializeHoloAdapterProject(resolveRuntimeProjectRoot(config), {
|
|
134
|
-
envName: resolveRuntimeEnvName(config.holo.appEnv),
|
|
135
|
-
preferCache: process.env.NODE_ENV === "production",
|
|
136
144
|
processEnv: process.env,
|
|
137
145
|
authRequest,
|
|
138
146
|
authorizationError: {
|
|
@@ -142,17 +150,12 @@ export const holo = createHoloProjectAccessors(async () => {
|
|
|
142
150
|
const runtimeGlobals = globalThis;
|
|
143
151
|
runtimeGlobals.__holoNuxtAuthRequestRunner = (accessors, callback) => project.runtime.runWithAuthRequestAccessors(accessors, callback);
|
|
144
152
|
return project;
|
|
145
|
-
}, {
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
}
|
|
150
|
-
|
|
151
|
-
if (connectionNames.includes("default")) {
|
|
152
|
-
return "default";
|
|
153
|
-
}
|
|
154
|
-
return connectionNames[0] ?? "default";
|
|
155
|
-
}
|
|
153
|
+
}, {
|
|
154
|
+
cache: () => resolveProjectAppEnvironmentSync({
|
|
155
|
+
cwd: resolveRuntimeProjectRoot(getRuntimeConfig()),
|
|
156
|
+
processEnv: process.env
|
|
157
|
+
}) === "production"
|
|
158
|
+
});
|
|
156
159
|
function normalizeConnection(connection) {
|
|
157
160
|
const driver = connection.driver ?? (connection.filename ? "sqlite" : void 0);
|
|
158
161
|
const database = connection.database ?? connection.filename;
|
|
@@ -171,14 +174,10 @@ function normalizeConnection(connection) {
|
|
|
171
174
|
};
|
|
172
175
|
}
|
|
173
176
|
export function useHoloDb() {
|
|
174
|
-
const
|
|
175
|
-
const group = config.db ?? { connections: {} };
|
|
177
|
+
const group = getHolo().loadedConfig.database;
|
|
176
178
|
const connections = group.connections ?? {};
|
|
177
179
|
return {
|
|
178
|
-
defaultConnection:
|
|
179
|
-
defaultConnection: group.defaultConnection,
|
|
180
|
-
connections
|
|
181
|
-
}),
|
|
180
|
+
defaultConnection: group.defaultConnection ?? "default",
|
|
182
181
|
connections: Object.fromEntries(
|
|
183
182
|
Object.entries(connections).map(([name, connection]) => {
|
|
184
183
|
if (typeof connection === "string") {
|
|
@@ -190,10 +189,8 @@ export function useHoloDb() {
|
|
|
190
189
|
};
|
|
191
190
|
}
|
|
192
191
|
export function useHoloEnv() {
|
|
193
|
-
|
|
194
|
-
return resolveRuntimeEnvName(config.holo.appEnv);
|
|
192
|
+
return getHolo().loadedConfig.environment.name;
|
|
195
193
|
}
|
|
196
194
|
export function useHoloDebug() {
|
|
197
|
-
|
|
198
|
-
return config.holo.appDebug;
|
|
195
|
+
return getHolo().loadedConfig.app.debug;
|
|
199
196
|
}
|
|
@@ -3,31 +3,47 @@ import {
|
|
|
3
3
|
configureHoloRuntimeConfig
|
|
4
4
|
} from "../composables/index.js";
|
|
5
5
|
import { createNuxtAuthorizationError } from "../authorization-error.js";
|
|
6
|
+
import { connectionAddress } from "../server/connection-address.js";
|
|
6
7
|
import { initializeHoloAdapterProject } from "@holo-js/core";
|
|
7
|
-
import {
|
|
8
|
-
import {
|
|
8
|
+
import { requestUrlInternals } from "@holo-js/kernel";
|
|
9
|
+
import { captureErrorReporter } from "@holo-js/kernel/error-reporting";
|
|
10
|
+
import { defineNitroPlugin, useEvent, useRuntimeConfig } from "#imports";
|
|
9
11
|
export default defineNitroPlugin((nitroApp) => {
|
|
10
12
|
const config = useRuntimeConfig();
|
|
11
13
|
configureHoloRuntimeConfig(config);
|
|
14
|
+
requestUrlInternals.provideConnectionAddress(() => connectionAddress(useEvent().node.req.socket));
|
|
12
15
|
const project = initializeHoloAdapterProject(config.holo.projectRoot?.trim() || process.cwd(), {
|
|
13
|
-
envName: config.holo.appEnv,
|
|
14
|
-
preferCache: process.env.NODE_ENV === "production",
|
|
15
16
|
processEnv: process.env,
|
|
16
17
|
authRequest: createNuxtAuthRequestAccessors(),
|
|
17
18
|
authorizationError: {
|
|
18
19
|
createError: createNuxtAuthorizationError
|
|
19
20
|
}
|
|
20
21
|
});
|
|
22
|
+
let projectPending = true;
|
|
23
|
+
const markProjectSettled = () => {
|
|
24
|
+
projectPending = false;
|
|
25
|
+
};
|
|
26
|
+
const projectSettled = project.then(markProjectSettled, markProjectSettled);
|
|
21
27
|
const onRequest = nitroApp.h3App.options.onRequest;
|
|
22
28
|
nitroApp.h3App.options.onRequest = async (event) => {
|
|
23
29
|
await project;
|
|
24
30
|
return await onRequest?.(event);
|
|
25
31
|
};
|
|
26
|
-
|
|
32
|
+
const shutdownProject = async () => {
|
|
33
|
+
let report;
|
|
27
34
|
try {
|
|
28
|
-
|
|
29
|
-
|
|
35
|
+
const { runtime } = await project;
|
|
36
|
+
report = captureErrorReporter();
|
|
37
|
+
await runtime.shutdown();
|
|
38
|
+
} catch (error) {
|
|
39
|
+
(report ?? captureErrorReporter())(error, { capability: "nuxt", operation: "shutdown" });
|
|
40
|
+
}
|
|
41
|
+
};
|
|
42
|
+
nitroApp.hooks.hook("close", async () => {
|
|
43
|
+
if (projectPending) {
|
|
44
|
+
void projectSettled.then(shutdownProject);
|
|
30
45
|
return;
|
|
31
46
|
}
|
|
47
|
+
await shutdownProject();
|
|
32
48
|
});
|
|
33
49
|
});
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
function isUnixSocket(socket) {
|
|
2
|
+
return !socket.destroyed && Object.keys(socket.address()).length === 0;
|
|
3
|
+
}
|
|
4
|
+
export function connectionAddress(socket) {
|
|
5
|
+
if (socket.remoteAddress) return socket.remoteAddress;
|
|
6
|
+
return isUnixSocket(socket) ? "127.0.0.1" : void 0;
|
|
7
|
+
}
|
|
@@ -1,26 +1,17 @@
|
|
|
1
|
-
import { send, setHeader, setResponseStatus } from "
|
|
2
|
-
import {
|
|
3
|
-
import { serializeRateLimitError } from "@holo-js/adapter-shared/server-errors";
|
|
1
|
+
import { send, setHeader, setResponseStatus } from "#imports";
|
|
2
|
+
import { serializeValidationException } from "@holo-js/validation";
|
|
3
|
+
import { serializeRateLimitError, serializeRequestBodyTooLargeError } from "@holo-js/adapter-shared/server-errors";
|
|
4
4
|
import {
|
|
5
5
|
applyFormFailureRedirect,
|
|
6
6
|
shouldRedirectFormFailure
|
|
7
7
|
} from "./form-failure.js";
|
|
8
|
-
function findValidationException(error) {
|
|
9
|
-
if (isValidationException(error)) {
|
|
10
|
-
return error;
|
|
11
|
-
}
|
|
12
|
-
if (!error || typeof error !== "object" || !("cause" in error)) {
|
|
13
|
-
return void 0;
|
|
14
|
-
}
|
|
15
|
-
return findValidationException(error.cause);
|
|
16
|
-
}
|
|
17
8
|
export default async function handleValidationError(error, event) {
|
|
18
|
-
const
|
|
19
|
-
const payload =
|
|
9
|
+
const bodyTooLarge = serializeRequestBodyTooLargeError(error);
|
|
10
|
+
const payload = bodyTooLarge ?? serializeValidationException(error) ?? serializeRateLimitError(error);
|
|
20
11
|
if (!payload) {
|
|
21
12
|
return;
|
|
22
13
|
}
|
|
23
|
-
if (shouldRedirectFormFailure(event)) {
|
|
14
|
+
if (!bodyTooLarge && shouldRedirectFormFailure(event)) {
|
|
24
15
|
const failure = { ...payload };
|
|
25
16
|
const response = {};
|
|
26
17
|
applyFormFailureRedirect(event, response, failure);
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { resolveRequestUrl, sameOriginRedirectPath } from "@holo-js/kernel";
|
|
1
2
|
const FORM_FAILURE_COOKIE = "holo_form_failure";
|
|
2
3
|
function getHeader(event, name) {
|
|
3
4
|
const value = event.node?.req?.headers?.[name.toLowerCase()];
|
|
@@ -42,12 +43,12 @@ function getRedirectLocation(event) {
|
|
|
42
43
|
try {
|
|
43
44
|
const url = new URL(referer);
|
|
44
45
|
if (url.host === host) {
|
|
45
|
-
return `${url.pathname}${url.search}
|
|
46
|
+
return sameOriginRedirectPath(`${url.pathname}${url.search}`);
|
|
46
47
|
}
|
|
47
48
|
} catch {
|
|
48
49
|
}
|
|
49
50
|
}
|
|
50
|
-
return event.path ?? event.node?.req?.url
|
|
51
|
+
return sameOriginRedirectPath(event.path ?? event.node?.req?.url);
|
|
51
52
|
}
|
|
52
53
|
function appendSetCookie(event, response, cookie) {
|
|
53
54
|
const responseCookie = event.node?.res?.getHeader?.("set-cookie");
|
|
@@ -79,9 +80,21 @@ function setHeader(event, response, name, value) {
|
|
|
79
80
|
response.headers ??= {};
|
|
80
81
|
response.headers[name] = value;
|
|
81
82
|
}
|
|
82
|
-
function
|
|
83
|
-
const
|
|
84
|
-
|
|
83
|
+
function isSecureRequest(event) {
|
|
84
|
+
const request = event.node?.req;
|
|
85
|
+
const socket = request?.socket;
|
|
86
|
+
const protocol = socket && "encrypted" in socket && socket.encrypted === true ? "https" : "http";
|
|
87
|
+
try {
|
|
88
|
+
return resolveRequestUrl({ url: `${protocol}://localhost/`, headers: request?.headers }).protocol === "https:";
|
|
89
|
+
} catch {
|
|
90
|
+
return protocol === "https";
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
function serializeFormFailureCookie(event, payload) {
|
|
94
|
+
const { values: _values, ...failure } = payload;
|
|
95
|
+
const encoded = encodeURIComponent(JSON.stringify(failure));
|
|
96
|
+
const secure = isSecureRequest(event) ? "; Secure" : "";
|
|
97
|
+
return `${FORM_FAILURE_COOKIE}=${encoded}; Path=/; Max-Age=60; SameSite=Lax${secure}`;
|
|
85
98
|
}
|
|
86
99
|
export function shouldRedirectFormFailure(event) {
|
|
87
100
|
return isUnsafeMethod(event) && acceptsHtml(event) && !isApiRequest(event);
|
|
@@ -96,7 +109,7 @@ export function applyFormFailureRedirect(event, response, failure) {
|
|
|
96
109
|
response.body = "";
|
|
97
110
|
setHeader(event, response, "location", getRedirectLocation(event));
|
|
98
111
|
setHeader(event, response, "content-type", "text/html; charset=utf-8");
|
|
99
|
-
appendSetCookie(event, response, serializeFormFailureCookie(failure));
|
|
112
|
+
appendSetCookie(event, response, serializeFormFailureCookie(event, failure));
|
|
100
113
|
}
|
|
101
114
|
export const formFailureInternals = {
|
|
102
115
|
appendSetCookie
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import { createError, getHeaders, getRequestHeader, getRequestURL } from "#imports";
|
|
2
|
+
import { HoloRequestBodyTooLargeError, readBoundedBufferedBody, readBoundedNodeRequestBody, requestBodyLimitFor } from "@holo-js/kernel";
|
|
3
|
+
async function readBoundedEventBody(event) {
|
|
4
|
+
const limit = requestBodyLimitFor(getRequestHeader(event, "content-type"));
|
|
5
|
+
try {
|
|
6
|
+
const node = event.node.req;
|
|
7
|
+
const buffered = await readBoundedBufferedBody(
|
|
8
|
+
event._requestBody || event.web?.request?.body || node[Symbol.for("h3RawBody")] || node.rawBody || node.body,
|
|
9
|
+
limit
|
|
10
|
+
);
|
|
11
|
+
if (buffered) return buffered;
|
|
12
|
+
const bytes = await readBoundedNodeRequestBody(event.node.req, limit, getRequestHeader(event, "content-length"));
|
|
13
|
+
event._requestBody = bytes;
|
|
14
|
+
Object.assign(event.node.req, { [Symbol.for("h3RawBody")]: bytes });
|
|
15
|
+
return { bytes };
|
|
16
|
+
} catch (error) {
|
|
17
|
+
if (error instanceof HoloRequestBodyTooLargeError) {
|
|
18
|
+
throw createError({ statusCode: error.status, statusMessage: "Payload Too Large", cause: error });
|
|
19
|
+
}
|
|
20
|
+
throw error;
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
export async function createWebRequest(event) {
|
|
24
|
+
const buffered = await readBoundedEventBody(event);
|
|
25
|
+
const headers = new Headers();
|
|
26
|
+
for (const [key, value] of Object.entries(getHeaders(event))) {
|
|
27
|
+
if (typeof value === "string") {
|
|
28
|
+
headers.set(key, value);
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
if (buffered.contentType) {
|
|
32
|
+
headers.set("content-type", buffered.contentType);
|
|
33
|
+
}
|
|
34
|
+
return new Request(getRequestURL(event, { xForwardedProto: false }), {
|
|
35
|
+
body: buffered.bytes,
|
|
36
|
+
headers,
|
|
37
|
+
method: event.method
|
|
38
|
+
});
|
|
39
|
+
}
|
|
@@ -1,6 +1,7 @@
|
|
|
1
|
-
import { defineEventHandler
|
|
1
|
+
import { defineEventHandler } from "#imports";
|
|
2
2
|
import { renderBroadcastAuthResponse } from "@holo-js/broadcast/auth";
|
|
3
3
|
import { holo } from "../../composables/index.js";
|
|
4
|
+
import { createWebRequest } from "../route-request.js";
|
|
4
5
|
function resolveBroadcastSigning(connection) {
|
|
5
6
|
if (!connection || typeof connection !== "object") {
|
|
6
7
|
return {};
|
|
@@ -20,18 +21,7 @@ export default defineEventHandler(async (event) => {
|
|
|
20
21
|
const broadcast = app.config?.broadcast;
|
|
21
22
|
const connection = broadcast ? broadcast.connections[broadcast.default] : void 0;
|
|
22
23
|
const signing = resolveBroadcastSigning(connection);
|
|
23
|
-
|
|
24
|
-
for (const [key, value] of Object.entries(getHeaders(event))) {
|
|
25
|
-
if (typeof value === "string") {
|
|
26
|
-
headers.set(key, value);
|
|
27
|
-
}
|
|
28
|
-
}
|
|
29
|
-
const request = new Request(getRequestURL(event), {
|
|
30
|
-
method: event.method,
|
|
31
|
-
headers,
|
|
32
|
-
body: await readRawBody(event)
|
|
33
|
-
});
|
|
34
|
-
return await renderBroadcastAuthResponse(request, {
|
|
24
|
+
return await renderBroadcastAuthResponse(await createWebRequest(event), {
|
|
35
25
|
...signing,
|
|
36
26
|
resolveUser: async (_request, context) => {
|
|
37
27
|
const guardAuth = context.guard ? auth?.guard(context.guard) : void 0;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { defineEventHandler } from "
|
|
1
|
+
import { defineEventHandler } from "#imports";
|
|
2
2
|
import { renderBroadcastClientConfigResponse } from "@holo-js/broadcast/client-config";
|
|
3
3
|
import { holo } from "../../composables/index.js";
|
|
4
4
|
export default defineEventHandler(async () => {
|
|
@@ -1,9 +1,10 @@
|
|
|
1
|
-
import { defineEventHandler } from "
|
|
2
|
-
import { useRuntimeConfig } from "#imports";
|
|
1
|
+
import { defineEventHandler, useRuntimeConfig } from "#imports";
|
|
3
2
|
import { handleRealtimeMutationRequest } from "@holo-js/realtime/server";
|
|
4
|
-
import {
|
|
3
|
+
import { realtimeDefinitions } from "#holo/realtime-definitions";
|
|
4
|
+
import { createWebRequest } from "../route-request.js";
|
|
5
5
|
export default defineEventHandler(async (event) => {
|
|
6
|
-
return await handleRealtimeMutationRequest(await
|
|
7
|
-
projectRoot: useRuntimeConfig().holo.projectRoot ?? process.cwd()
|
|
6
|
+
return await handleRealtimeMutationRequest(await createWebRequest(event), {
|
|
7
|
+
projectRoot: useRuntimeConfig().holo.projectRoot ?? process.cwd(),
|
|
8
|
+
definitions: realtimeDefinitions
|
|
8
9
|
});
|
|
9
10
|
});
|
|
@@ -1,9 +1,10 @@
|
|
|
1
|
-
import { defineEventHandler } from "
|
|
2
|
-
import { useRuntimeConfig } from "#imports";
|
|
1
|
+
import { defineEventHandler, useRuntimeConfig } from "#imports";
|
|
3
2
|
import { handleRealtimeQueryRequest } from "@holo-js/realtime/server";
|
|
4
|
-
import {
|
|
3
|
+
import { realtimeDefinitions } from "#holo/realtime-definitions";
|
|
4
|
+
import { createWebRequest } from "../route-request.js";
|
|
5
5
|
export default defineEventHandler(async (event) => {
|
|
6
|
-
return await handleRealtimeQueryRequest(await
|
|
7
|
-
projectRoot: useRuntimeConfig().holo.projectRoot ?? process.cwd()
|
|
6
|
+
return await handleRealtimeQueryRequest(await createWebRequest(event), {
|
|
7
|
+
projectRoot: useRuntimeConfig().holo.projectRoot ?? process.cwd(),
|
|
8
|
+
definitions: realtimeDefinitions
|
|
8
9
|
});
|
|
9
10
|
});
|
|
@@ -1,8 +1,14 @@
|
|
|
1
1
|
import { createPublicStorageResponse } from "@holo-js/storage";
|
|
2
|
-
import { defineEventHandler,
|
|
2
|
+
import { defineEventHandler, getRequestURL, sendWebResponse } from "#imports";
|
|
3
3
|
import { holo } from "../../composables/index.js";
|
|
4
|
+
function createStorageRequest(event) {
|
|
5
|
+
return event.web?.request ?? new Request(getRequestURL(event, { xForwardedProto: false }), {
|
|
6
|
+
method: event.method,
|
|
7
|
+
headers: event.headers
|
|
8
|
+
});
|
|
9
|
+
}
|
|
4
10
|
export default defineEventHandler(async (event) => {
|
|
5
11
|
const app = await holo.getApp();
|
|
6
|
-
const response = await createPublicStorageResponse(app.projectRoot, app.config.storage,
|
|
12
|
+
const response = await createPublicStorageResponse(app.projectRoot, app.config.storage, createStorageRequest(event), app.config.app.key);
|
|
7
13
|
return sendWebResponse(event, response);
|
|
8
14
|
});
|
package/dist/runtime/shims.d.ts
CHANGED
|
@@ -1,45 +1,12 @@
|
|
|
1
|
-
import type { RuntimeConfigInput
|
|
2
|
-
|
|
3
|
-
type HoloConnectionRuntimeConfig = RuntimeConnectionConfig
|
|
4
|
-
type HoloDatabaseRuntimeConfig = RuntimeDatabaseConfig
|
|
5
|
-
|
|
6
|
-
interface StorageRuntimeDriverShim {
|
|
7
|
-
name: string
|
|
8
|
-
driver: 'local' | 'public' | 's3'
|
|
9
|
-
visibility: 'private' | 'public'
|
|
10
|
-
root?: string
|
|
11
|
-
url?: string
|
|
12
|
-
bucket?: string
|
|
13
|
-
region?: string
|
|
14
|
-
endpoint?: string
|
|
15
|
-
accessKeyId?: string
|
|
16
|
-
secretAccessKey?: string
|
|
17
|
-
sessionToken?: string
|
|
18
|
-
forcePathStyleEndpoint?: boolean
|
|
19
|
-
}
|
|
1
|
+
import type { RuntimeConfigInput } from '@holo-js/db'
|
|
20
2
|
|
|
21
3
|
interface HoloRuntimeConfig extends RuntimeConfigInput {
|
|
22
4
|
holo: NonNullable<RuntimeConfigInput['holo']> & {
|
|
23
|
-
appEnv: 'production' | 'development' | 'test'
|
|
24
|
-
appDebug: boolean
|
|
25
5
|
appUrl?: string
|
|
26
6
|
projectRoot?: string
|
|
27
7
|
}
|
|
28
|
-
db?: HoloDatabaseRuntimeConfig
|
|
29
|
-
holoStorage: {
|
|
30
|
-
defaultDisk: string | undefined
|
|
31
|
-
diskNames: string[]
|
|
32
|
-
routePrefix: string
|
|
33
|
-
disks: Record<string, StorageRuntimeDriverShim>
|
|
34
|
-
}
|
|
35
8
|
}
|
|
36
9
|
|
|
37
|
-
/**
|
|
38
|
-
* Minimal Nuxt runtime shims for adapter typechecking.
|
|
39
|
-
*
|
|
40
|
-
* Keep these declarations limited to the fields consumed by adapter runtime code:
|
|
41
|
-
* runtime config, storage access, and Nitro route/plugin globals.
|
|
42
|
-
*/
|
|
43
10
|
declare module '#app' {
|
|
44
11
|
export function defineNuxtPlugin<T>(plugin: T): T
|
|
45
12
|
export function useRuntimeConfig(): HoloRuntimeConfig
|
|
@@ -48,23 +15,9 @@ declare module '#app' {
|
|
|
48
15
|
|
|
49
16
|
declare module '#imports' {
|
|
50
17
|
export function useRuntimeConfig(): HoloRuntimeConfig
|
|
51
|
-
export function
|
|
52
|
-
}
|
|
53
|
-
|
|
54
|
-
declare module 'nitropack/runtime/config' {
|
|
55
|
-
export function useRuntimeConfig(): HoloRuntimeConfig
|
|
56
|
-
}
|
|
57
|
-
|
|
58
|
-
declare module 'nitropack/runtime/context' {
|
|
59
|
-
export function useEvent(): unknown
|
|
60
|
-
}
|
|
61
|
-
|
|
62
|
-
declare module 'nitropack/runtime/plugin' {
|
|
18
|
+
export function useEvent(): import('h3').H3Event
|
|
63
19
|
export function defineNitroPlugin<T>(plugin: T): T
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
declare module 'nitropack/runtime/storage' {
|
|
67
|
-
export function useStorage(base: string): unknown
|
|
20
|
+
export * from 'h3'
|
|
68
21
|
}
|
|
69
22
|
|
|
70
23
|
declare global {
|
package/package.json
CHANGED
|
@@ -1,9 +1,14 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@holo-js/adapter-nuxt",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.4.0",
|
|
4
4
|
"description": "Holo-JS Framework - Nuxt adapter",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "MIT",
|
|
7
|
+
"repository": {
|
|
8
|
+
"type": "git",
|
|
9
|
+
"url": "git+https://github.com/cobraprojects/holo-js.git",
|
|
10
|
+
"directory": "packages/adapter-nuxt"
|
|
11
|
+
},
|
|
7
12
|
"exports": {
|
|
8
13
|
".": {
|
|
9
14
|
"types": "./dist/types.d.mts",
|
|
@@ -29,7 +34,8 @@
|
|
|
29
34
|
"main": "./dist/module.mjs",
|
|
30
35
|
"types": "./dist/types.d.mts",
|
|
31
36
|
"files": [
|
|
32
|
-
"dist"
|
|
37
|
+
"dist",
|
|
38
|
+
"LICENSE"
|
|
33
39
|
],
|
|
34
40
|
"scripts": {
|
|
35
41
|
"build": "nuxt-module-build build",
|
|
@@ -38,22 +44,22 @@
|
|
|
38
44
|
"test": "vitest --run"
|
|
39
45
|
},
|
|
40
46
|
"dependencies": {
|
|
41
|
-
"@holo-js/adapter-shared": "^0.
|
|
42
|
-
"@nuxt/kit": "^4.
|
|
43
|
-
"@holo-js/config": "^0.
|
|
44
|
-
"@holo-js/core": "^0.
|
|
45
|
-
"@holo-js/db": "^0.
|
|
46
|
-
"@holo-js/
|
|
47
|
-
"
|
|
48
|
-
"nitropack": "^2.13.4"
|
|
47
|
+
"@holo-js/adapter-shared": "^0.4.0",
|
|
48
|
+
"@nuxt/kit": "^4.6.2",
|
|
49
|
+
"@holo-js/config": "^0.4.0",
|
|
50
|
+
"@holo-js/core": "^0.4.0",
|
|
51
|
+
"@holo-js/db": "^0.4.0",
|
|
52
|
+
"@holo-js/kernel": "^0.4.0",
|
|
53
|
+
"@holo-js/validation": "^0.4.0"
|
|
49
54
|
},
|
|
50
55
|
"peerDependencies": {
|
|
56
|
+
"nuxt": "^4.6.2",
|
|
51
57
|
"vue": "^3.5.13",
|
|
52
|
-
"@holo-js/broadcast": "^0.
|
|
53
|
-
"@holo-js/forms": "^0.
|
|
54
|
-
"@holo-js/realtime": "^0.
|
|
55
|
-
"@holo-js/storage": "^0.
|
|
56
|
-
"@holo-js/storage-s3": "^0.
|
|
58
|
+
"@holo-js/broadcast": "^0.4.0",
|
|
59
|
+
"@holo-js/forms": "^0.4.0",
|
|
60
|
+
"@holo-js/realtime": "^0.4.0",
|
|
61
|
+
"@holo-js/storage": "^0.4.0",
|
|
62
|
+
"@holo-js/storage-s3": "^0.4.0"
|
|
57
63
|
},
|
|
58
64
|
"peerDependenciesMeta": {
|
|
59
65
|
"@holo-js/broadcast": {
|
|
@@ -74,17 +80,18 @@
|
|
|
74
80
|
},
|
|
75
81
|
"devDependencies": {
|
|
76
82
|
"vue": "^3.5.13",
|
|
77
|
-
"@holo-js/broadcast": "^0.
|
|
78
|
-
"@holo-js/realtime": "^0.
|
|
79
|
-
"@holo-js/storage-s3": "^0.
|
|
83
|
+
"@holo-js/broadcast": "^0.4.0",
|
|
84
|
+
"@holo-js/realtime": "^0.4.0",
|
|
85
|
+
"@holo-js/storage-s3": "^0.4.0",
|
|
80
86
|
"@nuxt/module-builder": "^1.0.2",
|
|
81
|
-
"@types/node": "^22.
|
|
82
|
-
"nuxt": "^4.
|
|
83
|
-
"typescript": "^
|
|
84
|
-
"vitest": "^
|
|
85
|
-
"@nuxt/nitro-server": "^4.
|
|
87
|
+
"@types/node": "^22.20.5",
|
|
88
|
+
"nuxt": "^4.6.2",
|
|
89
|
+
"typescript": "^6.0.3",
|
|
90
|
+
"vitest": "^5.0.5",
|
|
91
|
+
"@nuxt/nitro-server": "^4.6.2",
|
|
92
|
+
"h3": "^1.15.11"
|
|
86
93
|
},
|
|
87
94
|
"engines": {
|
|
88
|
-
"node": "^22.
|
|
95
|
+
"node": "^22.18.0 || ^24.0.0 || ^26.0.0"
|
|
89
96
|
}
|
|
90
97
|
}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export { default } from "@holo-js/storage-s3";
|
|
@@ -1,10 +0,0 @@
|
|
|
1
|
-
import { configureStorageRuntime } from "@holo-js/storage/runtime";
|
|
2
|
-
import { useRuntimeConfig } from "nitropack/runtime/config";
|
|
3
|
-
import { defineNitroPlugin } from "nitropack/runtime/plugin";
|
|
4
|
-
import { useStorage as useNitroStorage } from "nitropack/runtime/storage";
|
|
5
|
-
export default defineNitroPlugin(() => {
|
|
6
|
-
configureStorageRuntime({
|
|
7
|
-
getRuntimeConfig: () => useRuntimeConfig(),
|
|
8
|
-
getStorage: (base) => useNitroStorage(base)
|
|
9
|
-
});
|
|
10
|
-
});
|
|
File without changes
|
|
@@ -1,14 +0,0 @@
|
|
|
1
|
-
import { getHeaders, getRequestURL, readRawBody } from "h3";
|
|
2
|
-
export async function createRealtimeRequest(event) {
|
|
3
|
-
const headers = new Headers();
|
|
4
|
-
for (const [key, value] of Object.entries(getHeaders(event))) {
|
|
5
|
-
if (typeof value === "string") {
|
|
6
|
-
headers.set(key, value);
|
|
7
|
-
}
|
|
8
|
-
}
|
|
9
|
-
return new Request(getRequestURL(event), {
|
|
10
|
-
body: await readRawBody(event),
|
|
11
|
-
headers,
|
|
12
|
-
method: event.method
|
|
13
|
-
});
|
|
14
|
-
}
|
|
File without changes
|
|
File without changes
|