@modular-react/cli-core 0.1.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 (79) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +73 -0
  3. package/dist/cli.d.ts +12 -0
  4. package/dist/cli.d.ts.map +1 -0
  5. package/dist/cli.js +41 -0
  6. package/dist/cli.js.map +1 -0
  7. package/dist/commands/create-journey.d.ts +17 -0
  8. package/dist/commands/create-journey.d.ts.map +1 -0
  9. package/dist/commands/create-journey.js +193 -0
  10. package/dist/commands/create-journey.js.map +1 -0
  11. package/dist/commands/create-module.d.ts +17 -0
  12. package/dist/commands/create-module.d.ts.map +1 -0
  13. package/dist/commands/create-module.js +112 -0
  14. package/dist/commands/create-module.js.map +1 -0
  15. package/dist/commands/create-store.d.ts +9 -0
  16. package/dist/commands/create-store.d.ts.map +1 -0
  17. package/dist/commands/create-store.js +68 -0
  18. package/dist/commands/create-store.js.map +1 -0
  19. package/dist/commands/init.d.ts +17 -0
  20. package/dist/commands/init.d.ts.map +1 -0
  21. package/dist/commands/init.js +184 -0
  22. package/dist/commands/init.js.map +1 -0
  23. package/dist/index.d.ts +3 -0
  24. package/dist/index.d.ts.map +1 -0
  25. package/dist/index.js +2 -0
  26. package/dist/index.js.map +1 -0
  27. package/dist/naming.d.ts +4 -0
  28. package/dist/naming.d.ts.map +1 -0
  29. package/dist/naming.js +15 -0
  30. package/dist/naming.js.map +1 -0
  31. package/dist/preset.d.ts +112 -0
  32. package/dist/preset.d.ts.map +1 -0
  33. package/dist/preset.js +2 -0
  34. package/dist/preset.js.map +1 -0
  35. package/dist/runtime-versions.d.ts +15 -0
  36. package/dist/runtime-versions.d.ts.map +1 -0
  37. package/dist/runtime-versions.js +15 -0
  38. package/dist/runtime-versions.js.map +1 -0
  39. package/dist/templates/app-shared.d.ts +8 -0
  40. package/dist/templates/app-shared.d.ts.map +1 -0
  41. package/dist/templates/app-shared.js +63 -0
  42. package/dist/templates/app-shared.js.map +1 -0
  43. package/dist/templates/journey.d.ts +30 -0
  44. package/dist/templates/journey.d.ts.map +1 -0
  45. package/dist/templates/journey.js +166 -0
  46. package/dist/templates/journey.js.map +1 -0
  47. package/dist/templates/module.d.ts +8 -0
  48. package/dist/templates/module.d.ts.map +1 -0
  49. package/dist/templates/module.js +43 -0
  50. package/dist/templates/module.js.map +1 -0
  51. package/dist/templates/shell.d.ts +25 -0
  52. package/dist/templates/shell.d.ts.map +1 -0
  53. package/dist/templates/shell.js +162 -0
  54. package/dist/templates/shell.js.map +1 -0
  55. package/dist/templates/store.d.ts +6 -0
  56. package/dist/templates/store.d.ts.map +1 -0
  57. package/dist/templates/store.js +10 -0
  58. package/dist/templates/store.js.map +1 -0
  59. package/dist/templates/workspace.d.ts +8 -0
  60. package/dist/templates/workspace.d.ts.map +1 -0
  61. package/dist/templates/workspace.js +58 -0
  62. package/dist/templates/workspace.js.map +1 -0
  63. package/dist/utils/detect-scope.d.ts +2 -0
  64. package/dist/utils/detect-scope.d.ts.map +1 -0
  65. package/dist/utils/detect-scope.js +13 -0
  66. package/dist/utils/detect-scope.js.map +1 -0
  67. package/dist/utils/prompt.d.ts +14 -0
  68. package/dist/utils/prompt.d.ts.map +1 -0
  69. package/dist/utils/prompt.js +26 -0
  70. package/dist/utils/prompt.js.map +1 -0
  71. package/dist/utils/resolve-project.d.ts +9 -0
  72. package/dist/utils/resolve-project.d.ts.map +1 -0
  73. package/dist/utils/resolve-project.js +22 -0
  74. package/dist/utils/resolve-project.js.map +1 -0
  75. package/dist/utils/transform.d.ts +83 -0
  76. package/dist/utils/transform.d.ts.map +1 -0
  77. package/dist/utils/transform.js +250 -0
  78. package/dist/utils/transform.js.map +1 -0
  79. package/package.json +42 -0
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Igor Savin
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.
package/README.md ADDED
@@ -0,0 +1,73 @@
1
+ # @modular-react/cli-core
2
+
3
+ Internal foundation for the modular-react CLI binaries. Both
4
+ [`@react-router-modules/cli`](../react-router-cli) and
5
+ [`@tanstack-react-modules/cli`](../tanstack-router-cli) are thin
6
+ preset wrappers around this package: the commands, prompts, project
7
+ detection, file transforms, and router-agnostic templates all live here.
8
+
9
+ If you're scaffolding a project, install one of the router-specific
10
+ binaries — not this package.
11
+
12
+ ## What's in here
13
+
14
+ This package's public surface is intentionally tiny — `buildCli`,
15
+ `runCli`, and the `CliPreset` types in `src/index.ts`. Everything else
16
+ is internal machinery the commands rely on:
17
+
18
+ - Command implementations under `src/commands/`: `init`, `create module`,
19
+ `create store`, `create journey`. Each is a factory that takes a
20
+ `CliPreset` and returns a [`citty`](https://github.com/unjs/citty)
21
+ command. Wired together by `buildCli`.
22
+ - Project layout detection (`utils/resolve-project.ts`) and scope
23
+ detection (`utils/detect-scope.ts`).
24
+ - File transforms (`utils/transform.ts`) that edit `shell/src/main.tsx`,
25
+ `shell/package.json`, `app-shared/src/index.ts`, and
26
+ `pnpm-workspace.yaml` to wire newly scaffolded pieces in. Anchored on
27
+ comment markers and predictable shapes that the CLI's own templates
28
+ emit.
29
+ - Centralized runtime-package version pins in `runtime-versions.ts` —
30
+ bump in one place to refresh every generated `package.json`.
31
+ - Router-agnostic templates under `src/templates/`: workspace files,
32
+ `app-shared` package metadata, store stub, journey package +
33
+ definition + persistence.
34
+
35
+ ## Adding a router integration
36
+
37
+ Implement a `CliPreset`:
38
+
39
+ ```ts
40
+ import { runCli, type CliPreset } from "@modular-react/cli-core";
41
+
42
+ const preset: CliPreset = {
43
+ cliName: "your-router-modules",
44
+ cliVersion: "0.1.0",
45
+ cliDescription: "modular-react CLI (Your Router integration)",
46
+ packages: {
47
+ core: "@your-router-modules/core",
48
+ runtime: "@your-router-modules/runtime",
49
+ testing: "@your-router-modules/testing",
50
+ router: "your-router",
51
+ routerVersion: "^1.0.0",
52
+ },
53
+ docs: { shellPatterns: "shell-patterns-your-router.md" },
54
+ templates: {
55
+ appSharedIndex, // your `app-shared/src/index.ts` template
56
+ shellMain, // your `shell/src/main.tsx` template
57
+ shellRootLayout,
58
+ shellShellLayout,
59
+ shellSidebar,
60
+ shellViteDedupe: ["react", "react-dom", "react/jsx-runtime", "your-router", ...],
61
+ moduleDescriptor, // your `defineModule({...})` template
62
+ modulePage,
63
+ moduleListPage,
64
+ moduleDetailPanel,
65
+ moduleTest,
66
+ },
67
+ };
68
+
69
+ runCli(preset);
70
+ ```
71
+
72
+ The router-agnostic bits (project layout, journeys, stores, package
73
+ metadata) come from this package automatically.
package/dist/cli.d.ts ADDED
@@ -0,0 +1,12 @@
1
+ import type { CliPreset } from "./preset.js";
2
+ /**
3
+ * Build the top-level command tree for a router-specific CLI from a
4
+ * preset. The returned command can be passed straight to `citty.runMain`.
5
+ */
6
+ export declare function buildCli(preset: CliPreset): import("citty").CommandDef<import("citty").ArgsDef>;
7
+ /**
8
+ * Convenience for `react-router-cli` / `tanstack-router-cli`'s `cli.ts`.
9
+ * Equivalent to `runMain(buildCli(preset))`.
10
+ */
11
+ export declare function runCli(preset: CliPreset): void;
12
+ //# sourceMappingURL=cli.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cli.d.ts","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AAM7C;;;GAGG;AACH,wBAAgB,QAAQ,CAAC,MAAM,EAAE,SAAS,uDAwBzC;AAED;;;GAGG;AACH,wBAAgB,MAAM,CAAC,MAAM,EAAE,SAAS,GAAG,IAAI,CAE9C"}
package/dist/cli.js ADDED
@@ -0,0 +1,41 @@
1
+ import { defineCommand, runMain } from "citty";
2
+ import { createInitCommand } from "./commands/init.js";
3
+ import { createCreateModuleCommand } from "./commands/create-module.js";
4
+ import { createCreateStoreCommand } from "./commands/create-store.js";
5
+ import { createCreateJourneyCommand } from "./commands/create-journey.js";
6
+ /**
7
+ * Build the top-level command tree for a router-specific CLI from a
8
+ * preset. The returned command can be passed straight to `citty.runMain`.
9
+ */
10
+ export function buildCli(preset) {
11
+ const create = defineCommand({
12
+ meta: {
13
+ name: "create",
14
+ description: "Create a new module, store, or journey",
15
+ },
16
+ subCommands: {
17
+ module: createCreateModuleCommand(preset),
18
+ store: createCreateStoreCommand(preset),
19
+ journey: createCreateJourneyCommand(preset),
20
+ },
21
+ });
22
+ return defineCommand({
23
+ meta: {
24
+ name: preset.cliName,
25
+ version: preset.cliVersion,
26
+ description: preset.cliDescription,
27
+ },
28
+ subCommands: {
29
+ init: createInitCommand(preset),
30
+ create,
31
+ },
32
+ });
33
+ }
34
+ /**
35
+ * Convenience for `react-router-cli` / `tanstack-router-cli`'s `cli.ts`.
36
+ * Equivalent to `runMain(buildCli(preset))`.
37
+ */
38
+ export function runCli(preset) {
39
+ runMain(buildCli(preset));
40
+ }
41
+ //# sourceMappingURL=cli.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cli.js","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,OAAO,EAAE,MAAM,OAAO,CAAC;AAE/C,OAAO,EAAE,iBAAiB,EAAE,MAAM,oBAAoB,CAAC;AACvD,OAAO,EAAE,yBAAyB,EAAE,MAAM,6BAA6B,CAAC;AACxE,OAAO,EAAE,wBAAwB,EAAE,MAAM,4BAA4B,CAAC;AACtE,OAAO,EAAE,0BAA0B,EAAE,MAAM,8BAA8B,CAAC;AAE1E;;;GAGG;AACH,MAAM,UAAU,QAAQ,CAAC,MAAiB;IACxC,MAAM,MAAM,GAAG,aAAa,CAAC;QAC3B,IAAI,EAAE;YACJ,IAAI,EAAE,QAAQ;YACd,WAAW,EAAE,wCAAwC;SACtD;QACD,WAAW,EAAE;YACX,MAAM,EAAE,yBAAyB,CAAC,MAAM,CAAC;YACzC,KAAK,EAAE,wBAAwB,CAAC,MAAM,CAAC;YACvC,OAAO,EAAE,0BAA0B,CAAC,MAAM,CAAC;SAC5C;KACF,CAAC,CAAC;IAEH,OAAO,aAAa,CAAC;QACnB,IAAI,EAAE;YACJ,IAAI,EAAE,MAAM,CAAC,OAAO;YACpB,OAAO,EAAE,MAAM,CAAC,UAAU;YAC1B,WAAW,EAAE,MAAM,CAAC,cAAc;SACnC;QACD,WAAW,EAAE;YACX,IAAI,EAAE,iBAAiB,CAAC,MAAM,CAAC;YAC/B,MAAM;SACP;KACF,CAAC,CAAC;AACL,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,MAAM,CAAC,MAAiB;IACtC,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC,CAAC;AAC5B,CAAC"}
@@ -0,0 +1,17 @@
1
+ import type { CliPreset } from "../preset.js";
2
+ export declare function createCreateJourneyCommand(_preset: CliPreset): import("citty").CommandDef<{
3
+ readonly name: {
4
+ readonly type: "positional";
5
+ readonly description: "Journey name (e.g. customer-onboarding)";
6
+ readonly required: false;
7
+ };
8
+ readonly modules: {
9
+ readonly type: "string";
10
+ readonly description: "Comma-separated list of module names this journey composes (e.g. profile,plan,billing)";
11
+ };
12
+ readonly persistence: {
13
+ readonly type: "boolean";
14
+ readonly description: "Also generate a webStorage persistence adapter at shell/src/<journey>-persistence.ts";
15
+ };
16
+ }>;
17
+ //# sourceMappingURL=create-journey.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"create-journey.d.ts","sourceRoot":"","sources":["../../src/commands/create-journey.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,cAAc,CAAC;AAmB9C,wBAAgB,0BAA0B,CAAC,OAAO,EAAE,SAAS;;;;;;;;;;;;;;GAoL5D"}
@@ -0,0 +1,193 @@
1
+ import { defineCommand } from "citty";
2
+ import * as p from "@clack/prompts";
3
+ import { mkdirSync, writeFileSync, existsSync, readFileSync } from "node:fs";
4
+ import { resolve } from "pathe";
5
+ import { toCamelCase, toPascalCase } from "../naming.js";
6
+ import { resolveProject } from "../utils/resolve-project.js";
7
+ import { detectScope } from "../utils/detect-scope.js";
8
+ import { promptText } from "../utils/prompt.js";
9
+ import { addJourneyToMain, addJourneyToShellPackageJson, ensureJourneysInWorkspace, } from "../utils/transform.js";
10
+ import { journeyDefinition, journeyIndex, journeyPackageJson, journeyPersistence, journeyTsconfig, } from "../templates/journey.js";
11
+ export function createCreateJourneyCommand(_preset) {
12
+ return defineCommand({
13
+ meta: {
14
+ name: "journey",
15
+ description: "Scaffold a typed journey package and wire it into the shell's registry (see @modular-react/journeys)",
16
+ },
17
+ args: {
18
+ name: {
19
+ type: "positional",
20
+ description: "Journey name (e.g. customer-onboarding)",
21
+ required: false,
22
+ },
23
+ modules: {
24
+ type: "string",
25
+ description: "Comma-separated list of module names this journey composes (e.g. profile,plan,billing)",
26
+ },
27
+ persistence: {
28
+ type: "boolean",
29
+ description: "Also generate a webStorage persistence adapter at shell/src/<journey>-persistence.ts",
30
+ },
31
+ },
32
+ async run({ args }) {
33
+ const project = resolveProject();
34
+ const scope = detectScope(project.root);
35
+ const isNonInteractive = Boolean(args.name);
36
+ if (!isNonInteractive) {
37
+ p.intro("Create a new journey");
38
+ }
39
+ const name = args.name ||
40
+ (await promptText({
41
+ message: "Journey name",
42
+ placeholder: "customer-onboarding",
43
+ validate: (v) => {
44
+ if (!v)
45
+ return "Required";
46
+ if (!/^[a-z][a-z0-9-]*$/.test(v))
47
+ return "Use lowercase letters, digits, and dashes only.";
48
+ return undefined;
49
+ },
50
+ }));
51
+ const journeyDir = resolve(project.journeysDir, name);
52
+ if (existsSync(journeyDir)) {
53
+ const msg = `Journey "${name}" already exists at ${journeyDir}`;
54
+ if (isNonInteractive) {
55
+ console.error(msg);
56
+ process.exit(1);
57
+ }
58
+ p.cancel(msg);
59
+ process.exit(1);
60
+ }
61
+ const moduleNames = parseModuleList(args.modules);
62
+ const modules = moduleNames.map((moduleName) => toJourneyModule({ scope, moduleName, project }));
63
+ const missingModules = modules.filter((m) => !m.exists).map((m) => m.moduleName);
64
+ if (missingModules.length > 0) {
65
+ const msg = `Module(s) not found in modules/: ${missingModules.join(", ")}. Create them with \`create module\` first.`;
66
+ if (isNonInteractive) {
67
+ console.error(msg);
68
+ process.exit(1);
69
+ }
70
+ p.cancel(msg);
71
+ process.exit(1);
72
+ }
73
+ const withPersistence = args.persistence === true;
74
+ const journeyPascal = toPascalCase(name);
75
+ const journeyCamel = toCamelCase(name);
76
+ const journeyExportName = `${journeyCamel}Journey`;
77
+ const handleExportName = `${journeyCamel}Handle`;
78
+ const persistenceExportName = `${journeyCamel}Persistence`;
79
+ // 1. Scaffold the journey package.
80
+ mkdirSync(resolve(journeyDir, "src"), { recursive: true });
81
+ writeFileSync(resolve(journeyDir, "package.json"), journeyPackageJson({
82
+ scope,
83
+ journeyName: name,
84
+ journeyPascal,
85
+ journeyCamel,
86
+ modules,
87
+ withPersistence,
88
+ }));
89
+ writeFileSync(resolve(journeyDir, "tsconfig.json"), journeyTsconfig());
90
+ writeFileSync(resolve(journeyDir, "src", "index.ts"), journeyIndex({
91
+ scope,
92
+ journeyName: name,
93
+ journeyPascal,
94
+ journeyCamel,
95
+ modules,
96
+ withPersistence,
97
+ }));
98
+ writeFileSync(resolve(journeyDir, "src", `${name}.ts`), journeyDefinition({
99
+ scope,
100
+ journeyName: name,
101
+ journeyPascal,
102
+ journeyCamel,
103
+ modules,
104
+ withPersistence,
105
+ }));
106
+ // 2. Make sure pnpm-workspace.yaml has `journeys/*` (older projects).
107
+ ensureJourneysInWorkspace(project.root);
108
+ // 3. Add a shell dependency on the journey + the journeys runtime.
109
+ addJourneyToShellPackageJson(project.shellDir, { scope, journeyName: name });
110
+ // 4. Optional persistence adapter under shell/src/. Written before
111
+ // we wire main.tsx so the import we add is immediately valid.
112
+ if (withPersistence) {
113
+ const persistencePath = resolve(project.shellDir, "src", `${name}-persistence.ts`);
114
+ writeFileSync(persistencePath, journeyPersistence({
115
+ scope,
116
+ journeyName: name,
117
+ journeyPascal,
118
+ journeyCamel,
119
+ modules,
120
+ withPersistence,
121
+ }));
122
+ }
123
+ // 5. Wire the journey into shell/src/main.tsx (plugin install +
124
+ // registerJourney). When persistence was generated, the call
125
+ // becomes `registerJourney(<journey>, { persistence })` and the
126
+ // binding gets imported from the file we just wrote.
127
+ addJourneyToMain(project.shellDir, {
128
+ scope,
129
+ journeyName: name,
130
+ journeyExportName,
131
+ handleExportName,
132
+ persistenceExportName: withPersistence ? persistenceExportName : undefined,
133
+ });
134
+ const summary = [
135
+ `Journey: journeys/${name}/`,
136
+ `Package: ${scope}/${name}-journey`,
137
+ `Handle: ${handleExportName} (typed token for runtime.start(handle, input))`,
138
+ `Modules: ${modules.length === 0 ? "(none — add some via --modules)" : modules.map((m) => m.moduleName).join(", ")}`,
139
+ withPersistence
140
+ ? `Persistence: shell/src/${name}-persistence.ts (wired into registerJourney as { persistence: ${persistenceExportName} })`
141
+ : null,
142
+ "",
143
+ "Next:",
144
+ " - Fill in initialState, start, and transitions in the journey definition.",
145
+ " - On each composed module, add entryPoints + exitPoints (defineEntry / defineExit).",
146
+ withPersistence
147
+ ? ` - Tune ${persistenceExportName}.keyFor in shell/src/${name}-persistence.ts to match your input shape.`
148
+ : null,
149
+ " - Run pnpm install to link the new package.",
150
+ ]
151
+ .filter((line) => line !== null)
152
+ .join("\n");
153
+ if (!isNonInteractive) {
154
+ p.note(summary, "Created");
155
+ p.outro("Done!");
156
+ }
157
+ else {
158
+ console.log(`Journey "${name}" created at journeys/${name}/`);
159
+ }
160
+ },
161
+ });
162
+ }
163
+ function parseModuleList(value) {
164
+ if (!value)
165
+ return [];
166
+ return value
167
+ .split(",")
168
+ .map((s) => s.trim())
169
+ .filter(Boolean);
170
+ }
171
+ function toJourneyModule(args) {
172
+ const { scope, moduleName, project } = args;
173
+ const moduleDir = resolve(project.modulesDir, moduleName);
174
+ const pkgPath = resolve(moduleDir, "package.json");
175
+ let packageName = `${scope}/${moduleName}-module`;
176
+ if (existsSync(pkgPath)) {
177
+ try {
178
+ const pkg = JSON.parse(readFileSync(pkgPath, "utf-8"));
179
+ if (typeof pkg.name === "string")
180
+ packageName = pkg.name;
181
+ }
182
+ catch {
183
+ // Fall back to the conventional name.
184
+ }
185
+ }
186
+ return {
187
+ moduleName,
188
+ importName: toCamelCase(moduleName),
189
+ packageName,
190
+ exists: existsSync(moduleDir),
191
+ };
192
+ }
193
+ //# sourceMappingURL=create-journey.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"create-journey.js","sourceRoot":"","sources":["../../src/commands/create-journey.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,OAAO,CAAC;AACtC,OAAO,KAAK,CAAC,MAAM,gBAAgB,CAAC;AACpC,OAAO,EAAE,SAAS,EAAE,aAAa,EAAE,UAAU,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AAC7E,OAAO,EAAE,OAAO,EAAE,MAAM,OAAO,CAAC;AAEhC,OAAO,EAAE,WAAW,EAAE,YAAY,EAAE,MAAM,cAAc,CAAC;AACzD,OAAO,EAAE,cAAc,EAAE,MAAM,6BAA6B,CAAC;AAC7D,OAAO,EAAE,WAAW,EAAE,MAAM,0BAA0B,CAAC;AACvD,OAAO,EAAE,UAAU,EAAE,MAAM,oBAAoB,CAAC;AAChD,OAAO,EACL,gBAAgB,EAChB,4BAA4B,EAC5B,yBAAyB,GAC1B,MAAM,uBAAuB,CAAC;AAC/B,OAAO,EACL,iBAAiB,EACjB,YAAY,EACZ,kBAAkB,EAClB,kBAAkB,EAClB,eAAe,GAEhB,MAAM,yBAAyB,CAAC;AAEjC,MAAM,UAAU,0BAA0B,CAAC,OAAkB;IAC3D,OAAO,aAAa,CAAC;QACnB,IAAI,EAAE;YACJ,IAAI,EAAE,SAAS;YACf,WAAW,EACT,sGAAsG;SACzG;QACD,IAAI,EAAE;YACJ,IAAI,EAAE;gBACJ,IAAI,EAAE,YAAY;gBAClB,WAAW,EAAE,yCAAyC;gBACtD,QAAQ,EAAE,KAAK;aAChB;YACD,OAAO,EAAE;gBACP,IAAI,EAAE,QAAQ;gBACd,WAAW,EACT,wFAAwF;aAC3F;YACD,WAAW,EAAE;gBACX,IAAI,EAAE,SAAS;gBACf,WAAW,EACT,sFAAsF;aACzF;SACF;QACD,KAAK,CAAC,GAAG,CAAC,EAAE,IAAI,EAAE;YAChB,MAAM,OAAO,GAAG,cAAc,EAAE,CAAC;YACjC,MAAM,KAAK,GAAG,WAAW,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC;YAExC,MAAM,gBAAgB,GAAG,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;YAE5C,IAAI,CAAC,gBAAgB,EAAE,CAAC;gBACtB,CAAC,CAAC,KAAK,CAAC,sBAAsB,CAAC,CAAC;YAClC,CAAC;YAED,MAAM,IAAI,GACR,IAAI,CAAC,IAAI;gBACT,CAAC,MAAM,UAAU,CAAC;oBAChB,OAAO,EAAE,cAAc;oBACvB,WAAW,EAAE,qBAAqB;oBAClC,QAAQ,EAAE,CAAC,CAAC,EAAE,EAAE;wBACd,IAAI,CAAC,CAAC;4BAAE,OAAO,UAAU,CAAC;wBAC1B,IAAI,CAAC,mBAAmB,CAAC,IAAI,CAAC,CAAC,CAAC;4BAC9B,OAAO,iDAAiD,CAAC;wBAC3D,OAAO,SAAS,CAAC;oBACnB,CAAC;iBACF,CAAC,CAAC,CAAC;YAEN,MAAM,UAAU,GAAG,OAAO,CAAC,OAAO,CAAC,WAAW,EAAE,IAAI,CAAC,CAAC;YACtD,IAAI,UAAU,CAAC,UAAU,CAAC,EAAE,CAAC;gBAC3B,MAAM,GAAG,GAAG,YAAY,IAAI,uBAAuB,UAAU,EAAE,CAAC;gBAChE,IAAI,gBAAgB,EAAE,CAAC;oBACrB,OAAO,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;oBACnB,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;gBAClB,CAAC;gBACD,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;gBACd,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;YAClB,CAAC;YAED,MAAM,WAAW,GAAG,eAAe,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;YAClD,MAAM,OAAO,GAAG,WAAW,CAAC,GAAG,CAAC,CAAC,UAAU,EAAE,EAAE,CAC7C,eAAe,CAAC,EAAE,KAAK,EAAE,UAAU,EAAE,OAAO,EAAE,CAAC,CAChD,CAAC;YACF,MAAM,cAAc,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC;YACjF,IAAI,cAAc,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;gBAC9B,MAAM,GAAG,GAAG,oCAAoC,cAAc,CAAC,IAAI,CAAC,IAAI,CAAC,6CAA6C,CAAC;gBACvH,IAAI,gBAAgB,EAAE,CAAC;oBACrB,OAAO,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;oBACnB,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;gBAClB,CAAC;gBACD,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;gBACd,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;YAClB,CAAC;YAED,MAAM,eAAe,GAAG,IAAI,CAAC,WAAW,KAAK,IAAI,CAAC;YAClD,MAAM,aAAa,GAAG,YAAY,CAAC,IAAI,CAAC,CAAC;YACzC,MAAM,YAAY,GAAG,WAAW,CAAC,IAAI,CAAC,CAAC;YACvC,MAAM,iBAAiB,GAAG,GAAG,YAAY,SAAS,CAAC;YACnD,MAAM,gBAAgB,GAAG,GAAG,YAAY,QAAQ,CAAC;YACjD,MAAM,qBAAqB,GAAG,GAAG,YAAY,aAAa,CAAC;YAE3D,mCAAmC;YACnC,SAAS,CAAC,OAAO,CAAC,UAAU,EAAE,KAAK,CAAC,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;YAC3D,aAAa,CACX,OAAO,CAAC,UAAU,EAAE,cAAc,CAAC,EACnC,kBAAkB,CAAC;gBACjB,KAAK;gBACL,WAAW,EAAE,IAAI;gBACjB,aAAa;gBACb,YAAY;gBACZ,OAAO;gBACP,eAAe;aAChB,CAAC,CACH,CAAC;YACF,aAAa,CAAC,OAAO,CAAC,UAAU,EAAE,eAAe,CAAC,EAAE,eAAe,EAAE,CAAC,CAAC;YACvE,aAAa,CACX,OAAO,CAAC,UAAU,EAAE,KAAK,EAAE,UAAU,CAAC,EACtC,YAAY,CAAC;gBACX,KAAK;gBACL,WAAW,EAAE,IAAI;gBACjB,aAAa;gBACb,YAAY;gBACZ,OAAO;gBACP,eAAe;aAChB,CAAC,CACH,CAAC;YACF,aAAa,CACX,OAAO,CAAC,UAAU,EAAE,KAAK,EAAE,GAAG,IAAI,KAAK,CAAC,EACxC,iBAAiB,CAAC;gBAChB,KAAK;gBACL,WAAW,EAAE,IAAI;gBACjB,aAAa;gBACb,YAAY;gBACZ,OAAO;gBACP,eAAe;aAChB,CAAC,CACH,CAAC;YAEF,sEAAsE;YACtE,yBAAyB,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC;YAExC,mEAAmE;YACnE,4BAA4B,CAAC,OAAO,CAAC,QAAQ,EAAE,EAAE,KAAK,EAAE,WAAW,EAAE,IAAI,EAAE,CAAC,CAAC;YAE7E,mEAAmE;YACnE,iEAAiE;YACjE,IAAI,eAAe,EAAE,CAAC;gBACpB,MAAM,eAAe,GAAG,OAAO,CAAC,OAAO,CAAC,QAAQ,EAAE,KAAK,EAAE,GAAG,IAAI,iBAAiB,CAAC,CAAC;gBACnF,aAAa,CACX,eAAe,EACf,kBAAkB,CAAC;oBACjB,KAAK;oBACL,WAAW,EAAE,IAAI;oBACjB,aAAa;oBACb,YAAY;oBACZ,OAAO;oBACP,eAAe;iBAChB,CAAC,CACH,CAAC;YACJ,CAAC;YAED,gEAAgE;YAChE,gEAAgE;YAChE,mEAAmE;YACnE,wDAAwD;YACxD,gBAAgB,CAAC,OAAO,CAAC,QAAQ,EAAE;gBACjC,KAAK;gBACL,WAAW,EAAE,IAAI;gBACjB,iBAAiB;gBACjB,gBAAgB;gBAChB,qBAAqB,EAAE,eAAe,CAAC,CAAC,CAAC,qBAAqB,CAAC,CAAC,CAAC,SAAS;aAC3E,CAAC,CAAC;YAEH,MAAM,OAAO,GAAG;gBACd,wBAAwB,IAAI,GAAG;gBAC/B,eAAe,KAAK,IAAI,IAAI,UAAU;gBACtC,eAAe,gBAAgB,kDAAkD;gBACjF,eAAe,OAAO,CAAC,MAAM,KAAK,CAAC,CAAC,CAAC,CAAC,iCAAiC,CAAC,CAAC,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE;gBACvH,eAAe;oBACb,CAAC,CAAC,0BAA0B,IAAI,iEAAiE,qBAAqB,KAAK;oBAC3H,CAAC,CAAC,IAAI;gBACR,EAAE;gBACF,OAAO;gBACP,6EAA6E;gBAC7E,uFAAuF;gBACvF,eAAe;oBACb,CAAC,CAAC,YAAY,qBAAqB,wBAAwB,IAAI,4CAA4C;oBAC3G,CAAC,CAAC,IAAI;gBACR,+CAA+C;aAChD;iBACE,MAAM,CAAC,CAAC,IAAI,EAAkB,EAAE,CAAC,IAAI,KAAK,IAAI,CAAC;iBAC/C,IAAI,CAAC,IAAI,CAAC,CAAC;YAEd,IAAI,CAAC,gBAAgB,EAAE,CAAC;gBACtB,CAAC,CAAC,IAAI,CAAC,OAAO,EAAE,SAAS,CAAC,CAAC;gBAC3B,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC;YACnB,CAAC;iBAAM,CAAC;gBACN,OAAO,CAAC,GAAG,CAAC,YAAY,IAAI,yBAAyB,IAAI,GAAG,CAAC,CAAC;YAChE,CAAC;QACH,CAAC;KACF,CAAC,CAAC;AACL,CAAC;AAED,SAAS,eAAe,CAAC,KAAyB;IAChD,IAAI,CAAC,KAAK;QAAE,OAAO,EAAE,CAAC;IACtB,OAAO,KAAK;SACT,KAAK,CAAC,GAAG,CAAC;SACV,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC;SACpB,MAAM,CAAC,OAAO,CAAC,CAAC;AACrB,CAAC;AAED,SAAS,eAAe,CAAC,IAIxB;IACC,MAAM,EAAE,KAAK,EAAE,UAAU,EAAE,OAAO,EAAE,GAAG,IAAI,CAAC;IAC5C,MAAM,SAAS,GAAG,OAAO,CAAC,OAAO,CAAC,UAAU,EAAE,UAAU,CAAC,CAAC;IAC1D,MAAM,OAAO,GAAG,OAAO,CAAC,SAAS,EAAE,cAAc,CAAC,CAAC;IACnD,IAAI,WAAW,GAAG,GAAG,KAAK,IAAI,UAAU,SAAS,CAAC;IAClD,IAAI,UAAU,CAAC,OAAO,CAAC,EAAE,CAAC;QACxB,IAAI,CAAC;YACH,MAAM,GAAG,GAAG,IAAI,CAAC,KAAK,CAAC,YAAY,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC,CAAC;YACvD,IAAI,OAAO,GAAG,CAAC,IAAI,KAAK,QAAQ;gBAAE,WAAW,GAAG,GAAG,CAAC,IAAI,CAAC;QAC3D,CAAC;QAAC,MAAM,CAAC;YACP,sCAAsC;QACxC,CAAC;IACH,CAAC;IACD,OAAO;QACL,UAAU;QACV,UAAU,EAAE,WAAW,CAAC,UAAU,CAAC;QACnC,WAAW;QACX,MAAM,EAAE,UAAU,CAAC,SAAS,CAAC;KAC9B,CAAC;AACJ,CAAC"}
@@ -0,0 +1,17 @@
1
+ import type { CliPreset } from "../preset.js";
2
+ export declare function createCreateModuleCommand(preset: CliPreset): import("citty").CommandDef<{
3
+ readonly name: {
4
+ readonly type: "positional";
5
+ readonly description: "Module name";
6
+ readonly required: false;
7
+ };
8
+ readonly route: {
9
+ readonly type: "string";
10
+ readonly description: "Route path (defaults to module name)";
11
+ };
12
+ readonly "nav-group": {
13
+ readonly type: "string";
14
+ readonly description: "Navigation group";
15
+ };
16
+ }>;
17
+ //# sourceMappingURL=create-module.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"create-module.d.ts","sourceRoot":"","sources":["../../src/commands/create-module.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,cAAc,CAAC;AAQ9C,wBAAgB,yBAAyB,CAAC,MAAM,EAAE,SAAS;;;;;;;;;;;;;;GAiI1D"}
@@ -0,0 +1,112 @@
1
+ import { defineCommand } from "citty";
2
+ import * as p from "@clack/prompts";
3
+ import { mkdirSync, writeFileSync, existsSync } from "node:fs";
4
+ import { resolve } from "pathe";
5
+ import { toCamelCase, toPascalCase } from "../naming.js";
6
+ import { resolveProject } from "../utils/resolve-project.js";
7
+ import { detectScope } from "../utils/detect-scope.js";
8
+ import { promptText } from "../utils/prompt.js";
9
+ import { addModuleToMain, addModuleToShellPackageJson } from "../utils/transform.js";
10
+ import { modulePackageJson, moduleTsconfig } from "../templates/module.js";
11
+ export function createCreateModuleCommand(preset) {
12
+ return defineCommand({
13
+ meta: {
14
+ name: "module",
15
+ description: "Create a new module",
16
+ },
17
+ args: {
18
+ name: {
19
+ type: "positional",
20
+ description: "Module name",
21
+ required: false,
22
+ },
23
+ route: {
24
+ type: "string",
25
+ description: "Route path (defaults to module name)",
26
+ },
27
+ "nav-group": {
28
+ type: "string",
29
+ description: "Navigation group",
30
+ },
31
+ },
32
+ async run({ args }) {
33
+ const project = resolveProject();
34
+ const scope = detectScope(project.root);
35
+ const isNonInteractive = Boolean(args.name);
36
+ if (!isNonInteractive) {
37
+ p.intro("Create a new module");
38
+ }
39
+ const name = args.name ||
40
+ (await promptText({
41
+ message: "Module name",
42
+ placeholder: "billing",
43
+ validate: (v) => (!v ? "Required" : undefined),
44
+ }));
45
+ const moduleDir = resolve(project.modulesDir, name);
46
+ if (existsSync(moduleDir)) {
47
+ const msg = `Module "${name}" already exists at ${moduleDir}`;
48
+ if (isNonInteractive) {
49
+ console.error(msg);
50
+ process.exit(1);
51
+ }
52
+ p.cancel(msg);
53
+ process.exit(1);
54
+ }
55
+ const route = args.route ||
56
+ (isNonInteractive
57
+ ? name
58
+ : await promptText({
59
+ message: "Route path",
60
+ defaultValue: name,
61
+ placeholder: name,
62
+ }));
63
+ const navGroupRaw = args["nav-group"]
64
+ ? args["nav-group"]
65
+ : isNonInteractive
66
+ ? ""
67
+ : await promptText({
68
+ message: "Navigation group (optional)",
69
+ placeholder: "leave empty for none",
70
+ });
71
+ const navGroup = navGroupRaw || undefined;
72
+ const pageName = toPascalCase(name) + "Dashboard";
73
+ const listPageName = toPascalCase(name) + "List";
74
+ const importName = toCamelCase(name);
75
+ const moduleLabel = toPascalCase(name);
76
+ mkdirSync(resolve(moduleDir, "src", "pages"), { recursive: true });
77
+ mkdirSync(resolve(moduleDir, "src", "panels"), { recursive: true });
78
+ mkdirSync(resolve(moduleDir, "src", "__tests__"), { recursive: true });
79
+ writeFileSync(resolve(moduleDir, "package.json"), modulePackageJson({ scope, name, preset }));
80
+ writeFileSync(resolve(moduleDir, "tsconfig.json"), moduleTsconfig());
81
+ writeFileSync(resolve(moduleDir, "src", "index.ts"), preset.templates.moduleDescriptor({
82
+ scope,
83
+ name,
84
+ route,
85
+ pageName,
86
+ listPageName,
87
+ navGroup,
88
+ moduleLabel,
89
+ }));
90
+ writeFileSync(resolve(moduleDir, "src", "pages", `${pageName}.tsx`), preset.templates.modulePage({ scope, pageName, moduleLabel, moduleName: name }));
91
+ writeFileSync(resolve(moduleDir, "src", "pages", `${listPageName}.tsx`), preset.templates.moduleListPage({ scope, pageName: listPageName, moduleLabel }));
92
+ writeFileSync(resolve(moduleDir, "src", "panels", "DetailPanel.tsx"), preset.templates.moduleDetailPanel({ moduleLabel }));
93
+ writeFileSync(resolve(moduleDir, "src", "__tests__", `${name}.test.ts`), preset.templates.moduleTest({ scope, name, importName, route, pageName, moduleLabel }));
94
+ addModuleToShellPackageJson(project.shellDir, { scope, moduleName: name });
95
+ addModuleToMain(project.shellDir, { scope, moduleName: name, importName });
96
+ if (!isNonInteractive) {
97
+ p.note([
98
+ `Module: modules/${name}/`,
99
+ `Package: ${scope}/${name}-module`,
100
+ `Route: /${route}`,
101
+ "",
102
+ "Run pnpm install to link the new package.",
103
+ ].join("\n"), "Created");
104
+ p.outro("Done!");
105
+ }
106
+ else {
107
+ console.log(`Module "${name}" created at modules/${name}/`);
108
+ }
109
+ },
110
+ });
111
+ }
112
+ //# sourceMappingURL=create-module.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"create-module.js","sourceRoot":"","sources":["../../src/commands/create-module.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,9 @@
1
+ import type { CliPreset } from "../preset.js";
2
+ export declare function createCreateStoreCommand(_preset: CliPreset): import("citty").CommandDef<{
3
+ readonly name: {
4
+ readonly type: "positional";
5
+ readonly description: "Store name (e.g. notifications)";
6
+ readonly required: false;
7
+ };
8
+ }>;
9
+ //# sourceMappingURL=create-store.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"create-store.d.ts","sourceRoot":"","sources":["../../src/commands/create-store.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,cAAc,CAAC;AAQ9C,wBAAgB,wBAAwB,CAAC,OAAO,EAAE,SAAS;;;;;;GAkE1D"}
@@ -0,0 +1,68 @@
1
+ import { defineCommand } from "citty";
2
+ import * as p from "@clack/prompts";
3
+ import { writeFileSync, existsSync } from "node:fs";
4
+ import { resolve } from "pathe";
5
+ import { toCamelCase, toPascalCase } from "../naming.js";
6
+ import { resolveProject } from "../utils/resolve-project.js";
7
+ import { detectScope } from "../utils/detect-scope.js";
8
+ import { promptText } from "../utils/prompt.js";
9
+ import { addStoreToAppShared, addStoreToMain } from "../utils/transform.js";
10
+ import { storeFile } from "../templates/store.js";
11
+ export function createCreateStoreCommand(_preset) {
12
+ return defineCommand({
13
+ meta: {
14
+ name: "store",
15
+ description: "Create a new Zustand store and wire it into AppDependencies",
16
+ },
17
+ args: {
18
+ name: {
19
+ type: "positional",
20
+ description: "Store name (e.g. notifications)",
21
+ required: false,
22
+ },
23
+ },
24
+ async run({ args }) {
25
+ const project = resolveProject();
26
+ const scope = detectScope(project.root);
27
+ const isNonInteractive = Boolean(args.name);
28
+ if (!isNonInteractive) {
29
+ p.intro("Create a new store");
30
+ }
31
+ const name = args.name ||
32
+ (await promptText({
33
+ message: "Store name",
34
+ placeholder: "notifications",
35
+ validate: (v) => (!v ? "Required" : undefined),
36
+ }));
37
+ const storePath = resolve(project.shellDir, "src", "stores", `${name}.ts`);
38
+ if (existsSync(storePath)) {
39
+ const msg = `Store "${name}" already exists at ${storePath}`;
40
+ if (isNonInteractive) {
41
+ console.error(msg);
42
+ process.exit(1);
43
+ }
44
+ p.cancel(msg);
45
+ process.exit(1);
46
+ }
47
+ const interfaceName = toPascalCase(name) + "Store";
48
+ const exportName = toCamelCase(name) + "Store";
49
+ writeFileSync(storePath, storeFile({ scope, interfaceName, exportName }));
50
+ addStoreToAppShared(project.appSharedDir, { storeName: name, interfaceName });
51
+ addStoreToMain(project.shellDir, { storeName: name, importName: exportName });
52
+ if (!isNonInteractive) {
53
+ p.note([
54
+ `Store file: shell/src/stores/${name}.ts`,
55
+ `Interface: ${interfaceName} (in app-shared)`,
56
+ `Dependency: AppDependencies.${name}`,
57
+ "",
58
+ "Next: add state and actions to the interface and store.",
59
+ ].join("\n"), "Created");
60
+ p.outro("Done!");
61
+ }
62
+ else {
63
+ console.log(`Store "${name}" created at shell/src/stores/${name}.ts`);
64
+ }
65
+ },
66
+ });
67
+ }
68
+ //# sourceMappingURL=create-store.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"create-store.js","sourceRoot":"","sources":["../../src/commands/create-store.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,17 @@
1
+ import type { CliPreset } from "../preset.js";
2
+ export declare function createInitCommand(preset: CliPreset): import("citty").CommandDef<{
3
+ readonly name: {
4
+ readonly type: "positional";
5
+ readonly description: "Project name";
6
+ readonly required: false;
7
+ };
8
+ readonly scope: {
9
+ readonly type: "string";
10
+ readonly description: "Package scope (e.g. @myapp)";
11
+ };
12
+ readonly module: {
13
+ readonly type: "string";
14
+ readonly description: "First module name (e.g. dashboard)";
15
+ };
16
+ }>;
17
+ //# sourceMappingURL=init.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"init.d.ts","sourceRoot":"","sources":["../../src/commands/init.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,cAAc,CAAC;AA2B9C,wBAAgB,iBAAiB,CAAC,MAAM,EAAE,SAAS;;;;;;;;;;;;;;GAiHlD"}