@forgebook/nuxt 0.0.0-stage → 0.2.1

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.
Files changed (59) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +121 -2
  3. package/dist/src/app/components.d.ts +119 -0
  4. package/dist/src/app/components.js +196 -0
  5. package/dist/src/app/data.d.ts +109 -0
  6. package/dist/src/app/data.js +155 -0
  7. package/dist/src/app/define.d.ts +30 -0
  8. package/dist/src/app/define.js +30 -0
  9. package/dist/src/app/errors.d.ts +43 -0
  10. package/dist/src/app/errors.js +41 -0
  11. package/dist/src/app/fetch.d.ts +63 -0
  12. package/dist/src/app/fetch.js +73 -0
  13. package/dist/src/app/head.d.ts +28 -0
  14. package/dist/src/app/head.js +23 -0
  15. package/dist/src/app/router.d.ts +69 -0
  16. package/dist/src/app/router.js +93 -0
  17. package/dist/src/app/state.d.ts +107 -0
  18. package/dist/src/app/state.js +137 -0
  19. package/dist/src/asyncDataRun.d.ts +39 -0
  20. package/dist/src/asyncDataRun.js +128 -0
  21. package/dist/src/nuxtError.d.ts +50 -0
  22. package/dist/src/nuxtError.js +65 -0
  23. package/dist/src/nuxtRenderer.d.ts +14 -0
  24. package/dist/src/nuxtRenderer.js +67 -0
  25. package/dist/src/nuxtStore.d.ts +144 -0
  26. package/dist/src/nuxtStore.js +196 -0
  27. package/dist/src/pageProject.d.ts +11 -0
  28. package/dist/src/pageProject.js +11 -0
  29. package/dist/src/parameters.d.ts +67 -0
  30. package/dist/src/parameters.js +89 -0
  31. package/dist/src/project.d.ts +49 -0
  32. package/dist/src/project.js +7 -0
  33. package/dist/src/renderer.d.ts +9 -0
  34. package/dist/src/renderer.js +10 -0
  35. package/dist/src/stories.d.ts +54 -0
  36. package/dist/src/stories.js +11 -0
  37. package/dist/src/storyCode.d.ts +3 -0
  38. package/dist/src/storyCode.js +9 -0
  39. package/dist/src/storyFetch.d.ts +74 -0
  40. package/dist/src/storyFetch.js +146 -0
  41. package/dist/src/storyNuxt.d.ts +48 -0
  42. package/dist/src/storyNuxt.js +26 -0
  43. package/dist/src/vite/componentNames.d.ts +36 -0
  44. package/dist/src/vite/componentNames.js +72 -0
  45. package/dist/src/vite/extractDocs.d.ts +16 -0
  46. package/dist/src/vite/extractDocs.js +22 -0
  47. package/dist/src/vite/nuxt.d.ts +13 -0
  48. package/dist/src/vite/nuxt.js +36 -0
  49. package/dist/src/vite/nuxtConfig.d.ts +85 -0
  50. package/dist/src/vite/nuxtConfig.js +261 -0
  51. package/dist/src/vite/nuxtPlugin.d.ts +51 -0
  52. package/dist/src/vite/nuxtPlugin.js +466 -0
  53. package/dist/src/vite/pageRoutes.d.ts +23 -0
  54. package/dist/src/vite/pageRoutes.js +88 -0
  55. package/dist/src/vite/placeKeys.d.ts +10 -0
  56. package/dist/src/vite/placeKeys.js +117 -0
  57. package/dist/src/vite/standIns.d.ts +26 -0
  58. package/dist/src/vite/standIns.js +96 -0
  59. package/package.json +118 -3
