@moewolf/moe-icons-cli 0.0.1 → 0.0.3
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/README.md +249 -10
- package/bin/check-node.cjs +36 -0
- package/bin/moeicons.js +12 -1
- package/dist/api/client.d.ts +13 -2
- package/dist/api/client.js +145 -21
- package/dist/auth/device-login.d.ts +10 -7
- package/dist/auth/device-login.js +60 -37
- package/dist/auth/login-schemas.d.ts +24 -0
- package/dist/auth/login-schemas.js +67 -0
- package/dist/catalog/catalog.d.ts +11 -0
- package/dist/catalog/catalog.js +43 -0
- package/dist/catalog/catalog.json +12768 -3965
- package/dist/cli.d.ts +11 -2
- package/dist/cli.js +773 -147
- package/dist/commands/parser.d.ts +13 -2
- package/dist/commands/parser.js +138 -50
- package/dist/config-package/generated/SOURCE.json +25 -0
- package/dist/config-package/generated/moeicons-config.schema.json +191 -0
- package/dist/config-package/generated/moeicons.config.jsonc +42 -0
- package/dist/config-package/generated/render-config.cjs +145 -0
- package/dist/config-package/generated/validate-config.cjs +293 -0
- package/dist/config-package/generated-config.d.ts +32 -0
- package/dist/config-package/generated-config.js +19 -0
- package/dist/core/auth.d.ts +24 -0
- package/dist/core/auth.js +127 -8
- package/dist/core/bitmap-assets.d.ts +19 -5
- package/dist/core/bitmap-assets.js +40 -31
- package/dist/core/bitmap-shard-budget.d.ts +43 -0
- package/dist/core/bitmap-shard-budget.js +16 -0
- package/dist/core/bitmap-shard-cache.d.ts +68 -0
- package/dist/core/bitmap-shard-cache.js +115 -0
- package/dist/core/bitmap-shard-download.d.ts +130 -0
- package/dist/core/bitmap-shard-download.js +359 -0
- package/dist/core/bitmap-shard-resolver.d.ts +129 -0
- package/dist/core/bitmap-shard-resolver.js +262 -0
- package/dist/core/bitmap-shards.d.ts +70 -0
- package/dist/core/bitmap-shards.js +249 -0
- package/dist/core/bootstrap.d.ts +37 -0
- package/dist/core/bootstrap.js +54 -0
- package/dist/core/cache.d.ts +34 -0
- package/dist/core/cache.js +96 -0
- package/dist/core/context.d.ts +26 -0
- package/dist/core/doctor.d.ts +48 -0
- package/dist/core/doctor.js +190 -0
- package/dist/core/free-download.d.ts +64 -6
- package/dist/core/free-download.js +402 -30
- package/dist/core/generate.d.ts +29 -0
- package/dist/core/generate.js +341 -65
- package/dist/core/icon-selection.d.ts +8 -0
- package/dist/core/icon-selection.js +19 -0
- package/dist/core/install.d.ts +14 -0
- package/dist/core/install.js +132 -13
- package/dist/core/library-update.d.ts +5 -1
- package/dist/core/library-update.js +176 -17
- package/dist/core/local-test-env.d.ts +24 -0
- package/dist/core/local-test-env.js +43 -0
- package/dist/core/metadata-sync.d.ts +30 -0
- package/dist/core/metadata-sync.js +97 -0
- package/dist/core/pro-download.d.ts +63 -0
- package/dist/core/pro-download.js +247 -27
- package/dist/core/pro-install.d.ts +11 -3
- package/dist/core/pro-install.js +181 -19
- package/dist/core/pro-resources.d.ts +79 -0
- package/dist/core/pro-resources.js +204 -0
- package/dist/core/pro-selected-download.d.ts +18 -0
- package/dist/core/pro-selected-download.js +269 -0
- package/dist/core/release-descriptor.d.ts +42 -1
- package/dist/core/release-descriptor.js +117 -9
- package/dist/core/resource-variant.d.ts +27 -10
- package/dist/core/resource-variant.js +75 -34
- package/dist/core/selected-resources.d.ts +59 -0
- package/dist/core/selected-resources.js +350 -0
- package/dist/core/signed-artifact.d.ts +8 -1
- package/dist/core/signed-artifact.js +35 -11
- package/dist/core/target-subtree.d.ts +8 -0
- package/dist/core/target-subtree.js +54 -3
- package/dist/core/version-service.d.ts +11 -0
- package/dist/core/version-service.js +129 -24
- package/dist/core/wizard.d.ts +20 -17
- package/dist/core/wizard.js +66 -28
- package/dist/errors/errors.d.ts +2 -1
- package/dist/errors/errors.js +1 -0
- package/dist/generator/generate.d.ts +1 -1
- package/dist/generator/generate.js +420 -213
- package/dist/generator/shared/SOURCE.json +7 -0
- package/dist/generator/shared/svg-model.cjs +156 -0
- package/dist/generator/svg-model.d.ts +16 -0
- package/dist/generator/svg-model.js +4 -0
- package/dist/generator/theme-resolve.d.ts +2 -0
- package/dist/generator/theme-resolve.js +57 -26
- package/dist/mcp/server.d.ts +23 -36
- package/dist/mcp/server.js +74 -152
- package/dist/mcp/services.d.ts +4 -0
- package/dist/mcp/services.js +230 -0
- package/dist/metadata/archive.d.ts +38 -0
- package/dist/metadata/archive.js +94 -0
- package/dist/metadata/manifest.d.ts +33 -0
- package/dist/metadata/manifest.js +136 -0
- package/dist/metadata/version.d.ts +22 -0
- package/dist/metadata/version.js +53 -0
- package/dist/project/anchors/application.d.ts +13 -0
- package/dist/project/anchors/application.js +377 -0
- package/dist/project/anchors/apply.d.ts +28 -0
- package/dist/project/anchors/apply.js +65 -0
- package/dist/project/anchors/diagnose.d.ts +26 -0
- package/dist/project/anchors/diagnose.js +90 -0
- package/dist/project/anchors/helpers.d.ts +20 -0
- package/dist/project/anchors/helpers.js +55 -0
- package/dist/project/anchors/moeicons-config.d.ts +21 -0
- package/dist/project/anchors/moeicons-config.js +83 -0
- package/dist/project/anchors/parse.d.ts +14 -0
- package/dist/project/anchors/parse.js +36 -0
- package/dist/project/anchors/project-manifest.d.ts +19 -0
- package/dist/project/anchors/project-manifest.js +109 -0
- package/dist/project/anchors/style.d.ts +12 -0
- package/dist/project/anchors/style.js +87 -0
- package/dist/project/anchors/types.d.ts +32 -0
- package/dist/project/anchors/types.js +9 -0
- package/dist/project/config.d.ts +59 -5
- package/dist/project/config.js +234 -102
- package/dist/project/install-metadata.d.ts +23 -2
- package/dist/project/install-metadata.js +58 -7
- package/dist/project/install.d.ts +24 -4
- package/dist/project/install.js +402 -190
- package/dist/project/project-lock.d.ts +2 -2
- package/dist/project/project-lock.js +4 -4
- package/dist/project/tailwind.d.ts +2 -2
- package/dist/project/tailwind.js +3 -4
- package/dist/project/tar-gz.d.ts +18 -1
- package/dist/project/tar-gz.js +40 -3
- package/dist/tui/components.d.ts +62 -0
- package/dist/tui/components.js +100 -0
- package/dist/tui/primitives.d.ts +1 -0
- package/dist/tui/primitives.js +8 -1
- package/dist/ui/banner.d.ts +31 -3
- package/dist/ui/banner.js +120 -25
- package/dist/ui/branded-prompts.d.ts +41 -0
- package/dist/ui/branded-prompts.js +80 -0
- package/dist/ui/clack.d.ts +6 -3
- package/dist/ui/clack.js +56 -5
- package/dist/ui/create-ui.d.ts +1 -0
- package/dist/ui/create-ui.js +5 -1
- package/dist/ui/generated/wordmark-large.d.ts +17 -0
- package/dist/ui/generated/wordmark-large.js +28 -0
- package/dist/ui/generated/wordmark.d.ts +2 -0
- package/dist/ui/generated/wordmark.js +2 -0
- package/dist/ui/non-interactive.js +8 -0
- package/dist/ui/stream.js +30 -0
- package/dist/ui/theme.d.ts +42 -0
- package/dist/ui/theme.js +59 -0
- package/package.json +14 -6
|
@@ -1,5 +1,11 @@
|
|
|
1
|
+
import { type BitmapShard } from "../core/bitmap-shards.js";
|
|
1
2
|
export interface InstallMetadata {
|
|
2
3
|
readonly schemaVersion: 1;
|
|
4
|
+
readonly delivery?: {
|
|
5
|
+
readonly mode: "icons";
|
|
6
|
+
readonly indexSha256: string;
|
|
7
|
+
readonly bundleSha256: string;
|
|
8
|
+
};
|
|
3
9
|
readonly artifactVersion: string;
|
|
4
10
|
readonly tier: "free" | "pro";
|
|
5
11
|
readonly target: "react" | "vue" | "vanilla" | "assets";
|
|
@@ -8,10 +14,25 @@ export interface InstallMetadata {
|
|
|
8
14
|
readonly catalogSha256: string;
|
|
9
15
|
readonly installedAt: string;
|
|
10
16
|
readonly managedFiles: Readonly<Record<string, string>>;
|
|
17
|
+
/** Last successfully generated project proxy root; used for safe migrations. */
|
|
18
|
+
readonly generatedOutputDir?: string;
|
|
11
19
|
/** Verified target subtree hash/size recorded at install time. */
|
|
12
20
|
readonly targetSha256?: string;
|
|
13
21
|
readonly targetFileCount?: number;
|
|
14
22
|
readonly targetByteCount?: number;
|
|
23
|
+
/**
|
|
24
|
+
* DEV-G07: the exact bitmap shard identities selected by the config at
|
|
25
|
+
* install time. generate/repair/offline re-verify these pins before reuse.
|
|
26
|
+
*/
|
|
27
|
+
readonly bitmapShards?: readonly BitmapShard[];
|
|
28
|
+
readonly bitmapShardSetSha256?: string;
|
|
29
|
+
/** A-1b: present only for an installed local-test candidate. */
|
|
30
|
+
readonly channel?: "local-test";
|
|
31
|
+
readonly publishable?: boolean;
|
|
32
|
+
}
|
|
33
|
+
export interface InstallMetadataParseOptions {
|
|
34
|
+
/** A-1b: accept a declared `X.Y.Z-test` local-test candidate (local context only). */
|
|
35
|
+
readonly allowLocalTest?: boolean;
|
|
15
36
|
}
|
|
16
37
|
export type InstalledResourceState = {
|
|
17
38
|
readonly kind: "ok";
|
|
@@ -24,6 +45,6 @@ export type InstalledResourceState = {
|
|
|
24
45
|
readonly message: string;
|
|
25
46
|
};
|
|
26
47
|
export declare function sha256Bytes(value: string | Uint8Array): string;
|
|
27
|
-
export declare function parseInstallMetadata(raw: string): InstallMetadata | undefined;
|
|
48
|
+
export declare function parseInstallMetadata(raw: string, opts?: InstallMetadataParseOptions): InstallMetadata | undefined;
|
|
28
49
|
export declare function serializeInstallMetadata(metadata: InstallMetadata): string;
|
|
29
|
-
export declare function readInstalledResourceState(projectRoot: string, expectedTier?: "free" | "pro"): InstalledResourceState;
|
|
50
|
+
export declare function readInstalledResourceState(projectRoot: string, expectedTier?: "free" | "pro", opts?: InstallMetadataParseOptions): InstalledResourceState;
|
|
@@ -1,8 +1,10 @@
|
|
|
1
1
|
import { createHash } from "node:crypto";
|
|
2
2
|
import { existsSync, readFileSync } from "node:fs";
|
|
3
3
|
import { join } from "node:path";
|
|
4
|
+
import { bitmapShardSetSha256, parseBitmapShard } from "../core/bitmap-shards.js";
|
|
4
5
|
const SHA256 = /^[a-f0-9]{64}$/;
|
|
5
6
|
const VERSION = /^\d+\.\d+\.\d+(?:-(?:alpha|beta))?$/;
|
|
7
|
+
const LOCAL_TEST_VERSION = /^\d+\.\d+\.\d+-test$/;
|
|
6
8
|
const UTC_RFC3339 = /^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}(?:\.\d{1,3})?Z$/;
|
|
7
9
|
export function sha256Bytes(value) {
|
|
8
10
|
return createHash("sha256").update(value).digest("hex");
|
|
@@ -12,11 +14,13 @@ function safeManagedPath(path) {
|
|
|
12
14
|
!path.startsWith("/") &&
|
|
13
15
|
!/^[A-Za-z]:/.test(path) &&
|
|
14
16
|
!path.includes("\\") &&
|
|
15
|
-
|
|
17
|
+
path.split("/").every((part) => part.length > 0 && part !== "." && part !== "..") &&
|
|
18
|
+
![".git", "node_modules"].includes(path.split("/")[0] ?? ""));
|
|
16
19
|
}
|
|
17
|
-
export function parseInstallMetadata(raw) {
|
|
20
|
+
export function parseInstallMetadata(raw, opts = {}) {
|
|
18
21
|
try {
|
|
19
22
|
const value = JSON.parse(raw);
|
|
23
|
+
const allowLocalTest = opts.allowLocalTest === true;
|
|
20
24
|
const allowed = new Set([
|
|
21
25
|
"schemaVersion",
|
|
22
26
|
"artifactVersion",
|
|
@@ -27,13 +31,27 @@ export function parseInstallMetadata(raw) {
|
|
|
27
31
|
"catalogSha256",
|
|
28
32
|
"installedAt",
|
|
29
33
|
"managedFiles",
|
|
34
|
+
"generatedOutputDir",
|
|
30
35
|
"targetSha256",
|
|
31
36
|
"targetFileCount",
|
|
32
37
|
"targetByteCount",
|
|
38
|
+
"bitmapShards",
|
|
39
|
+
"bitmapShardSetSha256",
|
|
40
|
+
"delivery",
|
|
41
|
+
...(allowLocalTest ? ["channel", "publishable"] : []),
|
|
33
42
|
]);
|
|
34
43
|
if (Object.keys(value).some((key) => !allowed.has(key)) || value.schemaVersion !== 1)
|
|
35
44
|
return undefined;
|
|
36
|
-
|
|
45
|
+
const localTestMarked = value.channel === "local-test" && value.publishable === false;
|
|
46
|
+
const strictVersion = typeof value.artifactVersion === "string" && VERSION.test(value.artifactVersion);
|
|
47
|
+
// A formal (stable/alpha/beta) version must never carry the local-test marker.
|
|
48
|
+
if (strictVersion && (value.channel !== undefined || value.publishable !== undefined))
|
|
49
|
+
return undefined;
|
|
50
|
+
const versionAllowed = strictVersion ||
|
|
51
|
+
(allowLocalTest &&
|
|
52
|
+
localTestMarked &&
|
|
53
|
+
LOCAL_TEST_VERSION.test(value.artifactVersion));
|
|
54
|
+
if (!versionAllowed)
|
|
37
55
|
return undefined;
|
|
38
56
|
if (value.tier !== "free" && value.tier !== "pro")
|
|
39
57
|
return undefined;
|
|
@@ -63,9 +81,42 @@ export function parseInstallMetadata(raw) {
|
|
|
63
81
|
Array.isArray(value.managedFiles))
|
|
64
82
|
return undefined;
|
|
65
83
|
const managedFiles = value.managedFiles;
|
|
84
|
+
if (value.generatedOutputDir !== undefined &&
|
|
85
|
+
(typeof value.generatedOutputDir !== "string" ||
|
|
86
|
+
!safeManagedPath(value.generatedOutputDir) ||
|
|
87
|
+
value.generatedOutputDir.split("/").some((part) => !part || part === "." || part === "..")))
|
|
88
|
+
return undefined;
|
|
66
89
|
if (Object.keys(managedFiles).length === 0 ||
|
|
67
90
|
Object.entries(managedFiles).some(([path, hash]) => !safeManagedPath(path) || typeof hash !== "string" || !SHA256.test(hash)))
|
|
68
91
|
return undefined;
|
|
92
|
+
if (value.delivery !== undefined) {
|
|
93
|
+
const delivery = value.delivery;
|
|
94
|
+
if (!delivery ||
|
|
95
|
+
typeof delivery !== "object" ||
|
|
96
|
+
Array.isArray(delivery) ||
|
|
97
|
+
Object.keys(delivery).some((k) => !["mode", "indexSha256", "bundleSha256"].includes(k)) ||
|
|
98
|
+
delivery.mode !== "icons" ||
|
|
99
|
+
typeof delivery.indexSha256 !== "string" ||
|
|
100
|
+
!SHA256.test(delivery.indexSha256) ||
|
|
101
|
+
typeof delivery.bundleSha256 !== "string" ||
|
|
102
|
+
!SHA256.test(delivery.bundleSha256) ||
|
|
103
|
+
managedFiles[".moeicons/resource-index.json.gz"] !== delivery.indexSha256)
|
|
104
|
+
return undefined;
|
|
105
|
+
}
|
|
106
|
+
if (value.bitmapShards !== undefined || value.bitmapShardSetSha256 !== undefined) {
|
|
107
|
+
if (!Array.isArray(value.bitmapShards) || value.bitmapShards.length === 0)
|
|
108
|
+
return undefined;
|
|
109
|
+
const shards = value.bitmapShards.map((entry) => parseBitmapShard(entry));
|
|
110
|
+
for (const shard of shards) {
|
|
111
|
+
if (shard.resourceVersion !== value.artifactVersion)
|
|
112
|
+
return undefined;
|
|
113
|
+
}
|
|
114
|
+
const digest = value.bitmapShardSetSha256;
|
|
115
|
+
if (typeof digest !== "string" || !SHA256.test(digest))
|
|
116
|
+
return undefined;
|
|
117
|
+
if (bitmapShardSetSha256(shards) !== digest)
|
|
118
|
+
return undefined;
|
|
119
|
+
}
|
|
69
120
|
return value;
|
|
70
121
|
}
|
|
71
122
|
catch {
|
|
@@ -75,18 +126,18 @@ export function parseInstallMetadata(raw) {
|
|
|
75
126
|
export function serializeInstallMetadata(metadata) {
|
|
76
127
|
return `${JSON.stringify(metadata, null, 2)}\n`;
|
|
77
128
|
}
|
|
78
|
-
export function readInstalledResourceState(projectRoot, expectedTier) {
|
|
129
|
+
export function readInstalledResourceState(projectRoot, expectedTier, opts = {}) {
|
|
79
130
|
const metadataPath = join(projectRoot, ".moeicons", "install-metadata.json");
|
|
80
131
|
if (!existsSync(metadataPath))
|
|
81
132
|
return {
|
|
82
133
|
kind: "missing",
|
|
83
|
-
message: "managed install metadata is missing; run repair or reinstall",
|
|
134
|
+
message: "managed install metadata is missing; run 'moeicons install' to repair or reinstall",
|
|
84
135
|
};
|
|
85
|
-
const metadata = parseInstallMetadata(readFileSync(metadataPath, "utf8"));
|
|
136
|
+
const metadata = parseInstallMetadata(readFileSync(metadataPath, "utf8"), opts);
|
|
86
137
|
if (!metadata)
|
|
87
138
|
return {
|
|
88
139
|
kind: "invalid",
|
|
89
|
-
message: "managed install metadata is invalid; run repair or reinstall",
|
|
140
|
+
message: "managed install metadata is invalid; run 'moeicons install' to repair or reinstall",
|
|
90
141
|
};
|
|
91
142
|
if (expectedTier && metadata.tier !== expectedTier)
|
|
92
143
|
return {
|
|
@@ -13,6 +13,7 @@ export interface InstallPlanItem {
|
|
|
13
13
|
readonly bytes?: Uint8Array;
|
|
14
14
|
}
|
|
15
15
|
export interface InstallPlan {
|
|
16
|
+
readonly root?: string;
|
|
16
17
|
readonly items: readonly InstallPlanItem[];
|
|
17
18
|
}
|
|
18
19
|
export interface TransactionalFs {
|
|
@@ -27,11 +28,24 @@ export interface TransactionalFsWithCopy extends TransactionalFs {
|
|
|
27
28
|
readonly readdirSync: typeof readdirSync;
|
|
28
29
|
readonly copyFileSync: typeof copyFileSync;
|
|
29
30
|
}
|
|
31
|
+
/** Shared path boundary for install/update and doctor/init writes. */
|
|
32
|
+
export declare function safeManagedPath(projectRoot: string, relative: string): {
|
|
33
|
+
normalized: string;
|
|
34
|
+
target: string;
|
|
35
|
+
};
|
|
30
36
|
/**
|
|
31
37
|
* Atomically reconcile an explicit cross-directory managed set. `removePaths`
|
|
32
38
|
* must come from trusted metadata; this function never scans or uses globs.
|
|
33
39
|
*/
|
|
34
|
-
export declare function executeManagedReconcile(projectRoot: string, writes: Readonly<Record<string, string | Uint8Array>>, removePaths: readonly string[], fs_: TransactionalFsWithCopy
|
|
40
|
+
export declare function executeManagedReconcile(projectRoot: string, writes: Readonly<Record<string, string | Uint8Array>>, removePaths: readonly string[], fs_: TransactionalFsWithCopy, options?: {
|
|
41
|
+
readonly expectedText?: Readonly<Record<string, string | undefined>>;
|
|
42
|
+
readonly expectedSha256?: Readonly<Record<string, string | undefined>>;
|
|
43
|
+
}): void;
|
|
44
|
+
/** Recover an interrupted process while preserving any independently edited file.
|
|
45
|
+
* Must run under the same project lock as reconcile. Invalid journals fail closed.
|
|
46
|
+
* This covers process termination, not power loss or a hostile filesystem.
|
|
47
|
+
*/
|
|
48
|
+
export declare function recoverManagedReconcile(projectRoot: string, fs_: TransactionalFsWithCopy): number;
|
|
35
49
|
/** Pure list of install operations with expected checksums. */
|
|
36
50
|
export declare function createInstallPlan(targetRoot: string, files: Readonly<Record<string, string | Uint8Array>>): InstallPlan;
|
|
37
51
|
/** Create a deterministic ZIP for delivery (fixed mtime). */
|
|
@@ -68,9 +82,9 @@ export declare function executeGeneratedFiles(files: readonly {
|
|
|
68
82
|
* the output directory is never left in a partial state.
|
|
69
83
|
*
|
|
70
84
|
* The set of CLI-managed paths is determined by the `files` argument. Any file
|
|
71
|
-
* that already exists in outputDir
|
|
72
|
-
*
|
|
73
|
-
*
|
|
85
|
+
* that already exists in outputDir is considered user-owned and is preserved.
|
|
86
|
+
* This compatibility writer has no ownership metadata, so it refuses to
|
|
87
|
+
* replace an existing path. Production generation uses managed reconciliation.
|
|
74
88
|
*/
|
|
75
89
|
export declare function executeGeneratedFilesDir(files: readonly {
|
|
76
90
|
path: string;
|
|
@@ -103,6 +117,12 @@ export type DownloadResult = {
|
|
|
103
117
|
* Download an artifact. HTTPS only, optional host allowlist, bounded redirects,
|
|
104
118
|
* timeout, byte limit. Abort and temporary-file cleanup are handled by the
|
|
105
119
|
* caller via the injected fetch/signal.
|
|
120
|
+
*
|
|
121
|
+
* Redirect policy: unlike the API descriptor handshake (which uses
|
|
122
|
+
* `redirect: "error"`), payload downloads intentionally follow a bounded number
|
|
123
|
+
* of redirects because code/metadata archives are served from CDNs that 3xx to
|
|
124
|
+
* a signed object host; the destination host is re-checked against the
|
|
125
|
+
* allowlist on every hop.
|
|
106
126
|
*/
|
|
107
127
|
export declare function downloadArtifact(url: string, limits: DownloadLimits, deps?: {
|
|
108
128
|
fetchFn?: typeof fetch;
|