@topik/cli 0.1.0-alpha.5 → 0.1.0-alpha.7
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.mjs +60 -145
- package/package.json +9 -9
package/dist/cli.mjs
CHANGED
|
@@ -3,14 +3,12 @@ import { boolean, command, positional, run, string } from "@drizzle-team/brocli"
|
|
|
3
3
|
import { createHash, randomUUID } from "node:crypto";
|
|
4
4
|
import { closeSync, constants, fstatSync, lstatSync, openSync, readFileSync, readdirSync, renameSync, rmdirSync, unlinkSync } from "node:fs";
|
|
5
5
|
import { lstat, mkdir, mkdtemp, open, readFile, readdir, realpath, stat } from "node:fs/promises";
|
|
6
|
-
import { basename, dirname, extname, isAbsolute, join,
|
|
7
|
-
import {
|
|
8
|
-
import { sanitizeTopikContentDiagnostic } from "@topik/content
|
|
9
|
-
import { execFile } from "node:child_process";
|
|
10
|
-
import { promisify } from "node:util";
|
|
6
|
+
import { basename, dirname, extname, isAbsolute, join, relative, resolve } from "node:path";
|
|
7
|
+
import { ManifestSourceError, PublicCompileError, TOPIK_PREVIEW_PROTOCOL, compile, isErrorDiagnostic, lint, parseStrictTopikJson, publicCompileErrorMessage, serializeTopikJson, validateResources, validateTopikMaterializationRecord, watch } from "@topik/core";
|
|
8
|
+
import { sanitizeTopikContentDiagnostic } from "@topik/content";
|
|
11
9
|
import { createServer } from "node:http";
|
|
12
10
|
import { parseAllDocuments } from "yaml";
|
|
13
|
-
|
|
11
|
+
// src/diagnostics.ts
|
|
14
12
|
function formatDiagnostic(diagnostic) {
|
|
15
13
|
const sanitized = sanitizeTopikContentDiagnostic(diagnostic);
|
|
16
14
|
return `${sanitized.file ?? "content"}${sanitized.lines.length > 0 ? `:${sanitized.lines.join(",")}` : ""} ${sanitized.level} ${sanitized.id}: ${sanitized.message}`;
|
|
@@ -22,8 +20,7 @@ function printDiagnostics(diagnostics) {
|
|
|
22
20
|
else console.warn(output);
|
|
23
21
|
}
|
|
24
22
|
}
|
|
25
|
-
|
|
26
|
-
//#region src/errors.ts
|
|
23
|
+
// src/errors.ts
|
|
27
24
|
var CliError = class extends Error {
|
|
28
25
|
constructor(message, options) {
|
|
29
26
|
super(message, options);
|
|
@@ -32,6 +29,7 @@ var CliError = class extends Error {
|
|
|
32
29
|
};
|
|
33
30
|
const PUBLIC_CLI_ERROR_MESSAGES = Object.freeze({
|
|
34
31
|
"browser-origin-invalid": "Browser origin configuration is invalid",
|
|
32
|
+
"compilation-publication-failed": "Compilation output publication failed after moving the existing output aside. For manual recovery, first stop concurrent writers, then inspect .topik-compilation-prior-* directories beside the output path. Verify the backup contents and do not overwrite an existing output path.",
|
|
35
33
|
"resource-access-failed": "Resource input could not be accessed.",
|
|
36
34
|
"resource-format-unsupported": "Resource input format is unsupported.",
|
|
37
35
|
"resource-json-invalid": "JSON resource input could not be parsed.",
|
|
@@ -43,8 +41,8 @@ const PUBLIC_CLI_ERROR_MESSAGES = Object.freeze({
|
|
|
43
41
|
/** CLI failure admitted to presentation only through fixed catalog wording. */
|
|
44
42
|
var PublicCliError = class extends CliError {
|
|
45
43
|
id;
|
|
46
|
-
constructor(id) {
|
|
47
|
-
super(publicCliErrorMessage(id) ?? "Topik command failed.");
|
|
44
|
+
constructor(id, options) {
|
|
45
|
+
super(publicCliErrorMessage(id) ?? "Topik command failed.", options);
|
|
48
46
|
this.name = "PublicCliError";
|
|
49
47
|
this.id = id;
|
|
50
48
|
}
|
|
@@ -54,93 +52,22 @@ function publicCliErrorMessage(id) {
|
|
|
54
52
|
}
|
|
55
53
|
function formatPublicCliError(error) {
|
|
56
54
|
if (error instanceof PublicCliError) return publicCliErrorMessage(error.id) ?? "Topik command failed.";
|
|
55
|
+
if (error instanceof ManifestSourceError) {
|
|
56
|
+
const message = publicCompileErrorMessage(error.id) ?? "Topik command failed.";
|
|
57
|
+
const location = new PublicCompileError(error.id, error.location).location;
|
|
58
|
+
return `.topik.yaml ${Number.isSafeInteger(error.sourceIndex) && error.sourceIndex >= 0 ? `sources[${error.sourceIndex}]` : "source"}${error.kind === "wiki" || error.kind === "collection" || error.kind === "course" ? ` (${error.kind})` : ""}${location ? ` ${location}` : ""}: ${message}`;
|
|
59
|
+
}
|
|
57
60
|
if (error instanceof PublicCompileError) return publicCompileErrorMessage(error.id) ?? "Topik command failed.";
|
|
58
61
|
return "Topik command failed.";
|
|
59
62
|
}
|
|
60
|
-
|
|
61
|
-
//#region src/validation-output.ts
|
|
63
|
+
// src/validation-output.ts
|
|
62
64
|
function formatValidationFailure(errors, resourceCount, context) {
|
|
63
65
|
const lines = errors.map((error) => `${error.resource}: ${error.path} ${error.message}`);
|
|
64
66
|
lines.push("");
|
|
65
67
|
lines.push(`${errors.length} validation error(s) in ${resourceCount} resources while ${context}`);
|
|
66
68
|
return lines.join("\n");
|
|
67
69
|
}
|
|
68
|
-
|
|
69
|
-
//#region src/source-namespace.ts
|
|
70
|
-
const execFileAsync = promisify(execFile);
|
|
71
|
-
function requiresSourceNamespace(error) {
|
|
72
|
-
return error instanceof AssetCompilationError && error.diagnostics.some((diagnostic) => diagnostic.id === "TOPIK_ASSET_SOURCE_NAMESPACE_REQUIRED");
|
|
73
|
-
}
|
|
74
|
-
function sourceNamespaceOptions(value) {
|
|
75
|
-
if (value === void 0) return void 0;
|
|
76
|
-
const validation = validateStableSourceNamespace(value);
|
|
77
|
-
if (!validation.ok) throw new CliError("--source-namespace must be normalized portable text");
|
|
78
|
-
return { sourceNamespace: validation.value };
|
|
79
|
-
}
|
|
80
|
-
/** Derive only after automatic discovery proves that an Asset needs a namespace. */
|
|
81
|
-
async function deriveGitSourceNamespace(dir) {
|
|
82
|
-
let worktree;
|
|
83
|
-
let remotes;
|
|
84
|
-
try {
|
|
85
|
-
worktree = (await git(dir, ["rev-parse", "--show-toplevel"])).trim();
|
|
86
|
-
remotes = (await git(dir, ["remote"])).split(/\r?\n/u).filter(Boolean).sort();
|
|
87
|
-
} catch {
|
|
88
|
-
throw namespaceRequired();
|
|
89
|
-
}
|
|
90
|
-
const remoteName = remotes.includes("origin") ? "origin" : remotes.length === 1 ? remotes[0] : void 0;
|
|
91
|
-
if (remoteName === void 0) throw namespaceRequired();
|
|
92
|
-
let remote;
|
|
93
|
-
try {
|
|
94
|
-
remote = (await git(dir, [
|
|
95
|
-
"remote",
|
|
96
|
-
"get-url",
|
|
97
|
-
remoteName
|
|
98
|
-
])).trim();
|
|
99
|
-
} catch {
|
|
100
|
-
throw namespaceRequired();
|
|
101
|
-
}
|
|
102
|
-
const identity = normalizeRemote(remote);
|
|
103
|
-
if (identity === void 0) throw namespaceRequired();
|
|
104
|
-
const rootRelative = relative(resolve(worktree), resolve(dir)).split(sep).join(posix.sep);
|
|
105
|
-
if (rootRelative.startsWith("../") || rootRelative === "..") throw namespaceRequired();
|
|
106
|
-
const namespace = `topik-git-v1:${identity}#${rootRelative || "."}`;
|
|
107
|
-
const validation = validateStableSourceNamespace(namespace);
|
|
108
|
-
if (!validation.ok) throw namespaceRequired();
|
|
109
|
-
return validation.value;
|
|
110
|
-
}
|
|
111
|
-
function normalizeRemote(value) {
|
|
112
|
-
const scp = value.includes("://") ? null : /^(?:[^@/:]+@)?([^/:]+):(.+)$/u.exec(value);
|
|
113
|
-
const candidate = scp !== null ? `ssh://${scp[1]}/${scp[2]}` : value;
|
|
114
|
-
let url;
|
|
115
|
-
try {
|
|
116
|
-
url = new URL(candidate);
|
|
117
|
-
} catch {
|
|
118
|
-
return;
|
|
119
|
-
}
|
|
120
|
-
if (url.protocol !== "https:" && url.protocol !== "ssh:" && url.protocol !== "git:") return void 0;
|
|
121
|
-
if (url.hostname.length === 0 || url.password !== "" || url.protocol === "https:" && url.username !== "" || url.search || url.hash) return;
|
|
122
|
-
const path = url.pathname.replace(/^\/+|\/+$/gu, "").replace(/\.git$/u, "");
|
|
123
|
-
if (path.length === 0 || path.split("/").some((part) => part.length === 0 || part === "." || part === "..")) return;
|
|
124
|
-
const port = url.port && !(url.protocol === "https:" && url.port === "443" || url.protocol === "ssh:" && url.port === "22") ? `:${url.port}` : "";
|
|
125
|
-
return `${url.hostname.toLowerCase()}${port}/${path}`;
|
|
126
|
-
}
|
|
127
|
-
async function git(dir, args) {
|
|
128
|
-
const { stdout } = await execFileAsync("git", [
|
|
129
|
-
"-C",
|
|
130
|
-
dir,
|
|
131
|
-
...args
|
|
132
|
-
], {
|
|
133
|
-
encoding: "utf8",
|
|
134
|
-
timeout: 1e4,
|
|
135
|
-
windowsHide: true
|
|
136
|
-
});
|
|
137
|
-
return stdout;
|
|
138
|
-
}
|
|
139
|
-
function namespaceRequired() {
|
|
140
|
-
return new CliError("Automatic local Assets require --source-namespace because no stable Git remote identity could be derived");
|
|
141
|
-
}
|
|
142
|
-
//#endregion
|
|
143
|
-
//#region src/compile/index.ts
|
|
70
|
+
// src/compile/index.ts
|
|
144
71
|
const COMPILATION_GENERATION_PREFIX = ".topik-compilation-generation-";
|
|
145
72
|
const COMPILATION_PRIOR_PREFIX = ".topik-compilation-prior-";
|
|
146
73
|
const COMPILATION_DIRECTORIES = ["blobs", "resources"];
|
|
@@ -148,38 +75,24 @@ const ownedDescriptorDecoder = new TextDecoder("utf-8", { fatal: true });
|
|
|
148
75
|
const ownedDescriptorEncoder = new TextEncoder();
|
|
149
76
|
const compile$1 = command({
|
|
150
77
|
name: "compile",
|
|
151
|
-
desc: "Compile
|
|
78
|
+
desc: "Compile project content into Topik resource files",
|
|
152
79
|
options: {
|
|
153
|
-
dir: positional("dir").desc("
|
|
80
|
+
dir: positional("dir").desc("Project directory containing .topik.yaml").default("."),
|
|
154
81
|
outDir: string("out-dir").alias("o").desc("Output directory for compiled resources"),
|
|
155
82
|
format: string("format").alias("f").desc("Output format (canonical JSON only)").enum("json").default("json"),
|
|
156
83
|
dryRun: boolean("dry-run").desc("Show what would be compiled without writing files").default(false),
|
|
157
84
|
validate: boolean("validate").desc("Validate compiled resources against schemas").default(false),
|
|
158
|
-
links: string("links").desc("How unresolved wiki links and local guide fragments are handled").enum("error", "warning", "off").default("error")
|
|
159
|
-
sourceNamespace: string("source-namespace").desc("Stable source namespace for automatically discovered local Assets (derived from Git when omitted)")
|
|
85
|
+
links: string("links").desc("How unresolved wiki links and local guide fragments are handled").enum("error", "warning", "off").default("error")
|
|
160
86
|
},
|
|
161
87
|
handler: async (options) => {
|
|
162
88
|
const dir = resolve(options.dir);
|
|
163
89
|
const links = options.links;
|
|
164
90
|
const outDir = options.outDir ? resolve(options.outDir) : join(dir, ".topik");
|
|
165
91
|
await assertCompilationOutputScope(dir, outDir);
|
|
166
|
-
const
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
dir,
|
|
171
|
-
validation: { links },
|
|
172
|
-
assets: assetOptions
|
|
173
|
-
});
|
|
174
|
-
} catch (error) {
|
|
175
|
-
if (assetOptions !== void 0 || !requiresSourceNamespace(error)) throw error;
|
|
176
|
-
result = await compile({
|
|
177
|
-
dir,
|
|
178
|
-
validation: { links },
|
|
179
|
-
assets: { sourceNamespace: await deriveGitSourceNamespace(dir) }
|
|
180
|
-
});
|
|
181
|
-
}
|
|
182
|
-
const { diagnostics, materialization, payloads, resources, semantic } = result;
|
|
92
|
+
const { diagnostics, materialization, payloads, resources, semantic } = await compile({
|
|
93
|
+
dir,
|
|
94
|
+
validation: { links }
|
|
95
|
+
});
|
|
183
96
|
printDiagnostics(diagnostics);
|
|
184
97
|
if (options.validate) {
|
|
185
98
|
const { valid, errors } = validateResources(resources);
|
|
@@ -260,13 +173,14 @@ async function replaceCompilationTree(absolutePath, files) {
|
|
|
260
173
|
} catch (error) {
|
|
261
174
|
operationError = error;
|
|
262
175
|
}
|
|
176
|
+
if (!published && existing !== void 0 && existing.name !== target) operationError = new PublicCliError("compilation-publication-failed", { cause: operationError });
|
|
263
177
|
if (generation !== void 0 && !published) try {
|
|
264
178
|
generation.tree = bindCompleteCompilationTreeSync(generation.handle);
|
|
265
179
|
cleanupCompilationDirectory(parent, generation);
|
|
266
180
|
} catch (error) {
|
|
267
181
|
operationError ??= error;
|
|
268
182
|
}
|
|
269
|
-
if (existing !== void 0 && !existingRemoved && existing.name !== target) try {
|
|
183
|
+
if (published && existing !== void 0 && !existingRemoved && existing.name !== target) try {
|
|
270
184
|
cleanupCompilationDirectory(parent, existing);
|
|
271
185
|
} catch (error) {
|
|
272
186
|
operationError ??= error;
|
|
@@ -623,8 +537,9 @@ function procFd(fd) {
|
|
|
623
537
|
function procFdChild(fd, component) {
|
|
624
538
|
return `${procFd(fd)}/${component}`;
|
|
625
539
|
}
|
|
626
|
-
|
|
627
|
-
|
|
540
|
+
// package.json
|
|
541
|
+
var version = "0.1.0-alpha.7";
|
|
542
|
+
// src/dev/index.ts
|
|
628
543
|
const DEV_HOST = "127.0.0.1";
|
|
629
544
|
const DEFAULT_ALLOWED_ORIGIN = "https://write.subtopik.com";
|
|
630
545
|
const REQUEST_VARY_HEADERS = "Origin, Sec-Fetch-Site";
|
|
@@ -634,12 +549,10 @@ function sendSSE(res, event, data) {
|
|
|
634
549
|
function handleResources(watcher, res, corsHeaders) {
|
|
635
550
|
res.writeHead(200, {
|
|
636
551
|
"Content-Type": "application/json",
|
|
552
|
+
"Cache-Control": "no-store",
|
|
637
553
|
...corsHeaders
|
|
638
554
|
});
|
|
639
|
-
res.end(JSON.stringify(
|
|
640
|
-
resources: [...watcher.resources.values()],
|
|
641
|
-
payloads: [...watcher.payloads.values()].map(({ bytes: _bytes, ...payload }) => payload)
|
|
642
|
-
}));
|
|
555
|
+
res.end(JSON.stringify(watcher.state));
|
|
643
556
|
}
|
|
644
557
|
function handleEvents(watcher, res, corsHeaders) {
|
|
645
558
|
res.writeHead(200, {
|
|
@@ -648,6 +561,9 @@ function handleEvents(watcher, res, corsHeaders) {
|
|
|
648
561
|
Connection: "keep-alive",
|
|
649
562
|
...corsHeaders
|
|
650
563
|
});
|
|
564
|
+
sendSSE(res, "preview-state", watcher.state);
|
|
565
|
+
const onState = (state) => sendSSE(res, "preview-state", state);
|
|
566
|
+
watcher.on("preview-state", onState);
|
|
651
567
|
sendSSE(res, "sync", {
|
|
652
568
|
resources: Object.fromEntries(watcher.resources),
|
|
653
569
|
payloads: Object.fromEntries([...watcher.payloads].map(([path, { bytes: _bytes, ...payload }]) => [path, payload]))
|
|
@@ -661,6 +577,7 @@ function handleEvents(watcher, res, corsHeaders) {
|
|
|
661
577
|
watcher.on("update", onUpdate);
|
|
662
578
|
res.on("close", () => {
|
|
663
579
|
watcher.off("update", onUpdate);
|
|
580
|
+
watcher.off("preview-state", onState);
|
|
664
581
|
});
|
|
665
582
|
}
|
|
666
583
|
function handleAssetPayload(watcher, rawPathname, method, res, corsHeaders) {
|
|
@@ -770,9 +687,15 @@ function createRequestHandler(watcher, getPort, allowedOrigin) {
|
|
|
770
687
|
if (req.method === "GET" && url.pathname === "/health") {
|
|
771
688
|
res.writeHead(200, {
|
|
772
689
|
"Content-Type": "application/json",
|
|
690
|
+
"Cache-Control": "no-store",
|
|
773
691
|
...corsHeaders
|
|
774
692
|
});
|
|
775
|
-
res.end(JSON.stringify({
|
|
693
|
+
res.end(JSON.stringify({
|
|
694
|
+
status: "ok",
|
|
695
|
+
version,
|
|
696
|
+
capabilities: [TOPIK_PREVIEW_PROTOCOL],
|
|
697
|
+
sessionId: watcher.state.sessionId
|
|
698
|
+
}));
|
|
776
699
|
return;
|
|
777
700
|
}
|
|
778
701
|
if (req.method === "GET" && url.pathname === "/resources") {
|
|
@@ -783,6 +706,16 @@ function createRequestHandler(watcher, getPort, allowedOrigin) {
|
|
|
783
706
|
handleEvents(watcher, res, corsHeaders);
|
|
784
707
|
return;
|
|
785
708
|
}
|
|
709
|
+
if (url.pathname.startsWith("/blobs/") && (url.searchParams.has("sessionId") || url.searchParams.has("generation"))) {
|
|
710
|
+
if (url.searchParams.getAll("sessionId").length !== 1 || url.searchParams.getAll("generation").length !== 1 || url.searchParams.get("sessionId") !== watcher.state.sessionId || url.searchParams.get("generation") !== String(watcher.state.generation)) {
|
|
711
|
+
res.writeHead(409, {
|
|
712
|
+
...corsHeaders,
|
|
713
|
+
"Cache-Control": "no-store"
|
|
714
|
+
});
|
|
715
|
+
res.end();
|
|
716
|
+
return;
|
|
717
|
+
}
|
|
718
|
+
}
|
|
786
719
|
const queryOffset = requestTarget.indexOf("?");
|
|
787
720
|
const rawPathname = queryOffset === -1 ? requestTarget : requestTarget.slice(0, queryOffset);
|
|
788
721
|
if ((req.method === "GET" || req.method === "HEAD") && handleAssetPayload(watcher, rawPathname, req.method, res, corsHeaders)) return;
|
|
@@ -798,21 +731,9 @@ async function startDevServer(options) {
|
|
|
798
731
|
const dir = resolve(options.dir);
|
|
799
732
|
const allowedOrigin = normalizeAllowedOrigin(options.allowOrigin ?? DEFAULT_ALLOWED_ORIGIN);
|
|
800
733
|
console.log("Watching content for changes...");
|
|
801
|
-
const
|
|
802
|
-
|
|
803
|
-
|
|
804
|
-
watcher = await watch({
|
|
805
|
-
dir,
|
|
806
|
-
assets: assetOptions
|
|
807
|
-
});
|
|
808
|
-
} catch (error) {
|
|
809
|
-
if (assetOptions !== void 0 || !requiresSourceNamespace(error)) throw error;
|
|
810
|
-
watcher = await watch({
|
|
811
|
-
dir,
|
|
812
|
-
assets: { sourceNamespace: await deriveGitSourceNamespace(dir) }
|
|
813
|
-
});
|
|
814
|
-
}
|
|
815
|
-
console.log(`Compiled ${watcher.resources.size} resources`);
|
|
734
|
+
const watcher = await watch({ dir });
|
|
735
|
+
if (watcher.state.status === "error") console.error("Compile error:", watcher.state.diagnostics.map((diagnostic) => diagnostic.message).join(" "));
|
|
736
|
+
else console.log(`Compiled ${watcher.resources.size} resources`);
|
|
816
737
|
watcher.on("error", (error) => {
|
|
817
738
|
console.error("Compile error:", formatPublicCliError(error));
|
|
818
739
|
});
|
|
@@ -871,17 +792,15 @@ const dev = command({
|
|
|
871
792
|
name: "dev",
|
|
872
793
|
desc: "Start a development server that watches for content changes",
|
|
873
794
|
options: {
|
|
874
|
-
dir: positional("dir").desc("
|
|
795
|
+
dir: positional("dir").desc("Project directory containing .topik.yaml").default("."),
|
|
875
796
|
port: string("port").alias("p").desc("Port to listen on").default("50001"),
|
|
876
|
-
allowOrigin: string("allow-origin").desc(`Browser origin allowed to connect (default: ${DEFAULT_ALLOWED_ORIGIN})`)
|
|
877
|
-
sourceNamespace: string("source-namespace").desc("Stable source namespace for automatically discovered local Assets (derived from Git when omitted)")
|
|
797
|
+
allowOrigin: string("allow-origin").desc(`Browser origin allowed to connect (default: ${DEFAULT_ALLOWED_ORIGIN})`)
|
|
878
798
|
},
|
|
879
799
|
handler: async (options) => {
|
|
880
800
|
const runningServer = await startDevServer({
|
|
881
801
|
dir: resolve(options.dir),
|
|
882
802
|
port: parseInt(options.port, 10),
|
|
883
|
-
allowOrigin: options.allowOrigin
|
|
884
|
-
sourceNamespace: options.sourceNamespace
|
|
803
|
+
allowOrigin: options.allowOrigin
|
|
885
804
|
});
|
|
886
805
|
console.log(`Dev server listening on http://localhost:${runningServer.port}`);
|
|
887
806
|
process.once("SIGINT", async () => {
|
|
@@ -890,13 +809,12 @@ const dev = command({
|
|
|
890
809
|
});
|
|
891
810
|
}
|
|
892
811
|
});
|
|
893
|
-
|
|
894
|
-
//#region src/lint/index.ts
|
|
812
|
+
// src/lint/index.ts
|
|
895
813
|
const lint$1 = command({
|
|
896
814
|
name: "lint",
|
|
897
815
|
desc: "Lint Topik source content without writing compiled resources",
|
|
898
816
|
options: {
|
|
899
|
-
dir: positional("dir").desc("
|
|
817
|
+
dir: positional("dir").desc("Project directory containing .topik.yaml").default("."),
|
|
900
818
|
links: string("links").desc("How unresolved wiki links and local guide fragments are handled").enum("error", "warning", "off").default("error")
|
|
901
819
|
},
|
|
902
820
|
handler: async (options) => {
|
|
@@ -912,8 +830,7 @@ const lint$1 = command({
|
|
|
912
830
|
console.log(`Lint passed${warnings > 0 ? ` with ${warnings} warning(s)` : ""}`);
|
|
913
831
|
}
|
|
914
832
|
});
|
|
915
|
-
|
|
916
|
-
//#region src/validate/index.ts
|
|
833
|
+
// src/validate/index.ts
|
|
917
834
|
function parseJson(content) {
|
|
918
835
|
try {
|
|
919
836
|
return JSON.parse(content);
|
|
@@ -983,8 +900,7 @@ const validate = command({
|
|
|
983
900
|
else throw new PublicCliError("resource-validation-failed");
|
|
984
901
|
}
|
|
985
902
|
});
|
|
986
|
-
|
|
987
|
-
//#region src/cli.ts
|
|
903
|
+
// src/cli.ts
|
|
988
904
|
try {
|
|
989
905
|
await run([
|
|
990
906
|
compile$1,
|
|
@@ -999,5 +915,4 @@ try {
|
|
|
999
915
|
console.error(formatPublicCliError(error));
|
|
1000
916
|
process.exitCode = 1;
|
|
1001
917
|
}
|
|
1002
|
-
//#endregion
|
|
1003
918
|
export {};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@topik/cli",
|
|
3
|
-
"version": "0.1.0-alpha.
|
|
3
|
+
"version": "0.1.0-alpha.7",
|
|
4
4
|
"description": "Topik CLI",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"repository": {
|
|
@@ -23,17 +23,17 @@
|
|
|
23
23
|
"access": "public"
|
|
24
24
|
},
|
|
25
25
|
"dependencies": {
|
|
26
|
-
"@drizzle-team/brocli": "^0.12.
|
|
27
|
-
"
|
|
28
|
-
"@topik/
|
|
29
|
-
"
|
|
26
|
+
"@drizzle-team/brocli": "^0.12.1",
|
|
27
|
+
"@topik/content": "0.1.0-alpha.7",
|
|
28
|
+
"@topik/core": "0.1.0-alpha.7",
|
|
29
|
+
"yaml": "^2.9.1"
|
|
30
30
|
},
|
|
31
31
|
"devDependencies": {
|
|
32
|
-
"@types/bun": "^1.
|
|
33
|
-
"@types/node": "22.20.
|
|
32
|
+
"@types/bun": "^1.4.4",
|
|
33
|
+
"@types/node": "22.20.5",
|
|
34
34
|
"typescript": "^7.0.2",
|
|
35
|
-
"vite": "npm:@voidzero-dev/vite-plus-core@
|
|
36
|
-
"vite-plus": "
|
|
35
|
+
"vite": "npm:@voidzero-dev/vite-plus-core@1.4.0",
|
|
36
|
+
"vite-plus": "1.4.0"
|
|
37
37
|
},
|
|
38
38
|
"scripts": {
|
|
39
39
|
"build": "vp pack",
|