@@ -0,0 +1,261 @@
1
+ var __rewriteRelativeImportExtension = (this && this.__rewriteRelativeImportExtension) || function (path, preserveJsx) {
2
+ if (typeof path === "string" && /^\.\.?\//.test(path)) {
3
+ return path.replace(/\.(tsx)$|((?:\.d)?)((?:\.[^./]+?)?)\.([cm]?)ts$/i, function (m, tsx, d, ext, cm) {
4
+ return tsx ? preserveJsx ? ".jsx" : ".js" : d && (!ext || !cm) ? m : (d + ext + "." + cm.toLowerCase() + "js");
5
+ });
6
+ }
7
+ return path;
8
+ };
9
+ /**
10
+ * The project's `nuxt.config`, as far as a catalogue reads it: its folders, its aliases, its components' and
11
+ * auto-imports' folders, its style sheets, its public runtime config and its app config.
12
+ *
13
+ * @remarks
14
+ * The file is loaded as Node loads a module (a `nuxt.config.ts` with its types stripped), with `defineNuxtConfig`
15
+ * given as Nuxt gives it, a function that returns its argument; what it returns is read, never trusted: a field of the
16
+ * wrong type is left out. Everything else in it (modules, Nitro, the server's routes, the build) concerns Nuxt's server
17
+ * or its own build, so a story does not need it. A file that cannot be loaded is a warning, not a failure: the
18
+ * catalogue still opens with Nuxt's defaults.
19
+ *
20
+ * The runtime config keeps its `public` part only, since that is all Nuxt sends to the browser; a `NUXT_PUBLIC_`
21
+ * variable of the environment or the `.env` files replaces the value it names, as Nuxt's does.
22
+ *
23
+ * Every path it gives is in Vite's form, with forward slashes on every system: the plugin compares them with the ids
24
+ * Vite hands it and writes them into the modules it makes, which on Windows would not meet a path with backslashes.
25
+ *
26
+ * @module
27
+ */
28
+ import { existsSync, statSync } from "node:fs";
29
+ import nodePath from "node:path";
30
+ import { pathToFileURL } from "node:url";
31
+ import { normalizePath } from "vite";
32
+ /** The names `nuxt.config` may have, in the order Nuxt looks for them. */
33
+ export const NUXT_CONFIG_FILES = [
34
+ "nuxt.config.ts",
35
+ "nuxt.config.mts",
36
+ "nuxt.config.js",
37
+ "nuxt.config.mjs",
38
+ "nuxt.config.cjs"
39
+ ];
40
+ /** The names `app.config` may have. */
41
+ const APP_CONFIG_FILES = ["app.config.ts", "app.config.mts", "app.config.js", "app.config.mjs"];
42
+ /** The global function a `nuxt.config` calls without importing it. */
43
+ const DEFINE_CONFIG = "defineNuxtConfig";
44
+ /** Whether a value is a plain object. */
45
+ const isRecord = (value) => typeof value === "object" && value !== null && !Array.isArray(value);
46
+ /**
47
+ * An object field, or an empty object.
48
+ *
49
+ * @param config - the object.
50
+ * @param name - the field.
51
+ */
52
+ const objectField = (config, name) => {
53
+ const value = config[name];
54
+ return isRecord(value) ? value : {};
55
+ };
56
+ /**
57
+ * A text field, or none.
58
+ *
59
+ * @param config - the object.
60
+ * @param name - the field.
61
+ */
62
+ const textField = (config, name) => {
63
+ const value = config[name];
64
+ return typeof value === "string" ? value : undefined;
65
+ };
66
+ /** `path.join`, in Vite's form. */
67
+ const join = (...segments) => normalizePath(nodePath.join(...segments));
68
+ /** `path.resolve`, in Vite's form. */
69
+ const resolve = (...segments) => normalizePath(nodePath.resolve(...segments));
70
+ /** Whether a path is a folder. */
71
+ const isFolder = (path) => existsSync(path) && statSync(path).isDirectory();
72
+ /**
73
+ * A path as Nuxt resolves one written in its config: `~`, `@`, `~~` and `@@` replaced, a relative path from the
74
+ * project's folder, a package left as it is.
75
+ *
76
+ * @param path - the path.
77
+ * @param rootDir - the project's folder.
78
+ * @param srcDir - its sources' folder.
79
+ */
80
+ export const resolvedPath = (path, rootDir, srcDir) => {
81
+ const root = /^(~~|@@)(?=\/|$)/.exec(path);
82
+ if (root !== null)
83
+ return join(rootDir, path.slice(root[0].length));
84
+ const src = /^(~|@)(?=\/|$)/.exec(path);
85
+ if (src !== null)
86
+ return join(srcDir, path.slice(src[0].length));
87
+ if (nodePath.isAbsolute(path))
88
+ return normalizePath(path);
89
+ if (path.startsWith("."))
90
+ return resolve(rootDir, path);
91
+ return path;
92
+ };
93
+ /**
94
+ * A folder of `imports.dirs`: an alias as Nuxt resolves it, anything else from the sources' folder, as Nuxt reads it.
95
+ *
96
+ * @param path - the folder, as written.
97
+ * @param rootDir - the project's folder.
98
+ * @param srcDir - its sources' folder.
99
+ */
100
+ const importsDir = (path, rootDir, srcDir) => {
101
+ const resolved = resolvedPath(path, rootDir, srcDir);
102
+ return nodePath.isAbsolute(resolved) && resolved !== resolve(rootDir, path)
103
+ ? resolved
104
+ : resolve(srcDir, path);
105
+ };
106
+ /**
107
+ * The components' folders a config gives: `components/` of the sources by default, none for `false`, else each entry
108
+ * of the list (or of `dirs`), a path or `{ path, prefix, pathPrefix }`.
109
+ *
110
+ * @param value - `components`.
111
+ * @param rootDir - the project's folder.
112
+ * @param srcDir - its sources' folder.
113
+ */
114
+ const componentsDirsOf = (value, rootDir, srcDir) => {
115
+ if (value === false)
116
+ return [];
117
+ const entries = isRecord(value) ? value["dirs"] : value;
118
+ // Nuxt's own: the islands' and the global folders inside the components' one, each scanned before it
119
+ const list = Array.isArray(entries)
120
+ ? entries
121
+ : ["~/components/islands", "~/components/global", "~/components"];
122
+ return list.flatMap((entry) => {
123
+ if (typeof entry === "string")
124
+ return [{ path: resolvedPath(entry, rootDir, srcDir), prefix: "", pathPrefix: true }];
125
+ if (!isRecord(entry))
126
+ return [];
127
+ const path = textField(entry, "path");
128
+ if (path === undefined)
129
+ return [];
130
+ return [
131
+ {
132
+ path: resolvedPath(path, rootDir, srcDir),
133
+ prefix: textField(entry, "prefix") ?? "",
134
+ pathPrefix: entry["pathPrefix"] !== false
135
+ }
136
+ ];
137
+ });
138
+ };
139
+ /**
140
+ * What a catalogue reads of a configuration Nuxt would read.
141
+ *
142
+ * @param raw - what the file exported.
143
+ * @param file - the file.
144
+ * @param projectDir - the project's folder.
145
+ */
146
+ export const readNuxtConfig = (raw, file, projectDir) => {
147
+ const rootDir = normalizePath(projectDir);
148
+ const config = isRecord(raw) ? raw : {};
149
+ const srcGiven = textField(config, "srcDir");
150
+ // Nuxt 4 keeps the sources in `app/`; a project laid out as Nuxt 3's has them at its root
151
+ const nuxt4Dir = join(rootDir, "app");
152
+ const defaultDir = isFolder(nuxt4Dir) ? nuxt4Dir : rootDir;
153
+ const srcDir = srcGiven === undefined ? defaultDir : resolve(rootDir, srcGiven);
154
+ const dir = objectField(config, "dir");
155
+ const app = objectField(config, "app");
156
+ const imports = objectField(config, "imports");
157
+ const extraImports = imports["dirs"];
158
+ const css = config["css"];
159
+ const appConfigFile = APP_CONFIG_FILES.map((name) => join(srcDir, name)).find((path) => existsSync(path));
160
+ return {
161
+ file,
162
+ rootDir,
163
+ srcDir,
164
+ pagesDir: join(srcDir, textField(dir, "pages") ?? "pages"),
165
+ alias: {
166
+ ...Object.fromEntries(Object.entries(objectField(config, "alias")).flatMap(([name, path]) => typeof path === "string" ? [[name, resolvedPath(path, rootDir, srcDir)]] : []))
167
+ },
168
+ componentsDirs: componentsDirsOf(config["components"], rootDir, srcDir),
169
+ importsDirs: [
170
+ join(srcDir, "composables"),
171
+ join(srcDir, "utils"),
172
+ join(rootDir, "shared", "utils"),
173
+ ...(Array.isArray(extraImports)
174
+ ? extraImports.flatMap((each) => typeof each === "string" ? [importsDir(each, rootDir, srcDir)] : [])
175
+ : [])
176
+ ],
177
+ isAutoImport: imports["autoImport"] !== false,
178
+ css: Array.isArray(css)
179
+ ? css.flatMap((each) => typeof each === "string" ? [resolvedPath(each, rootDir, srcDir)] : [])
180
+ : [],
181
+ publicRuntimeConfig: objectField(objectField(config, "runtimeConfig"), "public"),
182
+ baseURL: textField(app, "baseURL") ?? "/",
183
+ buildAssetsDir: textField(app, "buildAssetsDir") ?? "/_nuxt/",
184
+ appConfig: objectField(config, "appConfig"),
185
+ appConfigFile
186
+ };
187
+ };
188
+ /**
189
+ * The project's `nuxt.config` file: the first Nuxt would find in its folder.
190
+ *
191
+ * @param rootDir - the project's folder.
192
+ */
193
+ export const nuxtConfigFile = (rootDir) => NUXT_CONFIG_FILES.map((name) => join(rootDir, name)).find((file) => existsSync(file));
194
+ /**
195
+ * Loads a project's `nuxt.config`.
196
+ *
197
+ * @param rootDir - the project's folder.
198
+ * @returns what the catalogue reads of it, and why it could not be loaded when it could not.
199
+ */
200
+ export const loadNuxtConfig = async (rootDir) => {
201
+ const file = nuxtConfigFile(rootDir);
202
+ if (file === undefined)
203
+ return { config: readNuxtConfig({}, undefined, rootDir), problem: undefined };
204
+ // Nuxt gives the file this function without an import; one the project already has (Nuxt's own) is left as it is
205
+ const isGiven = !(DEFINE_CONFIG in globalThis);
206
+ if (isGiven)
207
+ Reflect.set(globalThis, DEFINE_CONFIG, (config) => config);
208
+ try {
209
+ const loaded = await import(__rewriteRelativeImportExtension(pathToFileURL(file).href));
210
+ const exported = isRecord(loaded) && "default" in loaded ? loaded["default"] : loaded;
211
+ const raw = typeof exported === "function" ? await Reflect.apply(exported, undefined, []) : exported;
212
+ return { config: readNuxtConfig(raw, file, rootDir), problem: undefined };
213
+ }
214
+ catch (error) {
215
+ const reason = error instanceof Error ? error.message : String(error);
216
+ return { config: readNuxtConfig({}, file, rootDir), problem: `${file} could not be loaded (${reason})` };
217
+ }
218
+ finally {
219
+ if (isGiven)
220
+ Reflect.deleteProperty(globalThis, DEFINE_CONFIG);
221
+ }
222
+ };
223
+ /**
224
+ * A key as Nuxt writes it in a variable's name: `apiBase` as `API_BASE`.
225
+ *
226
+ * @param key - the key.
227
+ */
228
+ const envName = (key) => key
229
+ .replace(/([a-z\d])([A-Z])/g, "$1_$2")
230
+ .replace(/[-.]/g, "_")
231
+ .toUpperCase();
232
+ /**
233
+ * A variable's value as Nuxt reads it: JSON when it is (a number, a boolean, an object), else the text.
234
+ *
235
+ * @param value - the variable's value.
236
+ */
237
+ const envValue = (value) => {
238
+ try {
239
+ const parsed = JSON.parse(value);
240
+ return parsed;
241
+ }
242
+ catch {
243
+ return value;
244
+ }
245
+ };
246
+ /**
247
+ * The public runtime config with the environment's variables over it: `NUXT_PUBLIC_API_BASE` replaces
248
+ * `public.apiBase`, a nested key adding its name (`NUXT_PUBLIC_MAP_KEY` for `public.map.key`). Only a key the config
249
+ * has is replaced, as Nuxt replaces it.
250
+ *
251
+ * @param config - the config's `public` part.
252
+ * @param env - the variables, by name.
253
+ * @param prefix - the variables' prefix for this level; `NUXT_PUBLIC_` at the top.
254
+ */
255
+ export const withEnvironment = (config, env, prefix = "NUXT_PUBLIC_") => Object.fromEntries(Object.entries(config).map(([key, value]) => {
256
+ const name = `${prefix}${envName(key)}`;
257
+ const given = env[name];
258
+ if (given !== undefined)
259
+ return [key, envValue(given)];
260
+ return [key, isRecord(value) ? withEnvironment(value, env, `${name}_`) : value];
261
+ }));
@@ -0,0 +1,51 @@
1
+ import MagicString from "magic-string";
2
+ import { type PluginOption } from "vite";
3
+ import { type ProjectComponent } from "./componentNames.ts";
4
+ import type { NuxtOptions } from "./nuxt.ts";
5
+ import { type NuxtProjectConfig } from "./nuxtConfig.ts";
6
+ /** The frame page's module: Forgebook's frame with the Nuxt renderer, after the project's style sheets. */
7
+ export declare const FRAME_MODULE = "virtual:forgebook-nuxt/frame";
8
+ /**
9
+ * The project's components, by name: the first folder that names one wins, as in Nuxt. A file whose name makes no
10
+ * JavaScript name (`a;b.vue`) is left out, since its name is written into code.
11
+ *
12
+ * @param config - the project's config.
13
+ */
14
+ export declare const componentsOf: (config: NuxtProjectConfig) => {
15
+ readonly components: Map<string, ProjectComponent>;
16
+ readonly skipped: string[];
17
+ };
18
+ /**
19
+ * A template's components given their imports, as Nuxt's loader writes them: Nuxt's own, the project's, and a project
20
+ * component's `Lazy` form loaded when it is first drawn.
21
+ *
22
+ * @param code - the compiled component.
23
+ * @param components - the project's components, by name.
24
+ * @returns the code changed, or none when it names no component the plugin knows.
25
+ */
26
+ export declare const withComponentImports: (code: MagicString, components: ReadonlyMap<string, ProjectComponent>) => MagicString | undefined;
27
+ /**
28
+ * Nuxt 3's `process.client`, `process.server`, `process.browser` and `process.dev` written as their values in a
29
+ * project's file. Only there: given to the whole page (Vite's `define`), they would reach the libraries the frame
30
+ * loads, and one that reads `process.browser` would then read `process.env`, which the page does not have.
31
+ *
32
+ * @param code - the file's code, changed in place.
33
+ * @param isDev - whether the catalogue runs in development.
34
+ * @returns whether one was written.
35
+ */
36
+ export declare const withProcessFlags: (code: MagicString, isDev: boolean) => boolean;
37
+ /**
38
+ * Whether a file is one of the project's own: inside its folder, not in a folder beside it whose name starts the same
39
+ * (`app-admin` beside `app`).
40
+ *
41
+ * @param file - the file, as Vite names it.
42
+ * @param rootDir - the project's folder.
43
+ */
44
+ export declare const isProjectFile: (file: string, rootDir: string) => boolean;
45
+ /**
46
+ * The plugins of a Nuxt catalogue.
47
+ *
48
+ * @param options - the options of `nuxt()`.
49
+ * @returns the plugins.
50
+ */
51
+ export declare const nuxtPlugins: (options?: NuxtOptions) => PluginOption[];