@vttforge/cli 0.0.0 → 0.5.1
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/CHANGELOG.md +364 -0
- package/LICENSE +21 -0
- package/README.md +33 -5
- package/dist/bin.d.mts +1 -0
- package/dist/bin.mjs +201 -0
- package/dist/bin.mjs.map +1 -0
- package/dist/index.d.mts +496 -0
- package/dist/index.mjs +2 -0
- package/dist/src-CWhUNM__.mjs +2443 -0
- package/dist/src-CWhUNM__.mjs.map +1 -0
- package/package.json +62 -9
- package/templates/module-js/.github/workflows/release.yml +92 -0
- package/templates/module-js/README.md +57 -0
- package/templates/module-js/_gitignore +12 -0
- package/templates/module-js/lang/en.json +11 -0
- package/templates/module-js/module.json +20 -0
- package/templates/module-js/package.json +24 -0
- package/templates/module-js/scripts/main.mjs +65 -0
- package/templates/module-js/styles/main.css +16 -0
- package/templates/module-js/vite.config.mjs +13 -0
- package/templates/module-ts/.github/workflows/release.yml +92 -0
- package/templates/module-ts/README.md +57 -0
- package/templates/module-ts/_gitignore +12 -0
- package/templates/module-ts/lang/en.json +11 -0
- package/templates/module-ts/module.json +20 -0
- package/templates/module-ts/package.json +26 -0
- package/templates/module-ts/scripts/foundry-globals.ts +23 -0
- package/templates/module-ts/scripts/main.ts +71 -0
- package/templates/module-ts/styles/main.css +16 -0
- package/templates/module-ts/tsconfig.json +18 -0
- package/templates/module-ts/vite.config.mjs +13 -0
- package/templates/system-js/.github/workflows/release.yml +92 -0
- package/templates/system-js/README.md +57 -0
- package/templates/system-js/_gitignore +12 -0
- package/templates/system-js/lang/en.json +55 -0
- package/templates/system-js/package.json +25 -0
- package/templates/system-js/scripts/data/character-data.mjs +79 -0
- package/templates/system-js/scripts/data/gear-data.mjs +37 -0
- package/templates/system-js/scripts/main.mjs +79 -0
- package/templates/system-js/scripts/migrations.mjs +43 -0
- package/templates/system-js/scripts/sheets/character-sheet.mjs +164 -0
- package/templates/system-js/scripts/sheets/gear-sheet.mjs +65 -0
- package/templates/system-js/styles/main.css +495 -0
- package/templates/system-js/system.json +44 -0
- package/templates/system-js/template.json +8 -0
- package/templates/system-js/templates/actor/character-sheet.hbs +168 -0
- package/templates/system-js/templates/item/gear-sheet.hbs +54 -0
- package/templates/system-js/vite.config.mjs +16 -0
- package/templates/system-ts/.github/workflows/release.yml +92 -0
- package/templates/system-ts/README.md +57 -0
- package/templates/system-ts/_gitignore +12 -0
- package/templates/system-ts/lang/en.json +55 -0
- package/templates/system-ts/package.json +27 -0
- package/templates/system-ts/scripts/data/character-data.ts +81 -0
- package/templates/system-ts/scripts/data/gear-data.ts +37 -0
- package/templates/system-ts/scripts/foundry-globals.ts +33 -0
- package/templates/system-ts/scripts/main.ts +82 -0
- package/templates/system-ts/scripts/migrations.ts +43 -0
- package/templates/system-ts/scripts/sheets/character-sheet.ts +202 -0
- package/templates/system-ts/scripts/sheets/gear-sheet.ts +68 -0
- package/templates/system-ts/styles/main.css +495 -0
- package/templates/system-ts/system.json +44 -0
- package/templates/system-ts/template.json +8 -0
- package/templates/system-ts/templates/actor/character-sheet.hbs +168 -0
- package/templates/system-ts/templates/item/gear-sheet.hbs +54 -0
- package/templates/system-ts/tsconfig.json +18 -0
- package/templates/system-ts/vite.config.mjs +16 -0
package/dist/index.d.mts
ADDED
|
@@ -0,0 +1,496 @@
|
|
|
1
|
+
import { ChildProcess } from "node:child_process";
|
|
2
|
+
//#region src/audit/types.d.ts
|
|
3
|
+
/**
|
|
4
|
+
* Shared types for the `vttforge audit` rule engine.
|
|
5
|
+
*
|
|
6
|
+
* The audit catalog covers seven v13 footguns from the VTTForge audit
|
|
7
|
+
* spec. Each rule produces zero or more `RuleResult` entries; the
|
|
8
|
+
* orchestrator aggregates them into an `AuditReport` which the reporter
|
|
9
|
+
* renders as JSON or markdown.
|
|
10
|
+
*
|
|
11
|
+
* The CLI never touches the source tree — audit is purely read-only.
|
|
12
|
+
*/
|
|
13
|
+
type Severity = 'HIGH' | 'MEDIUM' | 'LOW';
|
|
14
|
+
interface RuleResult {
|
|
15
|
+
/** Stable identifier — used by users to suppress / pin / look up specific rules. */
|
|
16
|
+
ruleId: string;
|
|
17
|
+
/** Human title. Shown in markdown report headers. */
|
|
18
|
+
title: string;
|
|
19
|
+
severity: Severity;
|
|
20
|
+
/** Absolute or project-relative path of the file the finding refers to. */
|
|
21
|
+
filePath: string;
|
|
22
|
+
/** Optional line number (1-based) inside `filePath`. */
|
|
23
|
+
line?: number;
|
|
24
|
+
/** One-line description of what was found. */
|
|
25
|
+
message: string;
|
|
26
|
+
/** Optional follow-up describing how to fix it. */
|
|
27
|
+
remediation?: string;
|
|
28
|
+
}
|
|
29
|
+
interface AuditReport {
|
|
30
|
+
/** Project root the audit ran against. */
|
|
31
|
+
cwd: string;
|
|
32
|
+
/** ISO timestamp of when the run started. */
|
|
33
|
+
startedAt: string;
|
|
34
|
+
/** Findings, ordered by severity then by ruleId. */
|
|
35
|
+
findings: ReadonlyArray<RuleResult>;
|
|
36
|
+
/** Per-severity tallies, for exit-code logic and report headers. */
|
|
37
|
+
counts: {
|
|
38
|
+
HIGH: number;
|
|
39
|
+
MEDIUM: number;
|
|
40
|
+
LOW: number;
|
|
41
|
+
};
|
|
42
|
+
}
|
|
43
|
+
/** Severity rank for sorting (HIGH first). */
|
|
44
|
+
declare const SEVERITY_RANK: Record<Severity, number>;
|
|
45
|
+
/**
|
|
46
|
+
* A rule is a plain function over the project root. Manifest rules parse
|
|
47
|
+
* `system.json` / `module.json`; source rules walk `scripts/` / `src/`.
|
|
48
|
+
* Rules return their own findings — the orchestrator stitches them
|
|
49
|
+
* together. Pure functions over the filesystem so tests inject tmp dirs.
|
|
50
|
+
*/
|
|
51
|
+
type RuleFn = (cwd: string) => Promise<RuleResult[]> | RuleResult[];
|
|
52
|
+
//#endregion
|
|
53
|
+
//#region src/audit/index.d.ts
|
|
54
|
+
interface RunAuditOptions {
|
|
55
|
+
cwd: string;
|
|
56
|
+
}
|
|
57
|
+
declare function runAudit(options: RunAuditOptions): Promise<AuditReport>;
|
|
58
|
+
//#endregion
|
|
59
|
+
//#region src/audit/manifest-rules.d.ts
|
|
60
|
+
/**
|
|
61
|
+
* Entry point: run every manifest rule against every manifest at the
|
|
62
|
+
* project root.
|
|
63
|
+
*/
|
|
64
|
+
declare function runManifestRules(cwd: string): Promise<RuleResult[]>;
|
|
65
|
+
//#endregion
|
|
66
|
+
//#region src/audit/reporter.d.ts
|
|
67
|
+
type ReportFormat = 'json' | 'markdown';
|
|
68
|
+
declare function formatReport(report: AuditReport, format: ReportFormat): string;
|
|
69
|
+
//#endregion
|
|
70
|
+
//#region src/audit/source-rules.d.ts
|
|
71
|
+
/** Entry point: gather everything once, then dispatch to the per-file rules. */
|
|
72
|
+
declare function runSourceRules(cwd: string): Promise<RuleResult[]>;
|
|
73
|
+
//#endregion
|
|
74
|
+
//#region src/commands/audit.d.ts
|
|
75
|
+
interface AuditOptions {
|
|
76
|
+
/** Project root to scan. Defaults to `process.cwd()`. */
|
|
77
|
+
cwd?: string;
|
|
78
|
+
/** Output format. Default: 'markdown'. */
|
|
79
|
+
format?: ReportFormat;
|
|
80
|
+
/**
|
|
81
|
+
* When true, MEDIUM and LOW findings also trigger a non-zero exit.
|
|
82
|
+
* Default false — HIGH-only is the canonical "block CI" line.
|
|
83
|
+
*/
|
|
84
|
+
strict?: boolean;
|
|
85
|
+
/** Custom writer (tests). Defaults to process.stdout.write. */
|
|
86
|
+
write?: (chunk: string) => void;
|
|
87
|
+
}
|
|
88
|
+
interface AuditResult {
|
|
89
|
+
report: AuditReport;
|
|
90
|
+
/** Suggested exit code under the current strictness setting. */
|
|
91
|
+
exitCode: 0 | 1;
|
|
92
|
+
}
|
|
93
|
+
declare function runAuditCommand(options?: AuditOptions): Promise<AuditResult>;
|
|
94
|
+
//#endregion
|
|
95
|
+
//#region src/manifest.d.ts
|
|
96
|
+
/**
|
|
97
|
+
* Read a built manifest (`dist/system.json` or `dist/module.json`).
|
|
98
|
+
*
|
|
99
|
+
* The vite plugin emits the manifest into `dist/` during build, so the CLI
|
|
100
|
+
* commands that come after a build (dev's initial symlink, build's release
|
|
101
|
+
* zip) read from there rather than walking source. This file is intentionally
|
|
102
|
+
* tiny — we extract just the fields the CLI cares about and surface the
|
|
103
|
+
* rest as `raw` for any consumer that wants more.
|
|
104
|
+
*/
|
|
105
|
+
type PackageType = 'system' | 'module';
|
|
106
|
+
interface FoundryManifest {
|
|
107
|
+
/** Manifest id — folder name Foundry serves the package under. */
|
|
108
|
+
id: string;
|
|
109
|
+
/** Semver-ish version string from the manifest. */
|
|
110
|
+
version: string;
|
|
111
|
+
/** Detected from which filename was present in dist/. */
|
|
112
|
+
type: PackageType;
|
|
113
|
+
/** Full parsed JSON for callers that need extra fields (compatibility, etc.). */
|
|
114
|
+
raw: Record<string, unknown>;
|
|
115
|
+
}
|
|
116
|
+
/**
|
|
117
|
+
* Locate and parse the Foundry manifest inside the given dist directory.
|
|
118
|
+
* Prefers `system.json`, falls back to `module.json` (a single dist can't
|
|
119
|
+
* be both — the vite plugin emits exactly one based on the project type).
|
|
120
|
+
*
|
|
121
|
+
* Throws if neither file exists, required fields are missing/non-string,
|
|
122
|
+
* or the id/version contain characters that would let downstream `join()`
|
|
123
|
+
* calls escape their intended directory.
|
|
124
|
+
*/
|
|
125
|
+
declare function readManifest(distDir: string): Promise<FoundryManifest>;
|
|
126
|
+
//#endregion
|
|
127
|
+
//#region src/commands/build.d.ts
|
|
128
|
+
interface BuildOptions {
|
|
129
|
+
/** Override the project root. Defaults to `process.cwd()`. */
|
|
130
|
+
cwd?: string;
|
|
131
|
+
}
|
|
132
|
+
/**
|
|
133
|
+
* Internal building block exposed for tests: assumes dist/ is already
|
|
134
|
+
* populated (vite has run, manifest is present) and just emits the zip.
|
|
135
|
+
*/
|
|
136
|
+
declare function emitReleaseZip(opts: {
|
|
137
|
+
cwd: string;
|
|
138
|
+
}): Promise<{
|
|
139
|
+
zipFile: string;
|
|
140
|
+
byteSize: number;
|
|
141
|
+
manifest: FoundryManifest;
|
|
142
|
+
}>;
|
|
143
|
+
declare function runBuild(options?: BuildOptions): Promise<void>;
|
|
144
|
+
//#endregion
|
|
145
|
+
//#region src/commands/dev.d.ts
|
|
146
|
+
interface DevOptions {
|
|
147
|
+
/** Override the project root. Defaults to `process.cwd()`. */
|
|
148
|
+
cwd?: string;
|
|
149
|
+
/** `--data-dir` flag value. Skips env/config/prompt lookup when set. */
|
|
150
|
+
dataDir?: string;
|
|
151
|
+
/** Port for the hot reload bridge. */
|
|
152
|
+
hmrPort?: number;
|
|
153
|
+
}
|
|
154
|
+
declare function runDev(options?: DevOptions): Promise<void>;
|
|
155
|
+
/**
|
|
156
|
+
* Internal building block exposed for tests: given an already-built `dist/`
|
|
157
|
+
* (vite has run, manifest is present) and a resolved Foundry data dir,
|
|
158
|
+
* create the symlink and return the target path + manifest. Skips the
|
|
159
|
+
* vite spawn and the signal-loop, so tests can drive the orchestration
|
|
160
|
+
* deterministically.
|
|
161
|
+
*/
|
|
162
|
+
declare function setupDevSymlink(opts: {
|
|
163
|
+
cwd: string;
|
|
164
|
+
dataRoot: string;
|
|
165
|
+
}): Promise<{
|
|
166
|
+
target: string;
|
|
167
|
+
manifest: Awaited<ReturnType<typeof readManifest>>;
|
|
168
|
+
childProcess?: ChildProcess;
|
|
169
|
+
}>;
|
|
170
|
+
/**
|
|
171
|
+
* Tear down a dev symlink iff it still points at the expected source.
|
|
172
|
+
* Refuses to remove a symlink that another `vttforge dev` session (or a
|
|
173
|
+
* manual `ln -s`) has since redirected — that link doesn't belong to us
|
|
174
|
+
* and removing it would silently disconnect their setup.
|
|
175
|
+
*/
|
|
176
|
+
declare function cleanupDevSymlink(opts: {
|
|
177
|
+
target: string;
|
|
178
|
+
expectedSource: string;
|
|
179
|
+
}): Promise<void>;
|
|
180
|
+
//#endregion
|
|
181
|
+
//#region src/commands/init.d.ts
|
|
182
|
+
/**
|
|
183
|
+
* `vttforge init` — interactive scaffolder.
|
|
184
|
+
*
|
|
185
|
+
* Honors CLI flags first, prompts for everything missing, then copies the
|
|
186
|
+
* matching template into the destination directory. Optionally `git init`s
|
|
187
|
+
* and runs the detected package manager's install command at the end.
|
|
188
|
+
*/
|
|
189
|
+
interface InitOptions {
|
|
190
|
+
name?: string;
|
|
191
|
+
type?: 'system' | 'module';
|
|
192
|
+
lang?: 'ts' | 'js';
|
|
193
|
+
/** Manifest id. Defaults to a slug of the directory name. */
|
|
194
|
+
id?: string;
|
|
195
|
+
/** Human-readable title shown in Foundry's setup screens. */
|
|
196
|
+
title?: string;
|
|
197
|
+
/** One-line description for the manifest. */
|
|
198
|
+
description?: string;
|
|
199
|
+
/** Author name for the manifest. Defaults to the local git author. */
|
|
200
|
+
author?: string;
|
|
201
|
+
/** SPDX license id written to package.json. */
|
|
202
|
+
license?: string;
|
|
203
|
+
/**
|
|
204
|
+
* Take the default for anything not supplied instead of asking.
|
|
205
|
+
*
|
|
206
|
+
* Required to scaffold without a terminal — a prompt with nothing to read
|
|
207
|
+
* from waits forever, which is no way to fail.
|
|
208
|
+
*/
|
|
209
|
+
yes?: boolean;
|
|
210
|
+
noInstall?: boolean;
|
|
211
|
+
noGit?: boolean;
|
|
212
|
+
/** Override the working directory (test hook). Defaults to `process.cwd()`. */
|
|
213
|
+
cwd?: string;
|
|
214
|
+
}
|
|
215
|
+
interface ResolvedInitOptions extends Required<Omit<InitOptions, 'cwd' | 'id' | 'title' | 'description' | 'author' | 'license' | 'yes'>> {
|
|
216
|
+
cwd: string;
|
|
217
|
+
dest: string;
|
|
218
|
+
id: string;
|
|
219
|
+
title: string;
|
|
220
|
+
description: string;
|
|
221
|
+
author: string;
|
|
222
|
+
license: string;
|
|
223
|
+
foundryMinVersion: string;
|
|
224
|
+
foundryVerifiedVersion: string;
|
|
225
|
+
templateVariant: TemplateVariant;
|
|
226
|
+
}
|
|
227
|
+
type TemplateVariant = 'system-ts' | 'system-js' | 'module-ts' | 'module-js';
|
|
228
|
+
/**
|
|
229
|
+
* Thrown when the scaffolder cannot continue — bad input, an existing
|
|
230
|
+
* destination, a cancelled prompt, etc. `runInit` propagates these instead
|
|
231
|
+
* of calling `process.exit`, so library consumers (tests, other CLIs) can
|
|
232
|
+
* catch and recover. The `vttforge` bin wraps `runInit` in a top-level
|
|
233
|
+
* handler that prints the message and exits with code 1.
|
|
234
|
+
*/
|
|
235
|
+
declare class ScaffoldError extends Error {
|
|
236
|
+
constructor(message: string);
|
|
237
|
+
}
|
|
238
|
+
declare function runInit(options?: InitOptions): Promise<void>;
|
|
239
|
+
//#endregion
|
|
240
|
+
//#region src/foundry-data-dir.d.ts
|
|
241
|
+
/**
|
|
242
|
+
* Foundry user-data directory discovery + persistence.
|
|
243
|
+
*
|
|
244
|
+
* Foundry stores worlds, systems, and modules under a single user-data
|
|
245
|
+
* directory (`Data/` lives at its root). `vttforge dev` needs to know where
|
|
246
|
+
* that is so it can symlink the built `dist/` into `Data/systems/<id>/` or
|
|
247
|
+
* `Data/modules/<id>/` and let Foundry pick it up.
|
|
248
|
+
*
|
|
249
|
+
* Precedence (top wins):
|
|
250
|
+
* 1. Explicit `--data-dir` flag passed to the command
|
|
251
|
+
* 2. `FOUNDRY_DATA_DIR` env var (useful in Docker/CI)
|
|
252
|
+
* 3. `<project>/.vttforge/config.json :: foundryDataDir`
|
|
253
|
+
* 4. OS default + interactive prompt that saves to (3) for next time
|
|
254
|
+
*
|
|
255
|
+
* The OS-default detection treats `XDG_DATA_HOME` (Linux) and `%LOCALAPPDATA%`
|
|
256
|
+
* (Windows) as part of the OS convention, not as Foundry-specific overrides.
|
|
257
|
+
*
|
|
258
|
+
* Everything here is pure — `platform`, `env`, and `home` flow through
|
|
259
|
+
* options so tests can drive every branch without monkey-patching globals.
|
|
260
|
+
*/
|
|
261
|
+
/** Shape persisted to `<project>/.vttforge/config.json`. */
|
|
262
|
+
interface VTTForgeConfig {
|
|
263
|
+
foundryDataDir?: string;
|
|
264
|
+
}
|
|
265
|
+
/**
|
|
266
|
+
* Return the OS-default Foundry user-data directory, or `null` on unknown
|
|
267
|
+
* platforms / missing platform-specific env vars. Does NOT check existence —
|
|
268
|
+
* callers prompt the user when the suggested path doesn't resolve.
|
|
269
|
+
*/
|
|
270
|
+
declare function autoDetectFoundryDataDir(platform?: NodeJS.Platform, env?: NodeJS.ProcessEnv, home?: string): string | null;
|
|
271
|
+
/**
|
|
272
|
+
* Heuristic: a path looks like a Foundry user-data root if it contains a
|
|
273
|
+
* `Data/` subdirectory (canonical Foundry layout) OR if it already contains
|
|
274
|
+
* `systems/` or `modules/` (the path is already the Data folder itself).
|
|
275
|
+
*/
|
|
276
|
+
declare function looksLikeFoundryDataDir(path: string): boolean;
|
|
277
|
+
/** Absolute path to the project-local config file (whether or not it exists). */
|
|
278
|
+
declare function configPath(cwd: string): string;
|
|
279
|
+
/** Load `<cwd>/.vttforge/config.json` if it exists and is valid JSON. */
|
|
280
|
+
declare function loadConfig(cwd: string): Promise<VTTForgeConfig | null>;
|
|
281
|
+
/** Persist `<cwd>/.vttforge/config.json`. Creates the `.vttforge/` dir as needed. */
|
|
282
|
+
declare function saveConfig(cwd: string, config: VTTForgeConfig): Promise<void>;
|
|
283
|
+
/**
|
|
284
|
+
* Resolve the packages directory (`Data/systems/` or `Data/modules/`) under
|
|
285
|
+
* the given Foundry user-data root. Accepts the path Foundry itself runs
|
|
286
|
+
* with (the user-data folder, which contains `Data/`) OR the `Data/` folder
|
|
287
|
+
* directly — both are common in muscle memory.
|
|
288
|
+
*
|
|
289
|
+
* The returned path is not guaranteed to exist yet; callers `mkdir -p` it
|
|
290
|
+
* before creating the symlink.
|
|
291
|
+
*/
|
|
292
|
+
declare function foundryPackagesDir(dataRoot: string, type: 'system' | 'module'): string;
|
|
293
|
+
interface ResolveDataDirOptions {
|
|
294
|
+
/** Project root — also where `.vttforge/config.json` is read/written. */
|
|
295
|
+
cwd: string;
|
|
296
|
+
/** `--data-dir` flag value. Skips persistence and prompting when present. */
|
|
297
|
+
override?: string;
|
|
298
|
+
/**
|
|
299
|
+
* Interactive prompt for the first run. Receives the OS-default path
|
|
300
|
+
* (may be `null` on unknown platforms) and resolves with the chosen path,
|
|
301
|
+
* or `null` if the user cancelled. When undefined, the function refuses
|
|
302
|
+
* to ask and throws — appropriate for non-TTY contexts (CI, scripts).
|
|
303
|
+
*/
|
|
304
|
+
prompt?: (autoDetected: string | null) => Promise<string | null>;
|
|
305
|
+
/** Override `process.platform` (tests). */
|
|
306
|
+
platform?: NodeJS.Platform;
|
|
307
|
+
/** Override `process.env` (tests). */
|
|
308
|
+
env?: NodeJS.ProcessEnv;
|
|
309
|
+
/** Override `os.homedir()` (tests). */
|
|
310
|
+
home?: string;
|
|
311
|
+
}
|
|
312
|
+
/**
|
|
313
|
+
* Walk the precedence chain and return the chosen Foundry user-data path.
|
|
314
|
+
* Saves the user's choice to the project config on first interactive run so
|
|
315
|
+
* subsequent invocations skip the prompt.
|
|
316
|
+
*/
|
|
317
|
+
declare function resolveFoundryDataDir(opts: ResolveDataDirOptions): Promise<string>;
|
|
318
|
+
//#endregion
|
|
319
|
+
//#region src/package-manager.d.ts
|
|
320
|
+
/**
|
|
321
|
+
* Detect which package manager invoked the CLI so we can run the right
|
|
322
|
+
* `install` command after scaffolding.
|
|
323
|
+
*
|
|
324
|
+
* Strategy: read `npm_config_user_agent`, which pnpm/npm/bun/yarn all set when
|
|
325
|
+
* they spawn a child process (including `pnpm dlx`, `pnpm create`, etc.).
|
|
326
|
+
* Falls back to `pnpm` because that's the VTTForge house default and the
|
|
327
|
+
* most common Foundry-developer choice — but any concrete signal in the
|
|
328
|
+
* environment wins over the default.
|
|
329
|
+
*/
|
|
330
|
+
type PackageManager = 'pnpm' | 'npm' | 'bun' | 'yarn';
|
|
331
|
+
declare function detectPackageManager(env?: NodeJS.ProcessEnv): PackageManager;
|
|
332
|
+
declare function installCommand(pm: PackageManager): string;
|
|
333
|
+
/**
|
|
334
|
+
* Detect a project's package manager by looking at which lockfile it
|
|
335
|
+
* ships. `dev` and `build` need this — by the time the user runs
|
|
336
|
+
* `vttforge dev`, npm_config_user_agent reflects whatever shell launched
|
|
337
|
+
* the binary (often nothing in a global install), not how the project
|
|
338
|
+
* was bootstrapped. The lockfile is the project's own contract.
|
|
339
|
+
*
|
|
340
|
+
* Falls back to {@link detectPackageManager} for fresh checkouts that
|
|
341
|
+
* haven't been installed yet.
|
|
342
|
+
*/
|
|
343
|
+
declare function detectProjectPackageManager(cwd: string, env?: NodeJS.ProcessEnv): PackageManager;
|
|
344
|
+
/**
|
|
345
|
+
* Argument vector to invoke `vite` (or any other locally-installed CLI)
|
|
346
|
+
* via the project's package manager. We always shell out through `<pm>
|
|
347
|
+
* exec` so the call works regardless of the linker's choices — Yarn 4
|
|
348
|
+
* Plug'n'Play, pnpm's symlinked layout, npm's flattened node_modules,
|
|
349
|
+
* Bun's symlinked node_modules. Each manager exposes a uniform "run a
|
|
350
|
+
* locally-resolved binary in the project's dependency graph" command.
|
|
351
|
+
*/
|
|
352
|
+
declare function execInvocation(pm: PackageManager, bin: string): [string, string[]];
|
|
353
|
+
//#endregion
|
|
354
|
+
//#region src/scaffold.d.ts
|
|
355
|
+
/**
|
|
356
|
+
* Template copy with `{{var}}` placeholder substitution.
|
|
357
|
+
*
|
|
358
|
+
* Templates live under `packages/cli/templates/<variant>/` and are shipped
|
|
359
|
+
* inside the published tarball (see the `files` array in package.json).
|
|
360
|
+
* Each file is read, substituted, and written to the destination directory
|
|
361
|
+
* preserving the relative path. Directories are created lazily on first
|
|
362
|
+
* write.
|
|
363
|
+
*
|
|
364
|
+
* We intentionally avoid Handlebars or any other template engine — the
|
|
365
|
+
* substitution surface is small (a flat string-to-string map), and bundling
|
|
366
|
+
* a dependency for ten lines of regex would be wasteful in a tool whose
|
|
367
|
+
* value is being fast to invoke.
|
|
368
|
+
*/
|
|
369
|
+
interface ScaffoldVars {
|
|
370
|
+
ID: string;
|
|
371
|
+
TITLE: string;
|
|
372
|
+
DESCRIPTION: string;
|
|
373
|
+
AUTHOR: string;
|
|
374
|
+
LICENSE: string;
|
|
375
|
+
FOUNDRY_MIN_VERSION: string;
|
|
376
|
+
FOUNDRY_VERIFIED_VERSION: string;
|
|
377
|
+
LOCALE_PREFIX: string;
|
|
378
|
+
YEAR: string;
|
|
379
|
+
}
|
|
380
|
+
interface ScaffoldOptions {
|
|
381
|
+
/** Absolute path to the template root (e.g. `<cli-pkg>/templates/system-ts`). */
|
|
382
|
+
templateDir: string;
|
|
383
|
+
/** Absolute path to the destination directory. Created if it doesn't exist. */
|
|
384
|
+
destDir: string;
|
|
385
|
+
/** Variables to substitute into `{{NAME}}` placeholders inside template files. */
|
|
386
|
+
vars: ScaffoldVars;
|
|
387
|
+
}
|
|
388
|
+
/**
|
|
389
|
+
* Replace `{{NAME}}` placeholders in `content` using the `vars` map.
|
|
390
|
+
* Unknown placeholders are passed through unchanged so partially-templated
|
|
391
|
+
* files (e.g. a snippet that contains `{{handlebarsLikeSyntax}}` as literal
|
|
392
|
+
* content) still scaffold without surprises.
|
|
393
|
+
*/
|
|
394
|
+
declare function substitute(content: string, vars: ScaffoldVars): string;
|
|
395
|
+
declare function scaffold({ templateDir, destDir, vars }: ScaffoldOptions): Promise<void>;
|
|
396
|
+
/**
|
|
397
|
+
* Resolve the templates directory relative to this module's file URL. tsdown
|
|
398
|
+
* emits `dist/scaffold.mjs`, so `import.meta.url` points there at runtime;
|
|
399
|
+
* we walk up two segments to land at the package root, then descend into
|
|
400
|
+
* `templates/`.
|
|
401
|
+
*/
|
|
402
|
+
declare function templatesRoot(): string;
|
|
403
|
+
//#endregion
|
|
404
|
+
//#region src/symlink.d.ts
|
|
405
|
+
/**
|
|
406
|
+
* Cross-platform symlink helpers for `vttforge dev`.
|
|
407
|
+
*
|
|
408
|
+
* The dev loop drops a symlink from Foundry's `Data/<systems|modules>/<id>/`
|
|
409
|
+
* back to the project's `dist/` so Foundry serves freshly-built files as
|
|
410
|
+
* vite writes them. The win32 path matters: with `type: 'junction'` the
|
|
411
|
+
* operation works on standard Windows shells without Developer Mode, while
|
|
412
|
+
* `type: 'dir'` requires admin. We never silently fall back to copying —
|
|
413
|
+
* Foundry's HMR relies on live file mutation, and a copy snapshot defeats
|
|
414
|
+
* the loop. If the symlink fails, we surface the platform-specific fix.
|
|
415
|
+
*/
|
|
416
|
+
interface CreateLinkOptions {
|
|
417
|
+
/**
|
|
418
|
+
* Overwrite an existing symlink that points elsewhere. Real files and
|
|
419
|
+
* directories are never overwritten — that path needs explicit user
|
|
420
|
+
* action outside the tool.
|
|
421
|
+
*/
|
|
422
|
+
overwrite?: boolean;
|
|
423
|
+
}
|
|
424
|
+
/**
|
|
425
|
+
* Read a symlink target. Returns the absolute path the link points at, or
|
|
426
|
+
* `null` if `path` doesn't exist or isn't a symlink. Relative symlink
|
|
427
|
+
* targets are resolved against the link's own directory (matches the
|
|
428
|
+
* semantics callers expect when comparing to a known absolute source).
|
|
429
|
+
*/
|
|
430
|
+
declare function readLinkTarget(path: string): Promise<string | null>;
|
|
431
|
+
/**
|
|
432
|
+
* Create a symlink at `target` pointing to `source`. Win32 uses `'junction'`
|
|
433
|
+
* so the call succeeds without elevation; everywhere else uses `'dir'`.
|
|
434
|
+
*
|
|
435
|
+
* Idempotency:
|
|
436
|
+
* - target already points to source → no-op
|
|
437
|
+
* - target points elsewhere → throws unless `options.overwrite`
|
|
438
|
+
* - target is a real file/dir → throws unconditionally
|
|
439
|
+
*/
|
|
440
|
+
declare function createLink(target: string, source: string, options?: CreateLinkOptions): Promise<void>;
|
|
441
|
+
/**
|
|
442
|
+
* Remove a symlink at `path`. No-ops when the path doesn't exist. Throws
|
|
443
|
+
* when the path exists but isn't a symlink — we never unlink real files
|
|
444
|
+
* or directories.
|
|
445
|
+
*/
|
|
446
|
+
declare function removeLink(path: string): Promise<void>;
|
|
447
|
+
//#endregion
|
|
448
|
+
//#region src/vite-runner.d.ts
|
|
449
|
+
declare class ViteNotInstalledError extends Error {
|
|
450
|
+
constructor(message: string);
|
|
451
|
+
}
|
|
452
|
+
/** Spawn args for invoking the user's vite (e.g. `["pnpm", ["exec", "vite"]]`). */
|
|
453
|
+
declare function resolveViteInvocation(cwd: string): [string, string[]];
|
|
454
|
+
/** Run `vite build` once and wait for it to exit. Throws on non-zero exit. */
|
|
455
|
+
declare function runViteBuildOnce(cwd: string): Promise<void>;
|
|
456
|
+
/**
|
|
457
|
+
* Spawn `vite build --watch` and return the child process. The caller is
|
|
458
|
+
* responsible for waiting on it and tearing it down (the dev command kills
|
|
459
|
+
* it on SIGINT).
|
|
460
|
+
*/
|
|
461
|
+
declare function spawnViteWatch(cwd: string): ChildProcess;
|
|
462
|
+
//#endregion
|
|
463
|
+
//#region src/zip.d.ts
|
|
464
|
+
/**
|
|
465
|
+
* Emit a foundryvtt.com-compatible release zip.
|
|
466
|
+
*
|
|
467
|
+
* foundryvtt.com expects the package contents at the zip root (no wrapper
|
|
468
|
+
* folder), so `unzip release.zip` produces `system.json`, `scripts/`, etc.
|
|
469
|
+
* directly. The vite build output already matches that layout, so we feed
|
|
470
|
+
* `dist/` straight into archiver with `false` as the second arg to disable
|
|
471
|
+
* the wrap-with-source-dir-name default.
|
|
472
|
+
*
|
|
473
|
+
* Optional extras (LICENSE / README / CHANGELOG) ride along when present at
|
|
474
|
+
* the project root and not already inside `dist/`. We never duplicate.
|
|
475
|
+
*/
|
|
476
|
+
interface EmitZipOptions {
|
|
477
|
+
/** Directory whose contents go into the zip at root. */
|
|
478
|
+
sourceDir: string;
|
|
479
|
+
/** Output zip path. Parent directory must exist. */
|
|
480
|
+
outFile: string;
|
|
481
|
+
/** Filenames (relative to extrasFrom) to add at the zip root if present. */
|
|
482
|
+
extras?: string[];
|
|
483
|
+
/** Where to look for `extras`. Required when `extras` is non-empty. */
|
|
484
|
+
extrasFrom?: string;
|
|
485
|
+
}
|
|
486
|
+
interface EmitZipResult {
|
|
487
|
+
outFile: string;
|
|
488
|
+
byteSize: number;
|
|
489
|
+
}
|
|
490
|
+
declare function emitZip(opts: EmitZipOptions): Promise<EmitZipResult>;
|
|
491
|
+
//#endregion
|
|
492
|
+
//#region src/index.d.ts
|
|
493
|
+
declare const VTTFORGE_CLI_VERSION = "0.1.0";
|
|
494
|
+
//#endregion
|
|
495
|
+
export { type AuditOptions, type AuditReport, type AuditResult, type BuildOptions, type CreateLinkOptions, type DevOptions, type EmitZipOptions, type EmitZipResult, type FoundryManifest, type InitOptions, type PackageManager, type PackageType, type ReportFormat, type ResolveDataDirOptions, type ResolvedInitOptions, type RuleFn, type RuleResult, SEVERITY_RANK, ScaffoldError, type ScaffoldOptions, type ScaffoldVars, type Severity, type TemplateVariant, VTTFORGE_CLI_VERSION, type VTTForgeConfig, ViteNotInstalledError, autoDetectFoundryDataDir, cleanupDevSymlink, configPath, createLink, detectPackageManager, detectProjectPackageManager, emitReleaseZip, emitZip, execInvocation, formatReport, foundryPackagesDir, installCommand, loadConfig, looksLikeFoundryDataDir, readLinkTarget, readManifest, removeLink, resolveFoundryDataDir, resolveViteInvocation, runAudit, runAuditCommand, runBuild, runDev, runInit, runManifestRules, runSourceRules, runViteBuildOnce, saveConfig, scaffold, setupDevSymlink, spawnViteWatch, substitute, templatesRoot };
|
|
496
|
+
//# sourceMappingURL=index.d.mts.map
|
package/dist/index.mjs
ADDED
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
import { A as installCommand, C as ViteNotInstalledError, D as detectPackageManager, E as spawnViteWatch, F as SEVERITY_RANK, I as runSourceRules, L as runManifestRules, M as runAuditCommand, N as formatReport, O as detectProjectPackageManager, P as runAudit, S as emitZip, T as runViteBuildOnce, _ as createLink, a as substitute, b as emitReleaseZip, c as runDev, d as configPath, f as foundryPackagesDir, g as saveConfig, h as resolveFoundryDataDir, i as scaffold, j as readManifest, k as execInvocation, l as setupDevSymlink, m as looksLikeFoundryDataDir, n as ScaffoldError, o as templatesRoot, p as loadConfig, r as runInit, s as cleanupDevSymlink, t as VTTFORGE_CLI_VERSION, u as autoDetectFoundryDataDir, v as readLinkTarget, w as resolveViteInvocation, x as runBuild, y as removeLink } from "./src-CWhUNM__.mjs";
|
|
2
|
+
export { SEVERITY_RANK, ScaffoldError, VTTFORGE_CLI_VERSION, ViteNotInstalledError, autoDetectFoundryDataDir, cleanupDevSymlink, configPath, createLink, detectPackageManager, detectProjectPackageManager, emitReleaseZip, emitZip, execInvocation, formatReport, foundryPackagesDir, installCommand, loadConfig, looksLikeFoundryDataDir, readLinkTarget, readManifest, removeLink, resolveFoundryDataDir, resolveViteInvocation, runAudit, runAuditCommand, runBuild, runDev, runInit, runManifestRules, runSourceRules, runViteBuildOnce, saveConfig, scaffold, setupDevSymlink, spawnViteWatch, substitute, templatesRoot };
|