@holo-js/adapter-nuxt 0.3.15 → 0.3.17

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/dist/module.d.mts CHANGED
@@ -65,6 +65,7 @@ type NuxtViteOptions = {
65
65
  interface NuxtOptionsWithNitro {
66
66
  nitro: {
67
67
  storage: Record<string, unknown>;
68
+ moduleSideEffects?: string[];
68
69
  errorHandler?: string | string[];
69
70
  externals?: {
70
71
  external?: unknown[];
package/dist/module.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@holo-js/adapter-nuxt",
3
3
  "configKey": "@holo-js/adapter-nuxt",
4
- "version": "0.3.15",
4
+ "version": "0.3.17",
5
5
  "builder": {
6
6
  "@nuxt/module-builder": "1.0.2",
7
7
  "unbuild": "unknown"
package/dist/module.mjs CHANGED
@@ -364,7 +364,7 @@ function finalizeStorageSetup(storageModule, opts, resolver, s3Driver) {
364
364
  if (storageModule.hasPublicLocalDisk(normalized)) {
365
365
  addServerHandler({
366
366
  route: `${normalized.routePrefix}/**`,
367
- handler: resolver.resolve("./runtime/server/routes/storage.get")
367
+ handler: resolver.resolve("./runtime/server/routes/storage")
368
368
  });
369
369
  }
370
370
  }
@@ -373,10 +373,10 @@ function applyStorageRuntimeConfig(runtimeConfig, normalized) {
373
373
  runtimeConfig.holoStorage = normalized;
374
374
  }
375
375
  }
376
- async function createServerModelImports(sourceDir, modelsRelativePath, generatedSchemaRelativePath) {
377
- const modelsDir = resolve(sourceDir, modelsRelativePath);
378
- const generatedSchemaPath = resolve(sourceDir, generatedSchemaRelativePath);
379
- const modelImportDir = resolve(sourceDir, ".holo-js/generated/nuxt-server-imports");
376
+ async function createServerModelImports(projectRoot, modelsRelativePath, generatedSchemaRelativePath) {
377
+ const modelsDir = resolve(projectRoot, modelsRelativePath);
378
+ const generatedSchemaPath = resolve(projectRoot, generatedSchemaRelativePath);
379
+ const modelImportDir = resolve(projectRoot, ".holo-js/generated/nuxt-server-imports");
380
380
  const modelImportFile = resolve(modelImportDir, "models.ts");
381
381
  const modelPluginFile = resolve(modelImportDir, "plugin.ts");
382
382
  let modelFiles;
@@ -426,7 +426,6 @@ const module$1 = defineNuxtModule({
426
426
  const resolver = createResolver(import.meta.url);
427
427
  const opts = nuxt.options;
428
428
  const rootDir = opts.rootDir ?? opts.srcDir ?? process.cwd();
429
- const sourceDir = opts.srcDir ?? rootDir;
430
429
  const authTypesPath = resolve(rootDir, ".holo-js/generated/auth.d.ts");
431
430
  const authorizationTypesPath = resolve(rootDir, ".holo-js/generated/authorization/types.d.ts");
432
431
  const modelRegistryTypesPath = resolve(rootDir, ".holo-js/generated/model-registry.d.ts");
@@ -486,13 +485,14 @@ const module$1 = defineNuxtModule({
486
485
  addServerPlugin(resolver.resolve("./runtime/plugins/forms"));
487
486
  addServerImportsDir(resolver.resolve("./runtime/server/auto-imports"));
488
487
  const serverModelImports = await createServerModelImports(
489
- sourceDir,
488
+ rootDir,
490
489
  loaded.app.paths.models,
491
490
  loaded.app.paths.generatedSchema
492
491
  );
493
492
  if (serverModelImports) {
494
493
  addServerImportsDir(serverModelImports.importDir);
495
494
  addServerPlugin(serverModelImports.pluginFile);
495
+ opts.nitro.moduleSideEffects = [.../* @__PURE__ */ new Set([...opts.nitro.moduleSideEffects ?? [], resolve(rootDir, loaded.app.paths.generatedSchema)])];
496
496
  }
497
497
  opts._holoCoreRuntimeRegistered = true;
498
498
  }
@@ -1,5 +1,5 @@
1
- import type { FormSchema, InferFormData } from '@holo-js/forms'
2
- import type { ValidationErrorBag } from '@holo-js/forms'
1
+ import type { InferFormData } from '@holo-js/forms'
2
+ import type { ValidationErrorBag, ValidationSchema } from '@holo-js/validation'
3
3
  import type {
4
4
  InferFormFieldTree,
5
5
  UseFormOptions,
@@ -17,7 +17,7 @@ export type {
17
17
  ValidateOnMode,
18
18
  } from '@holo-js/forms/internal/client'
19
19
 
20
- export declare function useForm<TSchema extends FormSchema, TSuccess = unknown>(
20
+ export declare function useForm<TSchema extends ValidationSchema, TSuccess = unknown>(
21
21
  schemaDefinition: TSchema,
22
22
  options?: UseFormOptions<InferFormData<TSchema>, TSuccess>,
23
23
  ): UseFormResult<InferFormData<TSchema>, TSuccess, InferFormFieldTree<TSchema>>
@@ -1,4 +1,5 @@
1
1
  import type { HoloAdapterProjectAccessors } from '@holo-js/core'
2
+ import type { RuntimeDatabaseConfig } from '@holo-js/db'
2
3
 
3
4
  export interface HoloRuntimeConnection {
4
5
  driver?: 'sqlite' | 'postgres' | 'mysql'
@@ -26,6 +27,16 @@ export interface HoloRuntimeDefaultConnection extends HoloRuntimeConnection {
26
27
  }
27
28
 
28
29
  export declare const holo: HoloAdapterProjectAccessors
30
+ export declare function configureHoloRuntimeConfig(config: {
31
+ holo: {
32
+ appEnv: 'production' | 'development' | 'test'
33
+ appDebug: boolean
34
+ appUrl?: string
35
+ projectRoot?: string
36
+ }
37
+ db?: RuntimeDatabaseConfig
38
+ }): void
39
+ export declare function resetHoloRuntimeConfig(): void
29
40
  export type NuxtAuthRequestEvent = {
30
41
  readonly headers?: Pick<Headers, 'get'>
31
42
  readonly request?: {
@@ -39,8 +39,7 @@ export function createNuxtAuthRequestAccessors(requestEvent) {
39
39
  }
40
40
  }
41
41
  async function readHeader(name) {
42
- const nitroContext = await loadNitroContextModule();
43
- const event = requestEvent ?? nitroContext.useEvent();
42
+ const event = requestEvent ?? (await loadNitroContextModule()).useEvent();
44
43
  if (!event) {
45
44
  return void 0;
46
45
  }
@@ -82,8 +81,7 @@ export function createNuxtAuthRequestAccessors(requestEvent) {
82
81
  return void 0;
83
82
  }
84
83
  async function appendCookie(cookie) {
85
- const nitroContext = await loadNitroContextModule();
86
- const event = requestEvent ?? nitroContext.useEvent();
84
+ const event = requestEvent ?? (await loadNitroContextModule()).useEvent();
87
85
  const response = event?.node?.res;
88
86
  if (!response) {
89
87
  return;
@@ -109,8 +107,7 @@ export function createNuxtAuthRequestAccessors(requestEvent) {
109
107
  await appendCookie(cookie);
110
108
  };
111
109
  const redirectResponse = async (url, status) => {
112
- const nitroContext = await loadNitroContextModule();
113
- const event = requestEvent ?? nitroContext.useEvent();
110
+ const event = requestEvent ?? (await loadNitroContextModule()).useEvent();
114
111
  if (!event) {
115
112
  throw new TypeError("Holo Nuxt auth redirect requires an active Nitro event.");
116
113
  }
@@ -0,0 +1,8 @@
1
+ import { createPublicStorageResponse } from "@holo-js/storage";
2
+ import { defineEventHandler, sendWebResponse, toWebRequest } from "h3";
3
+ import { holo } from "../../composables/index.js";
4
+ export default defineEventHandler(async (event) => {
5
+ const app = await holo.getApp();
6
+ const response = await createPublicStorageResponse(app.projectRoot, app.config.storage, toWebRequest(event), app.config.app.key);
7
+ return sendWebResponse(event, response);
8
+ });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@holo-js/adapter-nuxt",
3
- "version": "0.3.15",
3
+ "version": "0.3.17",
4
4
  "description": "Holo-JS Framework - Nuxt adapter",
5
5
  "type": "module",
6
6
  "license": "MIT",
@@ -38,21 +38,21 @@
38
38
  "test": "vitest --run"
39
39
  },
40
40
  "dependencies": {
41
- "@holo-js/adapter-shared": "^0.3.15",
41
+ "@holo-js/adapter-shared": "^0.3.17",
42
42
  "@nuxt/kit": "^4.4.4",
43
- "@holo-js/config": "^0.3.15",
44
- "@holo-js/core": "^0.3.15",
45
- "@holo-js/db": "^0.3.15",
46
- "@holo-js/validation": "^0.3.15",
43
+ "@holo-js/config": "^0.3.17",
44
+ "@holo-js/core": "^0.3.17",
45
+ "@holo-js/db": "^0.3.17",
46
+ "@holo-js/validation": "^0.3.17",
47
47
  "h3": "^1.15.11",
48
48
  "nitropack": "^2.13.4"
49
49
  },
50
50
  "peerDependencies": {
51
- "@holo-js/broadcast": "^0.3.15",
52
- "@holo-js/forms": "^0.3.15",
53
- "@holo-js/realtime": "^0.3.15",
54
- "@holo-js/storage": "^0.3.15",
55
- "@holo-js/storage-s3": "^0.3.15"
51
+ "@holo-js/broadcast": "^0.3.17",
52
+ "@holo-js/forms": "^0.3.17",
53
+ "@holo-js/realtime": "^0.3.17",
54
+ "@holo-js/storage": "^0.3.17",
55
+ "@holo-js/storage-s3": "^0.3.17"
56
56
  },
57
57
  "peerDependenciesMeta": {
58
58
  "@holo-js/broadcast": {
@@ -72,9 +72,9 @@
72
72
  }
73
73
  },
74
74
  "devDependencies": {
75
- "@holo-js/broadcast": "^0.3.15",
76
- "@holo-js/realtime": "^0.3.15",
77
- "@holo-js/storage-s3": "^0.3.15",
75
+ "@holo-js/broadcast": "^0.3.17",
76
+ "@holo-js/realtime": "^0.3.17",
77
+ "@holo-js/storage-s3": "^0.3.17",
78
78
  "@nuxt/module-builder": "^1.0.2",
79
79
  "@types/node": "^22.10.2",
80
80
  "nuxt": "^4.4.4",
@@ -82,6 +82,6 @@
82
82
  "vitest": "^4.1.5"
83
83
  },
84
84
  "engines": {
85
- "node": ">=22.12.0"
85
+ "node": "^22.12.0 || ^24.0.0 || ^26.0.0"
86
86
  }
87
87
  }
@@ -1,220 +0,0 @@
1
- import { open, realpath, stat } from "node:fs/promises";
2
- import { extname, resolve, sep } from "node:path";
3
- import { createError, defineEventHandler, getRequestURL, setResponseHeader } from "h3";
4
- import { useRuntimeConfig } from "#imports";
5
- const NAMED_PUBLIC_DISK_ROUTE_SEGMENT = "__holo";
6
- function normalizeRequestPath(value) {
7
- return value.split("/").map((segment) => {
8
- const trimmed = segment.trim();
9
- if (!trimmed) {
10
- return trimmed;
11
- }
12
- try {
13
- return decodeURIComponent(trimmed);
14
- } catch {
15
- return trimmed;
16
- }
17
- }).filter(Boolean);
18
- }
19
- function isPublicLocalDisk(disk) {
20
- return Boolean(disk && disk.visibility === "public" && disk.driver !== "s3" && typeof disk.root === "string");
21
- }
22
- function isMissingFileError(error) {
23
- const code = error && typeof error === "object" && "code" in error ? error.code : void 0;
24
- return Boolean(
25
- error && typeof error === "object" && (code === "ENOENT" || code === "EISDIR" || code === "ENOTDIR")
26
- );
27
- }
28
- function resolveAbsolutePath(disk, fileSegments) {
29
- const root = resolve(disk.root);
30
- const absolutePath = resolve(root, ...fileSegments);
31
- if (absolutePath !== root && !absolutePath.startsWith(`${root}${sep}`)) {
32
- return null;
33
- }
34
- return absolutePath;
35
- }
36
- function resolveContentType(absolutePath) {
37
- switch (extname(absolutePath).toLowerCase()) {
38
- case ".avif":
39
- return "image/avif";
40
- case ".css":
41
- return "text/css; charset=utf-8";
42
- case ".gif":
43
- return "image/gif";
44
- case ".jpeg":
45
- case ".jpg":
46
- return "image/jpeg";
47
- case ".json":
48
- return "application/json; charset=utf-8";
49
- case ".mp3":
50
- return "audio/mpeg";
51
- case ".pdf":
52
- return "application/pdf";
53
- case ".png":
54
- return "image/png";
55
- case ".txt":
56
- return "text/plain; charset=utf-8";
57
- case ".webp":
58
- return "image/webp";
59
- case ".woff":
60
- return "font/woff";
61
- case ".woff2":
62
- return "font/woff2";
63
- default:
64
- return "application/octet-stream";
65
- }
66
- }
67
- function isActiveContentPath(absolutePath) {
68
- switch (extname(absolutePath).toLowerCase()) {
69
- case ".html":
70
- case ".js":
71
- case ".mjs":
72
- case ".svg":
73
- return true;
74
- default:
75
- return false;
76
- }
77
- }
78
- function setStorageResponseHeaders(event, absolutePath) {
79
- if (isActiveContentPath(absolutePath)) {
80
- setResponseHeader(event, "content-disposition", "attachment");
81
- setResponseHeader(event, "content-type", "application/octet-stream");
82
- setResponseHeader(event, "x-content-type-options", "nosniff");
83
- return;
84
- }
85
- setResponseHeader(event, "content-type", resolveContentType(absolutePath));
86
- setResponseHeader(event, "x-content-type-options", "nosniff");
87
- }
88
- function createMissingFileError(message) {
89
- const error = new Error(message);
90
- error.code = "ENOENT";
91
- return error;
92
- }
93
- function isPathWithinRoot(root, absolutePath) {
94
- return absolutePath === root || absolutePath.startsWith(`${root}${sep}`);
95
- }
96
- function isSameFile(left, right) {
97
- return left.dev === right.dev && left.ino === right.ino;
98
- }
99
- async function readPublicFile(event, disk, absolutePath) {
100
- const resolvedRoot = await realpath(resolve(disk.root));
101
- const file = await open(absolutePath, "r");
102
- try {
103
- const openedFile = await file.stat();
104
- const resolvedPath = await realpath(absolutePath);
105
- if (!isPathWithinRoot(resolvedRoot, resolvedPath)) {
106
- throw createMissingFileError("Storage file not found.");
107
- }
108
- const resolvedFile = await stat(resolvedPath);
109
- if (!isSameFile(openedFile, resolvedFile)) {
110
- throw createMissingFileError("Storage file not found.");
111
- }
112
- const contents = await file.readFile();
113
- setStorageResponseHeaders(event, absolutePath);
114
- return contents;
115
- } finally {
116
- await file.close();
117
- }
118
- }
119
- function resolveRouteSegments(routePath) {
120
- const segments = normalizeRequestPath(routePath);
121
- if (segments.length === 0 || segments.includes("..")) {
122
- return null;
123
- }
124
- return segments;
125
- }
126
- function resolveDefaultPublicStorageRequest(config, segments) {
127
- const disk = isPublicLocalDisk(config.disks.public) ? config.disks.public : void 0;
128
- if (!disk) {
129
- return null;
130
- }
131
- const absolutePath = resolveAbsolutePath(disk, segments);
132
- if (!absolutePath) {
133
- return null;
134
- }
135
- return { disk, absolutePath };
136
- }
137
- function usesReservedNamedDiskNamespace(segments) {
138
- return segments[0] === NAMED_PUBLIC_DISK_ROUTE_SEGMENT;
139
- }
140
- function resolveNamedPublicStorageRequest(config, segments) {
141
- const namedPublicDisks = Object.values(config.disks).filter((disk2) => {
142
- return isPublicLocalDisk(disk2) && disk2.name !== "public";
143
- });
144
- const usesReservedNamespace = segments[0] === NAMED_PUBLIC_DISK_ROUTE_SEGMENT;
145
- const diskName = usesReservedNamespace ? segments[1] : segments[0];
146
- const disk = diskName ? namedPublicDisks.find((candidate) => candidate.name === diskName) : void 0;
147
- if (!disk) {
148
- return null;
149
- }
150
- const fileSegments = usesReservedNamespace ? segments.slice(2) : segments.slice(1);
151
- if (fileSegments.length === 0) {
152
- return null;
153
- }
154
- const absolutePath = resolveAbsolutePath(disk, fileSegments);
155
- if (!absolutePath) {
156
- return null;
157
- }
158
- return { disk, absolutePath };
159
- }
160
- export function resolvePublicStorageRequest(config, routePath) {
161
- const segments = resolveRouteSegments(routePath);
162
- if (!segments) {
163
- return null;
164
- }
165
- if (usesReservedNamedDiskNamespace(segments)) {
166
- return resolveNamedPublicStorageRequest(config, segments) ?? resolveDefaultPublicStorageRequest(config, segments);
167
- }
168
- return resolveDefaultPublicStorageRequest(config, segments) ?? resolveNamedPublicStorageRequest(config, segments);
169
- }
170
- function resolveFallbackPublicStorageRequest(config, segments, attemptedDiskName) {
171
- if (usesReservedNamedDiskNamespace(segments)) {
172
- return null;
173
- }
174
- const candidates = [
175
- resolveDefaultPublicStorageRequest(config, segments),
176
- resolveNamedPublicStorageRequest(config, segments)
177
- ];
178
- return candidates.find((candidate) => candidate && candidate.disk.name !== attemptedDiskName) ?? null;
179
- }
180
- export default defineEventHandler(async (event) => {
181
- const runtimeConfig = useRuntimeConfig();
182
- const { holoStorage } = runtimeConfig;
183
- const pathname = getRequestURL(event).pathname;
184
- const routePath = pathname.startsWith(holoStorage.routePrefix) ? pathname.slice(holoStorage.routePrefix.length) : pathname;
185
- const segments = resolveRouteSegments(routePath);
186
- if (!segments) {
187
- throw createError({
188
- statusCode: 404,
189
- statusMessage: "Storage file not found."
190
- });
191
- }
192
- const resolved = resolvePublicStorageRequest(holoStorage, routePath);
193
- if (!resolved) {
194
- throw createError({
195
- statusCode: 404,
196
- statusMessage: "Storage file not found."
197
- });
198
- }
199
- try {
200
- return await readPublicFile(event, resolved.disk, resolved.absolutePath);
201
- } catch (error) {
202
- if (!isMissingFileError(error)) {
203
- throw error;
204
- }
205
- const fallback = resolveFallbackPublicStorageRequest(holoStorage, segments, resolved.disk.name);
206
- if (fallback) {
207
- try {
208
- return await readPublicFile(event, fallback.disk, fallback.absolutePath);
209
- } catch (fallbackError) {
210
- if (!isMissingFileError(fallbackError)) {
211
- throw fallbackError;
212
- }
213
- }
214
- }
215
- throw createError({
216
- statusCode: 404,
217
- statusMessage: "Storage file not found."
218
- });
219
- }
220
- });