@forgebook/nuxt 0.0.0-stage → 0.2.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.
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,117 @@
1
+ /**
2
+ * The keys of a place in the code, as Nuxt's compiler writes them: `useState()`, `useAsyncData(handler)` and
3
+ * `callOnce(fn)` called without a key get one more argument, a key made from the file and the call's place, so every
4
+ * component that calls them from that place shares the value, and only those.
5
+ *
6
+ * @remarks
7
+ * Nuxt adds the key when the call has fewer arguments than the function takes with one, as here; the stand-ins read a
8
+ * text last as that key (`src/app`). `useFetch` gets none: its key is the request, which a story writes. A call to a
9
+ * function of the same name imported from elsewhere is left alone.
10
+ *
11
+ * @module
12
+ */
13
+ import { createHash } from "node:crypto";
14
+ import { codeLiteral } from "forgebook/code-literal";
15
+ /** The functions keyed by their place, with the number of arguments a call has once keyed. */
16
+ const KEYED = {
17
+ useState: 2,
18
+ useAsyncData: 3,
19
+ useLazyAsyncData: 3,
20
+ callOnce: 3
21
+ };
22
+ /** The modules Nuxt's names come from, besides an auto-import. */
23
+ const NUXT_MODULE = /^(#imports|#app|nuxt\/app|@forgebook\/nuxt\/app\/.+)$/;
24
+ /** Whether a value is a plain object. */
25
+ const isRecord = (value) => typeof value === "object" && value !== null && !Array.isArray(value);
26
+ /**
27
+ * The names a file imports from a module that is not Nuxt's: a call of one of them is not Nuxt's.
28
+ *
29
+ * @param program - the file's syntax tree.
30
+ */
31
+ const foreignNames = (program) => {
32
+ const names = new Set();
33
+ const body = isRecord(program) && Array.isArray(program["body"]) ? program["body"] : [];
34
+ for (const statement of body)
35
+ for (const name of importedNames(statement))
36
+ names.add(name);
37
+ return names;
38
+ };
39
+ /**
40
+ * The names a statement imports from a module that is not Nuxt's; none for another statement.
41
+ *
42
+ * @param statement - the statement.
43
+ */
44
+ const importedNames = (statement) => {
45
+ if (!isRecord(statement) || statement["type"] !== "ImportDeclaration")
46
+ return [];
47
+ const source = statement["source"];
48
+ const from = isRecord(source) && typeof source["value"] === "string" ? source["value"] : "";
49
+ if (NUXT_MODULE.test(from))
50
+ return [];
51
+ const specifiers = Array.isArray(statement["specifiers"]) ? statement["specifiers"] : [];
52
+ return specifiers.flatMap((specifier) => {
53
+ const local = isRecord(specifier) ? specifier["local"] : undefined;
54
+ return isRecord(local) && typeof local["name"] === "string" ? [local["name"]] : [];
55
+ });
56
+ };
57
+ /**
58
+ * The calls of a syntax tree that get a key.
59
+ *
60
+ * @param node - the tree, or a part of it.
61
+ * @param foreign - the names imported from elsewhere.
62
+ * @param found - where the calls found are added.
63
+ */
64
+ const keyedCalls = (node, foreign, found) => {
65
+ if (Array.isArray(node)) {
66
+ for (const each of node)
67
+ keyedCalls(each, foreign, found);
68
+ return;
69
+ }
70
+ if (!isRecord(node))
71
+ return;
72
+ const call = keyedCall(node, foreign);
73
+ if (call !== undefined)
74
+ found.push(call);
75
+ for (const [field, value] of Object.entries(node))
76
+ if (field !== "type" && typeof value === "object")
77
+ keyedCalls(value, foreign, found);
78
+ };
79
+ /**
80
+ * Where a node's key goes, when it is a call of a keyed function without its key.
81
+ *
82
+ * @param node - the node.
83
+ * @param foreign - the names imported from elsewhere.
84
+ */
85
+ const keyedCall = (node, foreign) => {
86
+ if (node["type"] !== "CallExpression")
87
+ return undefined;
88
+ const callee = node["callee"];
89
+ const name = isRecord(callee) && callee["type"] === "Identifier" ? callee["name"] : undefined;
90
+ const length = typeof name === "string" && !foreign.has(name) ? KEYED[name] : undefined;
91
+ const args = Array.isArray(node["arguments"]) ? node["arguments"] : [];
92
+ if (length === undefined || args.length >= length)
93
+ return undefined;
94
+ const last = args.at(-1);
95
+ const lastEnd = isRecord(last) ? last["end"] : undefined;
96
+ if (typeof lastEnd === "number")
97
+ return { at: lastEnd, isAfterArgument: true };
98
+ const end = node["end"];
99
+ return args.length === 0 && typeof end === "number" ? { at: end - 1, isAfterArgument: false } : undefined;
100
+ };
101
+ /**
102
+ * Gives each call to a keyed function without a key the key of its place.
103
+ *
104
+ * @param code - the file's code, changed in place.
105
+ * @param program - its syntax tree, whose places are the code's.
106
+ * @param file - the file, as the project names it, which the keys are made from.
107
+ * @returns whether a key was written.
108
+ */
109
+ export const withPlaceKeys = (code, program, file) => {
110
+ const found = [];
111
+ keyedCalls(program, foreignNames(program), found);
112
+ for (const call of found) {
113
+ const key = `$${createHash("sha256").update(`${file}:${call.at}`).digest("base64url").slice(0, 10)}`;
114
+ code.appendLeft(call.at, `${call.isAfterArgument ? ", " : ""}${codeLiteral(key)}`);
115
+ }
116
+ return found.length > 0;
117
+ };
@@ -0,0 +1,26 @@
1
+ /**
2
+ * What a Nuxt project's code gets without importing it, and from where: Nuxt's composables and helpers from this
3
+ * package's stand-ins (`@forgebook/nuxt/app/…`), Vue's API, and the vue-router functions Nuxt imports for a project.
4
+ *
5
+ * @remarks
6
+ * The table is what `#app` exports, and with the project's own composables what `#imports` exports and what the plugin
7
+ * imports into a file that uses a name without importing it, as Nuxt does. A Nuxt function not in it is not given: a
8
+ * file that uses one fails on it by name, which says what a story lacks.
9
+ *
10
+ * @module
11
+ */
12
+ /** A name a file gets without importing it, and the module that has it. */
13
+ export type StandIn = {
14
+ /** The name. */
15
+ readonly name: string;
16
+ /** The module (`@forgebook/nuxt/app/router`). */
17
+ readonly from: string;
18
+ };
19
+ /** Nuxt's names, from this package's stand-ins: what `#app` exports. */
20
+ export declare const NUXT_STAND_INS: readonly StandIn[];
21
+ /** The vue-router functions a project's code gets without importing them. */
22
+ export declare const ROUTER_STAND_INS: readonly StandIn[];
23
+ /** The module of Nuxt's built-in components. */
24
+ export declare const COMPONENTS_MODULE = "@forgebook/nuxt/app/components";
25
+ /** Nuxt's built-in components, by name: what a template finds without importing them. */
26
+ export declare const BUILT_IN_COMPONENT_NAMES: readonly ["NuxtLink", "ClientOnly", "DevOnly", "NuxtLayout", "NuxtErrorBoundary", "NuxtPage", "NuxtLoadingIndicator", "NuxtRouteAnnouncer", "NuxtImg", "NuxtPicture"];
@@ -0,0 +1,96 @@
1
+ /**
2
+ * What a Nuxt project's code gets without importing it, and from where: Nuxt's composables and helpers from this
3
+ * package's stand-ins (`@forgebook/nuxt/app/…`), Vue's API, and the vue-router functions Nuxt imports for a project.
4
+ *
5
+ * @remarks
6
+ * The table is what `#app` exports, and with the project's own composables what `#imports` exports and what the plugin
7
+ * imports into a file that uses a name without importing it, as Nuxt does. A Nuxt function not in it is not given: a
8
+ * file that uses one fails on it by name, which says what a story lacks.
9
+ *
10
+ * @module
11
+ */
12
+ /** This package's stand-ins, by module: the names each exports. */
13
+ const STAND_INS = {
14
+ "@forgebook/nuxt/app/router": [
15
+ "useRoute",
16
+ "useRouter",
17
+ "navigateTo",
18
+ "abortNavigation",
19
+ "defineNuxtRouteMiddleware",
20
+ "addRouteMiddleware",
21
+ "definePageMeta",
22
+ "defineRouteRules",
23
+ "setPageLayout",
24
+ "preloadRouteComponents",
25
+ "preloadComponents",
26
+ "prefetchComponents",
27
+ "reloadNuxtApp"
28
+ ],
29
+ "@forgebook/nuxt/app/data": [
30
+ "useAsyncData",
31
+ "useLazyAsyncData",
32
+ "refreshNuxtData",
33
+ "clearNuxtData",
34
+ "useNuxtData"
35
+ ],
36
+ "@forgebook/nuxt/app/fetch": ["useFetch", "useLazyFetch", "$fetch"],
37
+ "@forgebook/nuxt/app/state": [
38
+ "useState",
39
+ "clearNuxtState",
40
+ "useCookie",
41
+ "refreshCookie",
42
+ "useRuntimeConfig",
43
+ "useAppConfig",
44
+ "updateAppConfig",
45
+ "useNuxtApp",
46
+ "tryUseNuxtApp",
47
+ "callOnce",
48
+ "onNuxtReady",
49
+ "useRequestHeaders",
50
+ "useRequestHeader",
51
+ "useRequestEvent",
52
+ "useRequestFetch",
53
+ "useRequestURL",
54
+ "isPrerendered",
55
+ "useLoadingIndicator"
56
+ ],
57
+ "@forgebook/nuxt/app/errors": ["createError", "isNuxtError", "useError", "showError", "clearError"],
58
+ "@forgebook/nuxt/app/head": [
59
+ "useHead",
60
+ "useHeadSafe",
61
+ "useSeoMeta",
62
+ "useServerHead",
63
+ "useServerHeadSafe",
64
+ "useServerSeoMeta"
65
+ ],
66
+ "@forgebook/nuxt/app/define": [
67
+ "defineNuxtComponent",
68
+ "defineNuxtPlugin",
69
+ "definePayloadPlugin",
70
+ "defineAppConfig"
71
+ ]
72
+ };
73
+ /** The vue-router functions Nuxt auto-imports besides its own `useRoute` and `useRouter`. */
74
+ const ROUTER_IMPORTS = ["onBeforeRouteLeave", "onBeforeRouteUpdate", "useLink"];
75
+ /** Nuxt's names, from this package's stand-ins: what `#app` exports. */
76
+ export const NUXT_STAND_INS = Object.entries(STAND_INS).flatMap(([from, names]) => names.map((name) => ({ name, from })));
77
+ /** The vue-router functions a project's code gets without importing them. */
78
+ export const ROUTER_STAND_INS = ROUTER_IMPORTS.map((name) => ({
79
+ name,
80
+ from: "vue-router"
81
+ }));
82
+ /** The module of Nuxt's built-in components. */
83
+ export const COMPONENTS_MODULE = "@forgebook/nuxt/app/components";
84
+ /** Nuxt's built-in components, by name: what a template finds without importing them. */
85
+ export const BUILT_IN_COMPONENT_NAMES = [
86
+ "NuxtLink",
87
+ "ClientOnly",
88
+ "DevOnly",
89
+ "NuxtLayout",
90
+ "NuxtErrorBoundary",
91
+ "NuxtPage",
92
+ "NuxtLoadingIndicator",
93
+ "NuxtRouteAnnouncer",
94
+ "NuxtImg",
95
+ "NuxtPicture"
96
+ ];
package/package.json CHANGED
@@ -1,6 +1,121 @@
1
1
  {
2
2
  "name": "@forgebook/nuxt",
3
- "version": "0.0.0-stage",
4
- "stub": true,
5
- "description": "Temporary package placeholder for staged publishing"
3
+ "version": "0.2.0",
4
+ "description": "Forgebook for Nuxt: a Nuxt project's components drawn outside Nuxt, with its auto-imports, its aliases, its router, NuxtLink, useFetch and useAsyncData, useState and its runtime config, on Vite.",
5
+ "keywords": [
6
+ "nuxt",
7
+ "vue",
8
+ "catalogue",
9
+ "stories"
10
+ ],
11
+ "license": "MIT",
12
+ "repository": {
13
+ "type": "git",
14
+ "url": "git+https://github.com/ensiria/forgebook.git",
15
+ "directory": "packages/nuxt"
16
+ },
17
+ "type": "module",
18
+ "files": [
19
+ "dist"
20
+ ],
21
+ "engines": {
22
+ "node": ">=22.18"
23
+ },
24
+ "sideEffects": false,
25
+ "exports": {
26
+ ".": {
27
+ "types": "./dist/src/stories.d.ts",
28
+ "default": "./dist/src/stories.js"
29
+ },
30
+ "./app/components": {
31
+ "types": "./dist/src/app/components.d.ts",
32
+ "default": "./dist/src/app/components.js"
33
+ },
34
+ "./app/data": {
35
+ "types": "./dist/src/app/data.d.ts",
36
+ "default": "./dist/src/app/data.js"
37
+ },
38
+ "./app/define": {
39
+ "types": "./dist/src/app/define.d.ts",
40
+ "default": "./dist/src/app/define.js"
41
+ },
42
+ "./app/errors": {
43
+ "types": "./dist/src/app/errors.d.ts",
44
+ "default": "./dist/src/app/errors.js"
45
+ },
46
+ "./app/fetch": {
47
+ "types": "./dist/src/app/fetch.d.ts",
48
+ "default": "./dist/src/app/fetch.js"
49
+ },
50
+ "./app/head": {
51
+ "types": "./dist/src/app/head.d.ts",
52
+ "default": "./dist/src/app/head.js"
53
+ },
54
+ "./app/router": {
55
+ "types": "./dist/src/app/router.d.ts",
56
+ "default": "./dist/src/app/router.js"
57
+ },
58
+ "./app/state": {
59
+ "types": "./dist/src/app/state.d.ts",
60
+ "default": "./dist/src/app/state.js"
61
+ },
62
+ "./code": {
63
+ "types": "./dist/src/storyCode.d.ts",
64
+ "default": "./dist/src/storyCode.js"
65
+ },
66
+ "./docs": {
67
+ "types": "./dist/src/vite/extractDocs.d.ts",
68
+ "default": "./dist/src/vite/extractDocs.js"
69
+ },
70
+ "./project": {
71
+ "types": "./dist/src/pageProject.d.ts",
72
+ "default": "./dist/src/pageProject.js"
73
+ },
74
+ "./renderer": {
75
+ "types": "./dist/src/renderer.d.ts",
76
+ "default": "./dist/src/renderer.js"
77
+ },
78
+ "./story": {
79
+ "types": "./dist/src/storyNuxt.d.ts",
80
+ "default": "./dist/src/storyNuxt.js"
81
+ },
82
+ "./vite": {
83
+ "types": "./dist/src/vite/nuxt.d.ts",
84
+ "default": "./dist/src/vite/nuxt.js"
85
+ }
86
+ },
87
+ "dependencies": {
88
+ "unimport": "7.0.2",
89
+ "magic-string": "1.4.5",
90
+ "@forgebook/story-format": "0.2.0",
91
+ "@forgebook/vue": "0.2.0"
92
+ },
93
+ "peerDependencies": {
94
+ "vite": "^8.0.0",
95
+ "vue": "^3.5.0",
96
+ "vue-router": "^4.5.0 || ^5.0.0",
97
+ "forgebook": "^0.2.0"
98
+ },
99
+ "devDependencies": {
100
+ "@types/node": "24.19.2",
101
+ "@vitejs/plugin-vue": "6.0.10",
102
+ "happy-dom": "21.0.4",
103
+ "vite": "8.3.5",
104
+ "vitest": "5.0.5",
105
+ "vue": "3.5.44",
106
+ "vue-router": "5.4.0",
107
+ "@forgebook/tools": "0.0.0",
108
+ "@forgebook/testing": "0.2.0",
109
+ "forgebook": "0.2.0",
110
+ "@forgebook/typescript-config": "0.0.0"
111
+ },
112
+ "publishConfig": {
113
+ "access": "public"
114
+ },
115
+ "scripts": {
116
+ "build": "package-build build",
117
+ "manifest": "package-build manifest",
118
+ "test": "vitest run",
119
+ "typecheck": "tsc -p src && tsc -p src/vite && tsc -p test"
120
+ }
6
121
  }