@saeroon/cli 0.2.1 → 0.2.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (2) hide show
  1. package/dist/index.js +160 -5
  2. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -249,6 +249,49 @@ var SaeroonApiClient = class _SaeroonApiClient {
249
249
  false
250
250
  );
251
251
  }
252
+ // --- Public Patterns ---
253
+ /**
254
+ * 공개 패턴 목록 조회. 인증 필요.
255
+ * GET /api/v1/hosting/public/patterns
256
+ */
257
+ async getPublicPatterns(options) {
258
+ const params = new URLSearchParams();
259
+ if (options?.category) params.set("category", options.category);
260
+ if (options?.search) params.set("search", options.search);
261
+ params.set("sort", options?.sort ?? "popular");
262
+ params.set("page", String(options?.page ?? 1));
263
+ params.set("pageSize", String(options?.pageSize ?? 50));
264
+ return this.request(
265
+ "GET",
266
+ `/api/v1/hosting/public/patterns?${params.toString()}`,
267
+ void 0,
268
+ true
269
+ );
270
+ }
271
+ /**
272
+ * 공개 패턴 상세 조회. 인증 필요.
273
+ * GET /api/v1/hosting/public/patterns/{patternId}
274
+ */
275
+ async getPublicPatternDetail(patternId) {
276
+ return this.request(
277
+ "GET",
278
+ `/api/v1/hosting/public/patterns/${encodeURIComponent(patternId)}`,
279
+ void 0,
280
+ true
281
+ );
282
+ }
283
+ /**
284
+ * 공개 패턴을 내 사이트로 Fork. 인증 필요.
285
+ * POST /api/v1/hosting/public/patterns/{patternId}/fork
286
+ */
287
+ async forkPublicPattern(patternId, targetSiteId) {
288
+ return this.request(
289
+ "POST",
290
+ `/api/v1/hosting/public/patterns/${encodeURIComponent(patternId)}/fork`,
291
+ { targetSiteId },
292
+ true
293
+ );
294
+ }
252
295
  // --- Template Submission ---
