@seed-design/cli 0.0.3 → 1.1.0
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 +73 -4
- package/bin/index.mjs +12 -2
- package/package.json +8 -6
- package/src/commands/add-all.ts +201 -0
- package/src/commands/add.ts +149 -149
- package/src/commands/init.ts +42 -8
- package/src/env.d.ts +13 -0
- package/src/index.ts +2 -0
- package/src/schema.ts +38 -64
- package/src/tests/resolve-dependencies.test.ts +424 -0
- package/src/utils/analytics.ts +119 -0
- package/src/utils/fetch.ts +122 -0
- package/src/utils/get-config.ts +15 -48
- package/src/utils/install.ts +7 -12
- package/src/utils/resolve-dependencies.ts +77 -0
- package/src/utils/transformers/index.ts +2 -1
- package/src/utils/transformers/transform-jsx.ts +0 -1
- package/src/utils/transformers/transform-rsc.ts +21 -4
- package/src/utils/write.ts +75 -0
- package/src/test/add-relative-registries.test.ts +0 -182
- package/src/utils/add-relative-registries.ts +0 -43
- package/src/utils/get-metadata.ts +0 -75
package/src/commands/add.ts
CHANGED
|
@@ -1,41 +1,31 @@
|
|
|
1
1
|
import { getConfig } from "@/src/utils/get-config";
|
|
2
|
-
import {
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
getRegistryUIIndex,
|
|
6
|
-
} from "@/src/utils/get-metadata";
|
|
7
|
-
import { transform } from "@/src/utils/transformers";
|
|
2
|
+
import { resolveDependencies } from "@/src/utils/resolve-dependencies";
|
|
3
|
+
import { fetchAvailableRegistries, fetchRegistry } from "@/src/utils/fetch";
|
|
4
|
+
import { writeRegistryItemSnippets } from "@/src/utils/write";
|
|
8
5
|
import * as p from "@clack/prompts";
|
|
9
|
-
import fs from "fs-extra";
|
|
10
6
|
import path from "path";
|
|
11
|
-
import color from "picocolors";
|
|
12
7
|
import { z } from "zod";
|
|
13
8
|
|
|
14
9
|
import type { CAC } from "cac";
|
|
15
10
|
import { BASE_URL } from "../constants";
|
|
16
|
-
import { addRelativeRegistries } from "../utils/add-relative-registries";
|
|
17
11
|
import { highlight } from "../utils/color";
|
|
18
12
|
import { installDependencies } from "../utils/install";
|
|
19
|
-
import
|
|
13
|
+
import { analytics } from "../utils/analytics";
|
|
20
14
|
|
|
21
15
|
const addOptionsSchema = z.object({
|
|
22
|
-
|
|
16
|
+
itemIds: z.array(z.string()).optional(),
|
|
17
|
+
/**
|
|
18
|
+
* @deprecated use `seed-design add-all` instead
|
|
19
|
+
*/
|
|
23
20
|
all: z.boolean(),
|
|
24
|
-
includeDeprecated: z.boolean().optional(),
|
|
25
21
|
cwd: z.string(),
|
|
26
22
|
baseUrl: z.string().optional(),
|
|
27
|
-
// yes: z.boolean(),
|
|
28
|
-
// overwrite: z.boolean(),
|
|
29
|
-
// path: z.string().optional(),
|
|
30
23
|
});
|
|
31
24
|
|
|
32
25
|
export const addCommand = (cli: CAC) => {
|
|
33
26
|
cli
|
|
34
|
-
.command("add [...
|
|
35
|
-
.option("-a, --all", "Add all
|
|
36
|
-
default: false,
|
|
37
|
-
})
|
|
38
|
-
.option("--include-deprecated", "Include deprecated components when used with `--all`", {
|
|
27
|
+
.command("add [...item-ids]", "add items")
|
|
28
|
+
.option("-a, --all", "[Deprecated] Add all items", {
|
|
39
29
|
default: false,
|
|
40
30
|
})
|
|
41
31
|
.option("-c, --cwd <cwd>", "the working directory. defaults to the current directory.", {
|
|
@@ -44,46 +34,76 @@ export const addCommand = (cli: CAC) => {
|
|
|
44
34
|
.option(
|
|
45
35
|
"-u, --baseUrl <baseUrl>",
|
|
46
36
|
"the base url of the registry. defaults to the current directory.",
|
|
47
|
-
{
|
|
48
|
-
default: BASE_URL,
|
|
49
|
-
},
|
|
37
|
+
{ default: BASE_URL },
|
|
50
38
|
)
|
|
51
|
-
.example("seed-design add action-button")
|
|
52
|
-
.example("seed-design add alert-dialog")
|
|
53
|
-
.action(async (
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
39
|
+
.example("seed-design add ui:action-button")
|
|
40
|
+
.example("seed-design add ui:alert-dialog")
|
|
41
|
+
.action(async (itemIds, opts) => {
|
|
42
|
+
const startTime = Date.now();
|
|
43
|
+
p.intro("seed-design add");
|
|
44
|
+
|
|
45
|
+
const {
|
|
46
|
+
success,
|
|
47
|
+
data: { all, ...options },
|
|
48
|
+
error,
|
|
49
|
+
} = addOptionsSchema.safeParse({ itemIds, ...opts });
|
|
50
|
+
|
|
51
|
+
if (!success) {
|
|
52
|
+
p.log.error(`잘못된 옵션이에요: ${error?.message}`);
|
|
53
|
+
|
|
54
|
+
process.exit(1);
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
if (all) {
|
|
58
|
+
p.log.error(
|
|
59
|
+
"`--all` 옵션은 더 이상 지원되지 않아요. 대신 `seed-design add-all` 명령어를 사용해주세요.",
|
|
60
|
+
);
|
|
61
|
+
|
|
62
|
+
process.exit(1);
|
|
63
|
+
}
|
|
64
|
+
|
|
59
65
|
const cwd = options.cwd;
|
|
60
66
|
const baseUrl = options.baseUrl;
|
|
61
67
|
const config = await getConfig(cwd);
|
|
62
|
-
const
|
|
63
|
-
const libRegistryIndex = await getRegistryLibIndex(baseUrl);
|
|
68
|
+
const rootPath = path.resolve(cwd, config.path);
|
|
64
69
|
|
|
65
|
-
const
|
|
66
|
-
if (options.all) {
|
|
67
|
-
if (options.includeDeprecated) return registryComponentIndex.map((c) => c.name);
|
|
70
|
+
const { start, stop } = p.spinner();
|
|
68
71
|
|
|
69
|
-
|
|
70
|
-
}
|
|
72
|
+
start("Registry를 가져오고 있어요...");
|
|
71
73
|
|
|
72
|
-
|
|
74
|
+
const publicRegistries = await Promise.all(
|
|
75
|
+
(await fetchAvailableRegistries({ baseUrl })).map(async ({ id }) =>
|
|
76
|
+
fetchRegistry({ baseUrl, registryId: id }),
|
|
77
|
+
),
|
|
78
|
+
);
|
|
79
|
+
|
|
80
|
+
stop("Registry를 가져왔어요.");
|
|
81
|
+
|
|
82
|
+
const selectedItemKeys: string[] = await (async () => {
|
|
83
|
+
if (options.itemIds.length > 0) return options.itemIds;
|
|
73
84
|
|
|
74
85
|
const selected = await p.multiselect({
|
|
75
|
-
message: "추가할
|
|
76
|
-
options:
|
|
77
|
-
.
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
86
|
+
message: "추가할 항목을 선택해주세요 (스페이스 바로 여러 개 선택 가능)",
|
|
87
|
+
options: publicRegistries
|
|
88
|
+
.filter(({ hideFromCLICatalog }) => !hideFromCLICatalog)
|
|
89
|
+
.flatMap(({ id: registryId, items }) =>
|
|
90
|
+
items
|
|
91
|
+
.filter(({ hideFromCLICatalog }) => !hideFromCLICatalog)
|
|
92
|
+
.sort((a, b) => a.id.localeCompare(b.id))
|
|
93
|
+
.map(({ id, description, deprecated }) => ({
|
|
94
|
+
label: `${deprecated ? "(deprecated) " : ""}${highlight(registryId)}:${id}`,
|
|
95
|
+
value: `${registryId}:${id}`,
|
|
96
|
+
hint: description,
|
|
97
|
+
|
|
98
|
+
// used for sorting
|
|
99
|
+
deprecated,
|
|
100
|
+
registryItemCount: items.length,
|
|
101
|
+
})),
|
|
102
|
+
)
|
|
83
103
|
.sort((a, b) => {
|
|
84
|
-
if (a.deprecated
|
|
104
|
+
if (a.deprecated !== b.deprecated) return a.deprecated ? 1 : -1;
|
|
85
105
|
|
|
86
|
-
return
|
|
106
|
+
return b.registryItemCount - a.registryItemCount;
|
|
87
107
|
}),
|
|
88
108
|
});
|
|
89
109
|
|
|
@@ -95,138 +115,118 @@ export const addCommand = (cli: CAC) => {
|
|
|
95
115
|
return selected;
|
|
96
116
|
})();
|
|
97
117
|
|
|
98
|
-
if (!
|
|
99
|
-
p.log.error("
|
|
118
|
+
if (!selectedItemKeys?.length) {
|
|
119
|
+
p.log.error("항목을 찾을 수 없어요.");
|
|
120
|
+
|
|
100
121
|
process.exit(0);
|
|
101
122
|
}
|
|
102
123
|
|
|
103
|
-
p.log.message(`선택된
|
|
124
|
+
p.log.message(`선택된 항목: ${highlight(selectedItemKeys.join(", "))}`);
|
|
104
125
|
|
|
105
|
-
const
|
|
106
|
-
userSelects: selectedComponents,
|
|
107
|
-
uiRegistryIndex: registryComponentIndex,
|
|
108
|
-
libRegistryIndex,
|
|
109
|
-
});
|
|
126
|
+
const filteredItemKeys: string[] = [];
|
|
110
127
|
|
|
111
|
-
const
|
|
128
|
+
for (const itemKey of selectedItemKeys) {
|
|
129
|
+
const [registryId, ...rest] = itemKey.split(":");
|
|
130
|
+
const itemId = rest.join(":");
|
|
112
131
|
|
|
113
|
-
|
|
114
|
-
|
|
132
|
+
if (!registryId || !itemId) {
|
|
133
|
+
p.log.error(
|
|
134
|
+
`${highlight(itemKey)}: 항목 이름이 잘못되었어요. ${highlight("ui:action-button")}과 같은 형식으로 입력해보세요.`,
|
|
135
|
+
);
|
|
115
136
|
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
allRegistryItems.push(registryItem);
|
|
119
|
-
}
|
|
137
|
+
process.exit(1);
|
|
138
|
+
}
|
|
120
139
|
|
|
121
|
-
|
|
140
|
+
const foundItem = publicRegistries
|
|
141
|
+
.find((r) => r.id === registryId)
|
|
142
|
+
?.items.find((i) => i.id === itemId);
|
|
122
143
|
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
(c) => !selectedComponents.includes(c.name),
|
|
126
|
-
);
|
|
127
|
-
p.log.message(
|
|
128
|
-
`추가로 설치될 레지스트리: ${highlight(
|
|
129
|
-
filteredRegistryItems.map((c) => c.name).join(", "),
|
|
130
|
-
)}`,
|
|
131
|
-
);
|
|
132
|
-
}
|
|
144
|
+
if (!foundItem) {
|
|
145
|
+
p.log.error(`${highlight(itemKey)}: 항목을 찾을 수 없어요.`);
|
|
133
146
|
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
filtered: new Set(),
|
|
139
|
-
};
|
|
140
|
-
for (const component of allRegistryItems) {
|
|
141
|
-
if (component.deprecated && !options.includeDeprecated) {
|
|
147
|
+
process.exit(1);
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
if (foundItem.deprecated) {
|
|
142
151
|
const confirm = await p.confirm({
|
|
143
|
-
message: `${highlight(
|
|
152
|
+
message: `${highlight(foundItem.id)}: deprecated 되었어요. 추가할까요?`,
|
|
144
153
|
initialValue: false,
|
|
145
154
|
});
|
|
146
155
|
|
|
147
156
|
if (confirm === false || p.isCancel(confirm)) {
|
|
148
|
-
p.log.info(`${highlight(
|
|
157
|
+
p.log.info(`${highlight(foundItem.id)}: 추가하지 않을게요.`);
|
|
149
158
|
|
|
150
159
|
continue;
|
|
151
160
|
}
|
|
152
161
|
}
|
|
153
162
|
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
switch (registry.type) {
|
|
157
|
-
case "ui":
|
|
158
|
-
targetPath = config.resolvedUIPaths;
|
|
159
|
-
break;
|
|
160
|
-
case "lib":
|
|
161
|
-
targetPath = config.resolvedLibPaths;
|
|
162
|
-
break;
|
|
163
|
-
default:
|
|
164
|
-
break;
|
|
165
|
-
}
|
|
163
|
+
filteredItemKeys.push(itemKey);
|
|
164
|
+
}
|
|
166
165
|
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
166
|
+
const { registryItemsToAdd, npmDependenciesToAdd } = resolveDependencies({
|
|
167
|
+
selectedItemKeys: filteredItemKeys,
|
|
168
|
+
publicRegistries,
|
|
169
|
+
});
|
|
170
170
|
|
|
171
|
-
|
|
171
|
+
p.log.info(
|
|
172
|
+
`추가할 항목: ${highlight(registryItemsToAdd.map((r) => r.items.map((i) => `${r.registryId}:${i.id}`).join(", ")).join(", ") || "없음")}
|
|
172
173
|
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
config,
|
|
176
|
-
raw: registry.content,
|
|
177
|
-
});
|
|
174
|
+
설치할 의존성: ${highlight(Array.from(npmDependenciesToAdd).join(", ") || "없음")}`,
|
|
175
|
+
);
|
|
178
176
|
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
177
|
+
await writeRegistryItemSnippets({
|
|
178
|
+
registryItemsToAdd,
|
|
179
|
+
rootPath,
|
|
180
|
+
cwd,
|
|
181
|
+
baseUrl,
|
|
182
|
+
config,
|
|
183
|
+
});
|
|
183
184
|
|
|
184
|
-
|
|
185
|
-
|
|
185
|
+
try {
|
|
186
|
+
const { installed, filtered } = await installDependencies({
|
|
187
|
+
cwd,
|
|
188
|
+
deps: Array.from(npmDependenciesToAdd),
|
|
189
|
+
});
|
|
186
190
|
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
path: relativePath,
|
|
190
|
-
});
|
|
191
|
+
if (installed.size === 0) {
|
|
192
|
+
p.log.message("모든 의존성이 이미 설치되어 있어요.");
|
|
191
193
|
}
|
|
192
194
|
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
const result = await installDependencies({ cwd, deps: component.dependencies });
|
|
196
|
-
installResult.installed = new Set([...installResult.installed, ...result.installed]);
|
|
197
|
-
installResult.filtered = new Set([...installResult.filtered, ...result.filtered]);
|
|
198
|
-
}
|
|
195
|
+
if (installed.size) {
|
|
196
|
+
p.log.message(`의존성 설치 완료: ${highlight(Array.from(installed).join(", "))}`);
|
|
199
197
|
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
dev: true,
|
|
206
|
-
});
|
|
207
|
-
installResult.installed = new Set([...installResult.installed, ...result.installed]);
|
|
208
|
-
installResult.filtered = new Set([...installResult.filtered, ...result.filtered]);
|
|
198
|
+
if (filtered.size) {
|
|
199
|
+
p.log.message(
|
|
200
|
+
`설치하지 않은 의존성 (이미 설치됨): ${highlight(Array.from(filtered).join(", "))}`,
|
|
201
|
+
);
|
|
202
|
+
}
|
|
209
203
|
}
|
|
210
|
-
|
|
211
|
-
|
|
204
|
+
p.outro("완료했어요.");
|
|
205
|
+
} catch (error) {
|
|
206
|
+
p.log.error(`추가에 실패했어요. ${error}`);
|
|
207
|
+
p.outro(highlight("작업이 취소됐어요."));
|
|
208
|
+
process.exit(1);
|
|
212
209
|
}
|
|
213
210
|
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
}
|
|
224
|
-
if (registryResult.length) {
|
|
225
|
-
for (const registry of registryResult) {
|
|
226
|
-
p.log.message(`추가된 파일: ${highlight(registry.path)}`);
|
|
227
|
-
}
|
|
228
|
-
}
|
|
211
|
+
// add 성공 이벤트 추적
|
|
212
|
+
const duration = Date.now() - startTime;
|
|
213
|
+
const uniqueRegistries = new Set(registryItemsToAdd.map((r) => r.registryId));
|
|
214
|
+
const hasDeprecated = selectedItemKeys.some((itemKey) => {
|
|
215
|
+
const [registryId, ...rest] = itemKey.split(":");
|
|
216
|
+
const itemId = rest.join(":");
|
|
217
|
+
return publicRegistries.find((r) => r.id === registryId)?.items.find((i) => i.id === itemId)
|
|
218
|
+
?.deprecated;
|
|
219
|
+
});
|
|
229
220
|
|
|
230
|
-
|
|
221
|
+
await analytics.track(options.cwd, {
|
|
222
|
+
event: "add",
|
|
223
|
+
properties: {
|
|
224
|
+
items_count: filteredItemKeys.length,
|
|
225
|
+
registries: Array.from(uniqueRegistries),
|
|
226
|
+
has_deprecated: hasDeprecated,
|
|
227
|
+
dependencies_count: npmDependenciesToAdd.size,
|
|
228
|
+
duration_ms: duration,
|
|
229
|
+
},
|
|
230
|
+
});
|
|
231
231
|
});
|
|
232
232
|
};
|
package/src/commands/init.ts
CHANGED
|
@@ -1,12 +1,14 @@
|
|
|
1
1
|
import * as p from "@clack/prompts";
|
|
2
2
|
import fs from "fs-extra";
|
|
3
3
|
import path from "path";
|
|
4
|
-
import color from "picocolors";
|
|
5
4
|
import { z } from "zod";
|
|
5
|
+
import { analytics } from "../utils/analytics";
|
|
6
|
+
import { highlight } from "../utils/color";
|
|
6
7
|
|
|
7
|
-
import type {
|
|
8
|
+
import type { Config } from "@/src/utils/get-config";
|
|
8
9
|
|
|
9
10
|
import type { CAC } from "cac";
|
|
11
|
+
import dedent from "dedent";
|
|
10
12
|
|
|
11
13
|
const initOptionsSchema = z.object({
|
|
12
14
|
cwd: z.string(),
|
|
@@ -21,15 +23,16 @@ export const initCommand = (cli: CAC) => {
|
|
|
21
23
|
})
|
|
22
24
|
.option("-y, --yes", "모든 질문에 대해 기본값으로 답변합니다.")
|
|
23
25
|
.action(async (opts) => {
|
|
24
|
-
const
|
|
25
|
-
p.intro(
|
|
26
|
+
const startTime = Date.now();
|
|
27
|
+
p.intro("seed-design.json 파일 생성");
|
|
26
28
|
|
|
27
29
|
const options = initOptionsSchema.parse(opts);
|
|
28
30
|
const isYesOption = options.yes;
|
|
29
|
-
let config:
|
|
31
|
+
let config: Config = {
|
|
30
32
|
rsc: false,
|
|
31
33
|
tsx: true,
|
|
32
34
|
path: "./seed-design",
|
|
35
|
+
telemetry: true,
|
|
33
36
|
};
|
|
34
37
|
|
|
35
38
|
if (!isYesOption) {
|
|
@@ -52,6 +55,11 @@ export const initCommand = (cli: CAC) => {
|
|
|
52
55
|
defaultValue: "./seed-design",
|
|
53
56
|
placeholder: "./seed-design",
|
|
54
57
|
}),
|
|
58
|
+
telemetry: () =>
|
|
59
|
+
p.confirm({
|
|
60
|
+
message: `개선을 위해 ${highlight("익명 사용 데이터")}를 수집할까요?`,
|
|
61
|
+
initialValue: true,
|
|
62
|
+
}),
|
|
55
63
|
},
|
|
56
64
|
{
|
|
57
65
|
onCancel: () => {
|
|
@@ -73,15 +81,41 @@ export const initCommand = (cli: CAC) => {
|
|
|
73
81
|
await fs.writeFile(targetPath, `${JSON.stringify(config, null, 2)}\n`, "utf-8");
|
|
74
82
|
const relativePath = path.relative(process.cwd(), targetPath);
|
|
75
83
|
stop(`seed-design.json 파일이 ${highlight(relativePath)}에 생성됐어요.`);
|
|
76
|
-
|
|
84
|
+
|
|
85
|
+
p.log.info(highlight("seed-design add {component} 명령어로 컴포넌트를 추가해보세요!"));
|
|
77
86
|
p.log.info(
|
|
78
|
-
|
|
87
|
+
highlight("seed-design add 명령어로 추가할 수 있는 모든 컴포넌트를 확인해보세요."),
|
|
88
|
+
);
|
|
89
|
+
|
|
90
|
+
p.note(
|
|
91
|
+
dedent(`SEED Design CLI는 개선을 위해 익명 사용 데이터를 수집해요.
|
|
92
|
+
|
|
93
|
+
비활성화하려면:
|
|
94
|
+
• seed-design.json에서 ${highlight('"telemetry": false')}로 설정
|
|
95
|
+
• ${highlight("DISABLE_TELEMETRY=true")} 환경 변수 설정
|
|
96
|
+
|
|
97
|
+
자세한 내용: https://seed-design.com/react/getting-started/cli/configuration#telemetry`),
|
|
98
|
+
"Telemetry 안내",
|
|
79
99
|
);
|
|
100
|
+
|
|
80
101
|
p.outro("작업이 완료됐어요.");
|
|
81
102
|
} catch (error) {
|
|
82
103
|
p.log.error(`seed-design.json 파일 생성에 실패했어요. ${error}`);
|
|
83
|
-
p.outro(
|
|
104
|
+
p.outro(highlight("작업이 취소됐어요."));
|
|
84
105
|
process.exit(1);
|
|
85
106
|
}
|
|
107
|
+
|
|
108
|
+
// init 성공 이벤트 추적
|
|
109
|
+
const duration = Date.now() - startTime;
|
|
110
|
+
await analytics.track(options.cwd, {
|
|
111
|
+
event: "init",
|
|
112
|
+
properties: {
|
|
113
|
+
tsx: config.tsx,
|
|
114
|
+
rsc: config.rsc,
|
|
115
|
+
telemetry: config.telemetry,
|
|
116
|
+
yes_option: isYesOption,
|
|
117
|
+
duration_ms: duration,
|
|
118
|
+
},
|
|
119
|
+
});
|
|
86
120
|
});
|
|
87
121
|
};
|
package/src/env.d.ts
ADDED
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
declare global {
|
|
2
|
+
namespace NodeJS {
|
|
3
|
+
interface ProcessEnv {
|
|
4
|
+
NODE_ENV: "dev" | "prod";
|
|
5
|
+
POSTHOG_API_KEY?: string;
|
|
6
|
+
POSTHOG_HOST?: string;
|
|
7
|
+
DISABLE_TELEMETRY?: "true" | "false";
|
|
8
|
+
SEED_DISABLE_TELEMETRY?: "true" | "false";
|
|
9
|
+
}
|
|
10
|
+
}
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
export {};
|
package/src/index.ts
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
|
|
3
3
|
import { addCommand } from "@/src/commands/add";
|
|
4
|
+
import { addAllCommand } from "@/src/commands/add-all";
|
|
4
5
|
import { initCommand } from "@/src/commands/init";
|
|
5
6
|
import { getPackageInfo } from "@/src/utils/get-package-info";
|
|
6
7
|
import { cac } from "cac";
|
|
@@ -13,6 +14,7 @@ async function main() {
|
|
|
13
14
|
|
|
14
15
|
/* Commands */
|
|
15
16
|
addCommand(CLI);
|
|
17
|
+
addAllCommand(CLI);
|
|
16
18
|
initCommand(CLI);
|
|
17
19
|
|
|
18
20
|
CLI.version(packageInfo.version || "1.0.0", "-v, --version");
|
package/src/schema.ts
CHANGED
|
@@ -1,81 +1,55 @@
|
|
|
1
1
|
import { z } from "zod";
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
* @example chip-tabs, alert-dialog
|
|
9
|
-
*/
|
|
10
|
-
name: z.string(),
|
|
3
|
+
/**
|
|
4
|
+
* this should be in sync with `docs/registry/schema.ts`
|
|
5
|
+
*/
|
|
6
|
+
export const publicRegistryItemSchema = z.object({
|
|
7
|
+
id: z.string(),
|
|
11
8
|
|
|
12
9
|
description: z.string().optional(),
|
|
13
10
|
|
|
14
|
-
|
|
15
|
-
* @description 레지스트리 의존성
|
|
16
|
-
* @example @seed-design/react-tabs
|
|
17
|
-
*/
|
|
18
|
-
dependencies: z.array(z.string()).optional(),
|
|
11
|
+
deprecated: z.boolean().optional(),
|
|
19
12
|
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
13
|
+
hideFromCLICatalog: z.boolean().optional(),
|
|
14
|
+
|
|
15
|
+
///////////////////////////////////////////////////////////////
|
|
16
|
+
|
|
17
|
+
dependencies: z.array(z.string()).optional(),
|
|
24
18
|
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
19
|
+
innerDependencies: z
|
|
20
|
+
.array(
|
|
21
|
+
z.object({
|
|
22
|
+
registryId: z.string(),
|
|
23
|
+
itemIds: z.array(z.string()),
|
|
24
|
+
}),
|
|
25
|
+
)
|
|
26
|
+
.optional(),
|
|
32
27
|
|
|
33
|
-
|
|
34
|
-
* @description
|
|
35
|
-
* 컴포넌트 코드 스니펫 경로, 여러 파일이 될 수 있어서 배열로 정의
|
|
36
|
-
* `:`를 기준으로 왼쪽은 {registryType}, 오른쪽은 파일 이름
|
|
37
|
-
* @example ui:alert-dialog.tsx
|
|
38
|
-
* @example ui:use-dismissible.ts
|
|
39
|
-
* @example lib:manner-temp-level.ts
|
|
40
|
-
*/
|
|
41
|
-
files: z.array(z.string()),
|
|
28
|
+
///////////////////////////////////////////////////////////////
|
|
42
29
|
|
|
43
|
-
|
|
44
|
-
* @description 컴포넌트 deprecated 여부
|
|
45
|
-
*/
|
|
46
|
-
deprecated: z.literal(true).optional(),
|
|
30
|
+
snippets: z.array(z.object({ path: z.string(), content: z.string() })),
|
|
47
31
|
});
|
|
48
|
-
export const registryUISchema = z.array(registryUIItemSchema);
|
|
49
32
|
|
|
50
33
|
/**
|
|
51
|
-
*
|
|
34
|
+
* this should be in sync with `packages/cli/src/schema.ts`
|
|
52
35
|
*/
|
|
53
|
-
const
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
}),
|
|
36
|
+
export const publicRegistrySchema = z.object({
|
|
37
|
+
id: z.string(),
|
|
38
|
+
|
|
39
|
+
hideFromCLICatalog: z.boolean().optional(),
|
|
40
|
+
|
|
41
|
+
items: z.array(
|
|
42
|
+
publicRegistryItemSchema
|
|
43
|
+
.omit({ snippets: true })
|
|
44
|
+
.extend({ snippets: z.array(z.object({ path: z.string() })) }),
|
|
63
45
|
),
|
|
64
46
|
});
|
|
65
|
-
export const registryComponentMachineGeneratedSchema = z.array(
|
|
66
|
-
registryUIItemMachineGeneratedSchema,
|
|
67
|
-
);
|
|
68
47
|
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
export type RegistryLibItem = z.infer<typeof registryUIItemSchema>;
|
|
74
|
-
export type RegistryLib = z.infer<typeof registryUISchema>;
|
|
75
|
-
export type RegistryUIItem = z.infer<typeof registryUIItemSchema>;
|
|
76
|
-
export type RegistryUI = z.infer<typeof registryUISchema>;
|
|
48
|
+
/**
|
|
49
|
+
* this should be in sync with `packages/cli/src/schema.ts`
|
|
50
|
+
*/
|
|
51
|
+
export const publicAvailableRegistriesSchema = z.array(z.object({ id: z.string() }));
|
|
77
52
|
|
|
78
|
-
export type
|
|
79
|
-
export type
|
|
80
|
-
export type
|
|
81
|
-
export type RegistryLibMachineGenerated = z.infer<typeof registryComponentMachineGeneratedSchema>;
|
|
53
|
+
export type PublicRegistryItem = z.infer<typeof publicRegistryItemSchema>;
|
|
54
|
+
export type PublicRegistry = z.infer<typeof publicRegistrySchema>;
|
|
55
|
+
export type PublicAvailableRegistries = z.infer<typeof publicAvailableRegistriesSchema>;
|