@uniformdev/csk-cli 6.0.123-alpha.1 → 6.1.63-alpha.1

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 (3) hide show
  1. package/README.md +64 -4
  2. package/dist/index.mjs +46 -37
  3. package/package.json +11 -11
package/README.md CHANGED
@@ -1,6 +1,6 @@
1
1
  # @uniformdev/csk-cli
2
2
 
3
- `@uniformdev/csk-cli` is a command-line interface (CLI) tool designed to streamline the development workflow within Uniform projects. It provides commands for pulling additional data and generating components based on Canvas data.
3
+ `@uniformdev/csk-cli` is a command-line interface (CLI) tool designed to streamline the development workflow within Uniform projects. It provides commands for initializing projects, pulling Canvas data, pulling additional data like locales, and generating components based on Canvas data.
4
4
 
5
5
  ## Installation
6
6
 
@@ -12,9 +12,9 @@ npm install @uniformdev/csk-cli --save-dev
12
12
 
13
13
  ## Commands
14
14
 
15
- ### `pull` Command
15
+ ### `init` Command
16
16
 
17
- The `pull` command retrieves additional data for the project. Currently, it supports pulling locales, with potential future expansions.
17
+ The `init` command initializes your Uniform project by pushing content, design extensions, and publishing the context manifest.
18
18
 
19
19
  #### Usage
20
20
 
@@ -22,19 +22,79 @@ Add the following script to your `package.json`:
22
22
 
23
23
  ```json
24
24
  "scripts": {
25
- "pull:locales": "csk-cli pull -l"
25
+ "init": "csk-cli init",
26
+ "init:dev": "csk-cli init --dev"
26
27
  }
27
28
  ```
28
29
 
29
30
  Run the command using:
30
31
 
31
32
  ```bash
33
+ npm run init
34
+ ```
35
+
36
+ #### Options
37
+
38
+ - `--dev` – Initializes the project in development mode, preserving all CSK variant folders.
39
+
40
+ #### What it does
41
+
42
+ 1. Pushes design extensions configuration
43
+ 2. Pushes content from `./content` folder using Uniform sync
44
+ 3. Publishes the context manifest
45
+ 4. If CSK variants are detected, prompts to select which variant to push
46
+ 5. In production mode (default), cleans up unused variant folders after initialization
47
+
48
+ #### Environment Variables
49
+
50
+ Before running the command, configure the following environment variables:
51
+
52
+ - `UNIFORM_API_KEY` – Your Uniform API key (must have "Developer" role).
53
+ - `UNIFORM_PROJECT_ID` – The ID of your Uniform project.
54
+
55
+ These can be set in a `.env` file or provided directly in the CLI environment.
56
+
57
+ ---
58
+
59
+ ### `pull` Command
60
+
61
+ The `pull` command retrieves data for the project. It supports pulling Uniform Canvas data and locales.
62
+
63
+ #### Usage
64
+
65
+ Add the following scripts to your `package.json`:
66
+
67
+ ```json
68
+ "scripts": {
69
+ "pull:uniform": "csk-cli pull -u",
70
+ "pull:uniform:dev": "csk-cli pull -u --dev",
71
+ "pull:locales": "csk-cli pull -l"
72
+ }
73
+ ```
74
+
75
+ Run the commands using:
76
+
77
+ ```bash
78
+ npm run pull:uniform
79
+ # or
32
80
  npm run pull:locales
33
81
  ```
34
82
 
35
83
  #### Options
36
84
 
85
+ - `-u, --uniform` – Pulls Uniform Canvas data including design extensions and content.
37
86
  - `-l, --locales` – Pulls locales configuration.
87
+ - `--dev` – Used with `-u` to pull in development mode, preserving all CSK variant folders.
88
+
89
+ #### Pull Uniform (`-u`)
90
+
91
+ When using the `-u` or `--uniform` flag, the command:
92
+
93
+ 1. Pulls design extensions configuration
94
+ 2. Applies design extensions to your project
95
+ 3. Pulls content using Uniform sync to `./content` folder
96
+ 4. If CSK variants are detected, prompts to select which variant to pull
97
+ 5. In production mode (default), cleans up unused variant folders after pulling
38
98
 
39
99
  #### Environment Variables
40
100
 
