lattice-ui 0.4.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/LICENSE +7 -0
- package/README.md +45 -0
- package/dist/cli.d.ts +1 -0
- package/dist/cli.js +426 -0
- package/dist/commands/add.d.ts +3 -0
- package/dist/commands/add.js +156 -0
- package/dist/commands/create.d.ts +23 -0
- package/dist/commands/create.js +351 -0
- package/dist/commands/doctor.d.ts +2 -0
- package/dist/commands/doctor.js +164 -0
- package/dist/commands/init.d.ts +21 -0
- package/dist/commands/init.js +547 -0
- package/dist/commands/remove.d.ts +3 -0
- package/dist/commands/remove.js +113 -0
- package/dist/commands/selection.d.ts +6 -0
- package/dist/commands/selection.js +27 -0
- package/dist/commands/upgrade.d.ts +3 -0
- package/dist/commands/upgrade.js +150 -0
- package/dist/core/errors.d.ts +21 -0
- package/dist/core/errors.js +52 -0
- package/dist/core/fs/copy.d.ts +13 -0
- package/dist/core/fs/copy.js +129 -0
- package/dist/core/fs/json.d.ts +3 -0
- package/dist/core/fs/json.js +163 -0
- package/dist/core/fs/patch.d.ts +16 -0
- package/dist/core/fs/patch.js +89 -0
- package/dist/core/logger.d.ts +27 -0
- package/dist/core/logger.js +166 -0
- package/dist/core/npm/latest.d.ts +1 -0
- package/dist/core/npm/latest.js +40 -0
- package/dist/core/output.d.ts +8 -0
- package/dist/core/output.js +20 -0
- package/dist/core/pm/detect.d.ts +18 -0
- package/dist/core/pm/detect.js +147 -0
- package/dist/core/pm/npm.d.ts +2 -0
- package/dist/core/pm/npm.js +48 -0
- package/dist/core/pm/pnpm.d.ts +2 -0
- package/dist/core/pm/pnpm.js +48 -0
- package/dist/core/pm/types.d.ts +8 -0
- package/dist/core/pm/types.js +2 -0
- package/dist/core/pm/yarn.d.ts +2 -0
- package/dist/core/pm/yarn.js +48 -0
- package/dist/core/project/findRoot.d.ts +1 -0
- package/dist/core/project/findRoot.js +60 -0
- package/dist/core/project/readPackageJson.d.ts +13 -0
- package/dist/core/project/readPackageJson.js +41 -0
- package/dist/core/project/writePackageJson.d.ts +2 -0
- package/dist/core/project/writePackageJson.js +41 -0
- package/dist/core/prompt.d.ts +23 -0
- package/dist/core/prompt.js +217 -0
- package/dist/core/registry/load.d.ts +3 -0
- package/dist/core/registry/load.js +59 -0
- package/dist/core/registry/schema.d.ts +18 -0
- package/dist/core/registry/schema.js +87 -0
- package/dist/ctx.d.ts +27 -0
- package/dist/ctx.js +75 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.js +21 -0
- package/package.json +27 -0
- package/registry/components.json +118 -0
- package/registry/presets.json +6 -0
- package/templates/init/default.project.json.template +67 -0
- package/templates/init/package.json +22 -0
- package/templates/init/src/client/App.tsx +21 -0
- package/templates/init/src/client/main.client.tsx +26 -0
- package/templates/init/src/server/main.server.ts +3 -0
- package/templates/init/src/shared/constants.ts +1 -0
- package/templates/init/tsconfig.json +27 -0
- package/templates/init-lint/.prettierrc +7 -0
- package/templates/init-lint/eslint.config.mjs +51 -0
- package/templates/init-lint/package.json +19 -0
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
export type PackageJson = {
|
|
2
|
+
name?: string;
|
|
3
|
+
version?: string;
|
|
4
|
+
private?: boolean;
|
|
5
|
+
packageManager?: string;
|
|
6
|
+
scripts?: Record<string, string>;
|
|
7
|
+
dependencies?: Record<string, string>;
|
|
8
|
+
devDependencies?: Record<string, string>;
|
|
9
|
+
peerDependencies?: Record<string, string>;
|
|
10
|
+
optionalDependencies?: Record<string, string>;
|
|
11
|
+
[key: string]: unknown;
|
|
12
|
+
};
|
|
13
|
+
export declare function readPackageJson(projectRoot: string): Promise<PackageJson>;
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
+
var ownKeys = function(o) {
|
|
20
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
+
var ar = [];
|
|
22
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
+
return ar;
|
|
24
|
+
};
|
|
25
|
+
return ownKeys(o);
|
|
26
|
+
};
|
|
27
|
+
return function (mod) {
|
|
28
|
+
if (mod && mod.__esModule) return mod;
|
|
29
|
+
var result = {};
|
|
30
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
+
__setModuleDefault(result, mod);
|
|
32
|
+
return result;
|
|
33
|
+
};
|
|
34
|
+
})();
|
|
35
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
36
|
+
exports.readPackageJson = readPackageJson;
|
|
37
|
+
const path = __importStar(require("node:path"));
|
|
38
|
+
const json_1 = require("../fs/json");
|
|
39
|
+
async function readPackageJson(projectRoot) {
|
|
40
|
+
return (0, json_1.readJsonFile)(path.join(projectRoot, "package.json"));
|
|
41
|
+
}
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
+
var ownKeys = function(o) {
|
|
20
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
+
var ar = [];
|
|
22
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
+
return ar;
|
|
24
|
+
};
|
|
25
|
+
return ownKeys(o);
|
|
26
|
+
};
|
|
27
|
+
return function (mod) {
|
|
28
|
+
if (mod && mod.__esModule) return mod;
|
|
29
|
+
var result = {};
|
|
30
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
+
__setModuleDefault(result, mod);
|
|
32
|
+
return result;
|
|
33
|
+
};
|
|
34
|
+
})();
|
|
35
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
36
|
+
exports.writePackageJson = writePackageJson;
|
|
37
|
+
const path = __importStar(require("node:path"));
|
|
38
|
+
const json_1 = require("../fs/json");
|
|
39
|
+
async function writePackageJson(projectRoot, manifest) {
|
|
40
|
+
await (0, json_1.writeJsonFile)(path.join(projectRoot, "package.json"), manifest, false);
|
|
41
|
+
}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
export interface PromptRuntime {
|
|
2
|
+
yes: boolean;
|
|
3
|
+
stdin?: NodeJS.ReadStream;
|
|
4
|
+
stdout?: NodeJS.WriteStream;
|
|
5
|
+
}
|
|
6
|
+
export interface PromptOption<T> {
|
|
7
|
+
label: string;
|
|
8
|
+
value: T;
|
|
9
|
+
}
|
|
10
|
+
export declare function promptInput(runtime: PromptRuntime, message: string, config?: {
|
|
11
|
+
defaultValue?: string;
|
|
12
|
+
required?: boolean;
|
|
13
|
+
}): Promise<string>;
|
|
14
|
+
export declare function promptConfirm(runtime: PromptRuntime, message: string, config?: {
|
|
15
|
+
defaultValue?: boolean;
|
|
16
|
+
}): Promise<boolean>;
|
|
17
|
+
export declare function promptSelect<T>(runtime: PromptRuntime, message: string, options: PromptOption<T>[], config?: {
|
|
18
|
+
defaultIndex?: number;
|
|
19
|
+
}): Promise<T>;
|
|
20
|
+
export declare function promptMultiSelect<T>(runtime: PromptRuntime, message: string, options: PromptOption<T>[], config?: {
|
|
21
|
+
allowEmpty?: boolean;
|
|
22
|
+
defaultIndices?: number[];
|
|
23
|
+
}): Promise<T[]>;
|
|
@@ -0,0 +1,217 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.promptInput = promptInput;
|
|
4
|
+
exports.promptConfirm = promptConfirm;
|
|
5
|
+
exports.promptSelect = promptSelect;
|
|
6
|
+
exports.promptMultiSelect = promptMultiSelect;
|
|
7
|
+
const promises_1 = require("node:readline/promises");
|
|
8
|
+
const errors_1 = require("./errors");
|
|
9
|
+
const ANSI = {
|
|
10
|
+
reset: "\u001b[0m",
|
|
11
|
+
cyan: "\u001b[36m",
|
|
12
|
+
magenta: "\u001b[35m",
|
|
13
|
+
gray: "\u001b[90m",
|
|
14
|
+
bold: "\u001b[1m",
|
|
15
|
+
};
|
|
16
|
+
const ICONS = {
|
|
17
|
+
tty: {
|
|
18
|
+
question: "?",
|
|
19
|
+
guide: "›",
|
|
20
|
+
},
|
|
21
|
+
plain: {
|
|
22
|
+
question: "[?]",
|
|
23
|
+
guide: "[>]",
|
|
24
|
+
},
|
|
25
|
+
};
|
|
26
|
+
function supportsColor(stdout) {
|
|
27
|
+
return Boolean(stdout.isTTY);
|
|
28
|
+
}
|
|
29
|
+
function supportsUnicodeIcons(stdout) {
|
|
30
|
+
return Boolean(stdout.isTTY);
|
|
31
|
+
}
|
|
32
|
+
function colorize(enabled, color, text) {
|
|
33
|
+
if (!enabled) {
|
|
34
|
+
return text;
|
|
35
|
+
}
|
|
36
|
+
return `${color}${text}${ANSI.reset}`;
|
|
37
|
+
}
|
|
38
|
+
function getRuntimeStreams(runtime) {
|
|
39
|
+
const stdin = runtime.stdin ?? process.stdin;
|
|
40
|
+
const stdout = runtime.stdout ?? process.stdout;
|
|
41
|
+
return { stdin, stdout };
|
|
42
|
+
}
|
|
43
|
+
function getPromptIcon(stdout, kind) {
|
|
44
|
+
if (supportsUnicodeIcons(stdout)) {
|
|
45
|
+
return ICONS.tty[kind];
|
|
46
|
+
}
|
|
47
|
+
return ICONS.plain[kind];
|
|
48
|
+
}
|
|
49
|
+
function ensureInteractive(runtime) {
|
|
50
|
+
const { stdin, stdout } = getRuntimeStreams(runtime);
|
|
51
|
+
if (runtime.yes) {
|
|
52
|
+
return { stdin, stdout };
|
|
53
|
+
}
|
|
54
|
+
if (!stdin.isTTY || !stdout.isTTY) {
|
|
55
|
+
throw (0, errors_1.usageError)("Interactive prompts require a TTY. Re-run with --yes and explicit options.");
|
|
56
|
+
}
|
|
57
|
+
return { stdin, stdout };
|
|
58
|
+
}
|
|
59
|
+
function printPromptHeader(stdout, message) {
|
|
60
|
+
const useColor = supportsColor(stdout);
|
|
61
|
+
const icon = colorize(useColor, ANSI.magenta, getPromptIcon(stdout, "question"));
|
|
62
|
+
const heading = colorize(useColor, ANSI.bold, message);
|
|
63
|
+
stdout.write(`\n${icon} ${heading}\n`);
|
|
64
|
+
}
|
|
65
|
+
function printPromptGuide(stdout, message) {
|
|
66
|
+
const useColor = supportsColor(stdout);
|
|
67
|
+
const icon = colorize(useColor, ANSI.cyan, getPromptIcon(stdout, "guide"));
|
|
68
|
+
const text = colorize(useColor, ANSI.gray, message);
|
|
69
|
+
stdout.write(`${icon} ${text}\n`);
|
|
70
|
+
}
|
|
71
|
+
function parseCsvIndices(input, optionCount) {
|
|
72
|
+
if (input.trim().length === 0) {
|
|
73
|
+
return [];
|
|
74
|
+
}
|
|
75
|
+
const output = [];
|
|
76
|
+
const parts = input
|
|
77
|
+
.split(",")
|
|
78
|
+
.map((part) => part.trim())
|
|
79
|
+
.filter((part) => part.length > 0);
|
|
80
|
+
for (const part of parts) {
|
|
81
|
+
const parsed = Number(part);
|
|
82
|
+
if (!Number.isInteger(parsed) || parsed < 1 || parsed > optionCount) {
|
|
83
|
+
throw (0, errors_1.usageError)(`Invalid selection "${part}". Choose numbers between 1 and ${optionCount}.`);
|
|
84
|
+
}
|
|
85
|
+
const index = parsed - 1;
|
|
86
|
+
if (!output.includes(index)) {
|
|
87
|
+
output.push(index);
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
return output;
|
|
91
|
+
}
|
|
92
|
+
async function promptInput(runtime, message, config) {
|
|
93
|
+
const required = config?.required ?? true;
|
|
94
|
+
const defaultValue = config?.defaultValue;
|
|
95
|
+
if (runtime.yes) {
|
|
96
|
+
if (defaultValue !== undefined) {
|
|
97
|
+
return defaultValue;
|
|
98
|
+
}
|
|
99
|
+
if (required) {
|
|
100
|
+
throw (0, errors_1.usageError)(`Missing required value for prompt: ${message}`);
|
|
101
|
+
}
|
|
102
|
+
return "";
|
|
103
|
+
}
|
|
104
|
+
const { stdin, stdout } = ensureInteractive(runtime);
|
|
105
|
+
printPromptHeader(stdout, message);
|
|
106
|
+
const rl = (0, promises_1.createInterface)({ input: stdin, output: stdout });
|
|
107
|
+
try {
|
|
108
|
+
const suffix = defaultValue !== undefined ? ` (default: ${defaultValue})` : "";
|
|
109
|
+
const answer = await rl.question(`${getPromptIcon(stdout, "guide")} Value${suffix}: `);
|
|
110
|
+
const trimmed = answer.trim();
|
|
111
|
+
if (trimmed.length > 0) {
|
|
112
|
+
return trimmed;
|
|
113
|
+
}
|
|
114
|
+
if (defaultValue !== undefined) {
|
|
115
|
+
return defaultValue;
|
|
116
|
+
}
|
|
117
|
+
if (required) {
|
|
118
|
+
throw (0, errors_1.usageError)(`Missing required value for prompt: ${message}`);
|
|
119
|
+
}
|
|
120
|
+
return "";
|
|
121
|
+
}
|
|
122
|
+
finally {
|
|
123
|
+
rl.close();
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
async function promptConfirm(runtime, message, config) {
|
|
127
|
+
const defaultValue = config?.defaultValue ?? false;
|
|
128
|
+
if (runtime.yes) {
|
|
129
|
+
return defaultValue;
|
|
130
|
+
}
|
|
131
|
+
const { stdin, stdout } = ensureInteractive(runtime);
|
|
132
|
+
printPromptHeader(stdout, message);
|
|
133
|
+
const rl = (0, promises_1.createInterface)({ input: stdin, output: stdout });
|
|
134
|
+
try {
|
|
135
|
+
const hint = defaultValue ? "Y/n" : "y/N";
|
|
136
|
+
const answer = (await rl.question(`${getPromptIcon(stdout, "guide")} Confirm (${hint}): `)).trim().toLowerCase();
|
|
137
|
+
if (answer.length === 0) {
|
|
138
|
+
return defaultValue;
|
|
139
|
+
}
|
|
140
|
+
if (answer === "y" || answer === "yes") {
|
|
141
|
+
return true;
|
|
142
|
+
}
|
|
143
|
+
if (answer === "n" || answer === "no") {
|
|
144
|
+
return false;
|
|
145
|
+
}
|
|
146
|
+
throw (0, errors_1.usageError)(`Invalid confirmation response "${answer}".`);
|
|
147
|
+
}
|
|
148
|
+
finally {
|
|
149
|
+
rl.close();
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
async function promptSelect(runtime, message, options, config) {
|
|
153
|
+
if (options.length === 0) {
|
|
154
|
+
throw (0, errors_1.usageError)(`Prompt "${message}" has no options.`);
|
|
155
|
+
}
|
|
156
|
+
const defaultIndex = config?.defaultIndex ?? 0;
|
|
157
|
+
if (defaultIndex < 0 || defaultIndex >= options.length) {
|
|
158
|
+
throw (0, errors_1.usageError)(`Prompt "${message}" has an invalid default index.`);
|
|
159
|
+
}
|
|
160
|
+
if (runtime.yes) {
|
|
161
|
+
return options[defaultIndex].value;
|
|
162
|
+
}
|
|
163
|
+
const { stdin, stdout } = ensureInteractive(runtime);
|
|
164
|
+
printPromptHeader(stdout, message);
|
|
165
|
+
options.forEach((option, index) => {
|
|
166
|
+
stdout.write(` ${index + 1}) ${option.label}\n`);
|
|
167
|
+
});
|
|
168
|
+
printPromptGuide(stdout, `Enter a number (default: ${defaultIndex + 1})`);
|
|
169
|
+
const rl = (0, promises_1.createInterface)({ input: stdin, output: stdout });
|
|
170
|
+
try {
|
|
171
|
+
const answer = (await rl.question(`${getPromptIcon(stdout, "guide")} Select one: `)).trim();
|
|
172
|
+
const indices = parseCsvIndices(answer, options.length);
|
|
173
|
+
if (indices.length === 0) {
|
|
174
|
+
return options[defaultIndex].value;
|
|
175
|
+
}
|
|
176
|
+
if (indices.length > 1) {
|
|
177
|
+
throw (0, errors_1.usageError)("Select exactly one option.");
|
|
178
|
+
}
|
|
179
|
+
return options[indices[0]].value;
|
|
180
|
+
}
|
|
181
|
+
finally {
|
|
182
|
+
rl.close();
|
|
183
|
+
}
|
|
184
|
+
}
|
|
185
|
+
async function promptMultiSelect(runtime, message, options, config) {
|
|
186
|
+
if (options.length === 0) {
|
|
187
|
+
return [];
|
|
188
|
+
}
|
|
189
|
+
const allowEmpty = config?.allowEmpty ?? false;
|
|
190
|
+
const defaultIndices = (config?.defaultIndices ?? []).filter((index) => index >= 0 && index < options.length);
|
|
191
|
+
if (runtime.yes) {
|
|
192
|
+
return defaultIndices.map((index) => options[index].value);
|
|
193
|
+
}
|
|
194
|
+
const { stdin, stdout } = ensureInteractive(runtime);
|
|
195
|
+
printPromptHeader(stdout, message);
|
|
196
|
+
options.forEach((option, index) => {
|
|
197
|
+
stdout.write(` ${index + 1}) ${option.label}\n`);
|
|
198
|
+
});
|
|
199
|
+
const defaultText = defaultIndices.length > 0
|
|
200
|
+
? `default: ${defaultIndices.map((index) => index + 1).join(",")}`
|
|
201
|
+
: allowEmpty
|
|
202
|
+
? "press enter to skip"
|
|
203
|
+
: "select at least one item";
|
|
204
|
+
printPromptGuide(stdout, `Enter comma-separated numbers (${defaultText})`);
|
|
205
|
+
const rl = (0, promises_1.createInterface)({ input: stdin, output: stdout });
|
|
206
|
+
try {
|
|
207
|
+
const answer = (await rl.question(`${getPromptIcon(stdout, "guide")} Select one or more: `)).trim();
|
|
208
|
+
const indices = answer.length > 0 ? parseCsvIndices(answer, options.length) : defaultIndices;
|
|
209
|
+
if (indices.length === 0 && !allowEmpty) {
|
|
210
|
+
throw (0, errors_1.usageError)("At least one option must be selected.");
|
|
211
|
+
}
|
|
212
|
+
return indices.map((index) => options[index].value);
|
|
213
|
+
}
|
|
214
|
+
finally {
|
|
215
|
+
rl.close();
|
|
216
|
+
}
|
|
217
|
+
}
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
+
var ownKeys = function(o) {
|
|
20
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
+
var ar = [];
|
|
22
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
+
return ar;
|
|
24
|
+
};
|
|
25
|
+
return ownKeys(o);
|
|
26
|
+
};
|
|
27
|
+
return function (mod) {
|
|
28
|
+
if (mod && mod.__esModule) return mod;
|
|
29
|
+
var result = {};
|
|
30
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
+
__setModuleDefault(result, mod);
|
|
32
|
+
return result;
|
|
33
|
+
};
|
|
34
|
+
})();
|
|
35
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
36
|
+
exports.resolveRegistryDir = resolveRegistryDir;
|
|
37
|
+
exports.loadRegistry = loadRegistry;
|
|
38
|
+
const path = __importStar(require("node:path"));
|
|
39
|
+
const errors_1 = require("../errors");
|
|
40
|
+
const json_1 = require("../fs/json");
|
|
41
|
+
const schema_1 = require("./schema");
|
|
42
|
+
function resolveRegistryDir(baseDir = __dirname) {
|
|
43
|
+
return path.resolve(baseDir, "../../../registry");
|
|
44
|
+
}
|
|
45
|
+
async function loadRegistry(registryDir = resolveRegistryDir()) {
|
|
46
|
+
const componentsPath = path.join(registryDir, "components.json");
|
|
47
|
+
const presetsPath = path.join(registryDir, "presets.json");
|
|
48
|
+
try {
|
|
49
|
+
const componentsSource = await (0, json_1.readJsonFile)(componentsPath);
|
|
50
|
+
const presetsSource = await (0, json_1.readJsonFile)(presetsPath);
|
|
51
|
+
return (0, schema_1.validateRegistry)(componentsSource, presetsSource);
|
|
52
|
+
}
|
|
53
|
+
catch (error) {
|
|
54
|
+
if (error instanceof Error) {
|
|
55
|
+
throw (0, errors_1.registryInvalidError)(`Failed to load registry: ${error.message}`, error);
|
|
56
|
+
}
|
|
57
|
+
throw (0, errors_1.registryInvalidError)("Failed to load registry.", error);
|
|
58
|
+
}
|
|
59
|
+
}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
export interface RegistryPackageEntry {
|
|
2
|
+
npm: string;
|
|
3
|
+
peers?: string[];
|
|
4
|
+
providers?: string[];
|
|
5
|
+
notes?: string[];
|
|
6
|
+
}
|
|
7
|
+
export interface Registry {
|
|
8
|
+
packages: Record<string, RegistryPackageEntry>;
|
|
9
|
+
presets: Record<string, string[]>;
|
|
10
|
+
}
|
|
11
|
+
export interface ProviderRequirement {
|
|
12
|
+
raw: string;
|
|
13
|
+
packageName: string;
|
|
14
|
+
providerName?: string;
|
|
15
|
+
optional: boolean;
|
|
16
|
+
}
|
|
17
|
+
export declare function parseProviderRequirement(rawValue: string): ProviderRequirement;
|
|
18
|
+
export declare function validateRegistry(componentsSource: unknown, presetsSource: unknown): Registry;
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.parseProviderRequirement = parseProviderRequirement;
|
|
4
|
+
exports.validateRegistry = validateRegistry;
|
|
5
|
+
const errors_1 = require("../errors");
|
|
6
|
+
function isRecord(value) {
|
|
7
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
8
|
+
}
|
|
9
|
+
function isStringArray(value) {
|
|
10
|
+
return Array.isArray(value) && value.every((entry) => typeof entry === "string");
|
|
11
|
+
}
|
|
12
|
+
function readStringArray(value, path) {
|
|
13
|
+
if (value === undefined) {
|
|
14
|
+
return undefined;
|
|
15
|
+
}
|
|
16
|
+
if (!isStringArray(value)) {
|
|
17
|
+
throw (0, errors_1.registryInvalidError)(`${path} must be an array of strings.`);
|
|
18
|
+
}
|
|
19
|
+
return value.slice();
|
|
20
|
+
}
|
|
21
|
+
function parseProviderRequirement(rawValue) {
|
|
22
|
+
const optional = rawValue.endsWith("?");
|
|
23
|
+
const normalized = optional ? rawValue.slice(0, -1) : rawValue;
|
|
24
|
+
const [packageName, providerName] = normalized.split(":");
|
|
25
|
+
if (!packageName || packageName.trim().length === 0) {
|
|
26
|
+
throw (0, errors_1.registryInvalidError)(`Invalid provider requirement "${rawValue}".`);
|
|
27
|
+
}
|
|
28
|
+
return {
|
|
29
|
+
raw: rawValue,
|
|
30
|
+
packageName,
|
|
31
|
+
providerName: providerName && providerName.length > 0 ? providerName : undefined,
|
|
32
|
+
optional,
|
|
33
|
+
};
|
|
34
|
+
}
|
|
35
|
+
function validateRegistry(componentsSource, presetsSource) {
|
|
36
|
+
if (!isRecord(componentsSource)) {
|
|
37
|
+
throw (0, errors_1.registryInvalidError)("components.json must be an object.");
|
|
38
|
+
}
|
|
39
|
+
if (!isRecord(presetsSource)) {
|
|
40
|
+
throw (0, errors_1.registryInvalidError)("presets.json must be an object.");
|
|
41
|
+
}
|
|
42
|
+
const packagesSource = componentsSource.packages;
|
|
43
|
+
if (!isRecord(packagesSource)) {
|
|
44
|
+
throw (0, errors_1.registryInvalidError)("components.json.packages must be an object.");
|
|
45
|
+
}
|
|
46
|
+
const packages = {};
|
|
47
|
+
for (const [componentName, rawEntry] of Object.entries(packagesSource)) {
|
|
48
|
+
if (!isRecord(rawEntry)) {
|
|
49
|
+
throw (0, errors_1.registryInvalidError)(`components.json.packages.${componentName} must be an object.`);
|
|
50
|
+
}
|
|
51
|
+
if (typeof rawEntry.npm !== "string" || rawEntry.npm.length === 0) {
|
|
52
|
+
throw (0, errors_1.registryInvalidError)(`components.json.packages.${componentName}.npm must be a non-empty string.`);
|
|
53
|
+
}
|
|
54
|
+
const peers = readStringArray(rawEntry.peers, `components.json.packages.${componentName}.peers`);
|
|
55
|
+
const providers = readStringArray(rawEntry.providers, `components.json.packages.${componentName}.providers`);
|
|
56
|
+
const notes = readStringArray(rawEntry.notes, `components.json.packages.${componentName}.notes`);
|
|
57
|
+
if (providers) {
|
|
58
|
+
for (const provider of providers) {
|
|
59
|
+
parseProviderRequirement(provider);
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
packages[componentName] = {
|
|
63
|
+
npm: rawEntry.npm,
|
|
64
|
+
peers,
|
|
65
|
+
providers,
|
|
66
|
+
notes,
|
|
67
|
+
};
|
|
68
|
+
}
|
|
69
|
+
const presetsContainer = presetsSource.presets;
|
|
70
|
+
if (!isRecord(presetsContainer)) {
|
|
71
|
+
throw (0, errors_1.registryInvalidError)("presets.json.presets must be an object.");
|
|
72
|
+
}
|
|
73
|
+
const presets = {};
|
|
74
|
+
for (const [presetName, rawPreset] of Object.entries(presetsContainer)) {
|
|
75
|
+
if (!isStringArray(rawPreset)) {
|
|
76
|
+
throw (0, errors_1.registryInvalidError)(`presets.json.presets.${presetName} must be an array of component names.`);
|
|
77
|
+
}
|
|
78
|
+
const presetMembers = rawPreset.slice();
|
|
79
|
+
for (const componentName of presetMembers) {
|
|
80
|
+
if (!packages[componentName]) {
|
|
81
|
+
throw (0, errors_1.registryInvalidError)(`presets.json.presets.${presetName} references unknown component "${componentName}".`);
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
presets[presetName] = presetMembers;
|
|
85
|
+
}
|
|
86
|
+
return { packages, presets };
|
|
87
|
+
}
|
package/dist/ctx.d.ts
ADDED
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import { type Logger } from "./core/logger";
|
|
2
|
+
import { type PackageManagerResolutionSource } from "./core/pm/detect";
|
|
3
|
+
import type { PackageManager, PackageManagerName } from "./core/pm/types";
|
|
4
|
+
import type { Registry } from "./core/registry/schema";
|
|
5
|
+
export interface ContextOptions {
|
|
6
|
+
cwd: string;
|
|
7
|
+
pm?: string;
|
|
8
|
+
dryRun: boolean;
|
|
9
|
+
yes: boolean;
|
|
10
|
+
verbose?: boolean;
|
|
11
|
+
}
|
|
12
|
+
export interface CliContext {
|
|
13
|
+
cwd: string;
|
|
14
|
+
projectRoot: string;
|
|
15
|
+
packageJsonPath: string;
|
|
16
|
+
options: ContextOptions;
|
|
17
|
+
logger: Logger;
|
|
18
|
+
pm: PackageManager;
|
|
19
|
+
pmName: PackageManagerName;
|
|
20
|
+
detectedLockfiles: PackageManagerName[];
|
|
21
|
+
installedPackageManagers: PackageManagerName[];
|
|
22
|
+
pmResolutionSource: PackageManagerResolutionSource;
|
|
23
|
+
registry: Registry;
|
|
24
|
+
}
|
|
25
|
+
export declare function createContext(options: ContextOptions, config?: {
|
|
26
|
+
allowMissingProject?: boolean;
|
|
27
|
+
}): Promise<CliContext>;
|
package/dist/ctx.js
ADDED
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
+
var ownKeys = function(o) {
|
|
20
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
+
var ar = [];
|
|
22
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
+
return ar;
|
|
24
|
+
};
|
|
25
|
+
return ownKeys(o);
|
|
26
|
+
};
|
|
27
|
+
return function (mod) {
|
|
28
|
+
if (mod && mod.__esModule) return mod;
|
|
29
|
+
var result = {};
|
|
30
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
+
__setModuleDefault(result, mod);
|
|
32
|
+
return result;
|
|
33
|
+
};
|
|
34
|
+
})();
|
|
35
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
36
|
+
exports.createContext = createContext;
|
|
37
|
+
const path = __importStar(require("node:path"));
|
|
38
|
+
const errors_1 = require("./core/errors");
|
|
39
|
+
const logger_1 = require("./core/logger");
|
|
40
|
+
const detect_1 = require("./core/pm/detect");
|
|
41
|
+
const findRoot_1 = require("./core/project/findRoot");
|
|
42
|
+
const load_1 = require("./core/registry/load");
|
|
43
|
+
async function createContext(options, config) {
|
|
44
|
+
const cwd = path.resolve(options.cwd);
|
|
45
|
+
const allowMissingProject = config?.allowMissingProject ?? false;
|
|
46
|
+
const projectRoot = (await (0, findRoot_1.findRoot)(cwd)) ?? (allowMissingProject ? cwd : undefined);
|
|
47
|
+
if (!projectRoot) {
|
|
48
|
+
throw (0, errors_1.projectNotFoundError)(cwd);
|
|
49
|
+
}
|
|
50
|
+
const logger = (0, logger_1.createLogger)({
|
|
51
|
+
verbose: options.verbose ?? false,
|
|
52
|
+
yes: options.yes,
|
|
53
|
+
});
|
|
54
|
+
const pm = await (0, detect_1.detectPackageManager)(projectRoot, options.pm, {
|
|
55
|
+
runtime: {
|
|
56
|
+
yes: options.yes,
|
|
57
|
+
stdin: process.stdin,
|
|
58
|
+
stdout: process.stdout,
|
|
59
|
+
},
|
|
60
|
+
});
|
|
61
|
+
const registry = await (0, load_1.loadRegistry)();
|
|
62
|
+
return {
|
|
63
|
+
cwd,
|
|
64
|
+
projectRoot,
|
|
65
|
+
packageJsonPath: path.join(projectRoot, "package.json"),
|
|
66
|
+
options,
|
|
67
|
+
logger,
|
|
68
|
+
pm: pm.manager,
|
|
69
|
+
pmName: pm.name,
|
|
70
|
+
detectedLockfiles: pm.lockfiles,
|
|
71
|
+
installedPackageManagers: pm.installed,
|
|
72
|
+
pmResolutionSource: pm.source,
|
|
73
|
+
registry,
|
|
74
|
+
};
|
|
75
|
+
}
|
package/dist/index.d.ts
ADDED
package/dist/index.js
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
"use strict";
|
|
3
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
4
|
+
const cli_1 = require("./cli");
|
|
5
|
+
const errors_1 = require("./core/errors");
|
|
6
|
+
async function main() {
|
|
7
|
+
try {
|
|
8
|
+
await (0, cli_1.runCli)(process.argv.slice(2));
|
|
9
|
+
}
|
|
10
|
+
catch (error) {
|
|
11
|
+
const cliError = (0, errors_1.toCliError)(error);
|
|
12
|
+
process.stderr.write(`Error: ${cliError.message}\n`);
|
|
13
|
+
if (cliError.kind === "Unexpected" && cliError.cause instanceof Error) {
|
|
14
|
+
process.stderr.write(`${cliError.cause.stack ?? cliError.cause.message}\n`);
|
|
15
|
+
}
|
|
16
|
+
process.exitCode = cliError.exitCode;
|
|
17
|
+
return;
|
|
18
|
+
}
|
|
19
|
+
process.exitCode = errors_1.ExitCode.Success;
|
|
20
|
+
}
|
|
21
|
+
void main();
|
package/package.json
ADDED
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "lattice-ui",
|
|
3
|
+
"version": "0.4.3",
|
|
4
|
+
"private": false,
|
|
5
|
+
"description": "Lattice UI CLI",
|
|
6
|
+
"main": "dist/index.js",
|
|
7
|
+
"types": "dist/index.d.ts",
|
|
8
|
+
"files": [
|
|
9
|
+
"dist",
|
|
10
|
+
"README.md",
|
|
11
|
+
"registry",
|
|
12
|
+
"templates"
|
|
13
|
+
],
|
|
14
|
+
"engines": {
|
|
15
|
+
"node": ">=20"
|
|
16
|
+
},
|
|
17
|
+
"bin": {
|
|
18
|
+
"lattice-ui": "dist/index.js",
|
|
19
|
+
"lattice": "dist/index.js"
|
|
20
|
+
},
|
|
21
|
+
"scripts": {
|
|
22
|
+
"build": "tsc -p tsconfig.json",
|
|
23
|
+
"prebuild": "node ./scripts/clean-dist.mjs",
|
|
24
|
+
"typecheck": "tsc -p tsconfig.json --noEmit",
|
|
25
|
+
"watch": "tsc -p tsconfig.json -w"
|
|
26
|
+
}
|
|
27
|
+
}
|