@voyantjs/cli 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.
- package/LICENSE +109 -0
- package/README.md +59 -0
- package/bin/voyant.mjs +9 -0
- package/dist/commands/config.d.ts +10 -0
- package/dist/commands/config.d.ts.map +1 -0
- package/dist/commands/config.js +90 -0
- package/dist/commands/db-sync-links.d.ts +19 -0
- package/dist/commands/db-sync-links.d.ts.map +1 -0
- package/dist/commands/db-sync-links.js +250 -0
- package/dist/commands/db.d.ts +18 -0
- package/dist/commands/db.d.ts.map +1 -0
- package/dist/commands/db.js +69 -0
- package/dist/commands/exec.d.ts +20 -0
- package/dist/commands/exec.d.ts.map +1 -0
- package/dist/commands/exec.js +109 -0
- package/dist/commands/generate-link.d.ts +11 -0
- package/dist/commands/generate-link.d.ts.map +1 -0
- package/dist/commands/generate-link.js +64 -0
- package/dist/commands/generate-module.d.ts +13 -0
- package/dist/commands/generate-module.d.ts.map +1 -0
- package/dist/commands/generate-module.js +64 -0
- package/dist/commands/help.d.ts +3 -0
- package/dist/commands/help.d.ts.map +1 -0
- package/dist/commands/help.js +31 -0
- package/dist/commands/new.d.ts +18 -0
- package/dist/commands/new.d.ts.map +1 -0
- package/dist/commands/new.js +317 -0
- package/dist/index.d.ts +16 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +62 -0
- package/dist/lib/args.d.ts +17 -0
- package/dist/lib/args.d.ts.map +1 -0
- package/dist/lib/args.js +32 -0
- package/dist/lib/config-loader.d.ts +45 -0
- package/dist/lib/config-loader.d.ts.map +1 -0
- package/dist/lib/config-loader.js +69 -0
- package/dist/lib/fs.d.ts +5 -0
- package/dist/lib/fs.d.ts.map +1 -0
- package/dist/lib/fs.js +11 -0
- package/dist/lib/strings.d.ts +12 -0
- package/dist/lib/strings.d.ts.map +1 -0
- package/dist/lib/strings.js +33 -0
- package/dist/templates/module-files.d.ts +16 -0
- package/dist/templates/module-files.d.ts.map +1 -0
- package/dist/templates/module-files.js +157 -0
- package/dist/types.d.ts +13 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +1 -0
- package/package.json +77 -0
package/dist/index.js
ADDED
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
import { configCommand } from "./commands/config.js";
|
|
2
|
+
import { dbCommand } from "./commands/db.js";
|
|
3
|
+
import { execCommand } from "./commands/exec.js";
|
|
4
|
+
import { generateLinkCommand } from "./commands/generate-link.js";
|
|
5
|
+
import { generateModuleCommand } from "./commands/generate-module.js";
|
|
6
|
+
import { helpCommand } from "./commands/help.js";
|
|
7
|
+
import { newCommand } from "./commands/new.js";
|
|
8
|
+
/**
|
|
9
|
+
* Entry point for the `voyant` CLI. Dispatches to subcommands.
|
|
10
|
+
*
|
|
11
|
+
* @param argv - arguments following the binary name (i.e. `process.argv.slice(2)`)
|
|
12
|
+
* @param opts - overrides for cwd + stdout/stderr streams (useful in tests)
|
|
13
|
+
* @returns the intended process exit code (0 on success)
|
|
14
|
+
*/
|
|
15
|
+
export async function main(argv, opts = {}) {
|
|
16
|
+
const ctx = {
|
|
17
|
+
argv,
|
|
18
|
+
cwd: opts.cwd ?? process.cwd(),
|
|
19
|
+
stdout: opts.stdout ?? ((chunk) => process.stdout.write(chunk)),
|
|
20
|
+
stderr: opts.stderr ?? ((chunk) => process.stderr.write(chunk)),
|
|
21
|
+
};
|
|
22
|
+
const [head, ...rest] = argv;
|
|
23
|
+
if (!head || head === "--help" || head === "-h" || head === "help") {
|
|
24
|
+
return helpCommand(ctx);
|
|
25
|
+
}
|
|
26
|
+
switch (head) {
|
|
27
|
+
case "generate": {
|
|
28
|
+
const [sub, ...subArgs] = rest;
|
|
29
|
+
const subCtx = { ...ctx, argv: subArgs };
|
|
30
|
+
if (sub === "module")
|
|
31
|
+
return generateModuleCommand(subCtx);
|
|
32
|
+
if (sub === "link")
|
|
33
|
+
return generateLinkCommand(subCtx);
|
|
34
|
+
ctx.stderr(`Unknown generate subcommand: ${sub ?? "(none)"}. ` + `Expected "module" or "link".\n`);
|
|
35
|
+
return 1;
|
|
36
|
+
}
|
|
37
|
+
case "config": {
|
|
38
|
+
return configCommand({ ...ctx, argv: rest });
|
|
39
|
+
}
|
|
40
|
+
case "new": {
|
|
41
|
+
return newCommand({ ...ctx, argv: rest });
|
|
42
|
+
}
|
|
43
|
+
case "exec": {
|
|
44
|
+
return execCommand({ ...ctx, argv: rest });
|
|
45
|
+
}
|
|
46
|
+
case "db": {
|
|
47
|
+
return dbCommand({ ...ctx, argv: rest });
|
|
48
|
+
}
|
|
49
|
+
case "db:generate":
|
|
50
|
+
case "db:migrate":
|
|
51
|
+
case "db:studio":
|
|
52
|
+
case "db:push":
|
|
53
|
+
case "db:check": {
|
|
54
|
+
return dbCommand({ ...ctx, argv: [head.slice(3), ...rest] });
|
|
55
|
+
}
|
|
56
|
+
default: {
|
|
57
|
+
ctx.stderr(`Unknown command: ${head}\n\n`);
|
|
58
|
+
helpCommand(ctx);
|
|
59
|
+
return 1;
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Minimal POSIX-ish argv parser.
|
|
3
|
+
*
|
|
4
|
+
* Recognises:
|
|
5
|
+
* - `--flag` → boolean flag (true)
|
|
6
|
+
* - `--key value` and `--key=value` → string value
|
|
7
|
+
* - `-x` → short boolean flag (true)
|
|
8
|
+
* - Everything else → positional
|
|
9
|
+
*
|
|
10
|
+
* Does not support short-flag clustering (`-xyz`) or numeric coercion.
|
|
11
|
+
*/
|
|
12
|
+
export interface ParsedArgs {
|
|
13
|
+
positionals: string[];
|
|
14
|
+
flags: Record<string, string | boolean>;
|
|
15
|
+
}
|
|
16
|
+
export declare function parseArgs(argv: ReadonlyArray<string>): ParsedArgs;
|
|
17
|
+
//# sourceMappingURL=args.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"args.d.ts","sourceRoot":"","sources":["../../src/lib/args.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AACH,MAAM,WAAW,UAAU;IACzB,WAAW,EAAE,MAAM,EAAE,CAAA;IACrB,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,CAAA;CACxC;AAED,wBAAgB,SAAS,CAAC,IAAI,EAAE,aAAa,CAAC,MAAM,CAAC,GAAG,UAAU,CAkCjE"}
|
package/dist/lib/args.js
ADDED
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
export function parseArgs(argv) {
|
|
2
|
+
const positionals = [];
|
|
3
|
+
const flags = {};
|
|
4
|
+
for (let i = 0; i < argv.length; i++) {
|
|
5
|
+
const token = argv[i];
|
|
6
|
+
if (token === undefined)
|
|
7
|
+
continue;
|
|
8
|
+
if (token.startsWith("--")) {
|
|
9
|
+
const body = token.slice(2);
|
|
10
|
+
const eq = body.indexOf("=");
|
|
11
|
+
if (eq >= 0) {
|
|
12
|
+
flags[body.slice(0, eq)] = body.slice(eq + 1);
|
|
13
|
+
continue;
|
|
14
|
+
}
|
|
15
|
+
const next = argv[i + 1];
|
|
16
|
+
if (next !== undefined && !next.startsWith("-")) {
|
|
17
|
+
flags[body] = next;
|
|
18
|
+
i++;
|
|
19
|
+
}
|
|
20
|
+
else {
|
|
21
|
+
flags[body] = true;
|
|
22
|
+
}
|
|
23
|
+
continue;
|
|
24
|
+
}
|
|
25
|
+
if (token.startsWith("-") && token.length > 1) {
|
|
26
|
+
flags[token.slice(1)] = true;
|
|
27
|
+
continue;
|
|
28
|
+
}
|
|
29
|
+
positionals.push(token);
|
|
30
|
+
}
|
|
31
|
+
return { positionals, flags };
|
|
32
|
+
}
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Supported config file names, in the order we probe them.
|
|
3
|
+
*/
|
|
4
|
+
export declare const CONFIG_FILENAMES: readonly ["voyant.config.ts", "voyant.config.mts", "voyant.config.mjs", "voyant.config.js", "voyant.config.cjs"];
|
|
5
|
+
export interface ResolveConfigOptions {
|
|
6
|
+
/** Explicit path override (accepts absolute or relative-to-cwd). */
|
|
7
|
+
path?: string;
|
|
8
|
+
/** Starting directory; defaults to `process.cwd()`. */
|
|
9
|
+
cwd?: string;
|
|
10
|
+
/**
|
|
11
|
+
* When true (the default), walk parent directories until a config file
|
|
12
|
+
* is found or the filesystem root is reached.
|
|
13
|
+
*/
|
|
14
|
+
walkUp?: boolean;
|
|
15
|
+
}
|
|
16
|
+
/**
|
|
17
|
+
* Locate the nearest voyant.config.* file relative to `cwd` (or a caller-
|
|
18
|
+
* provided absolute path).
|
|
19
|
+
*
|
|
20
|
+
* Returns null when nothing was found — callers decide whether that's an
|
|
21
|
+
* error (e.g. `voyant config` command) or a silent no-op (e.g. `voyant
|
|
22
|
+
* generate module` without a manifest).
|
|
23
|
+
*/
|
|
24
|
+
export declare function resolveConfigPath(opts?: ResolveConfigOptions): string | null;
|
|
25
|
+
/**
|
|
26
|
+
* A loaded voyant config plus the absolute path it came from.
|
|
27
|
+
*/
|
|
28
|
+
export interface LoadedConfig<T = unknown> {
|
|
29
|
+
/** Absolute path to the resolved config file. */
|
|
30
|
+
path: string;
|
|
31
|
+
/** The manifest object exported from the config file. */
|
|
32
|
+
config: T;
|
|
33
|
+
}
|
|
34
|
+
/**
|
|
35
|
+
* Dynamically import a voyant config file and return its default export.
|
|
36
|
+
*
|
|
37
|
+
* The CLI has zero runtime deps, so we rely on the platform:
|
|
38
|
+
* - `.js`, `.mjs`, `.cjs` are dynamic-importable in all Node versions.
|
|
39
|
+
* - `.ts`, `.mts` rely on Node's native TypeScript support
|
|
40
|
+
* (`--experimental-strip-types`, stable in Node 22.6+).
|
|
41
|
+
*
|
|
42
|
+
* Throws if the file cannot be imported or does not have a default export.
|
|
43
|
+
*/
|
|
44
|
+
export declare function loadVoyantConfigFile<T = unknown>(absPath: string): Promise<LoadedConfig<T>>;
|
|
45
|
+
//# sourceMappingURL=config-loader.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"config-loader.d.ts","sourceRoot":"","sources":["../../src/lib/config-loader.ts"],"names":[],"mappings":"AAIA;;GAEG;AACH,eAAO,MAAM,gBAAgB,kHAMnB,CAAA;AAEV,MAAM,WAAW,oBAAoB;IACnC,oEAAoE;IACpE,IAAI,CAAC,EAAE,MAAM,CAAA;IACb,uDAAuD;IACvD,GAAG,CAAC,EAAE,MAAM,CAAA;IACZ;;;OAGG;IACH,MAAM,CAAC,EAAE,OAAO,CAAA;CACjB;AAED;;;;;;;GAOG;AACH,wBAAgB,iBAAiB,CAAC,IAAI,GAAE,oBAAyB,GAAG,MAAM,GAAG,IAAI,CAoBhF;AAED;;GAEG;AACH,MAAM,WAAW,YAAY,CAAC,CAAC,GAAG,OAAO;IACvC,iDAAiD;IACjD,IAAI,EAAE,MAAM,CAAA;IACZ,yDAAyD;IACzD,MAAM,EAAE,CAAC,CAAA;CACV;AAED;;;;;;;;;GASG;AACH,wBAAsB,oBAAoB,CAAC,CAAC,GAAG,OAAO,EAAE,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC,CAkBjG"}
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
import { existsSync } from "node:fs";
|
|
2
|
+
import { dirname, isAbsolute, join, resolve } from "node:path";
|
|
3
|
+
import { pathToFileURL } from "node:url";
|
|
4
|
+
/**
|
|
5
|
+
* Supported config file names, in the order we probe them.
|
|
6
|
+
*/
|
|
7
|
+
export const CONFIG_FILENAMES = [
|
|
8
|
+
"voyant.config.ts",
|
|
9
|
+
"voyant.config.mts",
|
|
10
|
+
"voyant.config.mjs",
|
|
11
|
+
"voyant.config.js",
|
|
12
|
+
"voyant.config.cjs",
|
|
13
|
+
];
|
|
14
|
+
/**
|
|
15
|
+
* Locate the nearest voyant.config.* file relative to `cwd` (or a caller-
|
|
16
|
+
* provided absolute path).
|
|
17
|
+
*
|
|
18
|
+
* Returns null when nothing was found — callers decide whether that's an
|
|
19
|
+
* error (e.g. `voyant config` command) or a silent no-op (e.g. `voyant
|
|
20
|
+
* generate module` without a manifest).
|
|
21
|
+
*/
|
|
22
|
+
export function resolveConfigPath(opts = {}) {
|
|
23
|
+
const cwd = opts.cwd ?? process.cwd();
|
|
24
|
+
if (opts.path) {
|
|
25
|
+
const abs = isAbsolute(opts.path) ? opts.path : resolve(cwd, opts.path);
|
|
26
|
+
return existsSync(abs) ? abs : null;
|
|
27
|
+
}
|
|
28
|
+
const walkUp = opts.walkUp ?? true;
|
|
29
|
+
let current = cwd;
|
|
30
|
+
while (true) {
|
|
31
|
+
for (const name of CONFIG_FILENAMES) {
|
|
32
|
+
const candidate = join(current, name);
|
|
33
|
+
if (existsSync(candidate))
|
|
34
|
+
return candidate;
|
|
35
|
+
}
|
|
36
|
+
if (!walkUp)
|
|
37
|
+
return null;
|
|
38
|
+
const parent = dirname(current);
|
|
39
|
+
if (parent === current)
|
|
40
|
+
return null;
|
|
41
|
+
current = parent;
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
/**
|
|
45
|
+
* Dynamically import a voyant config file and return its default export.
|
|
46
|
+
*
|
|
47
|
+
* The CLI has zero runtime deps, so we rely on the platform:
|
|
48
|
+
* - `.js`, `.mjs`, `.cjs` are dynamic-importable in all Node versions.
|
|
49
|
+
* - `.ts`, `.mts` rely on Node's native TypeScript support
|
|
50
|
+
* (`--experimental-strip-types`, stable in Node 22.6+).
|
|
51
|
+
*
|
|
52
|
+
* Throws if the file cannot be imported or does not have a default export.
|
|
53
|
+
*/
|
|
54
|
+
export async function loadVoyantConfigFile(absPath) {
|
|
55
|
+
const href = pathToFileURL(absPath).href;
|
|
56
|
+
let imported;
|
|
57
|
+
try {
|
|
58
|
+
imported = await import(href);
|
|
59
|
+
}
|
|
60
|
+
catch (err) {
|
|
61
|
+
const reason = err instanceof Error ? err.message : String(err);
|
|
62
|
+
throw new Error(`Failed to load voyant config at ${absPath}: ${reason}`);
|
|
63
|
+
}
|
|
64
|
+
const mod = imported;
|
|
65
|
+
if (mod.default === undefined) {
|
|
66
|
+
throw new Error(`voyant config at ${absPath} has no default export. Export the result of defineVoyantConfig() as the default.`);
|
|
67
|
+
}
|
|
68
|
+
return { path: absPath, config: mod.default };
|
|
69
|
+
}
|
package/dist/lib/fs.d.ts
ADDED
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
/** Write `content` to `path`, creating parent directories as needed. */
|
|
2
|
+
export declare function writeTextFile(path: string, content: string): void;
|
|
3
|
+
/** Return true if `path` exists on disk. */
|
|
4
|
+
export declare function pathExists(path: string): boolean;
|
|
5
|
+
//# sourceMappingURL=fs.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"fs.d.ts","sourceRoot":"","sources":["../../src/lib/fs.ts"],"names":[],"mappings":"AAGA,wEAAwE;AACxE,wBAAgB,aAAa,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,IAAI,CAGjE;AAED,4CAA4C;AAC5C,wBAAgB,UAAU,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAEhD"}
|
package/dist/lib/fs.js
ADDED
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { existsSync, mkdirSync, writeFileSync } from "node:fs";
|
|
2
|
+
import { dirname } from "node:path";
|
|
3
|
+
/** Write `content` to `path`, creating parent directories as needed. */
|
|
4
|
+
export function writeTextFile(path, content) {
|
|
5
|
+
mkdirSync(dirname(path), { recursive: true });
|
|
6
|
+
writeFileSync(path, content, { encoding: "utf8" });
|
|
7
|
+
}
|
|
8
|
+
/** Return true if `path` exists on disk. */
|
|
9
|
+
export function pathExists(path) {
|
|
10
|
+
return existsSync(path);
|
|
11
|
+
}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Normalize a name into kebab-case (lowercase, hyphen-separated).
|
|
3
|
+
*
|
|
4
|
+
* Splits on whitespace, underscores, and camelCase boundaries. Strips
|
|
5
|
+
* characters outside `[a-z0-9-]`.
|
|
6
|
+
*/
|
|
7
|
+
export declare function toKebabCase(input: string): string;
|
|
8
|
+
/** Convert to camelCase (first word lowercase, subsequent words capitalized). */
|
|
9
|
+
export declare function toCamelCase(input: string): string;
|
|
10
|
+
/** Convert to PascalCase (every word capitalized, no separators). */
|
|
11
|
+
export declare function toPascalCase(input: string): string;
|
|
12
|
+
//# sourceMappingURL=strings.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"strings.d.ts","sourceRoot":"","sources":["../../src/lib/strings.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AACH,wBAAgB,WAAW,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CASjD;AAED,iFAAiF;AACjF,wBAAgB,WAAW,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAKjD;AAED,qEAAqE;AACrE,wBAAgB,YAAY,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAElD"}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Normalize a name into kebab-case (lowercase, hyphen-separated).
|
|
3
|
+
*
|
|
4
|
+
* Splits on whitespace, underscores, and camelCase boundaries. Strips
|
|
5
|
+
* characters outside `[a-z0-9-]`.
|
|
6
|
+
*/
|
|
7
|
+
export function toKebabCase(input) {
|
|
8
|
+
return input
|
|
9
|
+
.trim()
|
|
10
|
+
.replace(/([a-z0-9])([A-Z])/g, "$1-$2")
|
|
11
|
+
.replace(/[\s_]+/g, "-")
|
|
12
|
+
.toLowerCase()
|
|
13
|
+
.replace(/[^a-z0-9-]/g, "")
|
|
14
|
+
.replace(/-+/g, "-")
|
|
15
|
+
.replace(/^-|-$/g, "");
|
|
16
|
+
}
|
|
17
|
+
/** Convert to camelCase (first word lowercase, subsequent words capitalized). */
|
|
18
|
+
export function toCamelCase(input) {
|
|
19
|
+
const parts = toKebabCase(input).split("-").filter(Boolean);
|
|
20
|
+
if (parts.length === 0)
|
|
21
|
+
return "";
|
|
22
|
+
const [first, ...rest] = parts;
|
|
23
|
+
return first + rest.map(capitalize).join("");
|
|
24
|
+
}
|
|
25
|
+
/** Convert to PascalCase (every word capitalized, no separators). */
|
|
26
|
+
export function toPascalCase(input) {
|
|
27
|
+
return toKebabCase(input).split("-").filter(Boolean).map(capitalize).join("");
|
|
28
|
+
}
|
|
29
|
+
function capitalize(word) {
|
|
30
|
+
if (word.length === 0)
|
|
31
|
+
return word;
|
|
32
|
+
return word.charAt(0).toUpperCase() + word.slice(1);
|
|
33
|
+
}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
export interface ModuleNames {
|
|
2
|
+
/** Kebab-case name (e.g. "invoices"). Used for directory + package slug. */
|
|
3
|
+
kebab: string;
|
|
4
|
+
/** camelCase name (e.g. "invoices"). Used for variable names. */
|
|
5
|
+
camel: string;
|
|
6
|
+
/** PascalCase name (e.g. "Invoices"). Used for type names + exports. */
|
|
7
|
+
pascal: string;
|
|
8
|
+
}
|
|
9
|
+
export declare function packageJson(names: ModuleNames): string;
|
|
10
|
+
export declare function tsconfigJson(): string;
|
|
11
|
+
export declare function schemaTs(names: ModuleNames): string;
|
|
12
|
+
export declare function validationTs(names: ModuleNames): string;
|
|
13
|
+
export declare function serviceTs(names: ModuleNames): string;
|
|
14
|
+
export declare function routesTs(names: ModuleNames): string;
|
|
15
|
+
export declare function indexTs(names: ModuleNames): string;
|
|
16
|
+
//# sourceMappingURL=module-files.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"module-files.d.ts","sourceRoot":"","sources":["../../src/templates/module-files.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,WAAW;IAC1B,4EAA4E;IAC5E,KAAK,EAAE,MAAM,CAAA;IACb,iEAAiE;IACjE,KAAK,EAAE,MAAM,CAAA;IACb,wEAAwE;IACxE,MAAM,EAAE,MAAM,CAAA;CACf;AAED,wBAAgB,WAAW,CAAC,KAAK,EAAE,WAAW,GAAG,MAAM,CAyDtD;AAED,wBAAgB,YAAY,IAAI,MAAM,CAarC;AAED,wBAAgB,QAAQ,CAAC,KAAK,EAAE,WAAW,GAAG,MAAM,CAenD;AAED,wBAAgB,YAAY,CAAC,KAAK,EAAE,WAAW,GAAG,MAAM,CAiBvD;AAED,wBAAgB,SAAS,CAAC,KAAK,EAAE,WAAW,GAAG,MAAM,CAYpD;AAED,wBAAgB,QAAQ,CAAC,KAAK,EAAE,WAAW,GAAG,MAAM,CAanD;AAED,wBAAgB,OAAO,CAAC,KAAK,EAAE,WAAW,GAAG,MAAM,CAuBlD"}
|
|
@@ -0,0 +1,157 @@
|
|
|
1
|
+
export function packageJson(names) {
|
|
2
|
+
const body = {
|
|
3
|
+
name: `@voyantjs/${names.kebab}`,
|
|
4
|
+
version: "0.1.0",
|
|
5
|
+
type: "module",
|
|
6
|
+
exports: {
|
|
7
|
+
".": "./src/index.ts",
|
|
8
|
+
"./schema": "./src/schema.ts",
|
|
9
|
+
"./validation": "./src/validation.ts",
|
|
10
|
+
"./routes": "./src/routes.ts",
|
|
11
|
+
},
|
|
12
|
+
scripts: {
|
|
13
|
+
build: "tsc -p tsconfig.json",
|
|
14
|
+
clean: "rm -rf dist",
|
|
15
|
+
prepack: "pnpm run build",
|
|
16
|
+
typecheck: "tsc --noEmit",
|
|
17
|
+
lint: "biome check src/",
|
|
18
|
+
test: "vitest run",
|
|
19
|
+
},
|
|
20
|
+
dependencies: {
|
|
21
|
+
"@voyantjs/core": "workspace:*",
|
|
22
|
+
"@voyantjs/db": "workspace:*",
|
|
23
|
+
"@voyantjs/hono": "workspace:*",
|
|
24
|
+
"drizzle-orm": "^0.45.2",
|
|
25
|
+
hono: "^4.12.10",
|
|
26
|
+
zod: "^4.3.6",
|
|
27
|
+
},
|
|
28
|
+
devDependencies: {
|
|
29
|
+
"@voyantjs/voyant-typescript-config": "workspace:*",
|
|
30
|
+
typescript: "^6.0.2",
|
|
31
|
+
},
|
|
32
|
+
files: ["dist"],
|
|
33
|
+
publishConfig: {
|
|
34
|
+
access: "public",
|
|
35
|
+
main: "./dist/index.js",
|
|
36
|
+
types: "./dist/index.d.ts",
|
|
37
|
+
exports: {
|
|
38
|
+
".": {
|
|
39
|
+
types: "./dist/index.d.ts",
|
|
40
|
+
import: "./dist/index.js",
|
|
41
|
+
},
|
|
42
|
+
"./schema": {
|
|
43
|
+
types: "./dist/schema.d.ts",
|
|
44
|
+
import: "./dist/schema.js",
|
|
45
|
+
},
|
|
46
|
+
"./validation": {
|
|
47
|
+
types: "./dist/validation.d.ts",
|
|
48
|
+
import: "./dist/validation.js",
|
|
49
|
+
},
|
|
50
|
+
"./routes": {
|
|
51
|
+
types: "./dist/routes.d.ts",
|
|
52
|
+
import: "./dist/routes.js",
|
|
53
|
+
},
|
|
54
|
+
},
|
|
55
|
+
},
|
|
56
|
+
};
|
|
57
|
+
return `${JSON.stringify(body, null, 2)}\n`;
|
|
58
|
+
}
|
|
59
|
+
export function tsconfigJson() {
|
|
60
|
+
const body = {
|
|
61
|
+
extends: "@voyantjs/voyant-typescript-config/base.json",
|
|
62
|
+
compilerOptions: {
|
|
63
|
+
composite: false,
|
|
64
|
+
outDir: "dist",
|
|
65
|
+
rootDir: ".",
|
|
66
|
+
module: "ESNext",
|
|
67
|
+
moduleResolution: "Bundler",
|
|
68
|
+
},
|
|
69
|
+
include: ["src/**/*", "tests/**/*"],
|
|
70
|
+
};
|
|
71
|
+
return `${JSON.stringify(body, null, 2)}\n`;
|
|
72
|
+
}
|
|
73
|
+
export function schemaTs(names) {
|
|
74
|
+
return `import { typeId } from "@voyantjs/db/lib/typeid-column"
|
|
75
|
+
import { pgTable, text, timestamp } from "drizzle-orm/pg-core"
|
|
76
|
+
|
|
77
|
+
export const ${names.camel} = pgTable("${names.kebab}", {
|
|
78
|
+
id: typeId("${names.camel}"),
|
|
79
|
+
name: text("name").notNull(),
|
|
80
|
+
createdAt: timestamp("created_at", { withTimezone: true }).defaultNow().notNull(),
|
|
81
|
+
updatedAt: timestamp("updated_at", { withTimezone: true }).defaultNow().notNull(),
|
|
82
|
+
deletedAt: timestamp("deleted_at", { withTimezone: true }),
|
|
83
|
+
})
|
|
84
|
+
|
|
85
|
+
export type ${names.pascal} = typeof ${names.camel}.$inferSelect
|
|
86
|
+
export type New${names.pascal} = typeof ${names.camel}.$inferInsert
|
|
87
|
+
`;
|
|
88
|
+
}
|
|
89
|
+
export function validationTs(names) {
|
|
90
|
+
return `import { z } from "zod"
|
|
91
|
+
|
|
92
|
+
export const insert${names.pascal}Schema = z.object({
|
|
93
|
+
name: z.string().min(1),
|
|
94
|
+
})
|
|
95
|
+
|
|
96
|
+
export const update${names.pascal}Schema = insert${names.pascal}Schema.partial()
|
|
97
|
+
|
|
98
|
+
export const list${names.pascal}QuerySchema = z.object({
|
|
99
|
+
limit: z.coerce.number().int().positive().max(200).optional(),
|
|
100
|
+
offset: z.coerce.number().int().nonnegative().optional(),
|
|
101
|
+
})
|
|
102
|
+
|
|
103
|
+
export type Insert${names.pascal}Input = z.infer<typeof insert${names.pascal}Schema>
|
|
104
|
+
export type Update${names.pascal}Input = z.infer<typeof update${names.pascal}Schema>
|
|
105
|
+
`;
|
|
106
|
+
}
|
|
107
|
+
export function serviceTs(names) {
|
|
108
|
+
return `/**
|
|
109
|
+
* Thin service scaffold for the ${names.kebab} module.
|
|
110
|
+
*
|
|
111
|
+
* Replace this with \`createCrudService\` from \`@voyantjs/db/crud\`
|
|
112
|
+
* once your table is finalized, or expand to capture multi-step workflows
|
|
113
|
+
* and cross-module calls.
|
|
114
|
+
*/
|
|
115
|
+
export const ${names.camel}Service = {
|
|
116
|
+
name: "${names.camel}",
|
|
117
|
+
}
|
|
118
|
+
`;
|
|
119
|
+
}
|
|
120
|
+
export function routesTs(names) {
|
|
121
|
+
return `import { Hono } from "hono"
|
|
122
|
+
|
|
123
|
+
/**
|
|
124
|
+
* Admin routes for the ${names.kebab} module. Mounted at
|
|
125
|
+
* \`/v1/admin/${names.kebab}\` by \`createApp\`.
|
|
126
|
+
*/
|
|
127
|
+
export const ${names.camel}Routes = new Hono()
|
|
128
|
+
|
|
129
|
+
${names.camel}Routes.get("/", (c) => c.json({ data: [] }))
|
|
130
|
+
|
|
131
|
+
export type ${names.pascal}Routes = typeof ${names.camel}Routes
|
|
132
|
+
`;
|
|
133
|
+
}
|
|
134
|
+
export function indexTs(names) {
|
|
135
|
+
return `import type { Module } from "@voyantjs/core"
|
|
136
|
+
import type { HonoModule } from "@voyantjs/hono/module"
|
|
137
|
+
|
|
138
|
+
import { ${names.camel}Routes } from "./routes.js"
|
|
139
|
+
|
|
140
|
+
export const ${names.camel}Module: Module = {
|
|
141
|
+
name: "${names.kebab}",
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
export const ${names.camel}HonoModule: HonoModule = {
|
|
145
|
+
module: ${names.camel}Module,
|
|
146
|
+
adminRoutes: ${names.camel}Routes,
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
export type { ${names.pascal}, New${names.pascal} } from "./schema.js"
|
|
150
|
+
export { ${names.camel} } from "./schema.js"
|
|
151
|
+
export {
|
|
152
|
+
insert${names.pascal}Schema,
|
|
153
|
+
list${names.pascal}QuerySchema,
|
|
154
|
+
update${names.pascal}Schema,
|
|
155
|
+
} from "./validation.js"
|
|
156
|
+
`;
|
|
157
|
+
}
|
package/dist/types.d.ts
ADDED
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
export interface CommandContext {
|
|
2
|
+
/** Command-specific argv (already trimmed of parent subcommands). */
|
|
3
|
+
argv: ReadonlyArray<string>;
|
|
4
|
+
/** Working directory the command should use for relative paths. */
|
|
5
|
+
cwd: string;
|
|
6
|
+
/** Write to stdout. Never appends a trailing newline. */
|
|
7
|
+
stdout: (chunk: string) => void;
|
|
8
|
+
/** Write to stderr. Never appends a trailing newline. */
|
|
9
|
+
stderr: (chunk: string) => void;
|
|
10
|
+
}
|
|
11
|
+
/** Exit code. 0 = success, non-zero = failure. */
|
|
12
|
+
export type CommandResult = number;
|
|
13
|
+
//# sourceMappingURL=types.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,cAAc;IAC7B,qEAAqE;IACrE,IAAI,EAAE,aAAa,CAAC,MAAM,CAAC,CAAA;IAC3B,mEAAmE;IACnE,GAAG,EAAE,MAAM,CAAA;IACX,yDAAyD;IACzD,MAAM,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAA;IAC/B,yDAAyD;IACzD,MAAM,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAA;CAChC;AAED,kDAAkD;AAClD,MAAM,MAAM,aAAa,GAAG,MAAM,CAAA"}
|
package/dist/types.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
package/package.json
ADDED
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@voyantjs/cli",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"license": "FSL-1.1-Apache-2.0",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"bin": {
|
|
7
|
+
"voyant": "./bin/voyant.mjs"
|
|
8
|
+
},
|
|
9
|
+
"exports": {
|
|
10
|
+
".": {
|
|
11
|
+
"types": "./dist/index.d.ts",
|
|
12
|
+
"import": "./dist/index.js"
|
|
13
|
+
},
|
|
14
|
+
"./commands/generate-module": {
|
|
15
|
+
"types": "./dist/commands/generate-module.d.ts",
|
|
16
|
+
"import": "./dist/commands/generate-module.js"
|
|
17
|
+
},
|
|
18
|
+
"./commands/generate-link": {
|
|
19
|
+
"types": "./dist/commands/generate-link.d.ts",
|
|
20
|
+
"import": "./dist/commands/generate-link.js"
|
|
21
|
+
},
|
|
22
|
+
"./commands/config": {
|
|
23
|
+
"types": "./dist/commands/config.d.ts",
|
|
24
|
+
"import": "./dist/commands/config.js"
|
|
25
|
+
},
|
|
26
|
+
"./commands/db-sync-links": {
|
|
27
|
+
"types": "./dist/commands/db-sync-links.d.ts",
|
|
28
|
+
"import": "./dist/commands/db-sync-links.js"
|
|
29
|
+
},
|
|
30
|
+
"./commands/exec": {
|
|
31
|
+
"types": "./dist/commands/exec.d.ts",
|
|
32
|
+
"import": "./dist/commands/exec.js"
|
|
33
|
+
},
|
|
34
|
+
"./commands/new": {
|
|
35
|
+
"types": "./dist/commands/new.d.ts",
|
|
36
|
+
"import": "./dist/commands/new.js"
|
|
37
|
+
},
|
|
38
|
+
"./lib/strings": {
|
|
39
|
+
"types": "./dist/lib/strings.d.ts",
|
|
40
|
+
"import": "./dist/lib/strings.js"
|
|
41
|
+
},
|
|
42
|
+
"./lib/args": {
|
|
43
|
+
"types": "./dist/lib/args.d.ts",
|
|
44
|
+
"import": "./dist/lib/args.js"
|
|
45
|
+
},
|
|
46
|
+
"./lib/config-loader": {
|
|
47
|
+
"types": "./dist/lib/config-loader.d.ts",
|
|
48
|
+
"import": "./dist/lib/config-loader.js"
|
|
49
|
+
}
|
|
50
|
+
},
|
|
51
|
+
"files": [
|
|
52
|
+
"bin",
|
|
53
|
+
"dist"
|
|
54
|
+
],
|
|
55
|
+
"dependencies": {
|
|
56
|
+
"tar": "^7.4.3",
|
|
57
|
+
"@voyantjs/core": "0.1.0"
|
|
58
|
+
},
|
|
59
|
+
"devDependencies": {
|
|
60
|
+
"@types/node": "^22.10.1",
|
|
61
|
+
"typescript": "^6.0.2",
|
|
62
|
+
"vitest": "^4.1.2",
|
|
63
|
+
"@voyantjs/voyant-typescript-config": "0.1.0"
|
|
64
|
+
},
|
|
65
|
+
"publishConfig": {
|
|
66
|
+
"access": "public"
|
|
67
|
+
},
|
|
68
|
+
"scripts": {
|
|
69
|
+
"build": "tsc -p tsconfig.build.json",
|
|
70
|
+
"typecheck": "tsc --noEmit",
|
|
71
|
+
"lint": "biome check src/",
|
|
72
|
+
"test": "vitest run",
|
|
73
|
+
"clean": "rm -rf dist"
|
|
74
|
+
},
|
|
75
|
+
"main": "./dist/index.js",
|
|
76
|
+
"types": "./dist/index.d.ts"
|
|
77
|
+
}
|