@webda/create 0.0.0-stage → 4.0.0-beta.5

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 (90) hide show
  1. package/LICENSE +166 -0
  2. package/README.md +27 -2
  3. package/agent/.claude-plugin/plugin.json +7 -0
  4. package/agent/AGENTS.md +47 -0
  5. package/agent/CLAUDE.md +3 -0
  6. package/agent/skills/webda-configuration/SKILL.md +61 -0
  7. package/agent/skills/webda-deploy/SKILL.md +103 -0
  8. package/agent/skills/webda-models/SKILL.md +137 -0
  9. package/agent/skills/webda-operations/SKILL.md +82 -0
  10. package/agent/skills/webda-services/SKILL.md +90 -0
  11. package/agent/skills/webda-stores/SKILL.md +66 -0
  12. package/agent/skills/webda-testing/SKILL.md +80 -0
  13. package/lib/agents.d.ts +21 -0
  14. package/lib/agents.d.ts.map +1 -0
  15. package/lib/agents.js +33 -0
  16. package/lib/agents.js.map +1 -0
  17. package/lib/bin.d.ts +3 -0
  18. package/lib/bin.d.ts.map +1 -0
  19. package/lib/bin.js +4 -0
  20. package/lib/bin.js.map +1 -0
  21. package/lib/compose.d.ts +32 -0
  22. package/lib/compose.d.ts.map +1 -0
  23. package/lib/compose.js +51 -0
  24. package/lib/compose.js.map +1 -0
  25. package/lib/generate.d.ts +39 -0
  26. package/lib/generate.d.ts.map +1 -0
  27. package/lib/generate.js +85 -0
  28. package/lib/generate.js.map +1 -0
  29. package/lib/index.d.ts +26 -0
  30. package/lib/index.d.ts.map +1 -0
  31. package/lib/index.js +97 -0
  32. package/lib/index.js.map +1 -0
  33. package/lib/install.d.ts +25 -0
  34. package/lib/install.d.ts.map +1 -0
  35. package/lib/install.js +34 -0
  36. package/lib/install.js.map +1 -0
  37. package/lib/merge.d.ts +8 -0
  38. package/lib/merge.d.ts.map +1 -0
  39. package/lib/merge.js +25 -0
  40. package/lib/merge.js.map +1 -0
  41. package/lib/options.d.ts +64 -0
  42. package/lib/options.d.ts.map +1 -0
  43. package/lib/options.js +125 -0
  44. package/lib/options.js.map +1 -0
  45. package/lib/prompts.d.ts +27 -0
  46. package/lib/prompts.d.ts.map +1 -0
  47. package/lib/prompts.js +73 -0
  48. package/lib/prompts.js.map +1 -0
  49. package/lib/template.d.ts +25 -0
  50. package/lib/template.d.ts.map +1 -0
  51. package/lib/template.js +46 -0
  52. package/lib/template.js.map +1 -0
  53. package/lib/versions.d.ts +22 -0
  54. package/lib/versions.d.ts.map +1 -0
  55. package/lib/versions.js +52 -0
  56. package/lib/versions.js.map +1 -0
  57. package/lib/versions.json +42 -0
  58. package/package.json +44 -3
  59. package/templates/base/files/README.md +16 -0
  60. package/templates/base/files/_gitignore +6 -0
  61. package/templates/base/files/src/models/Project.model.ts +19 -0
  62. package/templates/base/files/src/models/Task.model.ts +24 -0
  63. package/templates/base/files/src/services/task.service.ts +29 -0
  64. package/templates/base/files/test/app.spec.ts +57 -0
  65. package/templates/base/files/tsconfig.json +18 -0
  66. package/templates/base/files/vitest.config.ts +10 -0
  67. package/templates/base/package.json +35 -0
  68. package/templates/base/webda.config.json +19 -0
  69. package/templates/features/graphql/agents.md +1 -0
  70. package/templates/features/graphql/package.json +5 -0
  71. package/templates/features/graphql/webda.config.json +1 -0
  72. package/templates/features/grpc/agents.md +1 -0
  73. package/templates/features/grpc/package.json +5 -0
  74. package/templates/features/grpc/webda.config.json +6 -0
  75. package/templates/features/mcp/agents.md +1 -0
  76. package/templates/features/mcp/package.json +5 -0
  77. package/templates/features/mcp/webda.config.json +1 -0
  78. package/templates/features/store-file/agents.md +1 -0
  79. package/templates/features/store-file/package.json +5 -0
  80. package/templates/features/store-file/webda.config.json +1 -0
  81. package/templates/features/store-mongodb/agents.md +1 -0
  82. package/templates/features/store-mongodb/files/.env.example +1 -0
  83. package/templates/features/store-mongodb/files/docker-compose.yml +8 -0
  84. package/templates/features/store-mongodb/package.json +5 -0
  85. package/templates/features/store-mongodb/webda.config.json +1 -0
  86. package/templates/features/store-postgres/agents.md +1 -0
  87. package/templates/features/store-postgres/files/.env.example +5 -0
  88. package/templates/features/store-postgres/files/docker-compose.yml +9 -0
  89. package/templates/features/store-postgres/package.json +5 -0
  90. package/templates/features/store-postgres/webda.config.json +1 -0
