@cimplify/cli 0.2.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 +69 -0
- package/dist/add-ZJQJZJEF.mjs +125 -0
- package/dist/chunk-4YSOZ6LY.mjs +61 -0
- package/dist/chunk-4ZVTPMUZ.mjs +155 -0
- package/dist/chunk-5XH72JMJ.mjs +211 -0
- package/dist/chunk-D7D75ONX.mjs +36 -0
- package/dist/chunk-JJYWETGA.mjs +127 -0
- package/dist/chunk-L6474RPL.mjs +37 -0
- package/dist/chunk-MQMNWLMU.mjs +48 -0
- package/dist/chunk-NZ4RG62Z.mjs +141 -0
- package/dist/chunk-TAMGCHIL.mjs +81 -0
- package/dist/chunk-XSWWWO6H.mjs +3779 -0
- package/dist/deploy-WCZOGMED.mjs +206 -0
- package/dist/dev-4HKIXWXX.mjs +130 -0
- package/dist/dispatcher.mjs +321 -0
- package/dist/domains-3RJ4T5IX.mjs +387 -0
- package/dist/env-LBYBCBWV.mjs +268 -0
- package/dist/link-SEJNW7JS.mjs +45 -0
- package/dist/list-D4JC2VWY.mjs +48 -0
- package/dist/login-MRYWLQRY.mjs +276 -0
- package/dist/logout-ZFZLSJ32.mjs +16 -0
- package/dist/logs-LK7CMBCE.mjs +95 -0
- package/dist/projects-QJUGOCQZ.mjs +164 -0
- package/dist/repo-MV22OHON.mjs +8 -0
- package/dist/rollback-XO7RIG2A.mjs +107 -0
- package/dist/status-7CMVLD54.mjs +127 -0
- package/dist/unlink-5ABCT7B6.mjs +16 -0
- package/dist/whoami-INHDUHWA.mjs +24 -0
- package/package.json +44 -0
- package/templates/storefront-bakery/.claude/skills/cimplify-storefront/SKILL.md +145 -0
- package/templates/storefront-bakery/.cursor/rules/cimplify-storefront.mdc +25 -0
- package/templates/storefront-bakery/.env.example +16 -0
- package/templates/storefront-bakery/AGENTS.md +120 -0
- package/templates/storefront-bakery/CLAUDE.md +22 -0
- package/templates/storefront-bakery/README.md +73 -0
- package/templates/storefront-bakery/__tests__/brand.test.ts +4 -0
- package/templates/storefront-bakery/__tests__/cart-flow.test.ts +4 -0
- package/templates/storefront-bakery/__tests__/contract.test.ts +4 -0
- package/templates/storefront-bakery/app/about/page.tsx +38 -0
- package/templates/storefront-bakery/app/accessibility/page.tsx +11 -0
- package/templates/storefront-bakery/app/account/addresses/page.tsx +21 -0
- package/templates/storefront-bakery/app/account/orders/page.tsx +21 -0
- package/templates/storefront-bakery/app/account/page.tsx +22 -0
- package/templates/storefront-bakery/app/account/settings/page.tsx +21 -0
- package/templates/storefront-bakery/app/cart/page.tsx +9 -0
- package/templates/storefront-bakery/app/categories/[slug]/listing-client.tsx +19 -0
- package/templates/storefront-bakery/app/categories/[slug]/page.tsx +118 -0
- package/templates/storefront-bakery/app/checkout/page.tsx +17 -0
- package/templates/storefront-bakery/app/collections/[slug]/listing-client.tsx +20 -0
- package/templates/storefront-bakery/app/collections/[slug]/page.tsx +118 -0
- package/templates/storefront-bakery/app/contact/contact-form.tsx +109 -0
- package/templates/storefront-bakery/app/contact/page.tsx +54 -0
- package/templates/storefront-bakery/app/error.tsx +60 -0
- package/templates/storefront-bakery/app/faq/page.tsx +46 -0
- package/templates/storefront-bakery/app/globals.css +47 -0
- package/templates/storefront-bakery/app/layout.tsx +82 -0
- package/templates/storefront-bakery/app/llms.txt/route.ts +94 -0
- package/templates/storefront-bakery/app/login/page.tsx +17 -0
- package/templates/storefront-bakery/app/not-found.tsx +39 -0
- package/templates/storefront-bakery/app/opensearch.xml/route.ts +37 -0
- package/templates/storefront-bakery/app/orders/[id]/page.tsx +21 -0
- package/templates/storefront-bakery/app/page.tsx +97 -0
- package/templates/storefront-bakery/app/privacy/page.tsx +44 -0
- package/templates/storefront-bakery/app/returns/page.tsx +11 -0
- package/templates/storefront-bakery/app/robots.ts +18 -0
- package/templates/storefront-bakery/app/search/page.tsx +38 -0
- package/templates/storefront-bakery/app/search/search-client.tsx +7 -0
- package/templates/storefront-bakery/app/shipping/page.tsx +16 -0
- package/templates/storefront-bakery/app/shop/page.tsx +31 -0
- package/templates/storefront-bakery/app/shop/shop-client.tsx +27 -0
- package/templates/storefront-bakery/app/signup/page.tsx +17 -0
- package/templates/storefront-bakery/app/sitemap-page/page.tsx +167 -0
- package/templates/storefront-bakery/app/sitemap.ts +62 -0
- package/templates/storefront-bakery/app/terms/page.tsx +44 -0
- package/templates/storefront-bakery/app/track-order/page.tsx +24 -0
- package/templates/storefront-bakery/app/track-order/track-order-form.tsx +69 -0
- package/templates/storefront-bakery/components/account-iframe.tsx +13 -0
- package/templates/storefront-bakery/components/cart-drawer.tsx +14 -0
- package/templates/storefront-bakery/components/cart-pill.tsx +36 -0
- package/templates/storefront-bakery/components/category-grid.tsx +28 -0
- package/templates/storefront-bakery/components/collection-strip.tsx +45 -0
- package/templates/storefront-bakery/components/footer.tsx +148 -0
- package/templates/storefront-bakery/components/header.tsx +43 -0
- package/templates/storefront-bakery/components/hero.tsx +25 -0
- package/templates/storefront-bakery/components/nav-link.tsx +20 -0
- package/templates/storefront-bakery/components/policy-page.tsx +49 -0
- package/templates/storefront-bakery/components/product-modal.tsx +104 -0
- package/templates/storefront-bakery/components/providers.tsx +35 -0
- package/templates/storefront-bakery/components/store-product-card.tsx +87 -0
- package/templates/storefront-bakery/lib/brand.ts +570 -0
- package/templates/storefront-bakery/lib/cart.ts +12 -0
- package/templates/storefront-bakery/next.config.ts +42 -0
- package/templates/storefront-bakery/package.json +35 -0
- package/templates/storefront-bakery/postcss.config.mjs +7 -0
- package/templates/storefront-bakery/tsconfig.json +23 -0
- package/templates/storefront-bakery/vitest.config.ts +9 -0
- package/templates/storefront-fashion/.claude/skills/cimplify-storefront/SKILL.md +145 -0
- package/templates/storefront-fashion/.cursor/rules/cimplify-storefront.mdc +25 -0
- package/templates/storefront-fashion/.env.example +16 -0
- package/templates/storefront-fashion/AGENTS.md +126 -0
- package/templates/storefront-fashion/CLAUDE.md +22 -0
- package/templates/storefront-fashion/README.md +77 -0
- package/templates/storefront-fashion/__tests__/brand.test.ts +4 -0
- package/templates/storefront-fashion/__tests__/cart-flow.test.ts +55 -0
- package/templates/storefront-fashion/__tests__/contract.test.ts +4 -0
- package/templates/storefront-fashion/app/about/page.tsx +41 -0
- package/templates/storefront-fashion/app/accessibility/page.tsx +11 -0
- package/templates/storefront-fashion/app/account/addresses/page.tsx +21 -0
- package/templates/storefront-fashion/app/account/orders/page.tsx +21 -0
- package/templates/storefront-fashion/app/account/page.tsx +22 -0
- package/templates/storefront-fashion/app/account/settings/page.tsx +21 -0
- package/templates/storefront-fashion/app/cart/page.tsx +9 -0
- package/templates/storefront-fashion/app/categories/[slug]/listing-client.tsx +19 -0
- package/templates/storefront-fashion/app/categories/[slug]/page.tsx +130 -0
- package/templates/storefront-fashion/app/checkout/page.tsx +17 -0
- package/templates/storefront-fashion/app/collections/[slug]/listing-client.tsx +20 -0
- package/templates/storefront-fashion/app/collections/[slug]/page.tsx +130 -0
- package/templates/storefront-fashion/app/contact/contact-form.tsx +109 -0
- package/templates/storefront-fashion/app/contact/page.tsx +54 -0
- package/templates/storefront-fashion/app/error.tsx +61 -0
- package/templates/storefront-fashion/app/faq/page.tsx +46 -0
- package/templates/storefront-fashion/app/globals.css +46 -0
- package/templates/storefront-fashion/app/layout.tsx +78 -0
- package/templates/storefront-fashion/app/llms.txt/route.ts +94 -0
- package/templates/storefront-fashion/app/login/page.tsx +17 -0
- package/templates/storefront-fashion/app/lookbook/page.tsx +132 -0
- package/templates/storefront-fashion/app/not-found.tsx +39 -0
- package/templates/storefront-fashion/app/opensearch.xml/route.ts +37 -0
- package/templates/storefront-fashion/app/orders/[id]/page.tsx +24 -0
- package/templates/storefront-fashion/app/page.tsx +183 -0
- package/templates/storefront-fashion/app/privacy/page.tsx +44 -0
- package/templates/storefront-fashion/app/products/[slug]/page.tsx +165 -0
- package/templates/storefront-fashion/app/products/[slug]/product-detail.tsx +70 -0
- package/templates/storefront-fashion/app/returns/page.tsx +11 -0
- package/templates/storefront-fashion/app/robots.ts +18 -0
- package/templates/storefront-fashion/app/search/page.tsx +38 -0
- package/templates/storefront-fashion/app/search/search-client.tsx +7 -0
- package/templates/storefront-fashion/app/shipping/page.tsx +16 -0
- package/templates/storefront-fashion/app/shop/page.tsx +63 -0
- package/templates/storefront-fashion/app/shop/shop-client.tsx +32 -0
- package/templates/storefront-fashion/app/signup/page.tsx +17 -0
- package/templates/storefront-fashion/app/sitemap-page/page.tsx +167 -0
- package/templates/storefront-fashion/app/sitemap.ts +59 -0
- package/templates/storefront-fashion/app/size-guide/page.tsx +155 -0
- package/templates/storefront-fashion/app/terms/page.tsx +44 -0
- package/templates/storefront-fashion/app/track-order/page.tsx +24 -0
- package/templates/storefront-fashion/app/track-order/track-order-form.tsx +69 -0
- package/templates/storefront-fashion/components/account-iframe.tsx +13 -0
- package/templates/storefront-fashion/components/brand-marquee.tsx +27 -0
- package/templates/storefront-fashion/components/cart-drawer.tsx +14 -0
- package/templates/storefront-fashion/components/cart-pill.tsx +36 -0
- package/templates/storefront-fashion/components/category-grid.tsx +28 -0
- package/templates/storefront-fashion/components/category-tiles.tsx +104 -0
- package/templates/storefront-fashion/components/collection-strip.tsx +45 -0
- package/templates/storefront-fashion/components/feature-hero.tsx +82 -0
- package/templates/storefront-fashion/components/footer.tsx +153 -0
- package/templates/storefront-fashion/components/header.tsx +43 -0
- package/templates/storefront-fashion/components/hero.tsx +28 -0
- package/templates/storefront-fashion/components/nav-link.tsx +20 -0
- package/templates/storefront-fashion/components/newsletter.tsx +50 -0
- package/templates/storefront-fashion/components/policy-page.tsx +49 -0
- package/templates/storefront-fashion/components/promo-banner.tsx +41 -0
- package/templates/storefront-fashion/components/providers.tsx +35 -0
- package/templates/storefront-fashion/components/section-heading.tsx +37 -0
- package/templates/storefront-fashion/components/store-product-card.tsx +87 -0
- package/templates/storefront-fashion/components/trade-in-cta.tsx +54 -0
- package/templates/storefront-fashion/components/trust-bar.tsx +66 -0
- package/templates/storefront-fashion/e2e/visual.spec.ts +52 -0
- package/templates/storefront-fashion/lib/brand.ts +518 -0
- package/templates/storefront-fashion/lib/cart.ts +12 -0
- package/templates/storefront-fashion/next.config.ts +42 -0
- package/templates/storefront-fashion/package.json +38 -0
- package/templates/storefront-fashion/playwright.config.ts +48 -0
- package/templates/storefront-fashion/postcss.config.mjs +7 -0
- package/templates/storefront-fashion/tsconfig.json +23 -0
- package/templates/storefront-fashion/vitest.config.ts +9 -0
- package/templates/storefront-grocery/.claude/skills/cimplify-storefront/SKILL.md +145 -0
- package/templates/storefront-grocery/.cursor/rules/cimplify-storefront.mdc +25 -0
- package/templates/storefront-grocery/.env.example +16 -0
- package/templates/storefront-grocery/AGENTS.md +96 -0
- package/templates/storefront-grocery/CLAUDE.md +22 -0
- package/templates/storefront-grocery/README.md +73 -0
- package/templates/storefront-grocery/__tests__/brand.test.ts +4 -0
- package/templates/storefront-grocery/__tests__/cart-flow.test.ts +4 -0
- package/templates/storefront-grocery/__tests__/contract.test.ts +4 -0
- package/templates/storefront-grocery/app/about/page.tsx +38 -0
- package/templates/storefront-grocery/app/accessibility/page.tsx +11 -0
- package/templates/storefront-grocery/app/account/addresses/page.tsx +21 -0
- package/templates/storefront-grocery/app/account/orders/page.tsx +21 -0
- package/templates/storefront-grocery/app/account/page.tsx +22 -0
- package/templates/storefront-grocery/app/account/settings/page.tsx +21 -0
- package/templates/storefront-grocery/app/cart/page.tsx +9 -0
- package/templates/storefront-grocery/app/categories/[slug]/listing-client.tsx +19 -0
- package/templates/storefront-grocery/app/categories/[slug]/page.tsx +118 -0
- package/templates/storefront-grocery/app/checkout/page.tsx +17 -0
- package/templates/storefront-grocery/app/collections/[slug]/listing-client.tsx +20 -0
- package/templates/storefront-grocery/app/collections/[slug]/page.tsx +118 -0
- package/templates/storefront-grocery/app/contact/contact-form.tsx +109 -0
- package/templates/storefront-grocery/app/contact/page.tsx +54 -0
- package/templates/storefront-grocery/app/error.tsx +60 -0
- package/templates/storefront-grocery/app/faq/page.tsx +46 -0
- package/templates/storefront-grocery/app/globals.css +45 -0
- package/templates/storefront-grocery/app/layout.tsx +77 -0
- package/templates/storefront-grocery/app/llms.txt/route.ts +94 -0
- package/templates/storefront-grocery/app/login/page.tsx +17 -0
- package/templates/storefront-grocery/app/not-found.tsx +39 -0
- package/templates/storefront-grocery/app/opensearch.xml/route.ts +37 -0
- package/templates/storefront-grocery/app/orders/[id]/page.tsx +21 -0
- package/templates/storefront-grocery/app/page.tsx +97 -0
- package/templates/storefront-grocery/app/privacy/page.tsx +44 -0
- package/templates/storefront-grocery/app/returns/page.tsx +11 -0
- package/templates/storefront-grocery/app/robots.ts +18 -0
- package/templates/storefront-grocery/app/search/page.tsx +38 -0
- package/templates/storefront-grocery/app/search/search-client.tsx +7 -0
- package/templates/storefront-grocery/app/shipping/page.tsx +16 -0
- package/templates/storefront-grocery/app/shop/page.tsx +31 -0
- package/templates/storefront-grocery/app/shop/shop-client.tsx +27 -0
- package/templates/storefront-grocery/app/signup/page.tsx +17 -0
- package/templates/storefront-grocery/app/sitemap-page/page.tsx +167 -0
- package/templates/storefront-grocery/app/sitemap.ts +62 -0
- package/templates/storefront-grocery/app/terms/page.tsx +44 -0
- package/templates/storefront-grocery/app/track-order/page.tsx +24 -0
- package/templates/storefront-grocery/app/track-order/track-order-form.tsx +69 -0
- package/templates/storefront-grocery/components/account-iframe.tsx +13 -0
- package/templates/storefront-grocery/components/cart-drawer.tsx +14 -0
- package/templates/storefront-grocery/components/cart-pill.tsx +36 -0
- package/templates/storefront-grocery/components/category-grid.tsx +28 -0
- package/templates/storefront-grocery/components/collection-strip.tsx +45 -0
- package/templates/storefront-grocery/components/footer.tsx +148 -0
- package/templates/storefront-grocery/components/header.tsx +43 -0
- package/templates/storefront-grocery/components/hero.tsx +25 -0
- package/templates/storefront-grocery/components/nav-link.tsx +20 -0
- package/templates/storefront-grocery/components/policy-page.tsx +49 -0
- package/templates/storefront-grocery/components/product-modal.tsx +104 -0
- package/templates/storefront-grocery/components/providers.tsx +35 -0
- package/templates/storefront-grocery/components/store-product-card.tsx +87 -0
- package/templates/storefront-grocery/lib/brand.ts +375 -0
- package/templates/storefront-grocery/lib/cart.ts +12 -0
- package/templates/storefront-grocery/next.config.ts +42 -0
- package/templates/storefront-grocery/package.json +35 -0
- package/templates/storefront-grocery/postcss.config.mjs +7 -0
- package/templates/storefront-grocery/tsconfig.json +23 -0
- package/templates/storefront-grocery/vitest.config.ts +9 -0
- package/templates/storefront-restaurant/.claude/skills/cimplify-storefront/SKILL.md +145 -0
- package/templates/storefront-restaurant/.cursor/rules/cimplify-storefront.mdc +25 -0
- package/templates/storefront-restaurant/.env.example +16 -0
- package/templates/storefront-restaurant/AGENTS.md +102 -0
- package/templates/storefront-restaurant/CLAUDE.md +22 -0
- package/templates/storefront-restaurant/README.md +73 -0
- package/templates/storefront-restaurant/__tests__/brand.test.ts +4 -0
- package/templates/storefront-restaurant/__tests__/cart-flow.test.ts +4 -0
- package/templates/storefront-restaurant/__tests__/contract.test.ts +4 -0
- package/templates/storefront-restaurant/app/about/page.tsx +38 -0
- package/templates/storefront-restaurant/app/accessibility/page.tsx +11 -0
- package/templates/storefront-restaurant/app/account/addresses/page.tsx +21 -0
- package/templates/storefront-restaurant/app/account/orders/page.tsx +21 -0
- package/templates/storefront-restaurant/app/account/page.tsx +22 -0
- package/templates/storefront-restaurant/app/account/settings/page.tsx +21 -0
- package/templates/storefront-restaurant/app/cart/page.tsx +9 -0
- package/templates/storefront-restaurant/app/categories/[slug]/listing-client.tsx +19 -0
- package/templates/storefront-restaurant/app/categories/[slug]/page.tsx +118 -0
- package/templates/storefront-restaurant/app/checkout/page.tsx +17 -0
- package/templates/storefront-restaurant/app/collections/[slug]/listing-client.tsx +20 -0
- package/templates/storefront-restaurant/app/collections/[slug]/page.tsx +118 -0
- package/templates/storefront-restaurant/app/contact/contact-form.tsx +109 -0
- package/templates/storefront-restaurant/app/contact/page.tsx +54 -0
- package/templates/storefront-restaurant/app/error.tsx +60 -0
- package/templates/storefront-restaurant/app/faq/page.tsx +46 -0
- package/templates/storefront-restaurant/app/globals.css +44 -0
- package/templates/storefront-restaurant/app/layout.tsx +82 -0
- package/templates/storefront-restaurant/app/llms.txt/route.ts +94 -0
- package/templates/storefront-restaurant/app/login/page.tsx +17 -0
- package/templates/storefront-restaurant/app/not-found.tsx +39 -0
- package/templates/storefront-restaurant/app/opensearch.xml/route.ts +37 -0
- package/templates/storefront-restaurant/app/orders/[id]/page.tsx +21 -0
- package/templates/storefront-restaurant/app/page.tsx +97 -0
- package/templates/storefront-restaurant/app/privacy/page.tsx +44 -0
- package/templates/storefront-restaurant/app/reservations/page.tsx +66 -0
- package/templates/storefront-restaurant/app/reservations/reservations-client.tsx +234 -0
- package/templates/storefront-restaurant/app/returns/page.tsx +11 -0
- package/templates/storefront-restaurant/app/robots.ts +18 -0
- package/templates/storefront-restaurant/app/search/page.tsx +38 -0
- package/templates/storefront-restaurant/app/search/search-client.tsx +7 -0
- package/templates/storefront-restaurant/app/shipping/page.tsx +16 -0
- package/templates/storefront-restaurant/app/shop/page.tsx +31 -0
- package/templates/storefront-restaurant/app/shop/shop-client.tsx +27 -0
- package/templates/storefront-restaurant/app/signup/page.tsx +17 -0
- package/templates/storefront-restaurant/app/sitemap-page/page.tsx +167 -0
- package/templates/storefront-restaurant/app/sitemap.ts +62 -0
- package/templates/storefront-restaurant/app/terms/page.tsx +44 -0
- package/templates/storefront-restaurant/app/track-order/page.tsx +24 -0
- package/templates/storefront-restaurant/app/track-order/track-order-form.tsx +69 -0
- package/templates/storefront-restaurant/components/account-iframe.tsx +13 -0
- package/templates/storefront-restaurant/components/cart-drawer.tsx +14 -0
- package/templates/storefront-restaurant/components/cart-pill.tsx +36 -0
- package/templates/storefront-restaurant/components/category-grid.tsx +28 -0
- package/templates/storefront-restaurant/components/collection-strip.tsx +45 -0
- package/templates/storefront-restaurant/components/footer.tsx +148 -0
- package/templates/storefront-restaurant/components/header.tsx +43 -0
- package/templates/storefront-restaurant/components/hero.tsx +25 -0
- package/templates/storefront-restaurant/components/nav-link.tsx +20 -0
- package/templates/storefront-restaurant/components/policy-page.tsx +49 -0
- package/templates/storefront-restaurant/components/product-modal.tsx +104 -0
- package/templates/storefront-restaurant/components/providers.tsx +35 -0
- package/templates/storefront-restaurant/components/store-product-card.tsx +87 -0
- package/templates/storefront-restaurant/lib/brand.ts +377 -0
- package/templates/storefront-restaurant/lib/cart.ts +12 -0
- package/templates/storefront-restaurant/next.config.ts +42 -0
- package/templates/storefront-restaurant/package.json +35 -0
- package/templates/storefront-restaurant/postcss.config.mjs +7 -0
- package/templates/storefront-restaurant/tsconfig.json +23 -0
- package/templates/storefront-restaurant/vitest.config.ts +9 -0
- package/templates/storefront-retail/.claude/skills/cimplify-storefront/SKILL.md +145 -0
- package/templates/storefront-retail/.cursor/rules/cimplify-storefront.mdc +25 -0
- package/templates/storefront-retail/.env.example +16 -0
- package/templates/storefront-retail/AGENTS.md +117 -0
- package/templates/storefront-retail/CLAUDE.md +22 -0
- package/templates/storefront-retail/README.md +77 -0
- package/templates/storefront-retail/__tests__/brand.test.ts +4 -0
- package/templates/storefront-retail/__tests__/cart-flow.test.ts +4 -0
- package/templates/storefront-retail/__tests__/contract.test.ts +4 -0
- package/templates/storefront-retail/app/about/page.tsx +41 -0
- package/templates/storefront-retail/app/accessibility/page.tsx +11 -0
- package/templates/storefront-retail/app/account/addresses/page.tsx +21 -0
- package/templates/storefront-retail/app/account/orders/page.tsx +21 -0
- package/templates/storefront-retail/app/account/page.tsx +22 -0
- package/templates/storefront-retail/app/account/settings/page.tsx +21 -0
- package/templates/storefront-retail/app/cart/page.tsx +9 -0
- package/templates/storefront-retail/app/categories/[slug]/listing-client.tsx +19 -0
- package/templates/storefront-retail/app/categories/[slug]/page.tsx +130 -0
- package/templates/storefront-retail/app/checkout/page.tsx +17 -0
- package/templates/storefront-retail/app/collections/[slug]/listing-client.tsx +20 -0
- package/templates/storefront-retail/app/collections/[slug]/page.tsx +130 -0
- package/templates/storefront-retail/app/contact/contact-form.tsx +109 -0
- package/templates/storefront-retail/app/contact/page.tsx +54 -0
- package/templates/storefront-retail/app/error.tsx +61 -0
- package/templates/storefront-retail/app/faq/page.tsx +46 -0
- package/templates/storefront-retail/app/globals.css +47 -0
- package/templates/storefront-retail/app/layout.tsx +77 -0
- package/templates/storefront-retail/app/llms.txt/route.ts +94 -0
- package/templates/storefront-retail/app/login/page.tsx +17 -0
- package/templates/storefront-retail/app/not-found.tsx +39 -0
- package/templates/storefront-retail/app/opensearch.xml/route.ts +37 -0
- package/templates/storefront-retail/app/orders/[id]/page.tsx +24 -0
- package/templates/storefront-retail/app/page.tsx +182 -0
- package/templates/storefront-retail/app/privacy/page.tsx +44 -0
- package/templates/storefront-retail/app/products/[slug]/page.tsx +165 -0
- package/templates/storefront-retail/app/products/[slug]/product-detail.tsx +70 -0
- package/templates/storefront-retail/app/returns/page.tsx +11 -0
- package/templates/storefront-retail/app/robots.ts +18 -0
- package/templates/storefront-retail/app/search/page.tsx +38 -0
- package/templates/storefront-retail/app/search/search-client.tsx +7 -0
- package/templates/storefront-retail/app/shipping/page.tsx +16 -0
- package/templates/storefront-retail/app/shop/page.tsx +63 -0
- package/templates/storefront-retail/app/shop/shop-client.tsx +32 -0
- package/templates/storefront-retail/app/signup/page.tsx +17 -0
- package/templates/storefront-retail/app/sitemap-page/page.tsx +167 -0
- package/templates/storefront-retail/app/sitemap.ts +59 -0
- package/templates/storefront-retail/app/terms/page.tsx +44 -0
- package/templates/storefront-retail/app/track-order/page.tsx +24 -0
- package/templates/storefront-retail/app/track-order/track-order-form.tsx +69 -0
- package/templates/storefront-retail/components/account-iframe.tsx +13 -0
- package/templates/storefront-retail/components/brand-marquee.tsx +27 -0
- package/templates/storefront-retail/components/cart-drawer.tsx +14 -0
- package/templates/storefront-retail/components/cart-pill.tsx +36 -0
- package/templates/storefront-retail/components/category-grid.tsx +28 -0
- package/templates/storefront-retail/components/category-tiles.tsx +104 -0
- package/templates/storefront-retail/components/collection-strip.tsx +45 -0
- package/templates/storefront-retail/components/feature-hero.tsx +84 -0
- package/templates/storefront-retail/components/footer.tsx +153 -0
- package/templates/storefront-retail/components/header.tsx +45 -0
- package/templates/storefront-retail/components/hero.tsx +28 -0
- package/templates/storefront-retail/components/nav-link.tsx +20 -0
- package/templates/storefront-retail/components/newsletter.tsx +50 -0
- package/templates/storefront-retail/components/policy-page.tsx +49 -0
- package/templates/storefront-retail/components/promo-banner.tsx +41 -0
- package/templates/storefront-retail/components/providers.tsx +35 -0
- package/templates/storefront-retail/components/section-heading.tsx +37 -0
- package/templates/storefront-retail/components/store-product-card.tsx +87 -0
- package/templates/storefront-retail/components/trade-in-cta.tsx +54 -0
- package/templates/storefront-retail/components/trust-bar.tsx +66 -0
- package/templates/storefront-retail/lib/brand.ts +664 -0
- package/templates/storefront-retail/lib/cart.ts +12 -0
- package/templates/storefront-retail/next.config.ts +42 -0
- package/templates/storefront-retail/package.json +35 -0
- package/templates/storefront-retail/postcss.config.mjs +7 -0
- package/templates/storefront-retail/tsconfig.json +23 -0
- package/templates/storefront-retail/vitest.config.ts +9 -0
- package/templates/storefront-services/.claude/skills/cimplify-storefront/SKILL.md +145 -0
- package/templates/storefront-services/.cursor/rules/cimplify-storefront.mdc +25 -0
- package/templates/storefront-services/.env.example +16 -0
- package/templates/storefront-services/AGENTS.md +101 -0
- package/templates/storefront-services/CLAUDE.md +22 -0
- package/templates/storefront-services/README.md +73 -0
- package/templates/storefront-services/__tests__/brand.test.ts +4 -0
- package/templates/storefront-services/__tests__/cart-flow.test.ts +4 -0
- package/templates/storefront-services/__tests__/contract.test.ts +4 -0
- package/templates/storefront-services/app/about/page.tsx +38 -0
- package/templates/storefront-services/app/accessibility/page.tsx +11 -0
- package/templates/storefront-services/app/account/addresses/page.tsx +21 -0
- package/templates/storefront-services/app/account/orders/page.tsx +21 -0
- package/templates/storefront-services/app/account/page.tsx +22 -0
- package/templates/storefront-services/app/account/settings/page.tsx +21 -0
- package/templates/storefront-services/app/book/book-client.tsx +195 -0
- package/templates/storefront-services/app/book/page.tsx +65 -0
- package/templates/storefront-services/app/cart/page.tsx +9 -0
- package/templates/storefront-services/app/categories/[slug]/listing-client.tsx +19 -0
- package/templates/storefront-services/app/categories/[slug]/page.tsx +118 -0
- package/templates/storefront-services/app/checkout/page.tsx +17 -0
- package/templates/storefront-services/app/collections/[slug]/listing-client.tsx +20 -0
- package/templates/storefront-services/app/collections/[slug]/page.tsx +118 -0
- package/templates/storefront-services/app/contact/contact-form.tsx +109 -0
- package/templates/storefront-services/app/contact/page.tsx +54 -0
- package/templates/storefront-services/app/error.tsx +60 -0
- package/templates/storefront-services/app/faq/page.tsx +46 -0
- package/templates/storefront-services/app/globals.css +45 -0
- package/templates/storefront-services/app/layout.tsx +82 -0
- package/templates/storefront-services/app/llms.txt/route.ts +94 -0
- package/templates/storefront-services/app/login/page.tsx +17 -0
- package/templates/storefront-services/app/not-found.tsx +39 -0
- package/templates/storefront-services/app/opensearch.xml/route.ts +37 -0
- package/templates/storefront-services/app/orders/[id]/page.tsx +21 -0
- package/templates/storefront-services/app/page.tsx +97 -0
- package/templates/storefront-services/app/privacy/page.tsx +44 -0
- package/templates/storefront-services/app/returns/page.tsx +11 -0
- package/templates/storefront-services/app/robots.ts +18 -0
- package/templates/storefront-services/app/search/page.tsx +38 -0
- package/templates/storefront-services/app/search/search-client.tsx +7 -0
- package/templates/storefront-services/app/shipping/page.tsx +16 -0
- package/templates/storefront-services/app/shop/page.tsx +31 -0
- package/templates/storefront-services/app/shop/shop-client.tsx +27 -0
- package/templates/storefront-services/app/signup/page.tsx +17 -0
- package/templates/storefront-services/app/sitemap-page/page.tsx +167 -0
- package/templates/storefront-services/app/sitemap.ts +62 -0
- package/templates/storefront-services/app/terms/page.tsx +44 -0
- package/templates/storefront-services/app/track-order/page.tsx +24 -0
- package/templates/storefront-services/app/track-order/track-order-form.tsx +69 -0
- package/templates/storefront-services/components/account-iframe.tsx +13 -0
- package/templates/storefront-services/components/cart-drawer.tsx +14 -0
- package/templates/storefront-services/components/cart-pill.tsx +36 -0
- package/templates/storefront-services/components/category-grid.tsx +28 -0
- package/templates/storefront-services/components/collection-strip.tsx +45 -0
- package/templates/storefront-services/components/footer.tsx +148 -0
- package/templates/storefront-services/components/header.tsx +43 -0
- package/templates/storefront-services/components/hero.tsx +25 -0
- package/templates/storefront-services/components/nav-link.tsx +20 -0
- package/templates/storefront-services/components/policy-page.tsx +49 -0
- package/templates/storefront-services/components/product-modal.tsx +104 -0
- package/templates/storefront-services/components/providers.tsx +35 -0
- package/templates/storefront-services/components/store-product-card.tsx +87 -0
- package/templates/storefront-services/lib/brand.ts +396 -0
- package/templates/storefront-services/lib/cart.ts +12 -0
- package/templates/storefront-services/next.config.ts +42 -0
- package/templates/storefront-services/package.json +35 -0
- package/templates/storefront-services/postcss.config.mjs +7 -0
- package/templates/storefront-services/tsconfig.json +23 -0
- package/templates/storefront-services/vitest.config.ts +9 -0
|
@@ -0,0 +1,387 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import { promptYesNo } from './chunk-L6474RPL.mjs';
|
|
3
|
+
import { ENV_SCOPE, DOMAIN_TYPE } from './chunk-MQMNWLMU.mjs';
|
|
4
|
+
import { parseArgs, flagBool, flagString } from './chunk-D7D75ONX.mjs';
|
|
5
|
+
import { ApiClient } from './chunk-4ZVTPMUZ.mjs';
|
|
6
|
+
import { readAuth, readProjectLink } from './chunk-JJYWETGA.mjs';
|
|
7
|
+
import { CliError, CLI_ERROR_CODE, info, dim, result, bold, success } from './chunk-NZ4RG62Z.mjs';
|
|
8
|
+
|
|
9
|
+
// src/commands/domains.ts
|
|
10
|
+
var SUB_LS = "ls";
|
|
11
|
+
var SUB_LIST = "list";
|
|
12
|
+
var SUB_ADD = "add";
|
|
13
|
+
var SUB_VERIFY = "verify";
|
|
14
|
+
var SUB_RM = "rm";
|
|
15
|
+
var SUB_REMOVE = "remove";
|
|
16
|
+
var SUB_ATTACH = "attach";
|
|
17
|
+
var SUB_DETACH = "detach";
|
|
18
|
+
var SUB_PRIMARY = "primary";
|
|
19
|
+
var FLAG_TYPE = "type";
|
|
20
|
+
var FLAG_YES = "yes";
|
|
21
|
+
var FLAG_ENV = "env";
|
|
22
|
+
var FLAG_PRIMARY = "primary";
|
|
23
|
+
var FLAG_ATTACHED = "attached";
|
|
24
|
+
var ENV_SCOPE_VALUES = new Set(Object.values(ENV_SCOPE));
|
|
25
|
+
function resolveEnvScope(value, fallback = ENV_SCOPE.PRODUCTION) {
|
|
26
|
+
if (value === void 0) return fallback;
|
|
27
|
+
if (!ENV_SCOPE_VALUES.has(value)) {
|
|
28
|
+
throw new CliError(
|
|
29
|
+
CLI_ERROR_CODE.INVALID_INPUT,
|
|
30
|
+
`Invalid env "${value}". Choose: ${[...ENV_SCOPE_VALUES].join(", ")}.`
|
|
31
|
+
);
|
|
32
|
+
}
|
|
33
|
+
return value;
|
|
34
|
+
}
|
|
35
|
+
function projectDomainsEndpoint(businessId, projectId) {
|
|
36
|
+
return `/v1/businesses/${encodeURIComponent(businessId)}/projects/${encodeURIComponent(projectId)}/domains`;
|
|
37
|
+
}
|
|
38
|
+
function projectDomainItemEndpoint(businessId, projectId, attachmentId) {
|
|
39
|
+
return `${projectDomainsEndpoint(businessId, projectId)}/${encodeURIComponent(attachmentId)}`;
|
|
40
|
+
}
|
|
41
|
+
function projectDomainPrimaryEndpoint(businessId, projectId, attachmentId) {
|
|
42
|
+
return `${projectDomainItemEndpoint(businessId, projectId, attachmentId)}/primary`;
|
|
43
|
+
}
|
|
44
|
+
var COL_GAP = " ";
|
|
45
|
+
var COL_DOMAIN = "DOMAIN";
|
|
46
|
+
var COL_TYPE = "TYPE";
|
|
47
|
+
var COL_VERIFIED = "VERIFIED";
|
|
48
|
+
var COL_PRIMARY = "PRIMARY";
|
|
49
|
+
var COL_CREATED = "CREATED";
|
|
50
|
+
var DNS_COL_TYPE = "Type";
|
|
51
|
+
var DNS_COL_NAME = "Name";
|
|
52
|
+
var DNS_COL_VALUE = "Value";
|
|
53
|
+
var VALID_DOMAIN_TYPES = new Set(Object.values(DOMAIN_TYPE));
|
|
54
|
+
function domainsEndpoint(businessId) {
|
|
55
|
+
return `/v1/businesses/${encodeURIComponent(businessId)}/domains`;
|
|
56
|
+
}
|
|
57
|
+
function domainItemEndpoint(businessId, id) {
|
|
58
|
+
return `${domainsEndpoint(businessId)}/${encodeURIComponent(id)}`;
|
|
59
|
+
}
|
|
60
|
+
function domainVerifyEndpoint(businessId, id) {
|
|
61
|
+
return `${domainItemEndpoint(businessId, id)}/verify`;
|
|
62
|
+
}
|
|
63
|
+
function dnsRecordsEndpoint(domain) {
|
|
64
|
+
return `/v1/hosting/domains/${encodeURIComponent(domain)}/dns-records`;
|
|
65
|
+
}
|
|
66
|
+
function resolveDomainType(value) {
|
|
67
|
+
if (value === void 0) return DOMAIN_TYPE.CUSTOM;
|
|
68
|
+
if (!VALID_DOMAIN_TYPES.has(value)) {
|
|
69
|
+
throw new CliError(
|
|
70
|
+
CLI_ERROR_CODE.INVALID_INPUT,
|
|
71
|
+
`Invalid domain type "${value}". Choose: ${[...VALID_DOMAIN_TYPES].join(", ")}.`
|
|
72
|
+
);
|
|
73
|
+
}
|
|
74
|
+
return value;
|
|
75
|
+
}
|
|
76
|
+
async function run(argv) {
|
|
77
|
+
const args = parseArgs(argv);
|
|
78
|
+
const sub = args.positional[0];
|
|
79
|
+
if (!sub) {
|
|
80
|
+
throw new CliError(
|
|
81
|
+
CLI_ERROR_CODE.INVALID_INPUT,
|
|
82
|
+
`Usage: cimplify domains <${SUB_LS}|${SUB_ADD}|${SUB_VERIFY}|${SUB_RM}|${SUB_ATTACH}|${SUB_DETACH}|${SUB_PRIMARY}>`
|
|
83
|
+
);
|
|
84
|
+
}
|
|
85
|
+
const auth = await readAuth();
|
|
86
|
+
const client = ApiClient.fromAuth(auth);
|
|
87
|
+
if (sub === SUB_LS || sub === SUB_LIST) {
|
|
88
|
+
if (flagBool(args, FLAG_ATTACHED)) {
|
|
89
|
+
await listAttachedForCurrentProject(client, auth.businessId);
|
|
90
|
+
} else {
|
|
91
|
+
await listDomains(client, auth.businessId);
|
|
92
|
+
}
|
|
93
|
+
return;
|
|
94
|
+
}
|
|
95
|
+
if (sub === SUB_ADD) {
|
|
96
|
+
await addDomain(client, auth.businessId, args);
|
|
97
|
+
return;
|
|
98
|
+
}
|
|
99
|
+
if (sub === SUB_VERIFY) {
|
|
100
|
+
await verifyDomain(client, auth.businessId, args);
|
|
101
|
+
return;
|
|
102
|
+
}
|
|
103
|
+
if (sub === SUB_RM || sub === SUB_REMOVE) {
|
|
104
|
+
await removeDomain(client, auth.businessId, args);
|
|
105
|
+
return;
|
|
106
|
+
}
|
|
107
|
+
if (sub === SUB_ATTACH) {
|
|
108
|
+
await attachDomain(client, auth.businessId, args);
|
|
109
|
+
return;
|
|
110
|
+
}
|
|
111
|
+
if (sub === SUB_DETACH) {
|
|
112
|
+
await detachDomain(client, auth.businessId, args);
|
|
113
|
+
return;
|
|
114
|
+
}
|
|
115
|
+
if (sub === SUB_PRIMARY) {
|
|
116
|
+
await setPrimaryAttachment(client, auth.businessId, args);
|
|
117
|
+
return;
|
|
118
|
+
}
|
|
119
|
+
throw new CliError(CLI_ERROR_CODE.INVALID_INPUT, `Unknown domains subcommand "${sub}"`);
|
|
120
|
+
}
|
|
121
|
+
async function listDomains(client, businessId) {
|
|
122
|
+
const domains = await client.get(domainsEndpoint(businessId));
|
|
123
|
+
if (domains.length === 0) {
|
|
124
|
+
info(dim("No domains. Add one: cimplify domains add <domain>"));
|
|
125
|
+
result({ domains: [] });
|
|
126
|
+
return;
|
|
127
|
+
}
|
|
128
|
+
const domainWidth = Math.max(COL_DOMAIN.length, ...domains.map((d) => d.domain.length));
|
|
129
|
+
const typeWidth = Math.max(COL_TYPE.length, ...domains.map((d) => String(d.domain_type).length));
|
|
130
|
+
const verifiedWidth = COL_VERIFIED.length;
|
|
131
|
+
const primaryWidth = COL_PRIMARY.length;
|
|
132
|
+
info(
|
|
133
|
+
bold(
|
|
134
|
+
[
|
|
135
|
+
COL_DOMAIN.padEnd(domainWidth),
|
|
136
|
+
COL_TYPE.padEnd(typeWidth),
|
|
137
|
+
COL_VERIFIED.padEnd(verifiedWidth),
|
|
138
|
+
COL_PRIMARY.padEnd(primaryWidth),
|
|
139
|
+
COL_CREATED
|
|
140
|
+
].join(COL_GAP)
|
|
141
|
+
)
|
|
142
|
+
);
|
|
143
|
+
for (const d of domains) {
|
|
144
|
+
info(
|
|
145
|
+
[
|
|
146
|
+
d.domain.padEnd(domainWidth),
|
|
147
|
+
String(d.domain_type).padEnd(typeWidth),
|
|
148
|
+
(d.is_verified ? "yes" : "no").padEnd(verifiedWidth),
|
|
149
|
+
(d.is_primary ? "yes" : "no").padEnd(primaryWidth),
|
|
150
|
+
d.created_at ?? ""
|
|
151
|
+
].join(COL_GAP)
|
|
152
|
+
);
|
|
153
|
+
}
|
|
154
|
+
result({
|
|
155
|
+
domains: domains.map((d) => ({
|
|
156
|
+
id: d.id,
|
|
157
|
+
domain: d.domain,
|
|
158
|
+
domain_type: d.domain_type,
|
|
159
|
+
is_verified: d.is_verified,
|
|
160
|
+
is_primary: d.is_primary,
|
|
161
|
+
created_at: d.created_at ?? null
|
|
162
|
+
}))
|
|
163
|
+
});
|
|
164
|
+
}
|
|
165
|
+
async function addDomain(client, businessId, args) {
|
|
166
|
+
const domain = args.positional[1];
|
|
167
|
+
if (!domain) {
|
|
168
|
+
throw new CliError(
|
|
169
|
+
CLI_ERROR_CODE.INVALID_INPUT,
|
|
170
|
+
`Usage: cimplify domains add <domain> [--type=custom|cimplify]`
|
|
171
|
+
);
|
|
172
|
+
}
|
|
173
|
+
const domainType = resolveDomainType(flagString(args, FLAG_TYPE));
|
|
174
|
+
const body = { domain, domain_type: domainType };
|
|
175
|
+
const created = await client.post(domainsEndpoint(businessId), body);
|
|
176
|
+
success(`Added ${created.domain} (${created.domain_type})`);
|
|
177
|
+
let dnsRecords = null;
|
|
178
|
+
if (domainType === DOMAIN_TYPE.CUSTOM) {
|
|
179
|
+
try {
|
|
180
|
+
const dns = await client.get(dnsRecordsEndpoint(domain));
|
|
181
|
+
dnsRecords = Array.isArray(dns) ? dns : dns.records;
|
|
182
|
+
printDnsRecords(domain, dnsRecords);
|
|
183
|
+
} catch (err) {
|
|
184
|
+
info(dim(`(Could not fetch DNS records: ${err instanceof Error ? err.message : String(err)})`));
|
|
185
|
+
}
|
|
186
|
+
}
|
|
187
|
+
result({
|
|
188
|
+
domain: {
|
|
189
|
+
id: created.id,
|
|
190
|
+
domain: created.domain,
|
|
191
|
+
domain_type: created.domain_type,
|
|
192
|
+
is_verified: created.is_verified
|
|
193
|
+
},
|
|
194
|
+
dns_records: dnsRecords
|
|
195
|
+
});
|
|
196
|
+
}
|
|
197
|
+
function printDnsRecords(domain, records) {
|
|
198
|
+
if (!records || records.length === 0) {
|
|
199
|
+
info(dim("No DNS records returned."));
|
|
200
|
+
return;
|
|
201
|
+
}
|
|
202
|
+
const typeWidth = Math.max(DNS_COL_TYPE.length, ...records.map((r) => r.type.length));
|
|
203
|
+
const nameWidth = Math.max(DNS_COL_NAME.length, ...records.map((r) => r.name.length));
|
|
204
|
+
const valueWidth = Math.max(DNS_COL_VALUE.length, ...records.map((r) => r.value.length));
|
|
205
|
+
info("");
|
|
206
|
+
info("Add the following DNS records:");
|
|
207
|
+
info("");
|
|
208
|
+
info(
|
|
209
|
+
` ${bold(DNS_COL_TYPE.padEnd(typeWidth))} ${bold(DNS_COL_NAME.padEnd(nameWidth))} ${bold(DNS_COL_VALUE)}`
|
|
210
|
+
);
|
|
211
|
+
info(
|
|
212
|
+
` ${"\u2500".repeat(typeWidth)} ${"\u2500".repeat(nameWidth)} ${"\u2500".repeat(Math.min(valueWidth, 40))}`
|
|
213
|
+
);
|
|
214
|
+
for (const r of records) {
|
|
215
|
+
info(` ${r.type.padEnd(typeWidth)} ${r.name.padEnd(nameWidth)} ${r.value}`);
|
|
216
|
+
}
|
|
217
|
+
info("");
|
|
218
|
+
info(`Then run: ${bold(`cimplify domains verify ${domain}`)}`);
|
|
219
|
+
}
|
|
220
|
+
async function verifyDomain(client, businessId, args) {
|
|
221
|
+
const domain = args.positional[1];
|
|
222
|
+
if (!domain) {
|
|
223
|
+
throw new CliError(
|
|
224
|
+
CLI_ERROR_CODE.INVALID_INPUT,
|
|
225
|
+
`Usage: cimplify domains verify <domain>`
|
|
226
|
+
);
|
|
227
|
+
}
|
|
228
|
+
const target = await findDomain(client, businessId, domain);
|
|
229
|
+
const verified = await client.post(domainVerifyEndpoint(businessId, target.id));
|
|
230
|
+
if (verified.is_verified) {
|
|
231
|
+
success(`Verified ${verified.domain}`);
|
|
232
|
+
} else {
|
|
233
|
+
info(dim(`Not yet verified \u2014 DNS may still be propagating. Try again in a few minutes.`));
|
|
234
|
+
}
|
|
235
|
+
result({ domain: verified.domain, verified: verified.is_verified });
|
|
236
|
+
}
|
|
237
|
+
async function removeDomain(client, businessId, args) {
|
|
238
|
+
const domain = args.positional[1];
|
|
239
|
+
if (!domain) {
|
|
240
|
+
throw new CliError(
|
|
241
|
+
CLI_ERROR_CODE.INVALID_INPUT,
|
|
242
|
+
`Usage: cimplify domains rm <domain> [--yes]`
|
|
243
|
+
);
|
|
244
|
+
}
|
|
245
|
+
const target = await findDomain(client, businessId, domain);
|
|
246
|
+
if (!flagBool(args, FLAG_YES)) {
|
|
247
|
+
const confirmed = await promptYesNo(`Remove ${domain}?`, true);
|
|
248
|
+
if (!confirmed) {
|
|
249
|
+
throw new CliError(CLI_ERROR_CODE.ABORTED, "Aborted by user.");
|
|
250
|
+
}
|
|
251
|
+
}
|
|
252
|
+
await client.delete(domainItemEndpoint(businessId, target.id));
|
|
253
|
+
success(`Removed ${domain}`);
|
|
254
|
+
result({ removed: true, domain });
|
|
255
|
+
}
|
|
256
|
+
async function findDomain(client, businessId, domain) {
|
|
257
|
+
const domains = await client.get(domainsEndpoint(businessId));
|
|
258
|
+
const match = domains.find((d) => d.domain === domain);
|
|
259
|
+
if (!match) {
|
|
260
|
+
throw new CliError(
|
|
261
|
+
CLI_ERROR_CODE.PROJECT_NOT_FOUND,
|
|
262
|
+
`Domain "${domain}" not found. List domains: cimplify domains ls`
|
|
263
|
+
);
|
|
264
|
+
}
|
|
265
|
+
return match;
|
|
266
|
+
}
|
|
267
|
+
async function attachDomain(client, businessId, args) {
|
|
268
|
+
const domain = args.positional[1];
|
|
269
|
+
if (!domain) {
|
|
270
|
+
throw new CliError(
|
|
271
|
+
CLI_ERROR_CODE.INVALID_INPUT,
|
|
272
|
+
`Usage: cimplify domains ${SUB_ATTACH} <domain> [--env=preview|production] [--primary]`
|
|
273
|
+
);
|
|
274
|
+
}
|
|
275
|
+
const link = await readProjectLink();
|
|
276
|
+
const target = await findDomain(client, businessId, domain);
|
|
277
|
+
if (!target.is_verified) {
|
|
278
|
+
throw new CliError(
|
|
279
|
+
CLI_ERROR_CODE.INVALID_INPUT,
|
|
280
|
+
`Domain "${domain}" is not verified. Run: cimplify domains verify ${domain}`
|
|
281
|
+
);
|
|
282
|
+
}
|
|
283
|
+
const envScope = resolveEnvScope(flagString(args, FLAG_ENV));
|
|
284
|
+
const isPrimary = flagBool(args, FLAG_PRIMARY);
|
|
285
|
+
const body = {
|
|
286
|
+
business_domain_id: target.id,
|
|
287
|
+
env_scope: envScope,
|
|
288
|
+
is_primary: isPrimary
|
|
289
|
+
};
|
|
290
|
+
await client.post(
|
|
291
|
+
projectDomainsEndpoint(businessId, link.projectId),
|
|
292
|
+
body
|
|
293
|
+
);
|
|
294
|
+
success(`Attached ${domain} to project for ${envScope}${isPrimary ? " (primary)" : ""}`);
|
|
295
|
+
info(dim("Next deploy will bind this domain. Run: cimplify deploy"));
|
|
296
|
+
result({ attached: true, domain, env: envScope, primary: isPrimary });
|
|
297
|
+
}
|
|
298
|
+
async function detachDomain(client, businessId, args) {
|
|
299
|
+
const domain = args.positional[1];
|
|
300
|
+
if (!domain) {
|
|
301
|
+
throw new CliError(
|
|
302
|
+
CLI_ERROR_CODE.INVALID_INPUT,
|
|
303
|
+
`Usage: cimplify domains ${SUB_DETACH} <domain> [--env=preview|production] [--yes]`
|
|
304
|
+
);
|
|
305
|
+
}
|
|
306
|
+
const link = await readProjectLink();
|
|
307
|
+
const envScope = resolveEnvScope(flagString(args, FLAG_ENV));
|
|
308
|
+
const attachment = await findAttachmentForCurrentProject(client, businessId, link.projectId, domain, envScope);
|
|
309
|
+
if (!flagBool(args, FLAG_YES)) {
|
|
310
|
+
const confirmed = await promptYesNo(`Detach ${domain} from this project (${envScope})?`, true);
|
|
311
|
+
if (!confirmed) {
|
|
312
|
+
throw new CliError(CLI_ERROR_CODE.ABORTED, "Aborted by user.");
|
|
313
|
+
}
|
|
314
|
+
}
|
|
315
|
+
await client.delete(projectDomainItemEndpoint(businessId, link.projectId, attachment.id));
|
|
316
|
+
success(`Detached ${domain} (${envScope})`);
|
|
317
|
+
info(dim("Next deploy will not bind this domain. Existing deployments continue serving until redeploy."));
|
|
318
|
+
result({ detached: true, domain, env: envScope });
|
|
319
|
+
}
|
|
320
|
+
async function setPrimaryAttachment(client, businessId, args) {
|
|
321
|
+
const domain = args.positional[1];
|
|
322
|
+
if (!domain) {
|
|
323
|
+
throw new CliError(
|
|
324
|
+
CLI_ERROR_CODE.INVALID_INPUT,
|
|
325
|
+
`Usage: cimplify domains ${SUB_PRIMARY} <domain> [--env=preview|production]`
|
|
326
|
+
);
|
|
327
|
+
}
|
|
328
|
+
const link = await readProjectLink();
|
|
329
|
+
const envScope = resolveEnvScope(flagString(args, FLAG_ENV));
|
|
330
|
+
const attachment = await findAttachmentForCurrentProject(client, businessId, link.projectId, domain, envScope);
|
|
331
|
+
await client.post(
|
|
332
|
+
projectDomainPrimaryEndpoint(businessId, link.projectId, attachment.id)
|
|
333
|
+
);
|
|
334
|
+
success(`Set ${domain} as primary for ${envScope}`);
|
|
335
|
+
result({ primary: true, domain, env: envScope });
|
|
336
|
+
}
|
|
337
|
+
async function listAttachedForCurrentProject(client, businessId) {
|
|
338
|
+
const link = await readProjectLink();
|
|
339
|
+
const attachments = await client.get(
|
|
340
|
+
projectDomainsEndpoint(businessId, link.projectId)
|
|
341
|
+
);
|
|
342
|
+
if (attachments.length === 0) {
|
|
343
|
+
info(dim("No domains attached to this project. Attach one: cimplify domains attach <domain>"));
|
|
344
|
+
result({ attached: [] });
|
|
345
|
+
return;
|
|
346
|
+
}
|
|
347
|
+
const domains = await client.get(domainsEndpoint(businessId));
|
|
348
|
+
const domainById = new Map(domains.map((d) => [d.id, d]));
|
|
349
|
+
info(bold(["DOMAIN", "ENV", "PRIMARY", "ATTACHED"].join(COL_GAP)));
|
|
350
|
+
for (const a of attachments) {
|
|
351
|
+
const bd = domainById.get(a.business_domain_id);
|
|
352
|
+
info(
|
|
353
|
+
[
|
|
354
|
+
bd?.domain ?? `<unknown:${a.business_domain_id}>`,
|
|
355
|
+
String(a.env_scope),
|
|
356
|
+
a.is_primary ? "yes" : "no",
|
|
357
|
+
a.attached_at
|
|
358
|
+
].join(COL_GAP)
|
|
359
|
+
);
|
|
360
|
+
}
|
|
361
|
+
result({
|
|
362
|
+
attached: attachments.map((a) => ({
|
|
363
|
+
attachment_id: a.id,
|
|
364
|
+
business_domain_id: a.business_domain_id,
|
|
365
|
+
domain: domainById.get(a.business_domain_id)?.domain ?? null,
|
|
366
|
+
env: a.env_scope,
|
|
367
|
+
primary: a.is_primary,
|
|
368
|
+
attached_at: a.attached_at
|
|
369
|
+
}))
|
|
370
|
+
});
|
|
371
|
+
}
|
|
372
|
+
async function findAttachmentForCurrentProject(client, businessId, projectId, domain, envScope) {
|
|
373
|
+
const target = await findDomain(client, businessId, domain);
|
|
374
|
+
const attachments = await client.get(projectDomainsEndpoint(businessId, projectId));
|
|
375
|
+
const match = attachments.find(
|
|
376
|
+
(a) => a.business_domain_id === target.id && a.env_scope === envScope
|
|
377
|
+
);
|
|
378
|
+
if (!match) {
|
|
379
|
+
throw new CliError(
|
|
380
|
+
CLI_ERROR_CODE.PROJECT_NOT_FOUND,
|
|
381
|
+
`${domain} is not attached to this project for env "${envScope}". List attached: cimplify domains ls --attached`
|
|
382
|
+
);
|
|
383
|
+
}
|
|
384
|
+
return match;
|
|
385
|
+
}
|
|
386
|
+
|
|
387
|
+
export { run as default, printDnsRecords };
|
|
@@ -0,0 +1,268 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import { formatEnvFile, parseEnvFile, parseKeyValueArg } from './chunk-4YSOZ6LY.mjs';
|
|
3
|
+
import { promptYesNo } from './chunk-L6474RPL.mjs';
|
|
4
|
+
import { ENV_SCOPE, PUBLIC_ENV_PREFIX, SECRET_MASK } from './chunk-MQMNWLMU.mjs';
|
|
5
|
+
import { parseArgs, flagString, flagBool } from './chunk-D7D75ONX.mjs';
|
|
6
|
+
import { ApiClient } from './chunk-4ZVTPMUZ.mjs';
|
|
7
|
+
import { readAuth, readProjectLink } from './chunk-JJYWETGA.mjs';
|
|
8
|
+
import { CliError, CLI_ERROR_CODE, info, dim, result, bold, success } from './chunk-NZ4RG62Z.mjs';
|
|
9
|
+
import { promises } from 'fs';
|
|
10
|
+
import path from 'path';
|
|
11
|
+
|
|
12
|
+
var SUB_LS = "ls";
|
|
13
|
+
var SUB_LIST = "list";
|
|
14
|
+
var SUB_PULL = "pull";
|
|
15
|
+
var SUB_PUSH = "push";
|
|
16
|
+
var SUB_ADD = "add";
|
|
17
|
+
var SUB_RM = "rm";
|
|
18
|
+
var SUB_REMOVE = "remove";
|
|
19
|
+
var FLAG_SCOPE = "scope";
|
|
20
|
+
var FLAG_SHOW = "show";
|
|
21
|
+
var FLAG_OUT = "out";
|
|
22
|
+
var FLAG_FILE = "file";
|
|
23
|
+
var FLAG_OVERWRITE = "overwrite";
|
|
24
|
+
var FLAG_SECRET = "secret";
|
|
25
|
+
var FLAG_PUBLIC = "public";
|
|
26
|
+
var FLAG_YES = "yes";
|
|
27
|
+
var DEFAULT_PULL_PATH = ".env.local";
|
|
28
|
+
var PULL_BACKUP_SUFFIX = ".bak";
|
|
29
|
+
var COL_GAP = " ";
|
|
30
|
+
var COL_KEY = "KEY";
|
|
31
|
+
var COL_SCOPE = "SCOPE";
|
|
32
|
+
var COL_SECRET = "SECRET";
|
|
33
|
+
var COL_VALUE = "VALUE";
|
|
34
|
+
var VALID_SCOPES = new Set(Object.values(ENV_SCOPE));
|
|
35
|
+
function envEndpoint(businessId, projectId) {
|
|
36
|
+
return `/v1/businesses/${encodeURIComponent(businessId)}/projects/${encodeURIComponent(projectId)}/env-vars`;
|
|
37
|
+
}
|
|
38
|
+
function envItemEndpoint(businessId, projectId, id) {
|
|
39
|
+
return `${envEndpoint(businessId, projectId)}/${encodeURIComponent(id)}`;
|
|
40
|
+
}
|
|
41
|
+
function bulkSetEndpoint(businessId, projectId) {
|
|
42
|
+
return `${envEndpoint(businessId, projectId)}/bulk-set`;
|
|
43
|
+
}
|
|
44
|
+
function resolveScope(value, fallback = ENV_SCOPE.PREVIEW) {
|
|
45
|
+
if (value === void 0) return fallback;
|
|
46
|
+
if (!VALID_SCOPES.has(value)) {
|
|
47
|
+
throw new CliError(
|
|
48
|
+
CLI_ERROR_CODE.INVALID_INPUT,
|
|
49
|
+
`Invalid scope "${value}". Choose one of: ${[...VALID_SCOPES].join(", ")}.`
|
|
50
|
+
);
|
|
51
|
+
}
|
|
52
|
+
return value;
|
|
53
|
+
}
|
|
54
|
+
function classifyIsSecret(key, override) {
|
|
55
|
+
if (override.secret && override.public) {
|
|
56
|
+
throw new CliError(
|
|
57
|
+
CLI_ERROR_CODE.INVALID_INPUT,
|
|
58
|
+
"Cannot pass both --secret and --public."
|
|
59
|
+
);
|
|
60
|
+
}
|
|
61
|
+
if (override.secret) return true;
|
|
62
|
+
if (override.public) return false;
|
|
63
|
+
return !key.startsWith(PUBLIC_ENV_PREFIX);
|
|
64
|
+
}
|
|
65
|
+
async function run(argv) {
|
|
66
|
+
const args = parseArgs(argv);
|
|
67
|
+
const sub = args.positional[0];
|
|
68
|
+
if (!sub) {
|
|
69
|
+
throw new CliError(
|
|
70
|
+
CLI_ERROR_CODE.INVALID_INPUT,
|
|
71
|
+
`Usage: cimplify env <${SUB_LS}|${SUB_PULL}|${SUB_PUSH}|${SUB_ADD}|${SUB_RM}>`
|
|
72
|
+
);
|
|
73
|
+
}
|
|
74
|
+
const auth = await readAuth();
|
|
75
|
+
const link = await readProjectLink();
|
|
76
|
+
const client = ApiClient.fromAuth(auth);
|
|
77
|
+
if (sub === SUB_LS || sub === SUB_LIST) {
|
|
78
|
+
await listEnv(client, link.businessId, link.projectId, args);
|
|
79
|
+
return;
|
|
80
|
+
}
|
|
81
|
+
if (sub === SUB_PULL) {
|
|
82
|
+
await pullEnv(client, link.businessId, link.projectId, args);
|
|
83
|
+
return;
|
|
84
|
+
}
|
|
85
|
+
if (sub === SUB_PUSH) {
|
|
86
|
+
await pushEnv(client, link.businessId, link.projectId, args);
|
|
87
|
+
return;
|
|
88
|
+
}
|
|
89
|
+
if (sub === SUB_ADD) {
|
|
90
|
+
await addEnv(client, link.businessId, link.projectId, args);
|
|
91
|
+
return;
|
|
92
|
+
}
|
|
93
|
+
if (sub === SUB_RM || sub === SUB_REMOVE) {
|
|
94
|
+
await removeEnv(client, link.businessId, link.projectId, args);
|
|
95
|
+
return;
|
|
96
|
+
}
|
|
97
|
+
throw new CliError(CLI_ERROR_CODE.INVALID_INPUT, `Unknown env subcommand "${sub}"`);
|
|
98
|
+
}
|
|
99
|
+
async function listEnv(client, businessId, projectId, args) {
|
|
100
|
+
const scope = resolveScope(flagString(args, FLAG_SCOPE));
|
|
101
|
+
const show = flagBool(args, FLAG_SHOW);
|
|
102
|
+
const records = await client.get(envEndpoint(businessId, projectId), {
|
|
103
|
+
query: { scope }
|
|
104
|
+
});
|
|
105
|
+
if (records.length === 0) {
|
|
106
|
+
info(dim(`No env vars in scope "${scope}". Add one: cimplify env add KEY=VALUE`));
|
|
107
|
+
result({ scope, vars: [] });
|
|
108
|
+
return;
|
|
109
|
+
}
|
|
110
|
+
const keyWidth = Math.max(COL_KEY.length, ...records.map((r) => r.key.length));
|
|
111
|
+
const scopeWidth = Math.max(COL_SCOPE.length, ...records.map((r) => String(r.scope).length));
|
|
112
|
+
const secretWidth = Math.max(COL_SECRET.length, "yes".length);
|
|
113
|
+
info(
|
|
114
|
+
bold(
|
|
115
|
+
[
|
|
116
|
+
COL_KEY.padEnd(keyWidth),
|
|
117
|
+
COL_SCOPE.padEnd(scopeWidth),
|
|
118
|
+
COL_SECRET.padEnd(secretWidth),
|
|
119
|
+
COL_VALUE
|
|
120
|
+
].join(COL_GAP)
|
|
121
|
+
)
|
|
122
|
+
);
|
|
123
|
+
for (const r of records) {
|
|
124
|
+
const value = renderValue(r, show);
|
|
125
|
+
info(
|
|
126
|
+
[
|
|
127
|
+
r.key.padEnd(keyWidth),
|
|
128
|
+
String(r.scope).padEnd(scopeWidth),
|
|
129
|
+
(r.is_secret ? "yes" : "no").padEnd(secretWidth),
|
|
130
|
+
value
|
|
131
|
+
].join(COL_GAP)
|
|
132
|
+
);
|
|
133
|
+
}
|
|
134
|
+
result({
|
|
135
|
+
scope,
|
|
136
|
+
vars: records.map((r) => ({
|
|
137
|
+
key: r.key,
|
|
138
|
+
scope: r.scope,
|
|
139
|
+
is_secret: r.is_secret,
|
|
140
|
+
value: r.is_secret ? null : r.value ?? null
|
|
141
|
+
}))
|
|
142
|
+
});
|
|
143
|
+
}
|
|
144
|
+
function renderValue(r, show) {
|
|
145
|
+
if (r.is_secret) return SECRET_MASK;
|
|
146
|
+
if (r.value === null) return SECRET_MASK;
|
|
147
|
+
if (!show) return r.value;
|
|
148
|
+
return r.value;
|
|
149
|
+
}
|
|
150
|
+
async function pullEnv(client, businessId, projectId, args) {
|
|
151
|
+
const scope = resolveScope(flagString(args, FLAG_SCOPE));
|
|
152
|
+
const outPath = path.resolve(process.cwd(), flagString(args, FLAG_OUT) ?? DEFAULT_PULL_PATH);
|
|
153
|
+
const records = await client.get(envEndpoint(businessId, projectId), {
|
|
154
|
+
query: { scope }
|
|
155
|
+
});
|
|
156
|
+
const blockedSecrets = records.filter((r) => r.is_secret).map((r) => r.key);
|
|
157
|
+
if (blockedSecrets.length > 0) {
|
|
158
|
+
throw new CliError(
|
|
159
|
+
CLI_ERROR_CODE.INVALID_INPUT,
|
|
160
|
+
`Cannot pull secret values: ${blockedSecrets.join(", ")}.
|
|
161
|
+
Secrets are never returned in plaintext to the CLI; use the dashboard to copy them.`
|
|
162
|
+
);
|
|
163
|
+
}
|
|
164
|
+
const entries = records.filter((r) => r.value !== null).map((r) => ({ key: r.key, value: r.value }));
|
|
165
|
+
await backupIfExists(outPath);
|
|
166
|
+
await promises.mkdir(path.dirname(outPath), { recursive: true });
|
|
167
|
+
await promises.writeFile(outPath, formatEnvFile(entries), "utf8");
|
|
168
|
+
success(`Pulled ${entries.length} var${entries.length === 1 ? "" : "s"} to ${path.relative(process.cwd(), outPath) || outPath}`);
|
|
169
|
+
result({ scope, count: entries.length, file: outPath });
|
|
170
|
+
}
|
|
171
|
+
async function backupIfExists(target) {
|
|
172
|
+
try {
|
|
173
|
+
await promises.stat(target);
|
|
174
|
+
} catch (err) {
|
|
175
|
+
if (err.code === "ENOENT") return;
|
|
176
|
+
throw err;
|
|
177
|
+
}
|
|
178
|
+
await promises.copyFile(target, `${target}${PULL_BACKUP_SUFFIX}`);
|
|
179
|
+
}
|
|
180
|
+
async function pushEnv(client, businessId, projectId, args) {
|
|
181
|
+
const scope = resolveScope(flagString(args, FLAG_SCOPE));
|
|
182
|
+
const filePath = path.resolve(process.cwd(), flagString(args, FLAG_FILE) ?? DEFAULT_PULL_PATH);
|
|
183
|
+
const overwrite = flagBool(args, FLAG_OVERWRITE);
|
|
184
|
+
let raw;
|
|
185
|
+
try {
|
|
186
|
+
raw = await promises.readFile(filePath, "utf8");
|
|
187
|
+
} catch (err) {
|
|
188
|
+
if (err.code === "ENOENT") {
|
|
189
|
+
throw new CliError(
|
|
190
|
+
CLI_ERROR_CODE.INVALID_INPUT,
|
|
191
|
+
`Env file not found: ${filePath}.
|
|
192
|
+
Use --file to point at a different path.`
|
|
193
|
+
);
|
|
194
|
+
}
|
|
195
|
+
throw err;
|
|
196
|
+
}
|
|
197
|
+
const entries = parseEnvFile(raw);
|
|
198
|
+
if (entries.length === 0) {
|
|
199
|
+
throw new CliError(
|
|
200
|
+
CLI_ERROR_CODE.INVALID_INPUT,
|
|
201
|
+
`No env vars found in ${filePath}.`
|
|
202
|
+
);
|
|
203
|
+
}
|
|
204
|
+
const body = {
|
|
205
|
+
scope,
|
|
206
|
+
vars: entries.map((e) => ({
|
|
207
|
+
key: e.key,
|
|
208
|
+
value: e.value,
|
|
209
|
+
is_secret: classifyIsSecret(e.key, { secret: false, public: false })
|
|
210
|
+
})),
|
|
211
|
+
overwrite
|
|
212
|
+
};
|
|
213
|
+
await client.post(bulkSetEndpoint(businessId, projectId), body);
|
|
214
|
+
success(`Pushed ${entries.length} var${entries.length === 1 ? "" : "s"} to ${scope}${overwrite ? " (overwrite)" : ""}`);
|
|
215
|
+
result({ scope, count: entries.length, overwrite });
|
|
216
|
+
}
|
|
217
|
+
async function addEnv(client, businessId, projectId, args) {
|
|
218
|
+
const positional = args.positional[1];
|
|
219
|
+
if (!positional) {
|
|
220
|
+
throw new CliError(
|
|
221
|
+
CLI_ERROR_CODE.INVALID_INPUT,
|
|
222
|
+
`Usage: cimplify env ${SUB_ADD} KEY=VALUE [--scope=<scope>] [--secret|--public]`
|
|
223
|
+
);
|
|
224
|
+
}
|
|
225
|
+
const { key, value } = parseKeyValueArg(positional);
|
|
226
|
+
const scope = resolveScope(flagString(args, FLAG_SCOPE));
|
|
227
|
+
const isSecret = classifyIsSecret(key, {
|
|
228
|
+
secret: flagBool(args, FLAG_SECRET),
|
|
229
|
+
public: flagBool(args, FLAG_PUBLIC)
|
|
230
|
+
});
|
|
231
|
+
const body = { key, value, scope, is_secret: isSecret };
|
|
232
|
+
const created = await client.post(envEndpoint(businessId, projectId), body);
|
|
233
|
+
success(`Added ${created.key} (${scope}, ${isSecret ? "secret" : "public"})`);
|
|
234
|
+
result({
|
|
235
|
+
var: { key: created.key, scope: created.scope, is_secret: created.is_secret }
|
|
236
|
+
});
|
|
237
|
+
}
|
|
238
|
+
async function removeEnv(client, businessId, projectId, args) {
|
|
239
|
+
const key = args.positional[1];
|
|
240
|
+
if (!key) {
|
|
241
|
+
throw new CliError(
|
|
242
|
+
CLI_ERROR_CODE.INVALID_INPUT,
|
|
243
|
+
`Usage: cimplify env ${SUB_RM} <KEY> [--scope=<scope>]`
|
|
244
|
+
);
|
|
245
|
+
}
|
|
246
|
+
const scope = resolveScope(flagString(args, FLAG_SCOPE));
|
|
247
|
+
const records = await client.get(envEndpoint(businessId, projectId), {
|
|
248
|
+
query: { scope }
|
|
249
|
+
});
|
|
250
|
+
const target = records.find((r) => r.key === key);
|
|
251
|
+
if (!target) {
|
|
252
|
+
throw new CliError(
|
|
253
|
+
CLI_ERROR_CODE.PROJECT_NOT_FOUND,
|
|
254
|
+
`No env var "${key}" in scope "${scope}".`
|
|
255
|
+
);
|
|
256
|
+
}
|
|
257
|
+
if (!flagBool(args, FLAG_YES)) {
|
|
258
|
+
const confirmed = await promptYesNo(`Delete ${key} from ${scope}?`, true);
|
|
259
|
+
if (!confirmed) {
|
|
260
|
+
throw new CliError(CLI_ERROR_CODE.ABORTED, "Aborted by user.");
|
|
261
|
+
}
|
|
262
|
+
}
|
|
263
|
+
await client.delete(envItemEndpoint(businessId, projectId, target.id));
|
|
264
|
+
success(`Removed ${key} from ${scope}`);
|
|
265
|
+
result({ removed: true, key, scope });
|
|
266
|
+
}
|
|
267
|
+
|
|
268
|
+
export { classifyIsSecret, run as default };
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import { parseArgs } from './chunk-D7D75ONX.mjs';
|
|
3
|
+
import { ApiClient } from './chunk-4ZVTPMUZ.mjs';
|
|
4
|
+
import { readAuth, writeProjectLink } from './chunk-JJYWETGA.mjs';
|
|
5
|
+
import { CliError, CLI_ERROR_CODE, success, info, dim, result } from './chunk-NZ4RG62Z.mjs';
|
|
6
|
+
|
|
7
|
+
// src/commands/link.ts
|
|
8
|
+
function projectEndpoint(businessId, projectId) {
|
|
9
|
+
return `/v1/businesses/${encodeURIComponent(businessId)}/projects/${encodeURIComponent(projectId)}`;
|
|
10
|
+
}
|
|
11
|
+
async function run(argv) {
|
|
12
|
+
const args = parseArgs(argv);
|
|
13
|
+
const projectId = args.positional[0];
|
|
14
|
+
if (!projectId) {
|
|
15
|
+
throw new CliError(
|
|
16
|
+
CLI_ERROR_CODE.INVALID_INPUT,
|
|
17
|
+
"Usage: cimplify link <project-id>\nList projects with `cimplify projects ls`."
|
|
18
|
+
);
|
|
19
|
+
}
|
|
20
|
+
const auth = await readAuth();
|
|
21
|
+
const client = ApiClient.fromAuth(auth);
|
|
22
|
+
const project = await client.get(
|
|
23
|
+
projectEndpoint(auth.businessId, projectId)
|
|
24
|
+
);
|
|
25
|
+
const link = {
|
|
26
|
+
projectId: project.id,
|
|
27
|
+
businessId: project.business_id,
|
|
28
|
+
businessHandle: auth.businessHandle ?? project.business_handle ?? void 0,
|
|
29
|
+
remoteUrl: project.metadata?.repo?.url,
|
|
30
|
+
defaultBranch: project.metadata?.repo?.default_branch,
|
|
31
|
+
framework: project.metadata?.framework ?? project.project_type,
|
|
32
|
+
linkedAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
33
|
+
};
|
|
34
|
+
await writeProjectLink(link);
|
|
35
|
+
success(`Linked to ${project.name} (${project.id})`);
|
|
36
|
+
if (link.remoteUrl) info(dim(`remote: ${link.remoteUrl}`));
|
|
37
|
+
result({
|
|
38
|
+
project: { id: project.id, name: project.name },
|
|
39
|
+
business: { id: project.business_id },
|
|
40
|
+
remote_url: link.remoteUrl ?? null,
|
|
41
|
+
default_branch: link.defaultBranch ?? null
|
|
42
|
+
});
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
export { run as default };
|