package/dist/index.mjs CHANGED
@@ -1,37 +1,46 @@
1
- import{program as $}from"commander";import w from"node:fs";import te from"node:path";import{LocaleClient as re}from"@uniformdev/canvas";import _ from"node:path";var L="\x1B[32m";var ee=_.join("src","i18n"),x=_.join(...(process.env.LOCALES_PATH??ee).split(/[\\/]/).filter(Boolean));var O=(e,r)=>{console.info(L,`The ${e} configuration was successfully ${r}`)};var S=async()=>{if(!w.existsSync(x)){console.error(`No such directory for locales files: ${x}. You can override it by setting LOCALES_PATH environment variable.`);return}let r=await new re({apiHost:process.env.UNIFORM_CLI_BASE_URL,apiKey:process.env.UNIFORM_API_KEY,projectId:process.env.UNIFORM_PROJECT_ID}).get(),{results:t}=r,o=t?.reduce((n,i)=>(n.locales.push(i.locale),n.localeNames[i.locale]=i.displayName,n.localeGroups[i.locale]=i.group??"",i.isDefault&&(n.defaultLocale=i.locale),n),{locales:[],localeNames:{},localeGroups:{},defaultLocale:null}),s=te.resolve(x,"locales.json");w.writeFile(s,JSON.stringify(o,void 0," "),n=>{n&&console.error(n)}),O("locales","pulled")};var I=async e=>{if(e?.locales){console.info("Pulling locales..."),S().catch(r=>console.error(r));return}};import*as J from"ora";import{select as Ie}from"@inquirer/prompts";import H from"node:path";var oe=H.join("src","components","custom-canvas"),A=H.join(...(process.env.CUSTOM_CANVAS_FOLDER_PATH??oe).split(/[\\/]/).filter(Boolean));var f=(n=>(n.SLOTS="slots",n.COMPONENT="component",n.CONTEXT="context",n.SLOT_INDEX="slotIndex",n.SLOT_NAME="slotName",n))(f||{}),R=/\b[a-zA-Z0-9_]+Mapping\s*=\s*{(?:[^{}]*|\{(?:[^{}]*|\{[^{}]*\})*\})*}/g,D=/(import .+;)(?![\s\S]*import .+)/,b=e=>new RegExp(`\\b${e}\\s*:\\s*[^,]+,?`,"g"),k=/}$/,G=/^[$_a-zA-Z][$_a-zA-Z0-9]*$/gm,F=/_{2,}/;import v from"fs";import*as W from"ora";import K from"path";import{confirm as Oe,input as we}from"@inquirer/prompts";import{exec as ne}from"child_process";import ae from"prettier";var E=async e=>new Promise((r,t)=>{ne(e,(o,s,n)=>{if(o){t(o.message);return}if(n){t(n);return}r(s)})}),h=(e,r)=>ae.format(e,{parser:"typescript",printWidth:120,singleQuote:!0,semi:!0,trailingComma:"es5",tabWidth:2,arrowParens:"avoid",endOfLine:"auto",...r});import{CanvasClient as _e}from"@uniformdev/canvas";import{input as X}from"@inquirer/prompts";var le={import:["import { UniformText } from '@uniformdev/canvas-next-rsc/component';"],needsProps:["context","component"],supports:"text",type:"string",render:e=>`<span>Text value: </span><UniformText parameterId="${e.canvasId||e.id}" placeholder="${e.name} goes here" context={context} component={component} />`},pe={supports:"number",type:"number",render:e=>`<span>Number value: </span>{${e.id}}`},ce={supports:"date",type:"string",render:e=>`<span>Date value: </span>{${e.id}}`},me={supports:"select",type:"string[]",render:e=>`<span>Selected value: </span>{${e.id}}`},de={supports:"multi-select",type:"string[]",render:e=>`<span>Selected values: </span>{${e.id}?.join(', ')}`},fe={supports:"datetime",type:"{ datetime: string; timeZone: string }",render:e=>`<p>Date value: {${e.id}?.datetime}</p><p>Timezone value: {${e.id}?.timeZone}</p>`},ue={import:["import { LinkParamValue } from '@uniformdev/canvas';","import NextLink from 'next/link';"],supports:"link",type:"LinkParamValue",render:e=>`<span>Link value: <NextLink href={${e.id}?.path ?? '#'}>Link Text</NextLink></span>`},ge={import:["import NextImage from 'next/image';","import type { AssetParamValue } from '@uniformdev/assets';","import { flattenValues } from '@uniformdev/canvas';"],supports:"asset",type:"AssetParamValue",render:e=>`<div className="flex flex-row gap-2 overflow-x-auto">
2
- {(flattenValues(${e.id} as never) || [])
1
+ import{program as A}from"commander";import{execSync as I}from"child_process";import{select as he}from"@inquirer/prompts";import{exec as fe}from"child_process";import p from"fs";import f from"path";import ue from"prettier";var ge=["aggregate","componentPattern","dataType","files","projectMapDefinition","redirect","asset","composition","enrichment","locale","projectMapNode","signal","category","compositionPattern","entry","previewUrl","prompt","test","component","contentType","entryPattern","previewViewport","quirk","workflow"],y=async e=>new Promise((t,o)=>{fe(e,(r,s,a)=>{if(r){o(r.message);return}if(a){o(a);return}t(s)})}),v=(e,t)=>ue.format(e,{parser:"typescript",printWidth:120,singleQuote:!0,semi:!0,trailingComma:"es5",tabWidth:2,arrowParens:"avoid",endOfLine:"auto",...t}),P=()=>{let e=f.resolve(process.cwd(),"content");if(!p.existsSync(e))return[];let t=p.readdirSync(e,{withFileTypes:!0}).filter(o=>o.isDirectory()).map(o=>o.name);return t.some(o=>ge.includes(o))?[]:t},T=e=>e.charAt(0).toUpperCase()+e.slice(1),C=(e,t)=>{let o=process.cwd();e.map(n=>f.resolve(o,`uniform.config.${n}.ts`)).forEach(n=>{p.existsSync(n)&&p.unlinkSync(n)});let s=f.resolve(o,"package.json");if(p.existsSync(s)){let n=JSON.parse(p.readFileSync(s,"utf-8"));n.scripts&&n.scripts.init&&(n.scripts.init="run-s uniform:push uniform:publish",n.scripts["uniform:pull"]="run-s pull:dex apply:dex pull:content",p.writeFileSync(s,JSON.stringify(n,null,2)+`
2
+ `))}let a=f.resolve(o,"content"),l=f.resolve(a,t);p.existsSync(l)&&p.readdirSync(l).forEach(c=>{let m=f.join(l,c),d=f.join(a,c);p.existsSync(d)&&p.rmSync(d,{recursive:!0,force:!0}),p.renameSync(m,d)}),e.forEach(n=>{let c=f.resolve(a,n);p.existsSync(c)&&p.rmSync(c,{recursive:!0,force:!0})})};var H=e=>{let t=process.cwd();I("design-extensions-tools push",{stdio:"inherit",cwd:t});let o=e?`uniform sync push --config ./uniform.config.${e}.ts`:"uniform sync push";I(o,{stdio:"inherit",cwd:t}),I("uniform context manifest publish",{stdio:"inherit",cwd:t})},D=async e=>{try{let{dev:t=!1}=e||{},o=P();if(o.length===0){H();return}let r=await he({message:"Select the CSK variant to push:",choices:o.map(s=>({name:T(s),value:s})),loop:!1});H(r),t||C(o,r)}catch(t){t instanceof Error&&(t.message.includes("force closed")?console.info(`
3
+ \u{1F44B} See you next time! \u{1F9E1}
4
+ `):(console.error(`
5
+ \u{1F641} Something went wrong. Please try again.
6
+ `),console.error(t)))}};import U from"fs";import Ee from"path";import{LocaleClient as ye}from"@uniformdev/canvas";import k from"path";var b="\x1B[32m";var xe=k.join("src","i18n"),N=k.join(...(process.env.LOCALES_PATH??xe).split(/[\\/]/).filter(Boolean));var F=(e,t)=>{console.info(b,`The ${e} configuration was successfully ${t}`)};var G=async()=>{if(!U.existsSync(N)){console.error(`No such directory for locales files: ${N}. You can override it by setting LOCALES_PATH environment variable.`);return}let t=await new ye({projectId:process.env.UNIFORM_PROJECT_ID,apiKey:process.env.UNIFORM_API_KEY,apiHost:process.env.UNIFORM_CLI_BASE_URL||"https://uniform.app"}).get(),{results:o}=t,r=o?.reduce((a,l)=>(a.locales.push(l.locale),a.localeNames[l.locale]=l.displayName,a.localeGroups[l.locale]=l.group??"",l.isDefault&&(a.defaultLocale=l.locale),a),{locales:[],localeNames:{},localeGroups:{},defaultLocale:null}),s=Ee.resolve(N,"locales.json");U.writeFile(s,JSON.stringify(r,void 0," "),a=>{a&&console.error(a)}),F("locales","pulled")};import{execSync as R}from"child_process";import{select as ve}from"@inquirer/prompts";var V=e=>{let t=process.cwd();R("design-extensions-tools pull",{stdio:"inherit",cwd:t}),R("design-extensions-tools apply",{stdio:"inherit",cwd:t});let o=e?`uniform sync pull --config ./uniform.config.${e}.ts`:"uniform sync pull";R(o,{stdio:"inherit",cwd:t})},j=async e=>{try{let t=P();if(t.length===0){V();return}let o=await ve({message:"Select the CSK variant to pull:",choices:t.map(r=>({name:T(r),value:r})),loop:!1});V(o),e||C(t,o)}catch(t){t instanceof Error&&(t.message.includes("force closed")?console.info(`
7
+ \u{1F44B} See you next time! \u{1F9E1}
8
+ `):(console.error(`
9
+ \u{1F641} Something went wrong. Please try again.
10
+ `),console.error(t)))}};var X=async e=>{let{dev:t,uniform:o,locales:r}=e||{};if(r){console.info("Pulling locales..."),G().catch(s=>console.error(s));return}else if(o){console.info("Pulling uniform canvas data..."),j(!!t).catch(s=>console.error(s));return}};import*as ie from"ora";import{select as Me}from"@inquirer/prompts";import W from"path";var Pe=W.join("src","components","custom-canvas"),K=W.join(...(process.env.CUSTOM_CANVAS_FOLDER_PATH??Pe).split(/[\\/]/).filter(Boolean));var h=(n=>(n.SLOTS="slots",n.COMPONENT="component",n.CONTEXT="context",n.SLOT_INDEX="slotIndex",n.SLOT_NAME="slotName",n.PARAMETERS="parameters",n.VARIANT="variant",n))(h||{}),M=/\b[a-zA-Z0-9_]+Mapping\s*=\s*{(?:[^{}]*|\{(?:[^{}]*|\{[^{}]*\})*\})*}/g,B=/(import .+;)(?![\s\S]*import .+)/,J=e=>new RegExp(`\\b${e}\\s*:\\s*[^,]+,?`,"g"),z=/}$/,q=/^[$_a-zA-Z][$_a-zA-Z0-9]*$/gm,Z=/_{2,}/;import S from"fs";import*as ne from"ora";import re from"path";import{confirm as Xe,input as We}from"@inquirer/prompts";import{CanvasClient as Ve}from"@uniformdev/canvas";import{input as ee}from"@inquirer/prompts";var Ce={import:["import { UniformText } from '@uniformdev/next-app-router/component';","import { ComponentParameter } from '@uniformdev/next-app-router/component';"],needsProps:["component","parameters"],supports:"text",type:"string",render:e=>`<span>Text value: </span><UniformText parameter={parameters.${e.canvasId||e.id} as ComponentParameter<string>} placeholder="${e.name} goes here" component={component} />`},Ne={supports:"number",type:"number",render:e=>`<span>Number value: </span>{${e.id}}`},Se={supports:"date",type:"string",render:e=>`<span>Date value: </span>{${e.id}}`},_e={supports:"select",type:"string[]",render:e=>`<span>Selected value: </span>{${e.id}}`},we={supports:"multi-select",type:"string[]",render:e=>`<span>Selected values: </span>{${e.id}?.join(', ')}`},$e={supports:"datetime",type:"{ datetime: string; timeZone: string }",render:e=>`<p>Date value: {${e.id}?.datetime}</p><p>Timezone value: {${e.id}?.timeZone}</p>`},Le={import:["import { LinkParamValue } from '@uniformdev/canvas';","import NextLink from 'next/link';"],supports:"link",type:"LinkParamValue",render:e=>`<span>Link value: <NextLink href={${e.id}?.path ?? '#'}>Link Text</NextLink></span>`},Ae={import:["import NextImage from 'next/image';","import type { AssetParamValue } from '@uniformdev/assets';","import { ReplaceFieldsWithAssets } from '@uniformdev/csk-components/types/cskTypes';"],supports:"asset",type:"AssetParamValue",render:e=>`<div className="flex flex-row gap-2 overflow-x-auto">
11
+ {(${e.id} || [])
3
12
  .filter(({ url }) => Boolean(url))
4
13
  .map(({ title, url }, index) => (
5
- <NextImage key={index} src={url} width={200} height={200} alt={title} style={{ objectFit: 'cover' }} />
14
+ <NextImage key={index} src={url} width={200} height={200} alt={title || ''} style={{ objectFit: 'cover' }} />
6
15
  ))}
7
- </div>`},xe={supports:"checkbox",type:"boolean",render:e=>`<span>Checkbox: {${e.id} ? "Marked" : "Unmarked"}</span>`},Ee={import:["import { UniformRichText } from '@uniformdev/canvas-next-rsc/component';","import { RichTextNode } from '@uniformdev/richtext';"],needsProps:["context","component"],supports:"richText",type:"RichTextNode",render:e=>`<UniformRichText placeholder="Content goes here..." className="prose max-w-full text-current marker:text-current [&_*:not(pre)]:text-current" parameterId="${e.canvasId||e.id}" context={context} component={component} />`},he={import:["import NextImage from 'next/image';"],supports:"imageUrl",type:"string",render:e=>`{!!${e.id} && <NextImage src={${e.id}} width={200} height={200} alt="example" style={{ objectFit: 'cover' }} />}`},ve={supports:"jsonData",type:"Record<string, unknown>",render:e=>`{JSON.stringify(${e.id})}`},ye={import:["import { cn } from '@uniformdev/csk-components/utils/styling';"],supports:"tp2-color-palette-parameter",type:"string",render:e=>`
16
+ </div>`},Oe={supports:"checkbox",type:"boolean",render:e=>`<span>Checkbox: {${e.id} ? "Marked" : "Unmarked"}</span>`},Ie={import:["import { UniformRichText } from '@uniformdev/next-app-router/component';","import { RichTextNode } from '@uniformdev/richtext';","import { ComponentParameter } from '@uniformdev/next-app-router/component';"],needsProps:["component","parameters"],supports:"richText",type:"RichTextNode",render:e=>`<UniformRichText placeholder="Content goes here..." className="prose max-w-full text-current marker:text-current [&_*:not(pre)]:text-current" parameter={parameters.${e.canvasId||e.id} as ComponentParameter<string>} component={component} />`},Re={import:["import NextImage from 'next/image';"],supports:"imageUrl",type:"string",render:e=>`{!!${e.id} && <NextImage src={${e.id}} width={200} height={200} alt="example" style={{ objectFit: 'cover' }} />}`},He={supports:"jsonData",type:"Record<string, unknown>",render:e=>`{JSON.stringify(${e.id})}`},De={import:["import { cn } from '@uniformdev/csk-components/utils/styling';"],supports:"dex-color-palette-parameter",type:"string",render:e=>`
8
17
  <div className="flex items-center gap-2">
9
18
  <div className={cn('size-10 rounded-full', { [\`bg-\${${e.id}}\`]: !!${e.id} })} />
10
19
  <span>Color Palette value: {${e.id}}</span>
11
- </div>`},Pe={import:["import { ViewPort } from '@uniformdev/csk-components/types/cskTypes';"],supports:"tp2-segmented-control-parameter",type:"string | ViewPort<string>",render:e=>`
20
+ </div>`},ke={import:["import { ViewPort } from '@uniformdev/csk-components/types/cskTypes';"],supports:"dex-segmented-control-parameter",type:"string | ViewPort<string>",render:e=>`
12
21
  <span>Selected value: </span>
13
22
  <span>
14
23
  {typeof ${e.id} === 'string' ? ${e.id} : JSON.stringify(${e.id}, null, 2)}
15
- </span>`},Te={import:["import { ViewPort } from '@uniformdev/csk-components/types/cskTypes';"],supports:"tp2-slider-control-parameter",type:"string | ViewPort<string>",render:e=>`
24
+ </span>`},be={import:["import { ViewPort } from '@uniformdev/csk-components/types/cskTypes';"],supports:"dex-slider-control-parameter",type:"string | ViewPort<string>",render:e=>`
16
25
  <span>Selected value: </span>
17
26
  <span>
18
27
  {typeof ${e.id} === 'string' ? ${e.id} : JSON.stringify(${e.id}, null, 2)}
19
- </span>`},Ne={import:["import { ViewPort } from '@uniformdev/csk-components/types/cskTypes';"],supports:"tp2-token-selector-parameter",type:"string | ViewPort<string>",render:e=>`
28
+ </span>`},Fe={import:["import { ViewPort } from '@uniformdev/csk-components/types/cskTypes';"],supports:"dex-token-selector-parameter",type:"string | ViewPort<string>",render:e=>`
20
29
  <span>Selected value: </span>
21
30
  <span>
22
31
  {typeof ${e.id} === 'string' ? ${e.id} : JSON.stringify(${e.id}, null, 2)}
23
- </span>`},Ce={import:["import { ViewPort } from '@uniformdev/csk-components/types/cskTypes';","import { SpaceType } from '@uniformdev/csk-components/types/cskTypes';"],supports:"tp2-space-control-parameter",type:"SpaceType | ViewPort<SpaceType>",render:e=>`<span>Spacing value: {JSON.stringify(${e.id}, null, 2)}</span>`},$e={import:["import { DataWithProperties } from '@uniformdev/canvas';"],supports:"$block",type:"DataWithProperties",render:e=>`<span>Block value: {JSON.stringify(${e.id}, null, 2)}</span>`},U=[le,pe,ce,me,de,fe,ue,ge,xe,Ee,he,ve,$e,ye,Pe,Te,Ne,Ce];var V=async()=>{let e=process.env.UNIFORM_CLI_BASE_URL||"https://uniform.app",r=process.env.UNIFORM_CLI_BASE_EDGE_URL||"https://uniform.global",t=process.env.UNIFORM_PROJECT_ID,o=process.env.UNIFORM_API_KEY;return t||(t=await X({message:"We didn't find Uniform Project ID. Could you please provide it here:",required:!0})),o||(o=await X({message:"We didn't find Uniform API Key. Could you please provide it here:",required:!0})),new _e({apiHost:e,apiKey:o,projectId:t,edgeApiHost:r,disableSWR:!0})},u=e=>e?e.charAt(0).toUpperCase()+e.slice(1):"UnknownComponent",Le=(e,r)=>{let t=["text","richText"].includes(e.type),o=e.id?.match(G);if(t){let s=(o?`_${e.id}`:`_parameter${r}`).replace(F,"_");return s==="_"?void 0:s}return o?void 0:`parameter${r}`},j=e=>{let r=Object.values(f);return e.filter(o=>!r.includes(o.id)).map((o,s)=>{let n=U.find(l=>l.supports.includes(o.type)),i=Le(o,s+1);return{...o,overriddenId:i,handler:n?{...n,render:l=>i?n.render({...l,id:i,canvasId:l.id}):n.render(l)}:void 0}}).filter(o=>!!o.handler)};var y=W.default(),P={path:async({definition:e,pathToCanvasFolder:r})=>(v.existsSync(r)||(r=await we({message:"We didn't find custom-canvas folder. Could you please provide path to the custom-canvas folder:",required:!0,validate:t=>v.existsSync(t)?!0:"Path is not valid"})),K.resolve(r,`${u(e?.id)}.tsx`)),write:async({destinationPath:e,definition:r})=>{try{let t=K.relative(process.cwd(),e),o=u(r.id);if(v.existsSync(e)&&!await Oe({message:`File ${t} already exists, would you like to overwrite it?`})){console.info(`The creation of the ${t} file for the ${o} component was skipped. Make sure the existing component exports a React component to connect it to the mapper.`);return}y?.start(`Generating ${t} file`);let s=j(r.parameters||[]),n=s?.map(({id:a,overriddenId:g,handler:Y})=>`${g?`'${a}'`:a}?: ${Y?.type||"unknown"};`),i=new Set(["import { FC } from 'react';","import { ComponentProps } from '@uniformdev/canvas-next-rsc/component';",...s.map(a=>a.handler?.import).filter(Boolean).flat()]),l=new Set(["component",...s.flatMap(a=>a.handler?.needsProps).filter(Boolean)]),p=r.slots?.map(({id:a})=>a)||[];p.length&&(i.add("import { UniformSlot } from '@uniformdev/canvas-next-rsc/component';"),l.add("slots"),l.add("context"));let c=(r.parameters||[]).filter(({type:a})=>a!=="group").length,d=s.length,C=p.length,q=Array.from(i).join(`
24
- `),Z=`
25
- export type ${o}Parameters = ${n.length?`{
26
- ${n.join(`
32
+ </span>`},Ue={import:["import { ViewPort } from '@uniformdev/csk-components/types/cskTypes';","import { SpaceType } from '@uniformdev/csk-components/types/cskTypes';"],supports:"dex-space-control-parameter",type:"SpaceType | ViewPort<SpaceType>",render:e=>`<span>Spacing value: {JSON.stringify(${e.id}, null, 2)}</span>`},Ge={import:["import { DataWithProperties } from '@uniformdev/canvas';"],supports:"$block",type:"DataWithProperties",render:e=>`<span>Block value: {JSON.stringify(${e.id}, null, 2)}</span>`},Y=[Ce,Ne,Se,_e,we,$e,Le,Ae,Oe,Ie,Re,He,Ge,De,ke,be,Fe,Ue];var te=async()=>{let e=process.env.UNIFORM_PROJECT_ID,t=process.env.UNIFORM_API_KEY,o=process.env.UNIFORM_CLI_BASE_URL||"https://uniform.app",r=process.env.UNIFORM_CLI_BASE_EDGE_URL||"https://uniform.global";return e||(e=await ee({message:"We didn't find Uniform Project ID. Could you please provide it here:",required:!0})),t||(t=await ee({message:"We didn't find Uniform API Key. Could you please provide it here:",required:!0})),new Ve({apiHost:o,apiKey:t,projectId:e,edgeApiHost:r,disableSWR:!0})},x=e=>e?e.charAt(0).toUpperCase()+e.slice(1):"UnknownComponent",je=(e,t)=>{let o=["text","richText"].includes(e.type),r=e.id?.match(q);if(o){let s=(r?`_${e.id}`:`_parameter${t}`).replace(Z,"_");return s==="_"?void 0:s}return r?void 0:`parameter${t}`},oe=e=>{let t=Object.values(h);return e.filter(r=>!t.includes(r.id)).map((r,s)=>{let a=Y.find(n=>n.supports.includes(r.type)),l=je(r,s+1);return{...r,overriddenId:l,handler:a?{...a,render:n=>l?a.render({...n,id:l,canvasId:n.id}):a.render(n)}:void 0}}).filter(r=>!!r.handler)};var _=ne.default(),w={path:async({definition:e,pathToCanvasFolder:t})=>(S.existsSync(t)||(t=await We({message:"We didn't find custom-canvas folder. Could you please provide path to the custom-canvas folder:",required:!0,validate:o=>S.existsSync(o)?!0:"Path is not valid"})),re.resolve(t,`${x(e?.id)}.tsx`)),write:async({destinationPath:e,definition:t})=>{try{let o=re.relative(process.cwd(),e),r=x(t.id);if(S.existsSync(e)&&!await Xe({message:`File ${o} already exists, would you like to overwrite it?`})){console.info(`The creation of the ${o} file for the ${r} component was skipped. Make sure the existing component exports a React component to connect it to the mapper.`);return}_?.start(`Generating ${o} file`);let s=oe(t.parameters||[]),a=s?.map(({id:i,overriddenId:E,handler:de})=>`${E?`'${i}'`:i}?: ${de?.type||"unknown"};`),l=new Set(["import { FC } from 'react';","import { ComponentProps } from '@uniformdev/csk-components/types/cskTypes';","import { withFlattenParameters } from '@uniformdev/csk-components/utils/withFlattenParameters';",...s.map(i=>i.handler?.import).filter(Boolean).flat()]),n=new Set(["context","variant",...s.flatMap(i=>i.handler?.needsProps).filter(Boolean)]),c=t.slots?.map(({id:i})=>i)||[];c.length&&(l.add("import { UniformSlot } from '@uniformdev/next-app-router/component';"),n.add("slots"));let m=s.filter(i=>i.handler?.supports==="asset").map(i=>i.id),d=(t.parameters||[]).filter(({type:i})=>i!=="group").length,g=s.length,O=c.length,ce=Array.from(l).join(`
33
+ `),pe=`
34
+ export type ${r}Parameters = ${a.length?`{
35
+ ${a.join(`
27
36
  `)}
28
37
  };`:"Record<string, never>;"}
29
38
 
30
- export type ${o}Props = ComponentProps<${o}Parameters${p.length?`, '${p.join("' | '")}'`:""}>;`,Q=`
31
- const ${o}:FC<${o}Props> = ({
32
- ${s.filter(a=>!a.handler?.hideDestructuring).map(({id:a,overriddenId:g})=>`${g?`"${a}": ${g}`:a},`).join(`
39
+ export type ${r}Props = ComponentProps<${r}Parameters${c.length?`, '${c.join("' | '")}'`:""}>${m.length?`& ReplaceFieldsWithAssets<${r}Parameters, '${m.join("' | '")}'>;`:`& ${r}Parameters;`}`,me=`
40
+ const ${r}:FC<${r}Props> = ({
41
+ ${s.filter(i=>!i.handler?.hideDestructuring).map(({id:i,overriddenId:E})=>`${E?`"${i}": ${E}`:i},`).join(`
33
42
  `)}
34
- ${Array.from(l).join(`,
43
+ ${Array.from(n).join(`,
35
44
  `)}
36
45
  }) => (
37
46
  <div className="flex flex-col gap-4 rounded-lg bg-white/75 p-4 backdrop-blur-sm">
@@ -39,32 +48,32 @@ import{program as $}from"commander";import w from"node:fs";import te from"node:p
39
48
  {/* Header section */}
40
49
  <div className="flex flex-col items-center">
41
50
  <div className="text-left">
42
- <h2 className="text-3xl text-black md:text-4xl">Component Name: ${o}</h2>
43
- <p className="text-gray-600">Public ID: {component.type}</p>
51
+ <h2 className="text-3xl text-black md:text-4xl">Component Name: ${r}</h2>
52
+ <p className="text-gray-600">Public ID: {context.type}</p>
44
53
  </div>
45
54
  </div>
46
55
 
47
- <h3 className="text-2xl text-black md:text-3xl">Component Variant ID: {component.variant || 'Default'}</h3>
56
+ <h3 className="text-2xl text-black md:text-3xl">Component Variant ID: {variant || 'Default'}</h3>
48
57
 
49
58
  {/* Parameters section */}
50
- ${d?`<div className="flex flex-col gap-1 text-black">
59
+ ${g?`<div className="flex flex-col gap-1 text-black">
51
60
  <div className="flex items-center gap-1">
52
61
  <h3 className="text-2xl text-black md:text-3xl">Parameters: </h3>
53
62
  <div
54
63
  className="rounded-full bg-black/10 px-2 py-1"
55
- title="${d===c?"All parameters detected":`${d} out of ${c} parameters detected`}"
64
+ title="${g===d?"All parameters detected":`${g} out of ${d} parameters detected`}"
56
65
  >
57
- <span> ${d===c?`${d}`:`${d} / ${c}`} </span>
66
+ <span> ${g===d?`${g}`:`${g} / ${d}`} </span>
58
67
  </div>
59
68
  </div>
60
69
  <ul className="list-inside list-disc space-y-1 pl-2">
61
- ${s.map(a=>`<li>
70
+ ${s.map(i=>`<li>
62
71
  <span>
63
- Parameter Name: <strong>${a.name}</strong>
72
+ Parameter Name: <strong>${i.name}</strong>
64
73
  </span>
65
- <p className="text-gray-600">Public ID: ${a.id}</p>
74
+ <p className="text-gray-600">Public ID: ${i.id}</p>
66
75
  <div>
67
- ${a?.handler?.render(a)||"unknown"}
76
+ ${i?.handler?.render(i)||"unknown"}
68
77
  </div>
69
78
  <div className="flex w-full items-center justify-center py-2">
70
79
  <div className="h-0.5 w-11/12 rounded-full bg-black/10" />
@@ -77,18 +86,18 @@ import{program as $}from"commander";import w from"node:fs";import te from"node:p
77
86
  </h3>`}
78
87
 
79
88
  {/* Slots section */}
80
- ${C?`<div className="flex flex-col gap-1">
89
+ ${O?`<div className="flex flex-col gap-1">
81
90
  <div className="flex items-center gap-1">
82
91
  <h3 className="text-2xl text-black md:text-3xl">Slots: </h3>
83
- <div className="rounded-full bg-black/10 px-2 py-1" title="${C} slots detected">
84
- <span> ${C} </span>
92
+ <div className="rounded-full bg-black/10 px-2 py-1" title="${O} slots detected">
93
+ <span> ${O} </span>
85
94
  </div>
86
95
  </div>
87
96
  <ul className="list-inside list-disc space-y-1 pl-2">
88
- ${p.map(a=>`<li>
89
- <strong>${a}: </strong>
97
+ ${c.map(i=>`<li>
98
+ <strong>${i}: </strong>
90
99
  <div className="min-h-20">
91
- <UniformSlot data={component} context={context} slot={slots['${a}']} />
100
+ <UniformSlot slot={slots['${i}']} />
92
101
  </div>
93
102
  </li>`).join(`
94
103
  `)}
@@ -102,12 +111,12 @@ import{program as $}from"commander";import w from"node:fs";import te from"node:p
102
111
  );
103
112
 
104
113
 
105
- export default ${o};
106
- `;await v.promises.writeFile(e,await h(`${q}
107
- ${Z}
108
- ${Q}`)),await E(`npx next lint --file ${t} --fix`).catch(()=>y.fail("Oops, we couldn\u2019t format your mapping file using your lint configuration. Please check it before running.")),y?.succeed(`${t} file was successfully generated`)}catch(t){throw y.stop(),t}}};import T from"fs";import*as M from"ora";import B from"path";import{input as Se}from"@inquirer/prompts";var m=M.default(),N={path:async({pathToCanvasFolder:e})=>{let r=B.resolve(e,"index.ts");return T.existsSync(e)||await Se({message:"We didn't find custom-canvas resolver file. Could you please provide path to the custom-canvas resolver file:",required:!0,validate:t=>T.existsSync(t)?!0:"Path is not valid"}),r},write:async({destinationPath:e,definition:r})=>{try{let t=u(r.id);m?.start(`Generating ${e} file`);let o=await T.promises.readFile(e,"utf-8"),s=`import ${t} from './${t}';`,n=o.replace(D,l=>o.includes(s)?(m.info(`Import already exists. This step will be skipped for the ${t} component.`),l):(m.info(`Import of ${t} component added successfully.`),`${l}
109
- ${s}`)).replace(R,l=>{let p=new RegExp(b(r.id));if(p.test(l))return m.info(`This registration key is already in use, so we have overridden it with the new ${t} component.`),l.replace(p,`${r.id}: { component: ${t} },`);{m.info(`Added registration for the new ${t} component in the mapper.`);let c=`${r.id}: { component: ${t} },`;return l.replace(k,`${c}}`)}}),i=B.relative(process.cwd(),e);await T.promises.writeFile(e,await h(`${n}`)),await E(`npx next lint --file ${i} --fix`).catch(()=>m.fail("Oops, we couldn\u2019t format your mapping file using your lint configuration. Please check it before running.")),m?.succeed(`Import of ${t} component was successfully added to the ${i} file. Before running, make sure this file is connected to the final resolver.`)}catch(t){throw m.stop(),t}}};var z=async()=>{try{let e=J.default();console.info("Uniform RSC Scaffolder");let r=await V();e?.start("Loading Component Definitions");let{componentDefinitions:t}=await r.getComponentDefinitions();e?.succeed("Component Definitions Loaded");let o=await Ie({message:"Select the necessary component to generate files:",choices:t.sort((p,c)=>new Date(c.created||"").getTime()-new Date(p.created||"").getTime()).map(({name:p},c)=>({value:c,name:p})),loop:!1}),s=t[o];if(!s){console.info("No component selected");return}let n={pathToCanvasFolder:A,definition:s},i=await P.path(n);await P.write({definition:s,destinationPath:i}).catch(()=>{throw e.fail("Oops, something went wrong. We couldn\u2019t generate the component for you."),e.stop(),new Error("Something went wrong")});let l=await N.path(n);await N.write({definition:s,destinationPath:l}).catch(()=>{throw e.fail("Oops, something went wrong. We couldn\u2019t connect the component to the mapper. Please check if the required file is available or manually connect a new component."),e.stop(),new Error("Something went wrong")})}catch(e){e instanceof Error&&(e.message.includes("force closed")?console.info(`
114
+ export default withFlattenParameters(${r});
115
+ `;await S.promises.writeFile(e,await v(`${ce}
116
+ ${pe}
117
+ ${me}`)),await y(`npx eslint ${o} --fix`).catch(()=>_.fail("Oops, we couldn\u2019t format your mapping file using your lint configuration. Please check it before running.")),_?.succeed(`${o} file was successfully generated`)}catch(o){throw _.stop(),o}}};import $ from"fs";import*as ae from"ora";import se from"path";import{input as Ke}from"@inquirer/prompts";var u=ae.default(),L={path:async({pathToCanvasFolder:e})=>{let t=se.resolve(e,"index.ts");return $.existsSync(e)||await Ke({message:"We didn't find custom-canvas resolver file. Could you please provide path to the custom-canvas resolver file:",required:!0,validate:o=>$.existsSync(o)?!0:"Path is not valid"}),t},write:async({destinationPath:e,definition:t})=>{try{let o=x(t.id);u?.start(`Generating ${e} file`);let r=await $.promises.readFile(e,"utf-8"),s=`import ${o} from './${o}';`,a=r.replace(B,n=>r.includes(s)?(u.info(`Import already exists. This step will be skipped for the ${o} component.`),n):(u.info(`Import of ${o} component added successfully.`),`${n}
118
+ ${s}`)).replace(M,n=>{let c=new RegExp(J(t.id));if(c.test(n))return u.info(`This registration key is already in use, so we have overridden it with the new ${o} component.`),n.replace(c,`${t.id}: ${o},`);{u.info(`Added registration for the new ${o} component in the mapper.`);let m=`${t.id}: ${o},`;return n.replace(z,`${m}}`)}}),l=se.relative(process.cwd(),e);await $.promises.writeFile(e,await v(`${a}`)),await y(`npx eslint ${l} --fix`).catch(()=>u.fail("Oops, we couldn\u2019t format your mapping file using your lint configuration. Please check it before running.")),u?.succeed(`Import of ${o} component was successfully added to the ${l} file. Before running, make sure this file is connected to the final resolver.`)}catch(o){throw u.stop(),o}}};var le=async()=>{try{let e=ie.default();console.info("Uniform RSC Scaffolder");let t=await te();e?.start("Loading Component Definitions");let{componentDefinitions:o}=await t.getComponentDefinitions();e?.succeed("Component Definitions Loaded");let r=await Me({message:"Select the necessary component to generate files:",choices:o.sort((c,m)=>new Date(m.created||"").getTime()-new Date(c.created||"").getTime()).map(({name:c},m)=>({value:m,name:c})),loop:!1}),s=o[r];if(!s){console.info("No component selected");return}let a={pathToCanvasFolder:K,definition:s},l=await w.path(a);await w.write({definition:s,destinationPath:l}).catch(()=>{throw e.fail("Oops, something went wrong. We couldn\u2019t generate the component for you."),e.stop(),new Error("Something went wrong")});let n=await L.path(a);await L.write({definition:s,destinationPath:n}).catch(()=>{throw e.fail("Oops, something went wrong. We couldn\u2019t connect the component to the mapper. Please check if the required file is available or manually connect a new component."),e.stop(),new Error("Something went wrong")})}catch(e){e instanceof Error&&(e.message.includes("force closed")?console.info(`
110
119
  \u{1F44B} See you next time! \u{1F9E1}
111
120
  `):console.error(`
112
121
  \u{1F641} Something went wrong. Please try again.
113
- `))}};$.command("scaffold").description("Generate a new component based on canvas data").action(z);$.command("pull").description("Pull additonal data").option("-l, --locales","locales configuration").action(I);$.parse(process.argv);
122
+ `))}};A.command("scaffold").description("Generate a new component based on canvas data").action(le);A.command("pull").description("Pull additonal data").option("-l, --locales","locales configuration").option("-u, --uniform","uniform canvas data").option("-d, --dev","development mode").action(X);A.command("init").description("Initialize the uniform project").option("-d, --dev","development mode").action(D);A.parse(process.argv);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@uniformdev/csk-cli",
3
- "version": "6.0.123-alpha.1",
3
+ "version": "6.1.63-alpha.1",
4
4
  "description": "Command-line interface (CLI) tool designed to streamline the development workflow within Uniform projects. It provides commands for pulling additional data and generating components based on Canvas data",
5
5
  "license": "SEE LICENSE IN LICENSE.txt",
6
6
  "engines": {
@@ -38,26 +38,26 @@
38
38
  "@inquirer/prompts": "^7.1.0",
39
39
  "commander": "^9.0.0",
40
40
  "dotenv": "16.4.7",
41
- "ora": "^8.1.1"
41
+ "ora": "^8.2.0"
42
42
  },
43
43
  "devDependencies": {
44
44
  "@repo/eslint-config": "*",
45
45
  "@repo/typescript-config": "*",
46
46
  "@types/jest": "^29.5.14",
47
- "@uniformdev/canvas": "^20.25.0",
48
- "next": "^15.4.2",
49
- "prettier": "3.5.2",
50
- "react": "^19.1.0",
51
- "react-dom": "^19.1.0",
47
+ "@uniformdev/canvas": "^20.48.0",
48
+ "next": "^16.1.1",
49
+ "prettier": "3.6.2",
50
+ "react": "^19.2.3",
51
+ "react-dom": "^19.2.3",
52
52
  "tsup": "^8.3.0",
53
53
  "typescript": "^5.7.3"
54
54
  },
55
55
  "peerDependencies": {
56
- "@uniformdev/canvas": ">=20",
57
- "next": ">=15",
56
+ "@uniformdev/canvas": "^20.48.0",
57
+ "next": ">=16",
58
58
  "prettier": ">=3",
59
- "react": ">=18",
60
- "react-dom": ">=18"
59
+ "react": ">=19",
60
+ "react-dom": ">=19"
61
61
  },
62
62
  "bin": {
63
63
  "csk-cli": "cli.js"