253
296
  /**
254
297
  * 템플릿을 마켓플레이스에 제출.
@@ -1166,7 +1209,7 @@ https://hosting.saeroon.com/llms-full.txt
1166
1209
 
1167
1210
  // src/templates/starters/restaurant.ts
1168
1211
  var RESTAURANT_STARTER = {
1169
- version: "1.16.0",
1212
+ version: "1.21.0",
1170
1213
  settings: {
1171
1214
  title: "\uB9DB\uC788\uB294 \uD55C\uC2DD\uB2F9",
1172
1215
  description: "\uC815\uC131\uC744 \uB2F4\uC740 \uD55C\uC2DD \uC694\uB9AC \uC804\uBB38\uC810. \uC2E0\uC120\uD55C \uC7AC\uB8CC\uB85C \uB9CC\uB4E0 \uAC74\uAC15\uD55C \uD55C \uB07C\uB97C \uC81C\uACF5\uD569\uB2C8\uB2E4."
@@ -1244,7 +1287,7 @@ var RESTAURANT_STARTER = {
1244
1287
 
1245
1288
  // src/templates/starters/portfolio.ts
1246
1289
  var PORTFOLIO_STARTER = {
1247
- version: "1.16.0",
1290
+ version: "1.21.0",
1248
1291
  settings: {
1249
1292
  title: "Jane Doe \u2014 Designer & Developer",
1250
1293
  description: "Creative portfolio showcasing design and development work."
@@ -1317,7 +1360,7 @@ var PORTFOLIO_STARTER = {
1317
1360
 
1318
1361
  // src/templates/starters/business.ts
1319
1362
  var BUSINESS_STARTER = {
1320
- version: "1.16.0",
1363
+ version: "1.21.0",
1321
1364
  settings: {
1322
1365
  title: "Apex Consulting",
1323
1366
  description: "Strategic consulting for growing businesses. We help you scale smarter."
@@ -1421,7 +1464,7 @@ var BUSINESS_STARTER = {
1421
1464
 
1422
1465
  // src/templates/starters/saas.ts
1423
1466
  var SAAS_STARTER = {
1424
- version: "1.16.0",
1467
+ version: "1.21.0",
1425
1468
  settings: {
1426
1469
  title: "Flowboard \u2014 Project Management Made Simple",
1427
1470
  description: "The all-in-one project management tool for modern teams. Plan, track, and ship faster."
@@ -3174,7 +3217,7 @@ async function deployToStaging(client, siteId, schema, _syncTemplate, templateId
3174
3217
  await client.updateSiteSchema(siteId, schema);
3175
3218
  deploySpinner.stop(chalk9.green("Staging \uBC30\uD3EC \uC644\uB8CC!"));
3176
3219
  console.log("");
3177
- console.log(chalk9.cyan(`Staging URL: https://${siteId}.staging.hosting.saeroon.com`));
3220
+ console.log(chalk9.cyan(`Staging URL: https://hosting.saeroon.com/staging-sites/${siteId}`));
3178
3221
  console.log(chalk9.dim(" \u2192 Draft \uC2A4\uD0A4\uB9C8\uAC00 \uC5C5\uB370\uC774\uD2B8\uB418\uC5C8\uC2B5\uB2C8\uB2E4. \uC2A4\uD14C\uC774\uC9D5\uC5D0\uC11C \uD655\uC778\uD558\uC138\uC694."));
3179
3222
  console.log("");
3180
3223
  console.log(chalk9.dim("\uD504\uB85C\uB355\uC158 \uBC30\uD3EC: npx @saeroon/cli deploy --target production"));
@@ -4569,6 +4612,115 @@ function printSyncDiffSummary(diff) {
4569
4612
  console.log("");
4570
4613
  }
4571
4614
 
4615
+ // src/commands/pattern.ts
4616
+ import chalk18 from "chalk";
4617
+ var V2_PATTERNS = [
4618
+ { id: "v2-faq-accordion", name: "FAQ \uC544\uCF54\uB514\uC5B8", nameEn: "FAQ Accordion", category: "interactive", description: "\uB124\uC774\uD2F0\uBE0C details/summary \uAE30\uBC18 \uC811\uAE30/\uD3BC\uCE58\uAE30" },
4619
+ { id: "v2-card-grid", name: "\uCE74\uB4DC \uADF8\uB9AC\uB4DC", nameEn: "Card Grid", category: "content", description: "repeat \uAE30\uBC18 \uCE74\uB4DC \uB808\uC774\uC544\uC6C3" },
4620
+ { id: "v2-image-gallery", name: "\uC774\uBBF8\uC9C0 \uAC24\uB7EC\uB9AC", nameEn: "Image Gallery", category: "content", description: "\uADF8\uB9AC\uB4DC + \uB77C\uC774\uD2B8\uBC15\uC2A4" },
4621
+ { id: "v2-tabs", name: "\uD0ED", nameEn: "Tabs", category: "interactive", description: "exclusive \uD328\uB110 \uC804\uD658" },
4622
+ { id: "v2-contact-form", name: "\uC5F0\uB77D\uCC98 \uD3FC", nameEn: "Contact Form", category: "form", description: "input-block + form behavior" },
4623
+ { id: "v2-image-slider", name: "\uC774\uBBF8\uC9C0 \uC2AC\uB77C\uC774\uB354", nameEn: "Image Slider", category: "hero", description: "CSS scroll-snap \uCE90\uB7EC\uC140" },
4624
+ { id: "v2-testimonials", name: "\uACE0\uAC1D \uD6C4\uAE30", nameEn: "Testimonials", category: "social", description: "\uCE74\uB4DC \uADF8\uB9AC\uB4DC \uCD94\uCC9C\uC0AC" },
4625
+ { id: "v2-newsletter", name: "\uB274\uC2A4\uB808\uD130 \uAD6C\uB3C5", nameEn: "Newsletter", category: "marketing", description: "\uC774\uBA54\uC77C \uC785\uB825 + \uAD6C\uB3C5 \uBC84\uD2BC" },
4626
+ { id: "v2-stats-counter", name: "\uD1B5\uACC4 \uCE74\uC6B4\uD130", nameEn: "Stats Counter", category: "social", description: "\uC22B\uC790 \uD1B5\uACC4 \uAC15\uC870" },
4627
+ { id: "v2-naver-map", name: "\uC9C0\uB3C4", nameEn: "Map", category: "content", description: "embed-block \uAE30\uBC18 \uC9C0\uB3C4" }
4628
+ ];
4629
+ var V1_PATTERNS = [
4630
+ { id: "hero", name: "\uD788\uC5B4\uB85C", nameEn: "Hero", category: "hero", description: "\uD788\uC5B4\uB85C \uC139\uC158 (3 \uB808\uC774\uC544\uC6C3)" },
4631
+ { id: "cta-banner", name: "CTA \uBC30\uB108", nameEn: "CTA Banner", category: "marketing", description: "\uC561\uC158 \uC720\uB3C4 \uBC30\uB108" },
4632
+ { id: "feature-grid", name: "\uAE30\uB2A5 \uADF8\uB9AC\uB4DC", nameEn: "Feature Grid", category: "content", description: "\uAE30\uB2A5 \uC18C\uAC1C \uCE74\uB4DC" },
4633
+ { id: "pricing-table", name: "\uAC00\uACA9\uD45C", nameEn: "Pricing Table", category: "marketing", description: "\uAC00\uACA9 \uBE44\uAD50 \uD14C\uC774\uBE14" },
4634
+ { id: "team-profile", name: "\uD300 \uC18C\uAC1C", nameEn: "Team Profile", category: "team", description: "\uD300\uC6D0 \uD504\uB85C\uD544 \uCE74\uB4DC" }
4635
+ ];
4636
+ async function commandPatterns(options) {
4637
+ if (options?.public) {
4638
+ const apiBaseUrl = await getApiBaseUrl();
4639
+ const apiKey = await resolveApiKey();
4640
+ const client = new SaeroonApiClient(apiKey, apiBaseUrl);
4641
+ const fetchSpinner = spinner("\uACF5\uAC1C \uD328\uD134\uC744 \uC870\uD68C\uD558\uB294 \uC911...");
4642
+ try {
4643
+ const result = await client.getPublicPatterns({
4644
+ category: options.role,
4645
+ search: options.search,
4646
+ sort: "popular",
4647
+ pageSize: 50
4648
+ });
4649
+ fetchSpinner.stop(chalk18.green(`${result.total}\uAC1C\uC758 \uACF5\uAC1C \uD328\uD134\uC744 \uC870\uD68C\uD588\uC2B5\uB2C8\uB2E4.`));
4650
+ if (result.data.length === 0) {
4651
+ console.log(chalk18.gray("\n \uACF5\uAC1C \uD328\uD134\uC774 \uC5C6\uC2B5\uB2C8\uB2E4.\n"));
4652
+ return;
4653
+ }
4654
+ console.log("");
4655
+ console.log(
4656
+ ` ${chalk18.gray("ID".padEnd(10))} ${"\uC774\uB984".padEnd(18)} ${chalk18.gray("\uCE74\uD14C\uACE0\uB9AC".padEnd(12))} ${chalk18.gray("\uC0AC\uC6A9")} ${chalk18.gray("\uC791\uC131\uC790")}`
4657
+ );
4658
+ console.log(chalk18.gray(" " + "-".repeat(70)));
4659
+ for (const p of result.data) {
4660
+ const shortId = p.id.substring(0, 8);
4661
+ console.log(
4662
+ ` ${chalk18.cyan(shortId.padEnd(10))} ${p.name.padEnd(18)} ${chalk18.gray(p.category.padEnd(12))} ${chalk18.yellow(String(p.usageCount).padEnd(4))} ${chalk18.gray(p.authorName ?? "")}`
4663
+ );
4664
+ }
4665
+ console.log(chalk18.gray(`
4666
+ Fork: npx @saeroon/cli fork-pattern <pattern-id> --site-id <site-id>
4667
+ `));
4668
+ } catch (error) {
4669
+ fetchSpinner.stop(
4670
+ chalk18.red(`\uACF5\uAC1C \uD328\uD134 \uC870\uD68C \uC2E4\uD328: ${error instanceof Error ? error.message : String(error)}`)
4671
+ );
4672
+ process.exit(1);
4673
+ }
4674
+ return;
4675
+ }
4676
+ console.log(chalk18.bold("\n V2 Patterns:\n"));
4677
+ const patterns = options?.role ? V2_PATTERNS.filter((p) => p.category === options.role) : V2_PATTERNS;
4678
+ for (const p of patterns) {
4679
+ console.log(` ${chalk18.cyan(p.id.padEnd(24))} ${p.name.padEnd(12)} ${chalk18.gray(p.description)}`);
4680
+ }
4681
+ console.log(chalk18.bold("\n V1 Patterns (legacy):\n"));
4682
+ for (const p of V1_PATTERNS) {
4683
+ console.log(` ${chalk18.gray(p.id.padEnd(24))} ${p.name.padEnd(12)} ${chalk18.gray(p.description)}`);
4684
+ }
4685
+ console.log(chalk18.gray(`
4686
+ \uCD1D ${V2_PATTERNS.length + V1_PATTERNS.length}\uAC1C \uB0B4\uC7A5 \uD328\uD134`));
4687
+ console.log(chalk18.gray(` \uACF5\uAC1C \uD328\uD134 \uC870\uD68C: npx @saeroon/cli patterns --public
4688
+ `));
4689
+ }
4690
+ async function commandAddPattern(patternId) {
4691
+ const pattern = V2_PATTERNS.find((p) => p.id === patternId) || V1_PATTERNS.find((p) => p.id === patternId);
4692
+ if (!pattern) {
4693
+ console.error(chalk18.red(`Pattern "${patternId}" not found.`));
4694
+ console.log(chalk18.gray("\uC0AC\uC6A9 \uAC00\uB2A5\uD55C \uD328\uD134: " + [...V2_PATTERNS, ...V1_PATTERNS].map((p) => p.id).join(", ")));
4695
+ process.exit(1);
4696
+ }
4697
+ console.log(chalk18.cyan(`
4698
+ Pattern: ${pattern.name} (${pattern.nameEn})`));
4699
+ console.log(chalk18.gray(` Category: ${pattern.category}`));
4700
+ console.log(chalk18.gray(` ${pattern.description}`));
4701
+ console.log(chalk18.yellow("\n \uD328\uD134 \uC0BD\uC785\uC740 \uC5D0\uB514\uD130 \uB610\uB294 MCP\uC5D0\uC11C \uC2E4\uD589\uD558\uC138\uC694."));
4702
+ console.log(chalk18.gray(" MCP: get_pattern \u2192 \uC2A4\uD0A4\uB9C8 JSON \uBC18\uD658\n"));
4703
+ }
4704
+ async function commandForkPattern(patternId, options) {
4705
+ if (!options.siteId) {
4706
+ console.error(chalk18.red("--site-id \uC635\uC158\uC774 \uD544\uC694\uD569\uB2C8\uB2E4."));
4707
+ process.exit(1);
4708
+ }
4709
+ const apiBaseUrl = await getApiBaseUrl();
4710
+ const apiKey = await resolveApiKey();
4711
+ const client = new SaeroonApiClient(apiKey, apiBaseUrl);
4712
+ const forkSpinner = spinner("\uACF5\uAC1C \uD328\uD134\uC744 Fork\uD558\uB294 \uC911...");
4713
+ try {
4714
+ await client.forkPublicPattern(patternId, options.siteId);
4715
+ forkSpinner.stop(chalk18.green(`\uD328\uD134\uC774 \uC0AC\uC774\uD2B8 ${options.siteId}\uB85C Fork\uB418\uC5C8\uC2B5\uB2C8\uB2E4.`));
4716
+ } catch (error) {
4717
+ forkSpinner.stop(
4718
+ chalk18.red(`Fork \uC2E4\uD328: ${error instanceof Error ? error.message : String(error)}`)
4719
+ );
4720
+ process.exit(1);
4721
+ }
4722
+ }
4723
+
4572
4724
  // src/index.ts
4573
4725
  var require2 = createRequire(import.meta.url);
4574
4726
  var { version } = require2("../package.json");
@@ -4580,6 +4732,9 @@ program.command("init").description("\uD504\uB85C\uC81D\uD2B8 \uCD08\uAE30\uD654
4580
4732
  program.command("preview").description("\uC2A4\uD0A4\uB9C8 \uD30C\uC77C\uC744 \uAC10\uC2DC\uD558\uACE0 \uC2E4\uC2DC\uAC04 \uD504\uB9AC\uBDF0 \uC81C\uACF5").argument("[schema-path]", "\uC2A4\uD0A4\uB9C8 JSON \uD30C\uC77C \uACBD\uB85C", "schema.json").option("--api-key <key>", "API Key").option("--device <device>", "\uD504\uB9AC\uBDF0 \uB514\uBC14\uC774\uC2A4: mobile|tablet|desktop", "desktop").option("--mode <mode>", "\uD504\uB9AC\uBDF0 \uBAA8\uB4DC: rest|ws", "rest").action(commandPreview);
4581
4733
  program.command("validate").description("\uC2A4\uD0A4\uB9C8 \uC720\uD6A8\uC131 \uAC80\uC99D + \uD488\uC9C8 \uC810\uC218 \uD655\uC778").argument("[schema-path]", "\uAC80\uC99D\uD560 \uC2A4\uD0A4\uB9C8 JSON \uD30C\uC77C \uACBD\uB85C", "schema.json").option("--api-key <key>", "API Key").option("--local", "\uB85C\uCEEC \uAC80\uC99D\uB9CC \uC218\uD589 (\uB124\uD2B8\uC6CC\uD06C \uBD88\uD544\uC694)").action(commandValidate);
4582
4734
  program.command("blocks").description("\uBE14\uB85D \uCE74\uD0C8\uB85C\uADF8 \uC870\uD68C").argument("[block-type]", "\uD2B9\uC815 \uBE14\uB85D \uD0C0\uC785 \uC0C1\uC138 \uC870\uD68C").action(commandBlocks);
4735
+ program.command("patterns").description("\uD328\uD134 \uCE74\uD0C8\uB85C\uADF8 \uC870\uD68C").option("--role <category>", "\uCE74\uD14C\uACE0\uB9AC \uD544\uD130").option("--public", "\uACF5\uAC1C \uD328\uD134 \uBAA9\uB85D \uC870\uD68C (API)").option("--search <query>", "\uD328\uD134 \uAC80\uC0C9 (--public\uACFC \uD568\uAED8 \uC0AC\uC6A9)").action(commandPatterns);
4736
+ program.command("add-pattern").description("\uC2A4\uD0A4\uB9C8\uC5D0 \uD328\uD134 \uC0BD\uC785 (\uC5D0\uB514\uD130/MCP \uC5F0\uB3D9)").argument("<pattern-id>", "\uC0BD\uC785\uD560 \uD328\uD134 ID").action(commandAddPattern);
4737
+ program.command("fork-pattern").description("\uACF5\uAC1C \uD328\uD134\uC744 \uB0B4 \uC0AC\uC774\uD2B8\uB85C \uD3EC\uD06C").argument("<pattern-id>", "\uD3EC\uD06C\uD560 \uACF5\uAC1C \uD328\uD134 ID").requiredOption("--site-id <id>", "\uB300\uC0C1 \uC0AC\uC774\uD2B8 ID").action(commandForkPattern);
4583
4738
  program.command("add").description("schema.json\uC5D0 \uBE14\uB85D \uCD94\uAC00 (\uAE30\uBCF8 props \uD3EC\uD568)").argument("<block-type>", "\uCD94\uAC00\uD560 \uBE14\uB85D \uD0C0\uC785 (e.g., heading-block, image-block)").option("--id <id>", "\uBE14\uB85D ID (\uBBF8\uC9C0\uC815 \uC2DC \uC790\uB3D9 \uC0DD\uC131)").option("--parent <parentId>", "\uBD80\uBAA8 \uBE14\uB85D ID").option("--after <siblingId>", "\uC0BD\uC785 \uC704\uCE58 (\uD615\uC81C \uBE14\uB85D \uB4A4)").option("--page <pageId>", "\uB300\uC0C1 \uD398\uC774\uC9C0 ID").action(commandAdd);
4584
4739
  program.command("generate").description("AI\uB85C \uC0AC\uC774\uD2B8 \uC2A4\uD0A4\uB9C8 \uC0DD\uC131").option("--ref <url>", "\uB808\uD37C\uB7F0\uC2A4 URL (\uC0AC\uC774\uD2B8\uB97C \uBD84\uC11D\uD558\uC5EC \uC720\uC0AC\uD55C \uC2A4\uD0A4\uB9C8 \uC0DD\uC131)").option("--prompt <text>", "\uD504\uB86C\uD504\uD2B8 \uD14D\uC2A4\uD2B8 (\uC124\uBA85 \uAE30\uBC18 \uC0DD\uC131)").option("--output <file>", "\uCD9C\uB825 \uD30C\uC77C \uACBD\uB85C", "schema.json").option("--api-key <key>", "API Key").action(commandGenerate);
4585
4740
  program.command("compare").description("\uB808\uD37C\uB7F0\uC2A4 \u2194 \uD504\uB9AC\uBDF0 \uC2DC\uAC01 \uBE44\uAD50 (Playwright \uC2A4\uD06C\uB9B0\uC0F7)").option("--ref <url>", "\uB808\uD37C\uB7F0\uC2A4 URL").option("--preview <url>", "\uD504\uB9AC\uBDF0 URL").option("--output <file>", "\uCD9C\uB825 \uD30C\uC77C \uACBD\uB85C", "compare-result.png").option("--width <px>", "\uBDF0\uD3EC\uD2B8 \uB108\uBE44", "1280").option("--height <px>", "\uBDF0\uD3EC\uD2B8 \uB192\uC774", "800").action(commandCompare);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@saeroon/cli",
3
- "version": "0.2.1",
3
+ "version": "0.2.2",
4
4
  "description": "Saeroon Hosting developer CLI — preview, validate, and deploy sites & templates",
5
5
  "private": false,
6
6
  "type": "module",