@wild-framework/cli 0.1.1 → 0.2.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cli.d.ts.map +1 -1
- package/dist/cli.js +109 -5
- package/dist/cli.js.map +1 -1
- package/dist/client/codegen.d.ts +32 -0
- package/dist/client/codegen.d.ts.map +1 -0
- package/dist/client/codegen.js +94 -0
- package/dist/client/codegen.js.map +1 -0
- package/dist/client/command.d.ts +29 -0
- package/dist/client/command.d.ts.map +1 -0
- package/dist/client/command.js +95 -0
- package/dist/client/command.js.map +1 -0
- package/dist/client/contract.d.ts +86 -0
- package/dist/client/contract.d.ts.map +1 -0
- package/dist/client/contract.js +12 -0
- package/dist/client/contract.js.map +1 -0
- package/dist/client/core.d.ts +80 -0
- package/dist/client/core.d.ts.map +1 -0
- package/dist/client/core.js +52 -0
- package/dist/client/core.js.map +1 -0
- package/dist/client/fs-writer.d.ts +13 -0
- package/dist/client/fs-writer.d.ts.map +1 -0
- package/dist/client/fs-writer.js +24 -0
- package/dist/client/fs-writer.js.map +1 -0
- package/dist/client/inspector.d.ts +19 -0
- package/dist/client/inspector.d.ts.map +1 -0
- package/dist/client/inspector.js +71 -0
- package/dist/client/inspector.js.map +1 -0
- package/dist/client/spec.d.ts +13 -0
- package/dist/client/spec.d.ts.map +1 -0
- package/dist/client/spec.js +235 -0
- package/dist/client/spec.js.map +1 -0
- package/dist/client/targets/index.d.ts +9 -0
- package/dist/client/targets/index.d.ts.map +1 -0
- package/dist/client/targets/index.js +11 -0
- package/dist/client/targets/index.js.map +1 -0
- package/dist/client/targets/react.d.ts +20 -0
- package/dist/client/targets/react.d.ts.map +1 -0
- package/dist/client/targets/react.js +519 -0
- package/dist/client/targets/react.js.map +1 -0
- package/dist/commands/ci.d.ts +5 -0
- package/dist/commands/ci.d.ts.map +1 -0
- package/dist/commands/ci.js +254 -0
- package/dist/commands/ci.js.map +1 -0
- package/dist/commands/db.d.ts +13 -0
- package/dist/commands/db.d.ts.map +1 -0
- package/dist/commands/db.js +104 -0
- package/dist/commands/db.js.map +1 -0
- package/dist/commands/docker.d.ts +9 -0
- package/dist/commands/docker.d.ts.map +1 -0
- package/dist/commands/docker.js +175 -0
- package/dist/commands/docker.js.map +1 -0
- package/dist/commands/graph.d.ts +9 -0
- package/dist/commands/graph.d.ts.map +1 -0
- package/dist/commands/graph.js +36 -0
- package/dist/commands/graph.js.map +1 -0
- package/dist/commands/make.d.ts +1 -1
- package/dist/commands/make.d.ts.map +1 -1
- package/dist/commands/make.js +51 -0
- package/dist/commands/make.js.map +1 -1
- package/dist/commands/new.d.ts +24 -0
- package/dist/commands/new.d.ts.map +1 -0
- package/dist/commands/new.js +374 -0
- package/dist/commands/new.js.map +1 -0
- package/dist/commands/resource.d.ts +33 -0
- package/dist/commands/resource.d.ts.map +1 -0
- package/dist/commands/resource.js +291 -0
- package/dist/commands/resource.js.map +1 -0
- package/dist/templates/resource-slice.d.ts +87 -0
- package/dist/templates/resource-slice.d.ts.map +1 -0
- package/dist/templates/resource-slice.js +513 -0
- package/dist/templates/resource-slice.js.map +1 -0
- package/package.json +9 -3
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Generator core — framework-agnostic.
|
|
3
|
+
*
|
|
4
|
+
* Orchestrates: contract → target adapter → file emission, with an
|
|
5
|
+
* overwrite/update strategy (existing files are skipped unless they're
|
|
6
|
+
* marked as regenerable).
|
|
7
|
+
*/
|
|
8
|
+
export class ClientGenerator {
|
|
9
|
+
targets;
|
|
10
|
+
writer;
|
|
11
|
+
constructor(targets, writer) {
|
|
12
|
+
this.targets = targets;
|
|
13
|
+
this.writer = writer;
|
|
14
|
+
}
|
|
15
|
+
/** Register a target adapter. */
|
|
16
|
+
register(target) {
|
|
17
|
+
this.targets[target.name] = target;
|
|
18
|
+
}
|
|
19
|
+
/** List available target names. */
|
|
20
|
+
availableTargets() {
|
|
21
|
+
return Object.keys(this.targets);
|
|
22
|
+
}
|
|
23
|
+
/**
|
|
24
|
+
* Generate a client for a target into an output directory.
|
|
25
|
+
*
|
|
26
|
+
* The generator only writes files the adapter returns; it never
|
|
27
|
+
* creates package.json, bundler config, entry points, or UI scaffolding.
|
|
28
|
+
*/
|
|
29
|
+
generate(contract, targetName, options = {}) {
|
|
30
|
+
const target = this.targets[targetName];
|
|
31
|
+
if (!target) {
|
|
32
|
+
throw new Error(`Unknown client target "${targetName}". Available: ${this.availableTargets().join(", ")}`);
|
|
33
|
+
}
|
|
34
|
+
const request = {
|
|
35
|
+
contract,
|
|
36
|
+
baseUrl: options.baseUrl ?? "/",
|
|
37
|
+
examples: options.examples ?? false,
|
|
38
|
+
};
|
|
39
|
+
const files = target.generateFiles(request);
|
|
40
|
+
const written = [];
|
|
41
|
+
const skipped = [];
|
|
42
|
+
for (const file of files) {
|
|
43
|
+
const outcome = this.writer.write(file, options.outputDir ?? process.cwd());
|
|
44
|
+
if (outcome === "written")
|
|
45
|
+
written.push(file.path);
|
|
46
|
+
else
|
|
47
|
+
skipped.push(file.path);
|
|
48
|
+
}
|
|
49
|
+
return { filesWritten: written, filesSkipped: skipped, target: targetName };
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
//# sourceMappingURL=core.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"core.js","sourceRoot":"","sources":["../../src/client/core.ts"],"names":[],"mappings":"AAuDA;;;;;;GAMG;AACH,MAAM,OAAO,eAAe;IAEH;IACA;IAFrB,YACqB,OAAqC,EACrC,MAAkB;QADlB,YAAO,GAAP,OAAO,CAA8B;QACrC,WAAM,GAAN,MAAM,CAAY;IACpC,CAAC;IAEJ,iCAAiC;IACjC,QAAQ,CAAC,MAAoB;QACzB,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,MAAM,CAAC;IACvC,CAAC;IAED,mCAAmC;IACnC,gBAAgB;QACZ,OAAO,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;IACrC,CAAC;IAED;;;;;OAKG;IACH,QAAQ,CAAC,QAA0B,EAAE,UAAkB,EAAE,UAA2B,EAAE;QAClF,MAAM,MAAM,GAAG,IAAI,CAAC,OAAO,CAAC,UAAU,CAAC,CAAC;QACxC,IAAI,CAAC,MAAM,EAAE,CAAC;YACV,MAAM,IAAI,KAAK,CAAC,0BAA0B,UAAU,iBAAiB,IAAI,CAAC,gBAAgB,EAAE,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;QAC/G,CAAC;QAED,MAAM,OAAO,GAAkB;YAC3B,QAAQ;YACR,OAAO,EAAE,OAAO,CAAC,OAAO,IAAI,GAAG;YAC/B,QAAQ,EAAE,OAAO,CAAC,QAAQ,IAAI,KAAK;SACtC,CAAC;QAEF,MAAM,KAAK,GAAG,MAAM,CAAC,aAAa,CAAC,OAAO,CAAC,CAAC;QAC5C,MAAM,OAAO,GAAa,EAAE,CAAC;QAC7B,MAAM,OAAO,GAAa,EAAE,CAAC;QAE7B,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;YACvB,MAAM,OAAO,GAAG,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,IAAI,EAAE,OAAO,CAAC,SAAS,IAAI,OAAO,CAAC,GAAG,EAAE,CAAC,CAAC;YAC5E,IAAI,OAAO,KAAK,SAAS;gBAAE,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;;gBAC9C,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QACjC,CAAC;QAED,OAAO,EAAE,YAAY,EAAE,OAAO,EAAE,YAAY,EAAE,OAAO,EAAE,MAAM,EAAE,UAAU,EAAE,CAAC;IAChF,CAAC;CACJ"}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import type { GeneratedFile, FileWriter, WriteOutcome } from "./core.js";
|
|
2
|
+
/**
|
|
3
|
+
* Default filesystem writer.
|
|
4
|
+
*
|
|
5
|
+
* Strategy:
|
|
6
|
+
* - Never overwrites existing files (skips with a message).
|
|
7
|
+
* - Creates parent directories as needed.
|
|
8
|
+
* - Only writes the files the adapter returned — never scaffolds a project.
|
|
9
|
+
*/
|
|
10
|
+
export declare class DiskWriter implements FileWriter {
|
|
11
|
+
write(file: GeneratedFile, root: string): WriteOutcome;
|
|
12
|
+
}
|
|
13
|
+
//# sourceMappingURL=fs-writer.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"fs-writer.d.ts","sourceRoot":"","sources":["../../src/client/fs-writer.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,aAAa,EAAE,UAAU,EAAE,YAAY,EAAE,MAAM,WAAW,CAAC;AAEzE;;;;;;;GAOG;AACH,qBAAa,UAAW,YAAW,UAAU;IACzC,KAAK,CAAC,IAAI,EAAE,aAAa,EAAE,IAAI,EAAE,MAAM,GAAG,YAAY;CAWzD"}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import { mkdirSync, writeFileSync, existsSync } from "node:fs";
|
|
2
|
+
import { join, dirname } from "node:path";
|
|
3
|
+
/**
|
|
4
|
+
* Default filesystem writer.
|
|
5
|
+
*
|
|
6
|
+
* Strategy:
|
|
7
|
+
* - Never overwrites existing files (skips with a message).
|
|
8
|
+
* - Creates parent directories as needed.
|
|
9
|
+
* - Only writes the files the adapter returned — never scaffolds a project.
|
|
10
|
+
*/
|
|
11
|
+
export class DiskWriter {
|
|
12
|
+
write(file, root) {
|
|
13
|
+
const target = join(root, file.path);
|
|
14
|
+
if (existsSync(target)) {
|
|
15
|
+
console.log(` skip ${file.path}`);
|
|
16
|
+
return "skipped";
|
|
17
|
+
}
|
|
18
|
+
mkdirSync(dirname(target), { recursive: true });
|
|
19
|
+
writeFileSync(target, file.content, "utf8");
|
|
20
|
+
console.log(` create ${file.path}`);
|
|
21
|
+
return "written";
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
//# sourceMappingURL=fs-writer.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"fs-writer.js","sourceRoot":"","sources":["../../src/client/fs-writer.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,aAAa,EAAE,UAAU,EAAE,MAAM,SAAS,CAAC;AAC/D,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAG1C;;;;;;;GAOG;AACH,MAAM,OAAO,UAAU;IACnB,KAAK,CAAC,IAAmB,EAAE,IAAY;QACnC,MAAM,MAAM,GAAG,IAAI,CAAC,IAAI,EAAE,IAAI,CAAC,IAAI,CAAC,CAAC;QACrC,IAAI,UAAU,CAAC,MAAM,CAAC,EAAE,CAAC;YACrB,OAAO,CAAC,GAAG,CAAC,WAAW,IAAI,CAAC,IAAI,EAAE,CAAC,CAAC;YACpC,OAAO,SAAS,CAAC;QACrB,CAAC;QACD,SAAS,CAAC,OAAO,CAAC,MAAM,CAAC,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;QAChD,aAAa,CAAC,MAAM,EAAE,IAAI,CAAC,OAAO,EAAE,MAAM,CAAC,CAAC;QAC5C,OAAO,CAAC,GAAG,CAAC,YAAY,IAAI,CAAC,IAAI,EAAE,CAAC,CAAC;QACrC,OAAO,SAAS,CAAC;IACrB,CAAC;CACJ"}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import type { ProjectDetection } from "./core.js";
|
|
2
|
+
/**
|
|
3
|
+
* Inspect an existing project directory and detect:
|
|
4
|
+
* - package manager (package-lock.json / pnpm-lock.yaml / yarn.lock / bun.lockb)
|
|
5
|
+
* - TypeScript (tsconfig.json)
|
|
6
|
+
* - frontend framework (react / vue / svelte / solid)
|
|
7
|
+
* - TanStack Query (package.json dependency)
|
|
8
|
+
* - existing source structure (src/ or lib/)
|
|
9
|
+
*
|
|
10
|
+
* Used by the `client` command to integrate into an existing project
|
|
11
|
+
* rather than assuming it owns the app.
|
|
12
|
+
*/
|
|
13
|
+
export declare function inspectProject(cwd: string): ProjectDetection;
|
|
14
|
+
/**
|
|
15
|
+
* Resolve the effective source directory for generated output:
|
|
16
|
+
* uses the detected src/ (or lib/), otherwise the cwd root.
|
|
17
|
+
*/
|
|
18
|
+
export declare function resolveSourceDir(cwd: string): string;
|
|
19
|
+
//# sourceMappingURL=inspector.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"inspector.d.ts","sourceRoot":"","sources":["../../src/client/inspector.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,WAAW,CAAC;AAElD;;;;;;;;;;GAUG;AACH,wBAAgB,cAAc,CAAC,GAAG,EAAE,MAAM,GAAG,gBAAgB,CAkD5D;AAED;;;GAGG;AACH,wBAAgB,gBAAgB,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAGpD"}
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
import { existsSync, readFileSync } from "node:fs";
|
|
2
|
+
import { join } from "node:path";
|
|
3
|
+
/**
|
|
4
|
+
* Inspect an existing project directory and detect:
|
|
5
|
+
* - package manager (package-lock.json / pnpm-lock.yaml / yarn.lock / bun.lockb)
|
|
6
|
+
* - TypeScript (tsconfig.json)
|
|
7
|
+
* - frontend framework (react / vue / svelte / solid)
|
|
8
|
+
* - TanStack Query (package.json dependency)
|
|
9
|
+
* - existing source structure (src/ or lib/)
|
|
10
|
+
*
|
|
11
|
+
* Used by the `client` command to integrate into an existing project
|
|
12
|
+
* rather than assuming it owns the app.
|
|
13
|
+
*/
|
|
14
|
+
export function inspectProject(cwd) {
|
|
15
|
+
const detection = {
|
|
16
|
+
packageManager: null,
|
|
17
|
+
sourceDir: null,
|
|
18
|
+
framework: null,
|
|
19
|
+
typescript: false,
|
|
20
|
+
tanstackQuery: false,
|
|
21
|
+
};
|
|
22
|
+
// --- package manager (lockfiles) ---
|
|
23
|
+
if (existsSync(join(cwd, "pnpm-lock.yaml")))
|
|
24
|
+
detection.packageManager = "pnpm";
|
|
25
|
+
else if (existsSync(join(cwd, "package-lock.json")))
|
|
26
|
+
detection.packageManager = "npm";
|
|
27
|
+
else if (existsSync(join(cwd, "yarn.lock")))
|
|
28
|
+
detection.packageManager = "yarn";
|
|
29
|
+
else if (existsSync(join(cwd, "bun.lockb")) || existsSync(join(cwd, "bun.lock")))
|
|
30
|
+
detection.packageManager = "bun";
|
|
31
|
+
// --- TypeScript ---
|
|
32
|
+
detection.typescript = existsSync(join(cwd, "tsconfig.json"));
|
|
33
|
+
// --- source structure ---
|
|
34
|
+
if (existsSync(join(cwd, "src")))
|
|
35
|
+
detection.sourceDir = "src";
|
|
36
|
+
else if (existsSync(join(cwd, "lib")))
|
|
37
|
+
detection.sourceDir = "lib";
|
|
38
|
+
// --- framework + TanStack Query from package.json ---
|
|
39
|
+
const pkgPath = join(cwd, "package.json");
|
|
40
|
+
if (existsSync(pkgPath)) {
|
|
41
|
+
try {
|
|
42
|
+
const pkg = JSON.parse(readFileSync(pkgPath, "utf8"));
|
|
43
|
+
const deps = { ...pkg.dependencies, ...pkg.devDependencies };
|
|
44
|
+
for (const [name, framework] of [
|
|
45
|
+
["react", "react"],
|
|
46
|
+
["vue", "vue"],
|
|
47
|
+
["svelte", "svelte"],
|
|
48
|
+
["solid-js", "solid"],
|
|
49
|
+
]) {
|
|
50
|
+
if (deps[name]) {
|
|
51
|
+
detection.framework = framework;
|
|
52
|
+
break;
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
detection.tanstackQuery = !!deps["@tanstack/react-query"];
|
|
56
|
+
}
|
|
57
|
+
catch {
|
|
58
|
+
// unreadable package.json — leave detection at defaults
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
return detection;
|
|
62
|
+
}
|
|
63
|
+
/**
|
|
64
|
+
* Resolve the effective source directory for generated output:
|
|
65
|
+
* uses the detected src/ (or lib/), otherwise the cwd root.
|
|
66
|
+
*/
|
|
67
|
+
export function resolveSourceDir(cwd) {
|
|
68
|
+
const detection = inspectProject(cwd);
|
|
69
|
+
return detection.sourceDir ? join(cwd, detection.sourceDir) : cwd;
|
|
70
|
+
}
|
|
71
|
+
//# sourceMappingURL=inspector.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"inspector.js","sourceRoot":"","sources":["../../src/client/inspector.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AACnD,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAGjC;;;;;;;;;;GAUG;AACH,MAAM,UAAU,cAAc,CAAC,GAAW;IACtC,MAAM,SAAS,GAAqB;QAChC,cAAc,EAAE,IAAI;QACpB,SAAS,EAAE,IAAI;QACf,SAAS,EAAE,IAAI;QACf,UAAU,EAAE,KAAK;QACjB,aAAa,EAAE,KAAK;KACvB,CAAC;IAEF,sCAAsC;IACtC,IAAI,UAAU,CAAC,IAAI,CAAC,GAAG,EAAE,gBAAgB,CAAC,CAAC;QAAE,SAAS,CAAC,cAAc,GAAG,MAAM,CAAC;SAC1E,IAAI,UAAU,CAAC,IAAI,CAAC,GAAG,EAAE,mBAAmB,CAAC,CAAC;QAAE,SAAS,CAAC,cAAc,GAAG,KAAK,CAAC;SACjF,IAAI,UAAU,CAAC,IAAI,CAAC,GAAG,EAAE,WAAW,CAAC,CAAC;QAAE,SAAS,CAAC,cAAc,GAAG,MAAM,CAAC;SAC1E,IAAI,UAAU,CAAC,IAAI,CAAC,GAAG,EAAE,WAAW,CAAC,CAAC,IAAI,UAAU,CAAC,IAAI,CAAC,GAAG,EAAE,UAAU,CAAC,CAAC;QAAE,SAAS,CAAC,cAAc,GAAG,KAAK,CAAC;IAEnH,qBAAqB;IACrB,SAAS,CAAC,UAAU,GAAG,UAAU,CAAC,IAAI,CAAC,GAAG,EAAE,eAAe,CAAC,CAAC,CAAC;IAE9D,2BAA2B;IAC3B,IAAI,UAAU,CAAC,IAAI,CAAC,GAAG,EAAE,KAAK,CAAC,CAAC;QAAE,SAAS,CAAC,SAAS,GAAG,KAAK,CAAC;SACzD,IAAI,UAAU,CAAC,IAAI,CAAC,GAAG,EAAE,KAAK,CAAC,CAAC;QAAE,SAAS,CAAC,SAAS,GAAG,KAAK,CAAC;IAEnE,uDAAuD;IACvD,MAAM,OAAO,GAAG,IAAI,CAAC,GAAG,EAAE,cAAc,CAAC,CAAC;IAC1C,IAAI,UAAU,CAAC,OAAO,CAAC,EAAE,CAAC;QACtB,IAAI,CAAC;YACD,MAAM,GAAG,GAAG,IAAI,CAAC,KAAK,CAAC,YAAY,CAAC,OAAO,EAAE,MAAM,CAAC,CAGnD,CAAC;YACF,MAAM,IAAI,GAAG,EAAE,GAAG,GAAG,CAAC,YAAY,EAAE,GAAG,GAAG,CAAC,eAAe,EAAE,CAAC;YAE7D,KAAK,MAAM,CAAC,IAAI,EAAE,SAAS,CAAC,IAAI;gBAC5B,CAAC,OAAO,EAAE,OAAO,CAAC;gBAClB,CAAC,KAAK,EAAE,KAAK,CAAC;gBACd,CAAC,QAAQ,EAAE,QAAQ,CAAC;gBACpB,CAAC,UAAU,EAAE,OAAO,CAAC;aACf,EAAE,CAAC;gBACT,IAAI,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC;oBACb,SAAS,CAAC,SAAS,GAAG,SAAS,CAAC;oBAChC,MAAM;gBACV,CAAC;YACL,CAAC;YACD,SAAS,CAAC,aAAa,GAAG,CAAC,CAAC,IAAI,CAAC,uBAAuB,CAAC,CAAC;QAC9D,CAAC;QAAC,MAAM,CAAC;YACL,wDAAwD;QAC5D,CAAC;IACL,CAAC;IAED,OAAO,SAAS,CAAC;AACrB,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,gBAAgB,CAAC,GAAW;IACxC,MAAM,SAAS,GAAG,cAAc,CAAC,GAAG,CAAC,CAAC;IACtC,OAAO,SAAS,CAAC,SAAS,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,EAAE,SAAS,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC;AACtE,CAAC"}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import type { ContractOperation, ResourceContract } from "./contract.js";
|
|
2
|
+
/** Load an OpenAPI spec from a file path (local) or a URL. */
|
|
3
|
+
export declare function loadSpec(source: string): Promise<Record<string, unknown>>;
|
|
4
|
+
/**
|
|
5
|
+
* Normalize an OpenAPI 3.0 document into a framework-agnostic ResourceContract.
|
|
6
|
+
*
|
|
7
|
+
* This is the single place where OpenAPI vocabulary leaks into the generator —
|
|
8
|
+
* everything downstream (core + adapters) only sees the contract.
|
|
9
|
+
*/
|
|
10
|
+
export declare function parseContract(spec: Record<string, unknown>): ResourceContract;
|
|
11
|
+
/** Convenience: filter operations by resource (used by adapters). */
|
|
12
|
+
export declare function operationsForResource(contract: ResourceContract, resourceKebab: string): ContractOperation[];
|
|
13
|
+
//# sourceMappingURL=spec.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"spec.d.ts","sourceRoot":"","sources":["../../src/client/spec.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAER,iBAAiB,EAKjB,gBAAgB,EACnB,MAAM,eAAe,CAAC;AAEvB,8DAA8D;AAC9D,wBAAsB,QAAQ,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CAc/E;AAED;;;;;GAKG;AACH,wBAAgB,aAAa,CAAC,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,gBAAgB,CAuE7E;AA6JD,qEAAqE;AACrE,wBAAgB,qBAAqB,CAAC,QAAQ,EAAE,gBAAgB,EAAE,aAAa,EAAE,MAAM,GAAG,iBAAiB,EAAE,CAE5G"}
|
|
@@ -0,0 +1,235 @@
|
|
|
1
|
+
import { existsSync, readFileSync } from "node:fs";
|
|
2
|
+
import { resolve } from "node:path";
|
|
3
|
+
/** Load an OpenAPI spec from a file path (local) or a URL. */
|
|
4
|
+
export async function loadSpec(source) {
|
|
5
|
+
if (/^https?:\/\//.test(source)) {
|
|
6
|
+
const res = await fetch(source);
|
|
7
|
+
if (!res.ok) {
|
|
8
|
+
throw new Error(`Failed to fetch spec from ${source}: HTTP ${res.status}`);
|
|
9
|
+
}
|
|
10
|
+
return (await res.json());
|
|
11
|
+
}
|
|
12
|
+
const filePath = resolve(source);
|
|
13
|
+
if (!existsSync(filePath)) {
|
|
14
|
+
throw new Error(`Spec file not found: ${source}`);
|
|
15
|
+
}
|
|
16
|
+
return JSON.parse(readFileSync(filePath, "utf8"));
|
|
17
|
+
}
|
|
18
|
+
/**
|
|
19
|
+
* Normalize an OpenAPI 3.0 document into a framework-agnostic ResourceContract.
|
|
20
|
+
*
|
|
21
|
+
* This is the single place where OpenAPI vocabulary leaks into the generator —
|
|
22
|
+
* everything downstream (core + adapters) only sees the contract.
|
|
23
|
+
*/
|
|
24
|
+
export function parseContract(spec) {
|
|
25
|
+
const info = (spec.info ?? {});
|
|
26
|
+
const paths = (spec.paths ?? {});
|
|
27
|
+
const components = (spec.components ?? {});
|
|
28
|
+
const schemas = (components.schemas ?? {});
|
|
29
|
+
const operations = [];
|
|
30
|
+
for (const [path, pathItem] of Object.entries(paths)) {
|
|
31
|
+
for (const method of ["get", "post", "put", "patch", "delete"]) {
|
|
32
|
+
const op = pathItem[method];
|
|
33
|
+
if (!op || typeof op !== "object")
|
|
34
|
+
continue;
|
|
35
|
+
const params = [];
|
|
36
|
+
const opParams = (op.parameters ?? []);
|
|
37
|
+
for (const param of opParams) {
|
|
38
|
+
const loc = param.in;
|
|
39
|
+
const name = String(param.name ?? "");
|
|
40
|
+
if (!loc || !name)
|
|
41
|
+
continue;
|
|
42
|
+
const schema = param.schema;
|
|
43
|
+
const schemaType = typeof schema?.type === "string" ? schema.type : undefined;
|
|
44
|
+
params.push({
|
|
45
|
+
name,
|
|
46
|
+
location: loc,
|
|
47
|
+
type: jsonTypeToTs(schemaType),
|
|
48
|
+
required: !!param.required || loc === "path",
|
|
49
|
+
});
|
|
50
|
+
}
|
|
51
|
+
// Request body → schema name
|
|
52
|
+
let requestSchema;
|
|
53
|
+
const requestBody = op.requestBody;
|
|
54
|
+
if (requestBody) {
|
|
55
|
+
const content = requestBody.content;
|
|
56
|
+
const json = content?.["application/json"];
|
|
57
|
+
const schema = json?.schema;
|
|
58
|
+
requestSchema = schema?.$ref
|
|
59
|
+
? String(schema.$ref).replace("#/components/schemas/", "")
|
|
60
|
+
: undefined;
|
|
61
|
+
}
|
|
62
|
+
const { resource, resourceKebab } = resourceFromPath(path);
|
|
63
|
+
const kind = classifyOperation(method, path);
|
|
64
|
+
operations.push({
|
|
65
|
+
method,
|
|
66
|
+
path,
|
|
67
|
+
resource,
|
|
68
|
+
resourceKebab,
|
|
69
|
+
kind,
|
|
70
|
+
isCollection: isCollectionRoot(path),
|
|
71
|
+
params,
|
|
72
|
+
requestSchema,
|
|
73
|
+
returnsList: kind === "list",
|
|
74
|
+
});
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
const contractSchemas = [];
|
|
78
|
+
for (const [name, schema] of Object.entries(schemas)) {
|
|
79
|
+
contractSchemas.push({
|
|
80
|
+
name,
|
|
81
|
+
fields: jsonSchemaToFields(schema, schemas),
|
|
82
|
+
});
|
|
83
|
+
}
|
|
84
|
+
return {
|
|
85
|
+
title: String(info.title ?? "API"),
|
|
86
|
+
version: String(info.version ?? "1.0.0"),
|
|
87
|
+
schemas: contractSchemas,
|
|
88
|
+
operations,
|
|
89
|
+
};
|
|
90
|
+
}
|
|
91
|
+
/** Extract the resource group + singular Pascal type from a path template. */
|
|
92
|
+
function resourceFromPath(path) {
|
|
93
|
+
const segments = path.split("/").filter(Boolean);
|
|
94
|
+
// Group by the FIRST path segment so namespaced routes stay together:
|
|
95
|
+
// /products, /products/{id} → "products"
|
|
96
|
+
// /auth/login, /auth/me → "auth"
|
|
97
|
+
const first = segments[0] ?? "resource";
|
|
98
|
+
const kebab = first.toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-+|-+$/g, "") || "resource";
|
|
99
|
+
// resource = singular Pascal type name ("products" → "Product")
|
|
100
|
+
const singular = singularize(kebab);
|
|
101
|
+
const pascal = singular.split("-").map((s) => s.charAt(0).toUpperCase() + s.slice(1)).join("");
|
|
102
|
+
return { resource: pascal, resourceKebab: kebab };
|
|
103
|
+
}
|
|
104
|
+
/** Best-effort singularization for REST resource names. */
|
|
105
|
+
function singularize(word) {
|
|
106
|
+
if (word.endsWith("ies") && word.length > 3)
|
|
107
|
+
return word.slice(0, -3) + "y";
|
|
108
|
+
if (/(ses|xes|zes|ches|shes)$/.test(word))
|
|
109
|
+
return word.slice(0, -2);
|
|
110
|
+
if (word.endsWith("s") && !word.endsWith("ss"))
|
|
111
|
+
return word.slice(0, -1);
|
|
112
|
+
return word;
|
|
113
|
+
}
|
|
114
|
+
/**
|
|
115
|
+
* A path is a collection ROOT if it has exactly one segment, no param:
|
|
116
|
+
* /products → true (collection resource root)
|
|
117
|
+
* /products/{id} → false (item)
|
|
118
|
+
* /auth/login → false (nested sub-path / action)
|
|
119
|
+
* /admin/users → false (nested resource, treated as an action group)
|
|
120
|
+
*/
|
|
121
|
+
function isCollectionRoot(path) {
|
|
122
|
+
const segments = path.split("/").filter(Boolean);
|
|
123
|
+
return segments.length === 1 && !/\{[^}]+\}/.test(segments[0] ?? "");
|
|
124
|
+
}
|
|
125
|
+
/** A path targets a single item (last segment is a path param). */
|
|
126
|
+
function isItemPath(path) {
|
|
127
|
+
const segments = path.split("/").filter(Boolean);
|
|
128
|
+
return /\{[^}]+\}/.test(segments.at(-1) ?? "");
|
|
129
|
+
}
|
|
130
|
+
/**
|
|
131
|
+
* Classify an operation structurally so the generator only emits methods
|
|
132
|
+
* that actually exist — never invented CRUD.
|
|
133
|
+
*
|
|
134
|
+
* REST shapes are recognised only at a resource ROOT (or its item path):
|
|
135
|
+
* GET /users → list
|
|
136
|
+
* POST /users → create
|
|
137
|
+
* GET /users/{id} → detail
|
|
138
|
+
* PUT /users/{id} → update
|
|
139
|
+
* DELETE /users/{id} → delete
|
|
140
|
+
* Anything nested (e.g. POST /auth/login) is an "action".
|
|
141
|
+
*/
|
|
142
|
+
function classifyOperation(method, path) {
|
|
143
|
+
const root = isCollectionRoot(path);
|
|
144
|
+
const item = isItemPath(path);
|
|
145
|
+
if (root) {
|
|
146
|
+
if (method === "get")
|
|
147
|
+
return "list";
|
|
148
|
+
if (method === "post")
|
|
149
|
+
return "create";
|
|
150
|
+
return "action";
|
|
151
|
+
}
|
|
152
|
+
if (item) {
|
|
153
|
+
if (method === "get")
|
|
154
|
+
return "detail";
|
|
155
|
+
if (method === "put" || method === "patch")
|
|
156
|
+
return "update";
|
|
157
|
+
if (method === "delete")
|
|
158
|
+
return "delete";
|
|
159
|
+
return "action";
|
|
160
|
+
}
|
|
161
|
+
// Nested sub-path → action (e.g. POST /auth/login, GET /auth/me)
|
|
162
|
+
return "action";
|
|
163
|
+
}
|
|
164
|
+
/** Convert a JSON Schema type to a TS type name. */
|
|
165
|
+
function jsonTypeToTs(type) {
|
|
166
|
+
switch (type) {
|
|
167
|
+
case "string": return "string";
|
|
168
|
+
case "number":
|
|
169
|
+
case "integer": return "number";
|
|
170
|
+
case "boolean": return "boolean";
|
|
171
|
+
default: return "unknown";
|
|
172
|
+
}
|
|
173
|
+
}
|
|
174
|
+
/** Convert a JSON Schema object into a flat-ish field list. */
|
|
175
|
+
function jsonSchemaToFields(schema, allSchemas, depth = 0) {
|
|
176
|
+
if (!schema || depth > 6)
|
|
177
|
+
return [];
|
|
178
|
+
if (schema.$ref) {
|
|
179
|
+
const name = String(schema.$ref).replace("#/components/schemas/", "");
|
|
180
|
+
const ref = allSchemas[name];
|
|
181
|
+
if (ref)
|
|
182
|
+
return [{ name: "", type: name, fields: jsonSchemaToFields(ref, allSchemas, depth + 1) }];
|
|
183
|
+
return [{ name: "", type: name }];
|
|
184
|
+
}
|
|
185
|
+
if (schema.allOf && Array.isArray(schema.allOf)) {
|
|
186
|
+
return schema.allOf.flatMap((s) => jsonSchemaToFields(s, allSchemas, depth + 1));
|
|
187
|
+
}
|
|
188
|
+
const props = (schema.properties ?? {});
|
|
189
|
+
const required = (schema.required ?? []);
|
|
190
|
+
return Object.entries(props).map(([name, propSchema]) => {
|
|
191
|
+
const field = jsonPropToField(name, propSchema, required.includes(name), allSchemas, depth + 1);
|
|
192
|
+
return field;
|
|
193
|
+
});
|
|
194
|
+
}
|
|
195
|
+
/** Convert a single property into a ContractField. */
|
|
196
|
+
function jsonPropToField(name, prop, required, allSchemas, depth) {
|
|
197
|
+
const base = { name, type: "unknown", optional: !required };
|
|
198
|
+
if (prop.$ref) {
|
|
199
|
+
const refName = String(prop.$ref).replace("#/components/schemas/", "");
|
|
200
|
+
base.type = refName;
|
|
201
|
+
const ref = allSchemas[refName];
|
|
202
|
+
if (ref)
|
|
203
|
+
base.fields = jsonSchemaToFields(ref, allSchemas, depth);
|
|
204
|
+
return base;
|
|
205
|
+
}
|
|
206
|
+
const type = prop.type;
|
|
207
|
+
if (type === "array") {
|
|
208
|
+
const items = prop.items;
|
|
209
|
+
base.type = "array";
|
|
210
|
+
if (items?.$ref) {
|
|
211
|
+
base.itemType = String(items.$ref).replace("#/components/schemas/", "");
|
|
212
|
+
}
|
|
213
|
+
else if (items?.type === "object" || items?.properties) {
|
|
214
|
+
// Inline object elements (e.g. order line items)
|
|
215
|
+
base.itemType = "object";
|
|
216
|
+
base.itemFields = jsonSchemaToFields(items, allSchemas, depth + 1);
|
|
217
|
+
}
|
|
218
|
+
else if (items) {
|
|
219
|
+
base.itemType = jsonTypeToTs(items.type);
|
|
220
|
+
}
|
|
221
|
+
return base;
|
|
222
|
+
}
|
|
223
|
+
if (type === "object" || prop.properties) {
|
|
224
|
+
base.type = "object";
|
|
225
|
+
base.fields = jsonSchemaToFields(prop, allSchemas, depth + 1);
|
|
226
|
+
return base;
|
|
227
|
+
}
|
|
228
|
+
base.type = jsonTypeToTs(type);
|
|
229
|
+
return base;
|
|
230
|
+
}
|
|
231
|
+
/** Convenience: filter operations by resource (used by adapters). */
|
|
232
|
+
export function operationsForResource(contract, resourceKebab) {
|
|
233
|
+
return contract.operations.filter((op) => op.resourceKebab === resourceKebab);
|
|
234
|
+
}
|
|
235
|
+
//# sourceMappingURL=spec.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"spec.js","sourceRoot":"","sources":["../../src/client/spec.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import type { ClientTarget } from "../core.js";
|
|
2
|
+
/**
|
|
3
|
+
* Target adapter registry.
|
|
4
|
+
*
|
|
5
|
+
* Add a new target by implementing `ClientTarget` and registering it here —
|
|
6
|
+
* no other code changes needed. The core generator and CLI stay agnostic.
|
|
7
|
+
*/
|
|
8
|
+
export declare const targets: Record<string, ClientTarget>;
|
|
9
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/client/targets/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAG/C;;;;;GAKG;AACH,eAAO,MAAM,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,YAAY,CAEhD,CAAC"}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { reactTarget } from "./react.js";
|
|
2
|
+
/**
|
|
3
|
+
* Target adapter registry.
|
|
4
|
+
*
|
|
5
|
+
* Add a new target by implementing `ClientTarget` and registering it here —
|
|
6
|
+
* no other code changes needed. The core generator and CLI stay agnostic.
|
|
7
|
+
*/
|
|
8
|
+
export const targets = {
|
|
9
|
+
react: reactTarget,
|
|
10
|
+
};
|
|
11
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/client/targets/index.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AAEzC;;;;;GAKG;AACH,MAAM,CAAC,MAAM,OAAO,GAAiC;IACjD,KAAK,EAAE,WAAW;CACrB,CAAC"}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import type { ClientTarget } from "../core.js";
|
|
2
|
+
/**
|
|
3
|
+
* React + TanStack Query adapter.
|
|
4
|
+
*
|
|
5
|
+
* Generates, per resource, under `generated/<resource>/`:
|
|
6
|
+
* api.ts — typed fetch client (list/get/create/update/delete)
|
|
7
|
+
* types.ts — request/response TypeScript types
|
|
8
|
+
* schemas.ts — Zod schemas (for runtime validation in the client)
|
|
9
|
+
* queries.ts — TanStack Query hooks (useUsers, useUser, …)
|
|
10
|
+
* mutations.ts — TanStack Query mutations (useCreateUser, …)
|
|
11
|
+
*
|
|
12
|
+
* Optionally (`--examples`) emits example components under
|
|
13
|
+
* `generated/examples/` — clearly labelled as examples, never owned by
|
|
14
|
+
* the framework.
|
|
15
|
+
*
|
|
16
|
+
* This adapter NEVER scaffolds an app: no package.json, no bundler config,
|
|
17
|
+
* no entry points, no routing, no styling system.
|
|
18
|
+
*/
|
|
19
|
+
export declare const reactTarget: ClientTarget;
|
|
20
|
+
//# sourceMappingURL=react.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"react.d.ts","sourceRoot":"","sources":["../../../src/client/targets/react.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAgC,MAAM,YAAY,CAAC;AAgB7E;;;;;;;;;;;;;;;;GAgBG;AACH,eAAO,MAAM,WAAW,EAAE,YA6CzB,CAAC"}
|