package/lib/index.js ADDED
@@ -0,0 +1,97 @@
1
+ import { readFile } from "node:fs/promises";
2
+ import { relative, resolve } from "node:path";
3
+ import { fileURLToPath } from "node:url";
4
+ import { checkTarget, generate, writeFiles } from "./generate.js";
5
+ import { initGit, installDependencies, spawnRunner } from "./install.js";
6
+ import { parseCliArgs } from "./options.js";
7
+ import { clackPrompter, resolveOptions } from "./prompts.js";
8
+ import { fromVersionsFile, fromWorkspace } from "./versions.js";
9
+ const HELP = `Usage: npm create @webda <directory> [-- options]
10
+
11
+ --store memory|file|mongodb|postgres default memory
12
+ --transports rest,graphql,grpc,mcp default rest
13
+ --namespace <PascalCase> default from the directory name
14
+ --pm pnpm|npm|yarn default: the package manager running this command
15
+ --no-install skip dependency installation
16
+ --no-git skip git init
17
+ -y, --yes accept defaults, never prompt`;
18
+ /**
19
+ * Run the CLI
20
+ * @param deps - environment, injectable for tests
21
+ * @returns process exit code
22
+ */
23
+ export async function main(deps) {
24
+ let writing = false;
25
+ let target = "";
26
+ try {
27
+ const args = parseCliArgs(deps.argv);
28
+ if (args.help) {
29
+ deps.log(HELP);
30
+ return 0;
31
+ }
32
+ const options = await resolveOptions(args, {
33
+ interactive: deps.interactive && !args.yes,
34
+ prompter: deps.prompter,
35
+ cwd: deps.cwd,
36
+ userAgent: deps.env.npm_config_user_agent
37
+ });
38
+ checkTarget(options.dir);
39
+ const resolveVersion = options.linkWorkspace
40
+ ? await fromWorkspace(resolve(deps.cwd, options.linkWorkspace))
41
+ : fromVersionsFile(deps.versions);
42
+ const files = await generate({ options, templatesDir: deps.templatesDir, agentDir: deps.agentDir, resolveVersion });
43
+ writing = true;
44
+ target = options.dir;
45
+ await writeFiles(options.dir, files);
46
+ writing = false;
47
+ deps.log(`Created ${options.dir}`);
48
+ if (options.install) {
49
+ const install = installDependencies(options.pm, options.dir, deps.run);
50
+ if (!install.ok) {
51
+ const reason = install.error ? ` (${install.error})` : "";
52
+ deps.log(`Installing dependencies failed${reason}. Retry with: cd ${options.dir} && ${options.pm} install`);
53
+ return 1;
54
+ }
55
+ }
56
+ if (options.git) {
57
+ const git = initGit(options.dir, deps.run);
58
+ if (git === "missing")
59
+ deps.log("git not found: skipped repository initialization");
60
+ if (git === "failed")
61
+ deps.log("git commands failed: skipped the initial commit");
62
+ }
63
+ const cd = relative(deps.cwd, options.dir) || ".";
64
+ deps.log([
65
+ "Next steps:",
66
+ ` cd ${cd}`,
67
+ ` ${options.pm} run debug # build, then dev server on http://localhost:18080`,
68
+ "Open the project in your coding agent: it reads AGENTS.md; skills are in .agents/skills/"
69
+ ].join("\n"));
70
+ return 0;
71
+ }
72
+ catch (err) {
73
+ const message = err instanceof Error ? err.message : String(err);
74
+ deps.log(writing ? `Writing files failed: ${message}. Remove ${target} before retrying.` : message);
75
+ return 1;
76
+ }
77
+ }
78
+ /**
79
+ * Dependencies for a real run
80
+ * @returns deps using the process, clack prompts and the packaged templates
81
+ */
82
+ export async function defaultDeps() {
83
+ const versionsFile = fileURLToPath(new URL("./versions.json", import.meta.url));
84
+ return {
85
+ argv: process.argv.slice(2),
86
+ cwd: process.cwd(),
87
+ env: process.env,
88
+ interactive: Boolean(process.stdin.isTTY && process.stdout.isTTY),
89
+ prompter: clackPrompter,
90
+ run: spawnRunner,
91
+ log: message => console.log(message),
92
+ templatesDir: fileURLToPath(new URL("../templates", import.meta.url)),
93
+ agentDir: fileURLToPath(new URL("../agent", import.meta.url)),
94
+ versions: JSON.parse(await readFile(versionsFile, "utf8"))
95
+ };
96
+ }
97
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,25 @@
1
+ import type { PackageManager } from "./options.js";
2
+ export type Runner = (cmd: string, args: string[], cwd: string) => {
3
+ status: number | null;
4
+ error?: NodeJS.ErrnoException;
5
+ };
6
+ export declare const spawnRunner: Runner;
7
+ /**
8
+ * Install dependencies
9
+ * @param pm - package manager
10
+ * @param dir - application directory
11
+ * @param run - command runner
12
+ * @returns ok, and the runner error message when there is one
13
+ */
14
+ export declare function installDependencies(pm: PackageManager, dir: string, run: Runner): {
15
+ ok: boolean;
16
+ error?: string;
17
+ };
18
+ /**
19
+ * Initialize a git repository with an initial commit
20
+ * @param dir - application directory
21
+ * @param run - command runner
22
+ * @returns `missing` when git is not installed, `failed` when a git command fails
23
+ */
24
+ export declare function initGit(dir: string, run: Runner): "done" | "missing" | "failed";
25
+ //# sourceMappingURL=install.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"install.d.ts","sourceRoot":"","sources":["../src/install.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,cAAc,CAAC;AAEnD,MAAM,MAAM,MAAM,GAAG,CACnB,GAAG,EAAE,MAAM,EACX,IAAI,EAAE,MAAM,EAAE,EACd,GAAG,EAAE,MAAM,KACR;IAAE,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC;IAAC,KAAK,CAAC,EAAE,MAAM,CAAC,cAAc,CAAA;CAAE,CAAC;AAG9D,eAAO,MAAM,WAAW,EAAE,MAGzB,CAAC;AAEF;;;;;;GAMG;AACH,wBAAgB,mBAAmB,CAAC,EAAE,EAAE,cAAc,EAAE,GAAG,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,GAAG;IAAE,EAAE,EAAE,OAAO,CAAC;IAAC,KAAK,CAAC,EAAE,MAAM,CAAA;CAAE,CAGjH;AAED;;;;;GAKG;AACH,wBAAgB,OAAO,CAAC,GAAG,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,GAAG,QAAQ,CAO/E"}
package/lib/install.js ADDED
@@ -0,0 +1,34 @@
1
+ import { spawnSync } from "node:child_process";
2
+ // pnpm/npm/yarn are .cmd shims on Windows and need a shell; git is an executable and its commit message contains spaces
3
+ export const spawnRunner = (cmd, args, cwd) => {
4
+ const result = spawnSync(cmd, args, { cwd, stdio: "inherit", shell: process.platform === "win32" && cmd !== "git" });
5
+ return { status: result.status, error: result.error };
6
+ };
7
+ /**
8
+ * Install dependencies
9
+ * @param pm - package manager
10
+ * @param dir - application directory
11
+ * @param run - command runner
12
+ * @returns ok, and the runner error message when there is one
13
+ */
14
+ export function installDependencies(pm, dir, run) {
15
+ const result = run(pm, ["install"], dir);
16
+ return { ok: result.status === 0, error: result.error?.message };
17
+ }
18
+ /**
19
+ * Initialize a git repository with an initial commit
20
+ * @param dir - application directory
21
+ * @param run - command runner
22
+ * @returns `missing` when git is not installed, `failed` when a git command fails
23
+ */
24
+ export function initGit(dir, run) {
25
+ const version = run("git", ["--version"], dir);
26
+ if (version.error?.code === "ENOENT")
27
+ return "missing";
28
+ for (const args of [["init"], ["add", "-A"], ["commit", "-m", "Initial commit from @webda/create"]]) {
29
+ if (run("git", args, dir).status !== 0)
30
+ return "failed";
31
+ }
32
+ return "done";
33
+ }
34
+ //# sourceMappingURL=install.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"install.js","sourceRoot":"","sources":["../src/install.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,oBAAoB,CAAC;AAS/C,wHAAwH;AACxH,MAAM,CAAC,MAAM,WAAW,GAAW,CAAC,GAAG,EAAE,IAAI,EAAE,GAAG,EAAE,EAAE;IACpD,MAAM,MAAM,GAAG,SAAS,CAAC,GAAG,EAAE,IAAI,EAAE,EAAE,GAAG,EAAE,KAAK,EAAE,SAAS,EAAE,KAAK,EAAE,OAAO,CAAC,QAAQ,KAAK,OAAO,IAAI,GAAG,KAAK,KAAK,EAAE,CAAC,CAAC;IACrH,OAAO,EAAE,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,KAAK,EAAE,MAAM,CAAC,KAA0C,EAAE,CAAC;AAC7F,CAAC,CAAC;AAEF;;;;;;GAMG;AACH,MAAM,UAAU,mBAAmB,CAAC,EAAkB,EAAE,GAAW,EAAE,GAAW;IAC9E,MAAM,MAAM,GAAG,GAAG,CAAC,EAAE,EAAE,CAAC,SAAS,CAAC,EAAE,GAAG,CAAC,CAAC;IACzC,OAAO,EAAE,EAAE,EAAE,MAAM,CAAC,MAAM,KAAK,CAAC,EAAE,KAAK,EAAE,MAAM,CAAC,KAAK,EAAE,OAAO,EAAE,CAAC;AACnE,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,OAAO,CAAC,GAAW,EAAE,GAAW;IAC9C,MAAM,OAAO,GAAG,GAAG,CAAC,KAAK,EAAE,CAAC,WAAW,CAAC,EAAE,GAAG,CAAC,CAAC;IAC/C,IAAI,OAAO,CAAC,KAAK,EAAE,IAAI,KAAK,QAAQ;QAAE,OAAO,SAAS,CAAC;IACvD,KAAK,MAAM,IAAI,IAAI,CAAC,CAAC,MAAM,CAAC,EAAE,CAAC,KAAK,EAAE,IAAI,CAAC,EAAE,CAAC,QAAQ,EAAE,IAAI,EAAE,mCAAmC,CAAC,CAAC,EAAE,CAAC;QACpG,IAAI,GAAG,CAAC,KAAK,EAAE,IAAI,EAAE,GAAG,CAAC,CAAC,MAAM,KAAK,CAAC;YAAE,OAAO,QAAQ,CAAC;IAC1D,CAAC;IACD,OAAO,MAAM,CAAC;AAChB,CAAC"}
package/lib/merge.d.ts ADDED
@@ -0,0 +1,8 @@
1
+ /**
2
+ * Deep merge `source` into a copy of `target`; arrays and primitives from `source` replace
3
+ * @param target - base value, not mutated
4
+ * @param source - fragment to merge
5
+ * @returns the merged copy
6
+ */
7
+ export declare function deepMerge<T>(target: T, source: unknown): T;
8
+ //# sourceMappingURL=merge.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"merge.d.ts","sourceRoot":"","sources":["../src/merge.ts"],"names":[],"mappings":"AASA;;;;;GAKG;AACH,wBAAgB,SAAS,CAAC,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,MAAM,EAAE,OAAO,GAAG,CAAC,CAS1D"}
package/lib/merge.js ADDED
@@ -0,0 +1,25 @@
1
+ /**
2
+ * Whether `value` is a plain object (not an array or null)
3
+ * @param value - value to test
4
+ * @returns true for `{...}` values
5
+ */
6
+ function isObject(value) {
7
+ return value !== null && typeof value === "object" && !Array.isArray(value);
8
+ }
9
+ /**
10
+ * Deep merge `source` into a copy of `target`; arrays and primitives from `source` replace
11
+ * @param target - base value, not mutated
12
+ * @param source - fragment to merge
13
+ * @returns the merged copy
14
+ */
15
+ export function deepMerge(target, source) {
16
+ if (!isObject(target) || !isObject(source)) {
17
+ return structuredClone(source === undefined ? target : source);
18
+ }
19
+ const out = structuredClone(target);
20
+ for (const [key, value] of Object.entries(source)) {
21
+ out[key] = key in out ? deepMerge(out[key], value) : structuredClone(value);
22
+ }
23
+ return out;
24
+ }
25
+ //# sourceMappingURL=merge.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"merge.js","sourceRoot":"","sources":["../src/merge.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AACH,SAAS,QAAQ,CAAC,KAAc;IAC9B,OAAO,KAAK,KAAK,IAAI,IAAI,OAAO,KAAK,KAAK,QAAQ,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC;AAC9E,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,SAAS,CAAI,MAAS,EAAE,MAAe;IACrD,IAAI,CAAC,QAAQ,CAAC,MAAM,CAAC,IAAI,CAAC,QAAQ,CAAC,MAAM,CAAC,EAAE,CAAC;QAC3C,OAAO,eAAe,CAAC,MAAM,KAAK,SAAS,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,MAAM,CAAM,CAAC;IACtE,CAAC;IACD,MAAM,GAAG,GAA4B,eAAe,CAAC,MAAM,CAAC,CAAC;IAC7D,KAAK,MAAM,CAAC,GAAG,EAAE,KAAK,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,MAAM,CAAC,EAAE,CAAC;QAClD,GAAG,CAAC,GAAG,CAAC,GAAG,GAAG,IAAI,GAAG,CAAC,CAAC,CAAC,SAAS,CAAC,GAAG,CAAC,GAAG,CAAC,EAAE,KAAK,CAAC,CAAC,CAAC,CAAC,eAAe,CAAC,KAAK,CAAC,CAAC;IAC9E,CAAC;IACD,OAAO,GAAQ,CAAC;AAClB,CAAC"}
@@ -0,0 +1,64 @@
1
+ export type Store = "memory" | "file" | "mongodb" | "postgres";
2
+ export declare const STORES: Store[];
3
+ export type Transport = "rest" | "graphql" | "grpc" | "mcp";
4
+ export declare const TRANSPORTS: Transport[];
5
+ export type PackageManager = "pnpm" | "npm" | "yarn";
6
+ export declare const PACKAGE_MANAGERS: PackageManager[];
7
+ /**
8
+ * Fully resolved options used to generate an application
9
+ */
10
+ export interface CreateOptions {
11
+ dir: string;
12
+ store: Store;
13
+ transports: Transport[];
14
+ namespace: string;
15
+ pm: PackageManager;
16
+ install: boolean;
17
+ git: boolean;
18
+ linkWorkspace?: string;
19
+ }
20
+ /**
21
+ * Command line arguments, before defaults and prompts
22
+ */
23
+ export interface ParsedArgs {
24
+ dir?: string;
25
+ store?: Store;
26
+ transports?: Transport[];
27
+ namespace?: string;
28
+ pm?: PackageManager;
29
+ install: boolean;
30
+ git: boolean;
31
+ yes: boolean;
32
+ help: boolean;
33
+ linkWorkspace?: string;
34
+ }
35
+ /**
36
+ * Invalid or missing user input; the CLI prints the message and exits 1
37
+ */
38
+ export declare class OptionsError extends Error {
39
+ }
40
+ /**
41
+ * Parse command line arguments
42
+ * @param argv - arguments without the node binary and script path
43
+ * @returns parsed arguments; values not given are undefined
44
+ */
45
+ export declare function parseCliArgs(argv: string[]): ParsedArgs;
46
+ /**
47
+ * Derive a PascalCase namespace from a directory name
48
+ * @param name - directory basename
49
+ * @returns a namespace matching /^[A-Z][A-Za-z0-9]*$/
50
+ */
51
+ export declare function toNamespace(name: string): string;
52
+ /**
53
+ * Derive a valid npm package name from a directory name
54
+ * @param name - directory basename
55
+ * @returns lowercase name using only a-z, 0-9, `-`, `_` and `.`
56
+ */
57
+ export declare function toPackageName(name: string): string;
58
+ /**
59
+ * Detect which package manager launched the command
60
+ * @param userAgent - `npm_config_user_agent`
61
+ * @returns the package manager, `npm` when unknown
62
+ */
63
+ export declare function detectPackageManager(userAgent: string | undefined): PackageManager;
64
+ //# sourceMappingURL=options.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"options.d.ts","sourceRoot":"","sources":["../src/options.ts"],"names":[],"mappings":"AAEA,MAAM,MAAM,KAAK,GAAG,QAAQ,GAAG,MAAM,GAAG,SAAS,GAAG,UAAU,CAAC;AAC/D,eAAO,MAAM,MAAM,EAAE,KAAK,EAA8C,CAAC;AACzE,MAAM,MAAM,SAAS,GAAG,MAAM,GAAG,SAAS,GAAG,MAAM,GAAG,KAAK,CAAC;AAC5D,eAAO,MAAM,UAAU,EAAE,SAAS,EAAuC,CAAC;AAC1E,MAAM,MAAM,cAAc,GAAG,MAAM,GAAG,KAAK,GAAG,MAAM,CAAC;AACrD,eAAO,MAAM,gBAAgB,EAAE,cAAc,EAA4B,CAAC;AAE1E;;GAEG;AACH,MAAM,WAAW,aAAa;IAC5B,GAAG,EAAE,MAAM,CAAC;IACZ,KAAK,EAAE,KAAK,CAAC;IACb,UAAU,EAAE,SAAS,EAAE,CAAC;IACxB,SAAS,EAAE,MAAM,CAAC;IAClB,EAAE,EAAE,cAAc,CAAC;IACnB,OAAO,EAAE,OAAO,CAAC;IACjB,GAAG,EAAE,OAAO,CAAC;IACb,aAAa,CAAC,EAAE,MAAM,CAAC;CACxB;AAED;;GAEG;AACH,MAAM,WAAW,UAAU;IACzB,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,KAAK,CAAC,EAAE,KAAK,CAAC;IACd,UAAU,CAAC,EAAE,SAAS,EAAE,CAAC;IACzB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,EAAE,CAAC,EAAE,cAAc,CAAC;IACpB,OAAO,EAAE,OAAO,CAAC;IACjB,GAAG,EAAE,OAAO,CAAC;IACb,GAAG,EAAE,OAAO,CAAC;IACb,IAAI,EAAE,OAAO,CAAC;IACd,aAAa,CAAC,EAAE,MAAM,CAAC;CACxB;AAED;;GAEG;AACH,qBAAa,YAAa,SAAQ,KAAK;CAAG;AAoC1C;;;;GAIG;AACH,wBAAgB,YAAY,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,UAAU,CA2CvD;AAED;;;;GAIG;AACH,wBAAgB,WAAW,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAOhD;AAED;;;;GAIG;AACH,wBAAgB,aAAa,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAOlD;AAED;;;;GAIG;AACH,wBAAgB,oBAAoB,CAAC,SAAS,EAAE,MAAM,GAAG,SAAS,GAAG,cAAc,CAGlF"}
package/lib/options.js ADDED
@@ -0,0 +1,125 @@
1
+ import { parseArgs } from "node:util";
2
+ export const STORES = ["memory", "file", "mongodb", "postgres"];
3
+ export const TRANSPORTS = ["rest", "graphql", "grpc", "mcp"];
4
+ export const PACKAGE_MANAGERS = ["pnpm", "npm", "yarn"];
5
+ /**
6
+ * Invalid or missing user input; the CLI prints the message and exits 1
7
+ */
8
+ export class OptionsError extends Error {
9
+ }
10
+ /**
11
+ * Check `value` is one of `allowed`
12
+ * @param flag - flag name used in the error message
13
+ * @param value - user value
14
+ * @param allowed - valid values
15
+ * @returns the value, typed
16
+ */
17
+ function oneOf(flag, value, allowed) {
18
+ if (!allowed.includes(value)) {
19
+ throw new OptionsError(`Invalid --${flag} "${value}". Valid values: ${allowed.join(", ")}`);
20
+ }
21
+ return value;
22
+ }
23
+ /**
24
+ * Parse a comma separated transport list, trimming and removing duplicates
25
+ * @param value - raw `--transports` value
26
+ * @returns at least one valid transport
27
+ */
28
+ function parseTransports(value) {
29
+ const list = [
30
+ ...new Set(value
31
+ .split(",")
32
+ .map(item => item.trim())
33
+ .filter(Boolean))
34
+ ];
35
+ if (list.length === 0) {
36
+ throw new OptionsError(`--transports needs at least one of: ${TRANSPORTS.join(", ")}`);
37
+ }
38
+ return list.map(item => oneOf("transports", item, TRANSPORTS));
39
+ }
40
+ /**
41
+ * Parse command line arguments
42
+ * @param argv - arguments without the node binary and script path
43
+ * @returns parsed arguments; values not given are undefined
44
+ */
45
+ export function parseCliArgs(argv) {
46
+ let parsed;
47
+ try {
48
+ parsed = parseArgs({
49
+ args: argv,
50
+ allowPositionals: true,
51
+ strict: true,
52
+ options: {
53
+ store: { type: "string" },
54
+ transports: { type: "string" },
55
+ namespace: { type: "string" },
56
+ pm: { type: "string" },
57
+ "no-install": { type: "boolean" },
58
+ "no-git": { type: "boolean" },
59
+ yes: { type: "boolean", short: "y" },
60
+ help: { type: "boolean", short: "h" },
61
+ "link-workspace": { type: "string" }
62
+ }
63
+ });
64
+ }
65
+ catch (err) {
66
+ throw new OptionsError(err.message);
67
+ }
68
+ const values = parsed.values;
69
+ if (parsed.positionals.length > 1) {
70
+ throw new OptionsError(`Expected one directory, got: ${parsed.positionals.join(" ")}`);
71
+ }
72
+ const namespace = values.namespace;
73
+ if (namespace !== undefined && !/^[A-Z][A-Za-z0-9]*$/.test(namespace)) {
74
+ throw new OptionsError(`Invalid --namespace "${namespace}": use PascalCase letters and digits, e.g. MyApp`);
75
+ }
76
+ const result = {
77
+ dir: parsed.positionals[0],
78
+ store: values.store === undefined ? undefined : oneOf("store", values.store, STORES),
79
+ transports: values.transports === undefined ? undefined : parseTransports(values.transports),
80
+ namespace,
81
+ pm: values.pm === undefined ? undefined : oneOf("pm", values.pm, PACKAGE_MANAGERS),
82
+ install: !values["no-install"],
83
+ git: !values["no-git"],
84
+ yes: Boolean(values.yes),
85
+ help: Boolean(values.help),
86
+ linkWorkspace: values["link-workspace"]
87
+ };
88
+ return result;
89
+ }
90
+ /**
91
+ * Derive a PascalCase namespace from a directory name
92
+ * @param name - directory basename
93
+ * @returns a namespace matching /^[A-Z][A-Za-z0-9]*$/
94
+ */
95
+ export function toNamespace(name) {
96
+ const pascal = name
97
+ .split(/[^A-Za-z0-9]+/)
98
+ .filter(Boolean)
99
+ .map(part => part[0].toUpperCase() + part.slice(1))
100
+ .join("");
101
+ return /^[A-Z]/.test(pascal) ? pascal : `App${pascal}`;
102
+ }
103
+ /**
104
+ * Derive a valid npm package name from a directory name
105
+ * @param name - directory basename
106
+ * @returns lowercase name using only a-z, 0-9, `-`, `_` and `.`
107
+ */
108
+ export function toPackageName(name) {
109
+ const cleaned = name
110
+ .toLowerCase()
111
+ .replace(/[^a-z0-9._-]+/g, "-")
112
+ .replace(/-+/g, "-")
113
+ .replace(/^[._-]+|[._-]+$/g, "");
114
+ return cleaned || "webda-app";
115
+ }
116
+ /**
117
+ * Detect which package manager launched the command
118
+ * @param userAgent - `npm_config_user_agent`
119
+ * @returns the package manager, `npm` when unknown
120
+ */
121
+ export function detectPackageManager(userAgent) {
122
+ const name = userAgent?.split("/")[0];
123
+ return PACKAGE_MANAGERS.includes(name) ? name : "npm";
124
+ }
125
+ //# sourceMappingURL=options.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"options.js","sourceRoot":"","sources":["../src/options.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,27 @@
1
+ import { CreateOptions, ParsedArgs } from "./options.js";
2
+ /**
3
+ * Questions asked in interactive mode; abstracted for tests
4
+ */
5
+ export interface Prompter {
6
+ text(message: string, initial: string): Promise<string>;
7
+ select<T extends string>(message: string, options: T[], initial: T): Promise<T>;
8
+ multiselect<T extends string>(message: string, options: T[], initial: T[]): Promise<T[]>;
9
+ }
10
+ export declare const clackPrompter: Prompter;
11
+ /**
12
+ * Apply defaults and, in interactive mode, ask for missing values
13
+ * @param args - parsed command line
14
+ * @param context - interactivity, prompter, working directory and package manager user agent
15
+ * @param context.interactive - whether running in interactive mode
16
+ * @param context.prompter - prompter implementation for interactive input
17
+ * @param context.cwd - current working directory
18
+ * @param context.userAgent - package manager user agent
19
+ * @returns complete options with an absolute `dir`
20
+ */
21
+ export declare function resolveOptions(args: ParsedArgs, context: {
22
+ interactive: boolean;
23
+ prompter: Prompter;
24
+ cwd: string;
25
+ userAgent?: string;
26
+ }): Promise<CreateOptions>;
27
+ //# sourceMappingURL=prompts.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"prompts.d.ts","sourceRoot":"","sources":["../src/prompts.ts"],"names":[],"mappings":"AAEA,OAAO,EACL,aAAa,EAGb,UAAU,EAMX,MAAM,cAAc,CAAC;AAEtB;;GAEG;AACH,MAAM,WAAW,QAAQ;IACvB,IAAI,CAAC,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC;IACxD,MAAM,CAAC,CAAC,SAAS,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,CAAC,EAAE,EAAE,OAAO,EAAE,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC,CAAC;IAChF,WAAW,CAAC,CAAC,SAAS,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,CAAC,EAAE,EAAE,OAAO,EAAE,CAAC,EAAE,GAAG,OAAO,CAAC,CAAC,EAAE,CAAC,CAAC;CAC1F;AAcD,eAAO,MAAM,aAAa,EAAE,QAuB3B,CAAC;AAEF;;;;;;;;;GASG;AACH,wBAAsB,cAAc,CAClC,IAAI,EAAE,UAAU,EAChB,OAAO,EAAE;IAAE,WAAW,EAAE,OAAO,CAAC;IAAC,QAAQ,EAAE,QAAQ,CAAC;IAAC,GAAG,EAAE,MAAM,CAAC;IAAC,SAAS,CAAC,EAAE,MAAM,CAAA;CAAE,GACrF,OAAO,CAAC,aAAa,CAAC,CA2BxB"}
package/lib/prompts.js ADDED
@@ -0,0 +1,73 @@
1
+ import * as clack from "@clack/prompts";
2
+ import { basename, resolve } from "node:path";
3
+ import { detectPackageManager, OptionsError, STORES, toNamespace, TRANSPORTS } from "./options.js";
4
+ /**
5
+ * Throw on Ctrl-C, otherwise return the answer
6
+ * @param value - clack answer
7
+ * @returns the answer
8
+ */
9
+ function answer(value) {
10
+ if (clack.isCancel(value)) {
11
+ throw new OptionsError("Cancelled");
12
+ }
13
+ return value;
14
+ }
15
+ export const clackPrompter = {
16
+ async text(message, initial) {
17
+ return answer(await clack.text({ message, initialValue: initial }));
18
+ },
19
+ async select(message, options, initial) {
20
+ return answer(await clack.select({
21
+ message,
22
+ options: options.map(value => ({ value, label: value })),
23
+ initialValue: initial
24
+ }));
25
+ },
26
+ async multiselect(message, options, initial) {
27
+ return answer(await clack.multiselect({
28
+ message,
29
+ options: options.map(value => ({ value, label: value })),
30
+ initialValues: initial,
31
+ required: false
32
+ }));
33
+ }
34
+ };
35
+ /**
36
+ * Apply defaults and, in interactive mode, ask for missing values
37
+ * @param args - parsed command line
38
+ * @param context - interactivity, prompter, working directory and package manager user agent
39
+ * @param context.interactive - whether running in interactive mode
40
+ * @param context.prompter - prompter implementation for interactive input
41
+ * @param context.cwd - current working directory
42
+ * @param context.userAgent - package manager user agent
43
+ * @returns complete options with an absolute `dir`
44
+ */
45
+ export async function resolveOptions(args, context) {
46
+ const { interactive, prompter, cwd } = context;
47
+ let dir = args.dir;
48
+ if (dir === undefined) {
49
+ if (!interactive) {
50
+ throw new OptionsError("Missing project directory: npm create @webda <directory>");
51
+ }
52
+ dir = (await prompter.text("Project directory", "my-webda-app")).trim();
53
+ if (!dir)
54
+ throw new OptionsError("Missing project directory");
55
+ }
56
+ const store = args.store ?? (interactive ? await prompter.select("Which store?", STORES, "memory") : "memory");
57
+ const transports = args.transports ?? (interactive ? await prompter.multiselect("Which transports?", TRANSPORTS, ["rest"]) : ["rest"]);
58
+ if (transports.length === 0) {
59
+ throw new OptionsError(`Select at least one transport: ${TRANSPORTS.join(", ")}`);
60
+ }
61
+ const absolute = resolve(cwd, dir);
62
+ return {
63
+ dir: absolute,
64
+ store,
65
+ transports,
66
+ namespace: args.namespace ?? toNamespace(basename(absolute)),
67
+ pm: args.pm ?? detectPackageManager(context.userAgent),
68
+ install: args.install,
69
+ git: args.git,
70
+ linkWorkspace: args.linkWorkspace
71
+ };
72
+ }
73
+ //# sourceMappingURL=prompts.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"prompts.js","sourceRoot":"","sources":["../src/prompts.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,25 @@
1
+ export type FileMap = Map<string, string>;
2
+ /**
3
+ * A base app or a feature overlay
4
+ */
5
+ export interface Template {
6
+ name: string;
7
+ files: FileMap;
8
+ packageJson: Record<string, any>;
9
+ config: Record<string, any>;
10
+ agents: string;
11
+ }
12
+ /**
13
+ * Read every file under `dir`
14
+ * @param dir - folder to read; a missing folder gives an empty map
15
+ * @returns POSIX relative path → content
16
+ */
17
+ export declare function readTree(dir: string): Promise<FileMap>;
18
+ /**
19
+ * Load a template folder: `files/`, `package.json`, `webda.config.json` and `agents.md`, all optional
20
+ * @param dir - template folder
21
+ * @param name - template name used in error messages
22
+ * @returns the template
23
+ */
24
+ export declare function loadTemplate(dir: string, name: string): Promise<Template>;
25
+ //# sourceMappingURL=template.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"template.d.ts","sourceRoot":"","sources":["../src/template.ts"],"names":[],"mappings":"AAIA,MAAM,MAAM,OAAO,GAAG,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;AAE1C;;GAEG;AACH,MAAM,WAAW,QAAQ;IACvB,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,OAAO,CAAC;IACf,WAAW,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;IACjC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;IAC5B,MAAM,EAAE,MAAM,CAAC;CAChB;AAED;;;;GAIG;AACH,wBAAsB,QAAQ,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAU5D;AAWD;;;;;GAKG;AACH,wBAAsB,YAAY,CAAC,GAAG,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,QAAQ,CAAC,CAS/E"}
@@ -0,0 +1,46 @@
1
+ import { existsSync } from "node:fs";
2
+ import { readdir, readFile } from "node:fs/promises";
3
+ import { join, relative, sep } from "node:path";
4
+ /**
5
+ * Read every file under `dir`
6
+ * @param dir - folder to read; a missing folder gives an empty map
7
+ * @returns POSIX relative path → content
8
+ */
9
+ export async function readTree(dir) {
10
+ const files = new Map();
11
+ if (!existsSync(dir))
12
+ return files;
13
+ const entries = await readdir(dir, { recursive: true, withFileTypes: true });
14
+ for (const entry of entries) {
15
+ if (!entry.isFile())
16
+ continue;
17
+ const full = join(entry.parentPath ?? entry.path, entry.name);
18
+ files.set(relative(dir, full).split(sep).join("/"), await readFile(full, "utf8"));
19
+ }
20
+ return files;
21
+ }
22
+ /**
23
+ * Read an optional JSON file
24
+ * @param file - path
25
+ * @returns parsed content, `{}` when the file does not exist
26
+ */
27
+ async function readJson(file) {
28
+ return existsSync(file) ? JSON.parse(await readFile(file, "utf8")) : {};
29
+ }
30
+ /**
31
+ * Load a template folder: `files/`, `package.json`, `webda.config.json` and `agents.md`, all optional
32
+ * @param dir - template folder
33
+ * @param name - template name used in error messages
34
+ * @returns the template
35
+ */
36
+ export async function loadTemplate(dir, name) {
37
+ const agentsFile = join(dir, "agents.md");
38
+ return {
39
+ name,
40
+ files: await readTree(join(dir, "files")),
41
+ packageJson: await readJson(join(dir, "package.json")),
42
+ config: await readJson(join(dir, "webda.config.json")),
43
+ agents: existsSync(agentsFile) ? await readFile(agentsFile, "utf8") : ""
44
+ };
45
+ }
46
+ //# sourceMappingURL=template.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"template.js","sourceRoot":"","sources":["../src/template.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,SAAS,CAAC;AACrC,OAAO,EAAE,OAAO,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AACrD,OAAO,EAAE,IAAI,EAAE,QAAQ,EAAE,GAAG,EAAE,MAAM,WAAW,CAAC;AAehD;;;;GAIG;AACH,MAAM,CAAC,KAAK,UAAU,QAAQ,CAAC,GAAW;IACxC,MAAM,KAAK,GAAY,IAAI,GAAG,EAAE,CAAC;IACjC,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC;QAAE,OAAO,KAAK,CAAC;IACnC,MAAM,OAAO,GAAG,MAAM,OAAO,CAAC,GAAG,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,aAAa,EAAE,IAAI,EAAE,CAAC,CAAC;IAC7E,KAAK,MAAM,KAAK,IAAI,OAAO,EAAE,CAAC;QAC5B,IAAI,CAAC,KAAK,CAAC,MAAM,EAAE;YAAE,SAAS;QAC9B,MAAM,IAAI,GAAG,IAAI,CAAC,KAAK,CAAC,UAAU,IAAK,KAAa,CAAC,IAAI,EAAE,KAAK,CAAC,IAAI,CAAC,CAAC;QACvE,KAAK,CAAC,GAAG,CAAC,QAAQ,CAAC,GAAG,EAAE,IAAI,CAAC,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE,MAAM,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC,CAAC;IACpF,CAAC;IACD,OAAO,KAAK,CAAC;AACf,CAAC;AAED;;;;GAIG;AACH,KAAK,UAAU,QAAQ,CAAC,IAAY;IAClC,OAAO,UAAU,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,MAAM,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;AAC1E,CAAC;AAED;;;;;GAKG;AACH,MAAM,CAAC,KAAK,UAAU,YAAY,CAAC,GAAW,EAAE,IAAY;IAC1D,MAAM,UAAU,GAAG,IAAI,CAAC,GAAG,EAAE,WAAW,CAAC,CAAC;IAC1C,OAAO;QACL,IAAI;QACJ,KAAK,EAAE,MAAM,QAAQ,CAAC,IAAI,CAAC,GAAG,EAAE,OAAO,CAAC,CAAC;QACzC,WAAW,EAAE,MAAM,QAAQ,CAAC,IAAI,CAAC,GAAG,EAAE,cAAc,CAAC,CAAC;QACtD,MAAM,EAAE,MAAM,QAAQ,CAAC,IAAI,CAAC,GAAG,EAAE,mBAAmB,CAAC,CAAC;QACtD,MAAM,EAAE,UAAU,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC,MAAM,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC,CAAC,CAAC,CAAC,EAAE;KACzE,CAAC;AACJ,CAAC"}
@@ -0,0 +1,22 @@
1
+ export type VersionResolver = (name: string) => string | undefined;
2
+ /** Tool versions taken from @webda/core devDependencies so apps build like the monorepo */
3
+ export declare const EXTERNAL_TOOLS: string[];
4
+ /**
5
+ * Replace template versions (`workspace:*` for @webda packages, `managed` for tools)
6
+ * @param pkg - package.json content, mutated
7
+ * @param resolve - version lookup
8
+ */
9
+ export declare function applyVersions(pkg: Record<string, any>, resolve: VersionResolver): void;
10
+ /**
11
+ * Resolve versions from the `versions.json` written at build time
12
+ * @param versions - package name → version
13
+ * @returns the resolver
14
+ */
15
+ export declare function fromVersionsFile(versions: Record<string, string>): VersionResolver;
16
+ /**
17
+ * Resolve @webda packages to `link:` paths in a monorepo checkout, tools from @webda/core devDependencies
18
+ * @param root - monorepo root
19
+ * @returns the resolver
20
+ */
21
+ export declare function fromWorkspace(root: string): Promise<VersionResolver>;
22
+ //# sourceMappingURL=versions.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"versions.d.ts","sourceRoot":"","sources":["../src/versions.ts"],"names":[],"mappings":"AAIA,MAAM,MAAM,eAAe,GAAG,CAAC,IAAI,EAAE,MAAM,KAAK,MAAM,GAAG,SAAS,CAAC;AAEnE,2FAA2F;AAC3F,eAAO,MAAM,cAAc,UAA2D,CAAC;AAEvF;;;;GAIG;AACH,wBAAgB,aAAa,CAAC,GAAG,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,EAAE,OAAO,EAAE,eAAe,GAAG,IAAI,CAYtF;AAED;;;;GAIG;AACH,wBAAgB,gBAAgB,CAAC,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GAAG,eAAe,CAElF;AAED;;;;GAIG;AACH,wBAAsB,aAAa,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,eAAe,CAAC,CAW1E"}