@vutex/vutex 0.0.0 → 0.0.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/bin/vutex.mjs +11 -11
- package/locales/en-US/cli.json +18 -18
- package/locales/locales.json +1 -1
- package/package.json +11 -6
- package/readme.md +18 -18
- package/src/cli/cli.ts +21 -21
- package/src/cli/commands/inspect.ts +33 -33
- package/src/cli/commands/package.ts +99 -99
- package/src/cli/commands/render.ts +38 -38
- package/src/cli/context.ts +27 -27
- package/src/cli/diagnostics.ts +23 -23
- package/src/cli/exit-codes.ts +5 -5
- package/src/cli/main.ts +5 -5
- package/src/index.ts +36 -36
- package/src/node/index.ts +1 -1
- package/src/node/load.ts +50 -50
- package/src/packages/lockfile.ts +35 -35
- package/src/packages/manager.ts +119 -119
- package/src/packages/manifest.ts +28 -28
- package/src/runtime.ts +87 -87
- package/src/types.ts +121 -121
package/src/index.ts
CHANGED
|
@@ -1,36 +1,36 @@
|
|
|
1
|
-
import { loadVuTeXNode } from "./node/load.js";
|
|
2
|
-
import { createVuTeXRuntime } from "./runtime.js";
|
|
3
|
-
import type { CreateVuTeXOptions, VuTeXRuntime } from "./types.js";
|
|
4
|
-
|
|
5
|
-
export type {
|
|
6
|
-
CreateVuTeXOptions,
|
|
7
|
-
FormulaDiagnostic,
|
|
8
|
-
FormulaMetrics,
|
|
9
|
-
FormulaRender,
|
|
10
|
-
FormulaRenderOptions,
|
|
11
|
-
InspectDocumentResult,
|
|
12
|
-
PackageDoctorReport,
|
|
13
|
-
PackageInstallOptions,
|
|
14
|
-
PackageRecord,
|
|
15
|
-
RenderDocumentOptions,
|
|
16
|
-
RenderDocumentResult,
|
|
17
|
-
VuTeXBackend,
|
|
18
|
-
VuTeXBindings,
|
|
19
|
-
VuTeXDiagnostic,
|
|
20
|
-
VuTeXHost,
|
|
21
|
-
VuTeXRuntime,
|
|
22
|
-
} from "./types.js";
|
|
23
|
-
|
|
24
|
-
export { loadVuTeXNode } from "./node/index.js";
|
|
25
|
-
export { createVuTeXRuntime } from "./runtime.js";
|
|
26
|
-
|
|
27
|
-
/** Create a VuTeX runtime for Node hosts (native binding). */
|
|
28
|
-
export async function createVuTeX(options: CreateVuTeXOptions = {}): Promise<VuTeXRuntime> {
|
|
29
|
-
const backend = options.backend ?? "auto";
|
|
30
|
-
const host = options.host ?? "node";
|
|
31
|
-
if (host !== "node" && backend !== "native") {
|
|
32
|
-
throw new Error("createVuTeX scaffold currently supports Node native hosts only");
|
|
33
|
-
}
|
|
34
|
-
const bindings = loadVuTeXNode();
|
|
35
|
-
return createVuTeXRuntime(bindings, options);
|
|
36
|
-
}
|
|
1
|
+
import { loadVuTeXNode } from "./node/load.js";
|
|
2
|
+
import { createVuTeXRuntime } from "./runtime.js";
|
|
3
|
+
import type { CreateVuTeXOptions, VuTeXRuntime } from "./types.js";
|
|
4
|
+
|
|
5
|
+
export type {
|
|
6
|
+
CreateVuTeXOptions,
|
|
7
|
+
FormulaDiagnostic,
|
|
8
|
+
FormulaMetrics,
|
|
9
|
+
FormulaRender,
|
|
10
|
+
FormulaRenderOptions,
|
|
11
|
+
InspectDocumentResult,
|
|
12
|
+
PackageDoctorReport,
|
|
13
|
+
PackageInstallOptions,
|
|
14
|
+
PackageRecord,
|
|
15
|
+
RenderDocumentOptions,
|
|
16
|
+
RenderDocumentResult,
|
|
17
|
+
VuTeXBackend,
|
|
18
|
+
VuTeXBindings,
|
|
19
|
+
VuTeXDiagnostic,
|
|
20
|
+
VuTeXHost,
|
|
21
|
+
VuTeXRuntime,
|
|
22
|
+
} from "./types.js";
|
|
23
|
+
|
|
24
|
+
export { loadVuTeXNode } from "./node/index.js";
|
|
25
|
+
export { createVuTeXRuntime } from "./runtime.js";
|
|
26
|
+
|
|
27
|
+
/** Create a VuTeX runtime for Node hosts (native binding). */
|
|
28
|
+
export async function createVuTeX(options: CreateVuTeXOptions = {}): Promise<VuTeXRuntime> {
|
|
29
|
+
const backend = options.backend ?? "auto";
|
|
30
|
+
const host = options.host ?? "node";
|
|
31
|
+
if (host !== "node" && backend !== "native") {
|
|
32
|
+
throw new Error("createVuTeX scaffold currently supports Node native hosts only");
|
|
33
|
+
}
|
|
34
|
+
const bindings = loadVuTeXNode();
|
|
35
|
+
return createVuTeXRuntime(bindings, options);
|
|
36
|
+
}
|
package/src/node/index.ts
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
export { loadVuTeXNode } from "./load.js";
|
|
1
|
+
export { loadVuTeXNode } from "./load.js";
|
package/src/node/load.ts
CHANGED
|
@@ -1,50 +1,50 @@
|
|
|
1
|
-
import { createRequire } from "node:module";
|
|
2
|
-
|
|
3
|
-
import type { VuTeXBindings } from "../types.js";
|
|
4
|
-
|
|
5
|
-
type NativeBinding = {
|
|
6
|
-
vutexVersion: () => string;
|
|
7
|
-
measureFormula: (source: string, optionsJson?: string) => string;
|
|
8
|
-
renderFormulaSvg: (source: string, optionsJson?: string) => string;
|
|
9
|
-
renderFormulaMathml: (source: string, optionsJson?: string) => string;
|
|
10
|
-
renderFormula: (source: string, optionsJson?: string) => string;
|
|
11
|
-
inspectDocument: (inputPath: string) => {
|
|
12
|
-
inputFormat: string;
|
|
13
|
-
path: string;
|
|
14
|
-
reportJson: string;
|
|
15
|
-
};
|
|
16
|
-
renderDocument: (inputPath: string, optionsJson?: string) => {
|
|
17
|
-
exitCode: number;
|
|
18
|
-
outputFormat: string;
|
|
19
|
-
svg?: string;
|
|
20
|
-
reportJson: string;
|
|
21
|
-
};
|
|
22
|
-
};
|
|
23
|
-
|
|
24
|
-
const PLATFORM_PACKAGES: Record<string, string> = {
|
|
25
|
-
"win32-x64": "@vutex/vutex-win32-x64",
|
|
26
|
-
"linux-x64": "@vutex/vutex-linux-x64",
|
|
27
|
-
"linux-arm64": "@vutex/vutex-linux-arm64",
|
|
28
|
-
"darwin-x64": "@vutex/vutex-darwin-x64",
|
|
29
|
-
"darwin-arm64": "@vutex/vutex-darwin-arm64",
|
|
30
|
-
};
|
|
31
|
-
|
|
32
|
-
/** Load the platform-specific Node-API binary from `@vutex/vutex-<platform>`. */
|
|
33
|
-
export function loadVuTeXNode(): VuTeXBindings {
|
|
34
|
-
const key = `${process.platform}-${process.arch}`;
|
|
35
|
-
const pkg = PLATFORM_PACKAGES[key];
|
|
36
|
-
if (!pkg) {
|
|
37
|
-
throw new Error(`Unsupported platform for VuTeX native bindings: ${key}`);
|
|
38
|
-
}
|
|
39
|
-
const require = createRequire(import.meta.url);
|
|
40
|
-
const binding = require(pkg).default as NativeBinding;
|
|
41
|
-
return {
|
|
42
|
-
vutexVersion: () => binding.vutexVersion(),
|
|
43
|
-
measureFormula: (source, optionsJson) => binding.measureFormula(source, optionsJson),
|
|
44
|
-
renderFormulaSvg: (source, optionsJson) => binding.renderFormulaSvg(source, optionsJson),
|
|
45
|
-
renderFormulaMathml: (source, optionsJson) => binding.renderFormulaMathml(source, optionsJson),
|
|
46
|
-
renderFormula: (source, optionsJson) => binding.renderFormula(source, optionsJson),
|
|
47
|
-
inspectDocument: (inputPath) => binding.inspectDocument(inputPath),
|
|
48
|
-
renderDocument: (inputPath, optionsJson) => binding.renderDocument(inputPath, optionsJson),
|
|
49
|
-
};
|
|
50
|
-
}
|
|
1
|
+
import { createRequire } from "node:module";
|
|
2
|
+
|
|
3
|
+
import type { VuTeXBindings } from "../types.js";
|
|
4
|
+
|
|
5
|
+
type NativeBinding = {
|
|
6
|
+
vutexVersion: () => string;
|
|
7
|
+
measureFormula: (source: string, optionsJson?: string) => string;
|
|
8
|
+
renderFormulaSvg: (source: string, optionsJson?: string) => string;
|
|
9
|
+
renderFormulaMathml: (source: string, optionsJson?: string) => string;
|
|
10
|
+
renderFormula: (source: string, optionsJson?: string) => string;
|
|
11
|
+
inspectDocument: (inputPath: string) => {
|
|
12
|
+
inputFormat: string;
|
|
13
|
+
path: string;
|
|
14
|
+
reportJson: string;
|
|
15
|
+
};
|
|
16
|
+
renderDocument: (inputPath: string, optionsJson?: string) => {
|
|
17
|
+
exitCode: number;
|
|
18
|
+
outputFormat: string;
|
|
19
|
+
svg?: string;
|
|
20
|
+
reportJson: string;
|
|
21
|
+
};
|
|
22
|
+
};
|
|
23
|
+
|
|
24
|
+
const PLATFORM_PACKAGES: Record<string, string> = {
|
|
25
|
+
"win32-x64": "@vutex/vutex-win32-x64",
|
|
26
|
+
"linux-x64": "@vutex/vutex-linux-x64",
|
|
27
|
+
"linux-arm64": "@vutex/vutex-linux-arm64",
|
|
28
|
+
"darwin-x64": "@vutex/vutex-darwin-x64",
|
|
29
|
+
"darwin-arm64": "@vutex/vutex-darwin-arm64",
|
|
30
|
+
};
|
|
31
|
+
|
|
32
|
+
/** Load the platform-specific Node-API binary from `@vutex/vutex-<platform>`. */
|
|
33
|
+
export function loadVuTeXNode(): VuTeXBindings {
|
|
34
|
+
const key = `${process.platform}-${process.arch}`;
|
|
35
|
+
const pkg = PLATFORM_PACKAGES[key];
|
|
36
|
+
if (!pkg) {
|
|
37
|
+
throw new Error(`Unsupported platform for VuTeX native bindings: ${key}`);
|
|
38
|
+
}
|
|
39
|
+
const require = createRequire(import.meta.url);
|
|
40
|
+
const binding = require(pkg).default as NativeBinding;
|
|
41
|
+
return {
|
|
42
|
+
vutexVersion: () => binding.vutexVersion(),
|
|
43
|
+
measureFormula: (source, optionsJson) => binding.measureFormula(source, optionsJson),
|
|
44
|
+
renderFormulaSvg: (source, optionsJson) => binding.renderFormulaSvg(source, optionsJson),
|
|
45
|
+
renderFormulaMathml: (source, optionsJson) => binding.renderFormulaMathml(source, optionsJson),
|
|
46
|
+
renderFormula: (source, optionsJson) => binding.renderFormula(source, optionsJson),
|
|
47
|
+
inspectDocument: (inputPath) => binding.inspectDocument(inputPath),
|
|
48
|
+
renderDocument: (inputPath, optionsJson) => binding.renderDocument(inputPath, optionsJson),
|
|
49
|
+
};
|
|
50
|
+
}
|
package/src/packages/lockfile.ts
CHANGED
|
@@ -1,35 +1,35 @@
|
|
|
1
|
-
import { readFile, writeFile } from "node:fs/promises";
|
|
2
|
-
import { join } from "node:path";
|
|
3
|
-
|
|
4
|
-
import TOML from "@iarna/toml";
|
|
5
|
-
|
|
6
|
-
export type LockedPackage = {
|
|
7
|
-
name: string;
|
|
8
|
-
version: string;
|
|
9
|
-
source: string;
|
|
10
|
-
contentHash: string;
|
|
11
|
-
dependencies: string[];
|
|
12
|
-
};
|
|
13
|
-
|
|
14
|
-
export type VuTeXLockfile = {
|
|
15
|
-
version: number;
|
|
16
|
-
packages: LockedPackage[];
|
|
17
|
-
};
|
|
18
|
-
|
|
19
|
-
export async function readLockfile(projectRoot: string): Promise<VuTeXLockfile | null> {
|
|
20
|
-
const path = join(projectRoot, "vutex.lock");
|
|
21
|
-
try {
|
|
22
|
-
const raw = await readFile(path, "utf8");
|
|
23
|
-
return TOML.parse(raw) as VuTeXLockfile;
|
|
24
|
-
} catch (error) {
|
|
25
|
-
if ((error as NodeJS.ErrnoException).code === "ENOENT") {
|
|
26
|
-
return null;
|
|
27
|
-
}
|
|
28
|
-
throw error;
|
|
29
|
-
}
|
|
30
|
-
}
|
|
31
|
-
|
|
32
|
-
export async function writeLockfile(projectRoot: string, lockfile: VuTeXLockfile): Promise<void> {
|
|
33
|
-
const path = join(projectRoot, "vutex.lock");
|
|
34
|
-
await writeFile(path, `${TOML.stringify(lockfile)}\n`, "utf8");
|
|
35
|
-
}
|
|
1
|
+
import { readFile, writeFile } from "node:fs/promises";
|
|
2
|
+
import { join } from "node:path";
|
|
3
|
+
|
|
4
|
+
import TOML from "@iarna/toml";
|
|
5
|
+
|
|
6
|
+
export type LockedPackage = {
|
|
7
|
+
name: string;
|
|
8
|
+
version: string;
|
|
9
|
+
source: string;
|
|
10
|
+
contentHash: string;
|
|
11
|
+
dependencies: string[];
|
|
12
|
+
};
|
|
13
|
+
|
|
14
|
+
export type VuTeXLockfile = {
|
|
15
|
+
version: number;
|
|
16
|
+
packages: LockedPackage[];
|
|
17
|
+
};
|
|
18
|
+
|
|
19
|
+
export async function readLockfile(projectRoot: string): Promise<VuTeXLockfile | null> {
|
|
20
|
+
const path = join(projectRoot, "vutex.lock");
|
|
21
|
+
try {
|
|
22
|
+
const raw = await readFile(path, "utf8");
|
|
23
|
+
return TOML.parse(raw) as VuTeXLockfile;
|
|
24
|
+
} catch (error) {
|
|
25
|
+
if ((error as NodeJS.ErrnoException).code === "ENOENT") {
|
|
26
|
+
return null;
|
|
27
|
+
}
|
|
28
|
+
throw error;
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
export async function writeLockfile(projectRoot: string, lockfile: VuTeXLockfile): Promise<void> {
|
|
33
|
+
const path = join(projectRoot, "vutex.lock");
|
|
34
|
+
await writeFile(path, `${TOML.stringify(lockfile)}\n`, "utf8");
|
|
35
|
+
}
|
package/src/packages/manager.ts
CHANGED
|
@@ -1,119 +1,119 @@
|
|
|
1
|
-
import { mkdir, writeFile } from "node:fs/promises";
|
|
2
|
-
import { join } from "node:path";
|
|
3
|
-
|
|
4
|
-
import TOML from "@iarna/toml";
|
|
5
|
-
|
|
6
|
-
import type { PackageDoctorReport, PackageInstallOptions, PackageRecord } from "../types.js";
|
|
7
|
-
import { readLockfile, writeLockfile, type LockedPackage } from "./lockfile.js";
|
|
8
|
-
import { readManifest } from "./manifest.js";
|
|
9
|
-
|
|
10
|
-
function hashPlaceholder(name: string, version: string): string {
|
|
11
|
-
return `sha256:scaffold:${name}@${version}`;
|
|
12
|
-
}
|
|
13
|
-
|
|
14
|
-
export class PackageManager {
|
|
15
|
-
constructor(private readonly projectRoot: string) {}
|
|
16
|
-
|
|
17
|
-
async list(): Promise<PackageRecord[]> {
|
|
18
|
-
const lock = await readLockfile(this.projectRoot);
|
|
19
|
-
if (!lock) {
|
|
20
|
-
const manifest = await readManifest(this.projectRoot);
|
|
21
|
-
if (!manifest?.packages) {
|
|
22
|
-
return [];
|
|
23
|
-
}
|
|
24
|
-
return Object.entries(manifest.packages).map(([alias, version]) => ({
|
|
25
|
-
name: alias,
|
|
26
|
-
version,
|
|
27
|
-
source: "manifest",
|
|
28
|
-
}));
|
|
29
|
-
}
|
|
30
|
-
return lock.packages.map((item) => ({
|
|
31
|
-
name: item.name,
|
|
32
|
-
version: item.version,
|
|
33
|
-
source: item.source,
|
|
34
|
-
}));
|
|
35
|
-
}
|
|
36
|
-
|
|
37
|
-
async add(name: string, options: PackageInstallOptions = {}): Promise<void> {
|
|
38
|
-
const manifest = (await readManifest(this.projectRoot)) ?? {};
|
|
39
|
-
const packages = { ...(manifest.packages ?? {}) };
|
|
40
|
-
const alias = name.includes("/") ? name.split("/").pop() ?? name : name;
|
|
41
|
-
packages[alias] = options.version ?? "latest";
|
|
42
|
-
const next = {
|
|
43
|
-
...manifest,
|
|
44
|
-
packages,
|
|
45
|
-
};
|
|
46
|
-
await writeFile(join(this.projectRoot, "vutex.toml"), `${TOML.stringify(next)}\n`, "utf8");
|
|
47
|
-
}
|
|
48
|
-
|
|
49
|
-
async remove(name: string): Promise<void> {
|
|
50
|
-
const manifest = await readManifest(this.projectRoot);
|
|
51
|
-
if (!manifest?.packages) {
|
|
52
|
-
return;
|
|
53
|
-
}
|
|
54
|
-
const packages = { ...manifest.packages };
|
|
55
|
-
delete packages[name];
|
|
56
|
-
const next = { ...manifest, packages };
|
|
57
|
-
await writeFile(join(this.projectRoot, "vutex.toml"), `${TOML.stringify(next)}\n`, "utf8");
|
|
58
|
-
}
|
|
59
|
-
|
|
60
|
-
async install(options: PackageInstallOptions = {}): Promise<void> {
|
|
61
|
-
const manifest = await readManifest(this.projectRoot);
|
|
62
|
-
const cacheDir = join(this.projectRoot, ".vutex", "packages");
|
|
63
|
-
await mkdir(cacheDir, { recursive: true });
|
|
64
|
-
|
|
65
|
-
const entries: LockedPackage[] = [];
|
|
66
|
-
const sourcePackages = manifest?.packages ?? {};
|
|
67
|
-
if (options.name) {
|
|
68
|
-
sourcePackages[options.name] = options.version ?? "latest";
|
|
69
|
-
}
|
|
70
|
-
|
|
71
|
-
for (const [alias, version] of Object.entries(sourcePackages)) {
|
|
72
|
-
entries.push({
|
|
73
|
-
name: alias,
|
|
74
|
-
version,
|
|
75
|
-
source: `@vutex/${alias}`,
|
|
76
|
-
contentHash: hashPlaceholder(alias, version),
|
|
77
|
-
dependencies: [],
|
|
78
|
-
});
|
|
79
|
-
}
|
|
80
|
-
|
|
81
|
-
await writeLockfile(this.projectRoot, {
|
|
82
|
-
version: 1,
|
|
83
|
-
packages: entries,
|
|
84
|
-
});
|
|
85
|
-
}
|
|
86
|
-
|
|
87
|
-
async update(): Promise<void> {
|
|
88
|
-
await this.install();
|
|
89
|
-
}
|
|
90
|
-
|
|
91
|
-
async doctor(): Promise<PackageDoctorReport> {
|
|
92
|
-
const checks: PackageDoctorReport["checks"] = [];
|
|
93
|
-
const manifest = await readManifest(this.projectRoot);
|
|
94
|
-
const lock = await readLockfile(this.projectRoot);
|
|
95
|
-
|
|
96
|
-
checks.push({
|
|
97
|
-
id: "manifest",
|
|
98
|
-
ok: manifest !== null,
|
|
99
|
-
message: manifest ? "vutex.toml present" : "vutex.toml missing (optional for scaffold)",
|
|
100
|
-
});
|
|
101
|
-
|
|
102
|
-
if (manifest?.packages && Object.keys(manifest.packages).length > 0) {
|
|
103
|
-
checks.push({
|
|
104
|
-
id: "lockfile",
|
|
105
|
-
ok: lock !== null && lock.packages.length > 0,
|
|
106
|
-
message: lock ? `vutex.lock tracks ${lock.packages.length} package(s)` : "vutex.lock missing",
|
|
107
|
-
});
|
|
108
|
-
} else {
|
|
109
|
-
checks.push({
|
|
110
|
-
id: "lockfile",
|
|
111
|
-
ok: true,
|
|
112
|
-
message: "no resource packages declared",
|
|
113
|
-
});
|
|
114
|
-
}
|
|
115
|
-
|
|
116
|
-
const ok = checks.every((check) => check.ok);
|
|
117
|
-
return { ok, checks };
|
|
118
|
-
}
|
|
119
|
-
}
|
|
1
|
+
import { mkdir, writeFile } from "node:fs/promises";
|
|
2
|
+
import { join } from "node:path";
|
|
3
|
+
|
|
4
|
+
import TOML from "@iarna/toml";
|
|
5
|
+
|
|
6
|
+
import type { PackageDoctorReport, PackageInstallOptions, PackageRecord } from "../types.js";
|
|
7
|
+
import { readLockfile, writeLockfile, type LockedPackage } from "./lockfile.js";
|
|
8
|
+
import { readManifest } from "./manifest.js";
|
|
9
|
+
|
|
10
|
+
function hashPlaceholder(name: string, version: string): string {
|
|
11
|
+
return `sha256:scaffold:${name}@${version}`;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
export class PackageManager {
|
|
15
|
+
constructor(private readonly projectRoot: string) {}
|
|
16
|
+
|
|
17
|
+
async list(): Promise<PackageRecord[]> {
|
|
18
|
+
const lock = await readLockfile(this.projectRoot);
|
|
19
|
+
if (!lock) {
|
|
20
|
+
const manifest = await readManifest(this.projectRoot);
|
|
21
|
+
if (!manifest?.packages) {
|
|
22
|
+
return [];
|
|
23
|
+
}
|
|
24
|
+
return Object.entries(manifest.packages).map(([alias, version]) => ({
|
|
25
|
+
name: alias,
|
|
26
|
+
version,
|
|
27
|
+
source: "manifest",
|
|
28
|
+
}));
|
|
29
|
+
}
|
|
30
|
+
return lock.packages.map((item) => ({
|
|
31
|
+
name: item.name,
|
|
32
|
+
version: item.version,
|
|
33
|
+
source: item.source,
|
|
34
|
+
}));
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
async add(name: string, options: PackageInstallOptions = {}): Promise<void> {
|
|
38
|
+
const manifest = (await readManifest(this.projectRoot)) ?? {};
|
|
39
|
+
const packages = { ...(manifest.packages ?? {}) };
|
|
40
|
+
const alias = name.includes("/") ? name.split("/").pop() ?? name : name;
|
|
41
|
+
packages[alias] = options.version ?? "latest";
|
|
42
|
+
const next = {
|
|
43
|
+
...manifest,
|
|
44
|
+
packages,
|
|
45
|
+
};
|
|
46
|
+
await writeFile(join(this.projectRoot, "vutex.toml"), `${TOML.stringify(next)}\n`, "utf8");
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
async remove(name: string): Promise<void> {
|
|
50
|
+
const manifest = await readManifest(this.projectRoot);
|
|
51
|
+
if (!manifest?.packages) {
|
|
52
|
+
return;
|
|
53
|
+
}
|
|
54
|
+
const packages = { ...manifest.packages };
|
|
55
|
+
delete packages[name];
|
|
56
|
+
const next = { ...manifest, packages };
|
|
57
|
+
await writeFile(join(this.projectRoot, "vutex.toml"), `${TOML.stringify(next)}\n`, "utf8");
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
async install(options: PackageInstallOptions = {}): Promise<void> {
|
|
61
|
+
const manifest = await readManifest(this.projectRoot);
|
|
62
|
+
const cacheDir = join(this.projectRoot, ".vutex", "packages");
|
|
63
|
+
await mkdir(cacheDir, { recursive: true });
|
|
64
|
+
|
|
65
|
+
const entries: LockedPackage[] = [];
|
|
66
|
+
const sourcePackages = manifest?.packages ?? {};
|
|
67
|
+
if (options.name) {
|
|
68
|
+
sourcePackages[options.name] = options.version ?? "latest";
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
for (const [alias, version] of Object.entries(sourcePackages)) {
|
|
72
|
+
entries.push({
|
|
73
|
+
name: alias,
|
|
74
|
+
version,
|
|
75
|
+
source: `@vutex/${alias}`,
|
|
76
|
+
contentHash: hashPlaceholder(alias, version),
|
|
77
|
+
dependencies: [],
|
|
78
|
+
});
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
await writeLockfile(this.projectRoot, {
|
|
82
|
+
version: 1,
|
|
83
|
+
packages: entries,
|
|
84
|
+
});
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
async update(): Promise<void> {
|
|
88
|
+
await this.install();
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
async doctor(): Promise<PackageDoctorReport> {
|
|
92
|
+
const checks: PackageDoctorReport["checks"] = [];
|
|
93
|
+
const manifest = await readManifest(this.projectRoot);
|
|
94
|
+
const lock = await readLockfile(this.projectRoot);
|
|
95
|
+
|
|
96
|
+
checks.push({
|
|
97
|
+
id: "manifest",
|
|
98
|
+
ok: manifest !== null,
|
|
99
|
+
message: manifest ? "vutex.toml present" : "vutex.toml missing (optional for scaffold)",
|
|
100
|
+
});
|
|
101
|
+
|
|
102
|
+
if (manifest?.packages && Object.keys(manifest.packages).length > 0) {
|
|
103
|
+
checks.push({
|
|
104
|
+
id: "lockfile",
|
|
105
|
+
ok: lock !== null && lock.packages.length > 0,
|
|
106
|
+
message: lock ? `vutex.lock tracks ${lock.packages.length} package(s)` : "vutex.lock missing",
|
|
107
|
+
});
|
|
108
|
+
} else {
|
|
109
|
+
checks.push({
|
|
110
|
+
id: "lockfile",
|
|
111
|
+
ok: true,
|
|
112
|
+
message: "no resource packages declared",
|
|
113
|
+
});
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
const ok = checks.every((check) => check.ok);
|
|
117
|
+
return { ok, checks };
|
|
118
|
+
}
|
|
119
|
+
}
|
package/src/packages/manifest.ts
CHANGED
|
@@ -1,28 +1,28 @@
|
|
|
1
|
-
import { readFile } from "node:fs/promises";
|
|
2
|
-
import { join } from "node:path";
|
|
3
|
-
|
|
4
|
-
import TOML from "@iarna/toml";
|
|
5
|
-
|
|
6
|
-
export type VuTeXManifest = {
|
|
7
|
-
document?: {
|
|
8
|
-
input?: string;
|
|
9
|
-
output?: string;
|
|
10
|
-
};
|
|
11
|
-
profile?: {
|
|
12
|
-
name?: string;
|
|
13
|
-
};
|
|
14
|
-
packages?: Record<string, string>;
|
|
15
|
-
};
|
|
16
|
-
|
|
17
|
-
export async function readManifest(projectRoot: string): Promise<VuTeXManifest | null> {
|
|
18
|
-
const path = join(projectRoot, "vutex.toml");
|
|
19
|
-
try {
|
|
20
|
-
const raw = await readFile(path, "utf8");
|
|
21
|
-
return TOML.parse(raw) as VuTeXManifest;
|
|
22
|
-
} catch (error) {
|
|
23
|
-
if ((error as NodeJS.ErrnoException).code === "ENOENT") {
|
|
24
|
-
return null;
|
|
25
|
-
}
|
|
26
|
-
throw error;
|
|
27
|
-
}
|
|
28
|
-
}
|
|
1
|
+
import { readFile } from "node:fs/promises";
|
|
2
|
+
import { join } from "node:path";
|
|
3
|
+
|
|
4
|
+
import TOML from "@iarna/toml";
|
|
5
|
+
|
|
6
|
+
export type VuTeXManifest = {
|
|
7
|
+
document?: {
|
|
8
|
+
input?: string;
|
|
9
|
+
output?: string;
|
|
10
|
+
};
|
|
11
|
+
profile?: {
|
|
12
|
+
name?: string;
|
|
13
|
+
};
|
|
14
|
+
packages?: Record<string, string>;
|
|
15
|
+
};
|
|
16
|
+
|
|
17
|
+
export async function readManifest(projectRoot: string): Promise<VuTeXManifest | null> {
|
|
18
|
+
const path = join(projectRoot, "vutex.toml");
|
|
19
|
+
try {
|
|
20
|
+
const raw = await readFile(path, "utf8");
|
|
21
|
+
return TOML.parse(raw) as VuTeXManifest;
|
|
22
|
+
} catch (error) {
|
|
23
|
+
if ((error as NodeJS.ErrnoException).code === "ENOENT") {
|
|
24
|
+
return null;
|
|
25
|
+
}
|
|
26
|
+
throw error;
|
|
27
|
+
}
|
|
28
|
+
}
|