@artech-global/cli 1.0.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.
package/README.md ADDED
@@ -0,0 +1,84 @@
1
+ # Artech CLI
2
+
3
+ CLI tool for the Artech/Breezing platform to manage sites, widgets, and forms.
4
+
5
+ ## Installation
6
+
7
+ ```bash
8
+ npm install -g @artech-global/artech-cli
9
+ ```
10
+
11
+ ## Usage
12
+
13
+ ```bash
14
+ artech [command] [options]
15
+ ```
16
+
17
+ ### Commands
18
+
19
+ #### `init`
20
+ Initialize a new Artech project in the current directory.
21
+ ```bash
22
+ artech init
23
+ artech init --pull # Init and pull data
24
+ ```
25
+
26
+ #### `site`
27
+ Manage site deployment and data.
28
+
29
+ **Deploy**
30
+ Push local config to remote.
31
+ ```bash
32
+ artech site deploy # Update layout only (default)
33
+ artech site deploy --data # Update layout + content
34
+ artech site deploy --force # Force update
35
+ artech site deploy --dry-run # Preview changes
36
+ ```
37
+
38
+ **Pull**
39
+ Pull remote data to local config.
40
+ ```bash
41
+ artech site pull # Pull all data
42
+ artech site pull --layout-only # Pull layout only
43
+ ```
44
+
45
+ #### `form`
46
+ Manage forms.
47
+
48
+ **Deploy**
49
+ Deploy forms from `site-spec.yml`.
50
+ ```bash
51
+ artech form deploy
52
+ artech form deploy --dry-run
53
+ artech form deploy --prune # Remove unused remote forms
54
+ ```
55
+
56
+ **Pull**
57
+ Pull forms from remote to `site-spec.yml` and save email bodies to files.
58
+ ```bash
59
+ artech form pull
60
+ ```
61
+
62
+ #### `widget`
63
+ Manage widget types.
64
+
65
+ **Deploy Type**
66
+ Deploy widget types defined in project.
67
+ ```bash
68
+ artech widget type deploy
69
+ artech widget type deploy --dry-run
70
+ ```
71
+
72
+ ## Environment Variables
73
+ Create a `.env` file or export variables:
74
+
75
+ ```env
76
+ ARTECH_API_URL=
77
+ ARTECH_API_TOKEN=
78
+ ```
79
+
80
+ ## Config Files
81
+ - `artech.config.yml`: Project configuration
82
+ - `config/site-spec.yml`: Site layout and forms structure
83
+ - `config/site-data.yml`: Site content data
84
+
@@ -0,0 +1 @@
1
+ #!/usr/bin/env node
package/dist/index.js ADDED
@@ -0,0 +1,34 @@
1
+ #!/usr/bin/env node
2
+ import{Command as rt}from"commander";import x from"chalk";import it from"dotenv";import j from"fs/promises";import L from"path";import We from"js-yaml";import c from"chalk";import Te from"axios";import Ee from"chalk";async function P(e,t,r,o){let n=e.target?.api,s=e.target?.token;if(!n||!s)throw new Error(`API configuration missing in context (target: ${e.target?.name})`);try{return(await Te({method:t,url:`${n}${r}`,headers:{Authorization:`Bearer ${s}`,"Content-Type":"application/json"},...o&&{data:o}})).data}catch(a){throw a.response?.status===422&&(console.log(Ee.red("\u274C 422 Validation Error Response Data:")),console.log(JSON.stringify(a.response.data,null,2))),new Error(`API request failed: ${a.response?.data?.message||a.message}`)}}import te from"fs/promises";import oe from"js-yaml";async function R(e){try{let t=await te.readFile(e,"utf8");return oe.load(t)}catch(t){throw new Error(`Failed to load ${e}: ${t.message}`)}}async function W(e,t,r={}){try{let o={};t.site&&(o.site=t.site),t.pages&&(o.pages=t.pages),t.widgets&&(o.widgets=t.widgets),t.widgetTypes&&(o.widgetTypes=t.widgetTypes),t.forms&&(o.forms=t.forms),t.environments&&(o.environments=t.environments);let n=oe.dump(o,{indent:4,lineWidth:200,noRefs:!0,sortKeys:!1,flowLevel:r.flowLevel||4});n=n.replace(/\n(pages):/g,`
3
+
4
+ $1:`).replace(/\n(widgets):/g,`
5
+
6
+ $1:`).replace(/\n(widgetTypes):/g,`
7
+
8
+ $1:`).replace(/\n(forms):/g,`
9
+
10
+ $1:`).replace(/\n(environments):/g,`
11
+
12
+ $1:`).replace(/^\n/,""),await te.writeFile(e,n)}catch(o){throw new Error(`Failed to save ${e}: ${o.message}`)}}import Ce from"fs/promises";import M from"path";import Re from"js-yaml";import ke from"dotenv";import xe from"chalk";async function k(e={}){let t=e.cwd?M.resolve(e.cwd):process.cwd(),r=e.config?M.resolve(t,e.config):M.join(t,"artech.config.yml"),o=M.join(t,".env");try{ke.config({path:o})}catch{}let n={siteSpecFile:"config/site-spec.yml",siteDataFile:"config/site-data.yml",targets:{}};try{let g=await Ce.readFile(r,"utf8");n=Re.load(g)}catch(g){(e.config||g.code!=="ENOENT")&&console.warn(xe.yellow(`\u26A0\uFE0F Could not load config file: ${r}`))}let s=e.target||"default",a=n.targets?.[s],i=M.resolve(t,n.siteSpecFile),l=M.resolve(t,n.siteDataFile),d="",m="",w="";if(a){if(a.api){let g=a.api;if(g.startsWith("env:")){let D=g.substring(4);g=process.env[D]||""}d=g}if(a.token){let g=a.token;if(g.startsWith("env:")){let D=g.substring(4);g=process.env[D]||""}m=g}a.site?.slug&&(w=a.site.slug)}return{cwd:t,target:{name:s,api:d,token:m,site:a?.site},config:n,paths:{siteSpec:i,siteData:l}}}import J from"fs/promises";import H from"path";import G from"chalk";async function V(e,t=process.cwd()){if(!e||typeof e!="string")return e;if(e.startsWith("file:")||e.startsWith("~~/")){let r=e.replace(/^(file:|~~)(\/|\\)?/,""),o=H.resolve(t,r);try{return await J.readFile(o,"utf8")}catch{return console.warn(G.yellow(`\u26A0\uFE0F Could not load file: ${o}`)),e}}return e}async function z(e,t,r=process.cwd()){if(!t||!t.startsWith("file:")&&!t.startsWith("~~/"))return;let o=t.replace(/^(file:|~~)(\/|\\)?/,""),n=H.resolve(r,o);try{console.log(G.gray(` Saving file to: ${n}`)),await J.mkdir(H.dirname(n),{recursive:!0}),await J.writeFile(n,e,"utf8"),console.log(G.green(`\u2705 Content saved to: ${t}`))}catch{console.warn(G.yellow(`\u26A0\uFE0F Could not save file: ${n}`))}}function q(e){if(!e||typeof e!="object")return e;if(Array.isArray(e))return e.map(r=>q(r)).filter(r=>r!=null&&r!=="");let t={};for(let r in e){let o=e[r];if(o!=null&&o!=="")if(typeof o=="object"){let n=q(o);Object.keys(n).length>0&&(t[r]=n)}else t[r]=o}return t}var Ae=["formID"];function ne(){return process.env.SITE_CWD?L.resolve(process.env.SITE_CWD):process.cwd()}async function _e(e){try{let t=await j.readFile(e,"utf8"),r=We.load(t);if(r.site?.styleBody&&(r.site.styleBody=await V(r.site.styleBody,ne())),r.pages){r.widgets||(r.widgets=[]);for(let o of r.pages)if(o.widgets&&Array.isArray(o.widgets)){let n=o.widgets.map(s=>s.scopedID).filter(Boolean);o.widgets.forEach(s=>{r.widgets.find(i=>i.scopedID===s.scopedID)||r.widgets.push(s)}),o.widgetScopedIDs=n,delete o.widgets}}return r}catch(t){throw new Error(`Failed to load ${e}: ${t.message}`)}}var A={site:{config:["title","description","keywords","favicon","socialImage","siteTheme","updateTime"],data:["title","description","keywords","favicon","socialImage","siteTheme","image","published","createTime","updateTime"]},page:{config:["scopedID","name","slug","type","widgetScopedIDs","headerScopedID","footerScopedID"],data:["scopedID","name","slug","type","title","description","keywords","image","bodyClass","isCustomStyle","styleBody","widgetScopedIDs","headerScopedID","footerScopedID","status","position","removable","editable"]},widget:{config:["scopedID","type","^background"],data:["scopedID","type","name","domID","domClass","isCustomStyle","styleBody","isCustomTemplate","templateBody","margin","padding","background","props","removable","editable"]}};function _(e,t){let r={};for(let o of t){let n=o.startsWith("^"),s=n?o.substring(1):o;if(e.hasOwnProperty(s)){if(n&&(!e[s]||e[s].toString().trim()===""))continue;r[s]=e[s]}}return r}function N(e){return e?typeof e=="string"?JSON.parse(e):e:{}}function Me(e,t,r){let o=N(e),n=N(t),s=N(r),a={...o,...n,...s};return Ae.forEach(i=>{o[i]!==void 0&&(a[i]=o[i])}),a}async function Ne(e,t){try{let o=(await P(e,"GET",`/widget-type?key=${t.type}&pageSize=1000`,void 0)).items?.[0];if(o&&o.defaultProps){console.log(c.blue(` Creating new widget: ${t.scopedID} (${t.type})`));let n=N(o.defaultProps),s=N(t.props);return{...n,...s}}else console.log(c.red(`\u26A0\uFE0F Widget type ${t.type} not found, creating new widget`))}catch(r){console.warn(c.yellow(` \u26A0\uFE0F Could not load default props for widget ${t.type}: ${r.message}`))}return N(t.props)}async function se(e,t,r){let o={};e.pages?.forEach(i=>{i.widgetScopedIDs?.forEach(l=>{o[l]=(o[l]||0)+1}),i.headerScopedID&&(o[i.headerScopedID]=(o[i.headerScopedID]||0)+1),i.footerScopedID&&(o[i.footerScopedID]=(o[i.footerScopedID]||0)+1)});let n=r.filter(i=>i.scopedID&&o[i.scopedID]&&o[i.scopedID]>1).map(i=>_(i,A.widget.config)),s=e.pages?.map(i=>{let l=_(i,A.page.config),d=i.widgetScopedIDs?.map(m=>{let w=r.find(g=>g.scopedID===m);return w?_(w,A.widget.config):null}).filter(Boolean)||[];return delete l.widgetScopedIDs,{...l,widgets:d}})||[],a=e.styleBody;if(a){let i=t.site?.styleBody,l;i&&(i.startsWith("~~/")||i.startsWith("file:"))?l=i:console.warn(c.yellow("\u26A0\uFE0F Site style file not specified in config")),l&&(await z(a,l,ne()),a=l)}return{site:{..._(e,A.site.config),styleBody:a},pages:s,widgets:n,forms:t.forms||[]}}function Oe(e,t,r){return{site:[_(e,A.site.data)],pages:e.pages?.map(o=>({..._(o,A.page.data)}))||[],widgets:t.map(o=>{let n=_(o,A.widget.data);if(n.props&&typeof n.props=="string")try{n.props=JSON.parse(n.props)}catch(s){console.warn(c.yellow(`\u26A0\uFE0F Could not parse props for widget ${o.scopedID}: ${s.message}`))}return n})}}async function re(e){let t=e.cwd?L.resolve(e.cwd):process.cwd();console.log(c.blue("\u{1F680} Initializing Artech project..."));let r={"artech.config.yml":{siteSpecFile:"config/site-spec.yml",siteDataFile:"config/site-data.yml",targets:{default:{api:"env:ARTECH_API_URL",token:"env:ARTECH_API_TOKEN",site:{slug:"my-site"}}}},"config/site-spec.yml":{site:{title:"My Site"},pages:[],widgets:[],forms:[]},"config/site-data.yml":{site:{},pages:[],widgets:[],forms:[]}};for(let[s,a]of Object.entries(r)){let i=L.join(t,s);try{let l=L.dirname(i);await j.mkdir(l,{recursive:!0}),await j.access(i),console.log(c.yellow(`\u26A0\uFE0F ${s} already exists, skipping.`))}catch{await W(i,a),console.log(c.green(`\u2705 Created ${s}`))}}let o=L.join(t,".env.example"),n=`ARTECH_API_URL=https://api.artech.global
13
+ ARTECH_API_TOKEN=
14
+ `;try{await j.access(o),console.log(c.yellow("\u26A0\uFE0F .env.example already exists, skipping."))}catch{await j.writeFile(o,n),console.log(c.green("\u2705 Created .env.example"))}console.log(c.green(`
15
+ \u2728 Project initialized successfully!`)),e.pull&&(console.log(c.blue("\u{1F4E5} Pulling site data... (Not yet implemented in init --pull)")),console.warn(c.yellow("\u26A0\uFE0F --pull requested but you need to setup .env and artech.config.yml with valid tokens/slugs first.")))}async function ie(e,t){let r=e.paths.siteSpec,o=e.paths.siteData;console.log(c.blue("\u2B07\uFE0F Pulling latest site data..."));let n=await R(r),s=e.target.site?.slug;if(!s)throw new Error(`Site slug not found for target: ${e.target.name}`);console.log(c.gray(`Target: ${e.target.name}`)),console.log(c.gray(`Site slug: ${s}`)),console.log(c.blue("\u{1F50D} Checking site existence..."));let a=await P(e,"GET",`/site?slug=${s}`,void 0);if(!a.items||a.items.length===0)throw new Error(`Site with slug "${s}" not found`);let i=a.items[0].id,l=a.items[0];if(console.log(c.green(`\u2705 Found site: ${l.name} (ID: ${i})`)),console.log(c.gray(` Site: ${l.name} (${l.slug})`)),console.log(c.gray(` Updated: ${new Date(l.updateTime*1e3).toISOString()}`)),t.layoutOnly){console.log(c.gray(" Skipping data pull (layout only)")),console.log(c.blue("\u{1F4C4} Fetching site layout data..."));let d=await P(e,"GET",`/site/${i}`,void 0),w=(await P(e,"GET",`/widget?siteID=${i}`,void 0)).items||[];console.log(c.blue("\u{1F4DD} Updating site-spec.yml..."));let g=await se(d,n,w);await W(r,g,{flowLevel:4}),console.log(c.green("\u2705 site-spec.yml updated"))}else{console.log(c.blue("\u{1F4C4} Fetching complete site data..."));let d=await P(e,"GET",`/site/${i}`,void 0),w=(await P(e,"GET",`/widget?siteID=${i}`,void 0)).items||[];d.pages&&d.pages.sort((y,E)=>{let v=y.position||0,f=E.position||0;return v-f}),console.log(c.blue("\u{1F4DD} Updating site-spec.yml..."));let g=await se(d,n,w);await W(r,g,{flowLevel:4}),console.log(c.green("\u2705 site-spec.yml updated")),console.log(c.blue("\u{1F4DD} Updating site-data.yml..."));let D=await R(o),p=Oe(d,w,D);await W(o,p,{flowLevel:10}),console.log(c.green("\u2705 site-data.yml updated")),console.log(c.gray(` Pages: ${d.pages?.length||0}, Widgets: ${w.length}`))}console.log(c.green("\u{1F389} Pull completed successfully!"))}async function ae(e,t){let r=e.paths.siteSpec,o=e.paths.siteData,n=t.data?"complete":"layout";console.log(c.blue(`\u{1F680} Deploying site (${n} mode)...`)),t.dryRun&&console.log(c.yellow("\u26A0\uFE0F DRY RUN MODE: No changes will be applied"));let s=await _e(r),a=t.data?await R(o):{site:[],pages:[],widgets:[]},i=e.target.site?.slug;if(!i)throw new Error(`Site slug not found for target: ${e.target.name}`);console.log(c.gray(`Target: ${e.target.name}`)),console.log(c.gray(`Site slug: ${i}`)),console.log(c.blue("\u{1F50D} Checking site version..."));let l=await P(e,"GET",`/site?slug=${i}`,void 0);if(!l.items||l.items.length===0)throw new Error(`Site with slug "${i}" not found`);let d=l.items[0],m=d.id,w=s.site.updateTime||0,g=d.updateTime||0;if(console.log(c.gray(` Local version: ${new Date(w*1e3).toISOString()}`)),console.log(c.gray(` Remote version: ${new Date(g*1e3).toISOString()}`)),g>w&&!t.force)throw console.log(c.yellow("\u26A0\uFE0F Remote version is newer than local version!")),console.log(c.red("\u274C Cannot deploy: Remote has newer changes")),console.log(c.blue('\u{1F4A1} Please run "artech site pull" first to get latest changes')),new Error("Remote has newer changes");g>w&&t.force?console.log(c.yellow("\u26A0\uFE0F Force mode: Deploying despite remote being newer")):console.log(c.green("\u2705 Local version is up to date")),console.log(c.blue("\u{1F4C4} Fetching current site data...")),d=await P(e,"GET",`/site/${m}`,void 0);let p=(await P(e,"GET",`/widget?siteID=${m}`,void 0)).items||[];console.log(c.blue("\u{1F504} Merging data..."));let y={...d,...a.site?.[0],...s.site},E=s.pages?.map((f,$)=>{let h=a.pages?.find(S=>S.scopedID===f.scopedID);return{...d.pages?.find(S=>S.scopedID===f.scopedID),...h,...f,position:$+1}})||[],v=await Promise.all((s.widgets||[]).map(async f=>{let $=a.widgets?.find(T=>T.scopedID===f.scopedID),h=p.find(T=>T.scopedID===f.scopedID),u={...f};return h?(u={...h,...$,...f},u.props=Me(h.props,$?.props,f.props)):u.props=await Ne(e,f),u}));if(console.log(c.blue("\u{1F4DD} Updating site...")),t.dryRun||await P(e,"PUT","/site",y),d.pages&&d.pages.length>0){console.log(c.blue("\u{1F5D1}\uFE0F Checking for unused remote pages..."));let f=new Set;E.forEach(h=>{h.scopedID&&f.add(h.scopedID)});let $=d.pages.filter(h=>!f.has(h.scopedID)&&!h.deleteTime);if($.length>0)if(console.log(c.yellow(`\u26A0\uFE0F Found ${$.length} unused remote page(s).`)),t.prune){console.log(c.yellow(" Marking for deletion..."));let h=Math.floor(Date.now()/1e3);for(let u of $)if(console.log(c.yellow(` - ${u.name} (${u.scopedID})`)),!t.dryRun)try{await P(e,"PUT","/page",{...u,deleteTime:h}),console.log(c.green(` \u2705 Marked page ${u.scopedID} for deletion`))}catch(T){console.log(c.red(` \u274C Failed to mark page ${u.scopedID} for deletion: ${T.message}`))}}else console.log(c.gray(" Use --prune to delete these pages."));else console.log(c.gray(" No unused remote pages found"))}console.log(c.blue("\u{1F4C4} Updating pages..."));for(let f of E)if(f.name&&f.type&&f.scopedID){let $=d.pages?.find(h=>h.scopedID===f.scopedID);if($){let h={id:$.id,siteID:m,...f};t.dryRun||await P(e,"PUT","/page",h),console.log(c.gray(` Updated page: ${f.slug}`))}else{let h={siteID:m,...f};t.dryRun||await P(e,"POST","/page",h),console.log(c.blue(` Creating new page: ${f.slug}`))}}if(p&&p.length>0){console.log(c.blue("\u{1F5D1}\uFE0F Checking for unused remote widgets..."));let f=new Set;E.forEach(h=>{h.widgetScopedIDs&&Array.isArray(h.widgetScopedIDs)&&h.widgetScopedIDs.forEach(u=>{u&&f.add(u)}),h.headerScopedID&&f.add(h.headerScopedID),h.footerScopedID&&f.add(h.footerScopedID)});let $=p.filter(h=>!f.has(h.scopedID)&&!h.deleteTime);if($.length>0)if(console.log(c.yellow(`\u26A0\uFE0F Found ${$.length} unused remote widget(s).`)),t.prune){console.log(c.yellow(" Marking for deletion..."));let h=Math.floor(Date.now()/1e3);if($.forEach(u=>{console.log(c.yellow(` - ${u.name} (${u.scopedID})`))}),!t.dryRun){let u=$.map(T=>({...T,deleteTime:h}));try{await P(e,"PUT","/widget-multiple",{siteID:m,widgets:u,upsert:!1}),console.log(c.green(` \u2705 Marked ${$.length} unused widgets for deletion`))}catch(T){console.log(c.red(` \u274C Failed to mark unused widgets for deletion: ${T.message}`))}}}else console.log(c.gray(" Use --prune to delete these widgets."));else console.log(c.gray(" No unused remote widgets found"))}if(v&&v.length>0){console.log(c.blue("\u{1F9E9} Updating widgets..."));let f=new Set;E.forEach(S=>{S.widgetScopedIDs&&Array.isArray(S.widgetScopedIDs)&&S.widgetScopedIDs.forEach(C=>{C&&f.add(C)}),S.headerScopedID&&f.add(S.headerScopedID),S.footerScopedID&&f.add(S.footerScopedID)});let $=Math.floor(Date.now()/1e3),h=v.map(S=>{let C=f.has(S.scopedID);return{scopedID:S.scopedID,type:S.type,name:S.name,domID:S.domID,domClass:S.domClass,background:S.background,styleBody:S.styleBody,margin:S.margin,padding:S.padding,props:typeof S.props=="string"?S.props:JSON.stringify(S.props),deleteTime:C?void 0:$}}),u=h.filter(S=>S.deleteTime),T=h.length-u.length;if(console.log(c.gray(` Updating ${T} active widgets`)),u.length>0&&(t.prune?console.log(c.yellow(` Marking ${u.length} unused widgets (from config) for deletion`)):console.log(c.yellow(` ${u.length} widgets in config are not used in pages.`))),!t.dryRun){let S=h.map(C=>{if(C.deleteTime&&!t.prune){let{deleteTime:at,...ve}=C;return ve}return C});await P(e,"PUT","/widget-multiple",{siteID:m,widgets:S,upsert:!0}),console.log(c.gray(" \u2705 Widget update completed"))}}console.log(c.green(`\u2705 Site deployed successfully (${n} mode)!`))}import{readFileSync as Y,existsSync as O,readdirSync as le}from"fs";import*as I from"path";import{parse as ce,compileScript as Ue,compileTemplate as je,compileStyleAsync as Le}from"@vue/compiler-sfc";import Be from"hash-sum";import Ge from"clean-css";import b from"chalk";import{createRequire as de}from"module";import pe from"@babel/plugin-transform-modules-commonjs";import{transformFromAstAsync as ge,types as K,traverse as ze}from"@babel/core";import{parse as me}from"@babel/parser";import qe from"@vue/babel-plugin-jsx";import fe from"@babel/plugin-transform-typescript";var Ve=de(import.meta.url),U="__bz__",Ye="__bz_import__",X=!1;async function ue(e,t){let r=t.cwd?I.resolve(t.cwd):e.cwd||process.cwd();console.log(b.blue(`Creating list of widget types in: ${r}...`));let o=Z(r);if(o.length===0){console.log(b.yellow("No widget types found."));return}console.log(b.green(`Found ${o.length} widget types:`));for(let n of o){let s=I.relative(r,n.dir);console.log(`- ${b.cyan(n.name)} (${s})`)}}async function Je(e){let t=Y(e,"utf-8"),r=me(t,{sourceType:"module",sourceFilename:e,plugins:["typescript"]}),{code:o}=await ge(r,t,{filename:e,presets:[],plugins:[fe,pe],babelrc:!1,configFile:!1})||{code:""},n={exports:{}},s=de(e);return new Function("module","exports","require",o)(n,n.exports,s),n.exports.default||n.exports}async function Q(e,t){let r=t.name;t.dryRun&&console.log(b.yellow("\u26A0\uFE0F DRY RUN MODE: No changes will be applied"));let o=e.cwd?I.resolve(e.cwd,"widgets"):I.resolve(process.cwd(),"widgets"),n=we(r,o);if(!n)throw new Error(`Widget "${r}" not found in "${o}" or its subdirectories. Make sure both "${r}.ts" and "${r}.vue" files exist.`);let{tsFile:s,vueFile:a,widgetDir:i}=n;console.log(b.green("\u2705 Found widget files:")),console.log(b.gray(` TS: ${s}`)),console.log(b.gray(` Vue: ${a}`)),console.log(b.gray(` Directory: ${i}`)),console.log(b.blue("\u{1F504} Processing component and dependencies..."));let l=await he(a,new Set,!0),d=Y(a,"utf-8"),{descriptor:m}=ce(d,{filename:I.basename(a),sourceMap:!0}),w=m.script?.lang||m.scriptSetup?.lang,g=!!(w&&/(\.|\b)tsx?$/.test(w)),D=!!(w&&/(\.|\b)tsx?$/.test(w)),p=await ot(l,r,g,D);console.log(b.green(`\u2705 Build module successfully (${p.scriptSource.length} + ${p.styleSource.length} bytes).`));let y=await Je(s);y.sfcSource=Y(a,"utf-8"),y.scriptSource=p.scriptSource,y.styleSource=p.styleSource;let E=await P(e,"GET",`/widget-type?key=${y.key}`,void 0);console.log(b.green(`\u2705 Fetch ${y.key} widget successfully.`));let v=E,f="",$={};if(!v||!v.items||!v.items[0])console.log(b.blue(`The widget type "${y.key}" does not exist. Creating new...`)),f="POST";else if(f="PUT",$=v.items[0],$.key!=y.key)throw new Error(`The key "${y.key}" != "${$.key}".`);t.dryRun?console.log(b.yellow(`\u2705 DRY RUN: Widget ${y.key} deployed successfully (simulated).`)):(await P(e,f,"/widget-type",{...$,...y}),console.log(b.green(`\u2705 Widget ${y.key} deployed successfully.`)))}async function ye(e,t){console.log(b.blue("\u{1F9E9} Deploying widget types...")),t.dryRun&&console.log(b.yellow("\u26A0\uFE0F DRY RUN MODE: No changes will be applied"));let r=e.cwd?I.resolve(e.cwd,"widgets"):I.resolve(process.cwd(),"widgets"),n=Z(r).map(s=>({key:s.name}));if(n.length===0){console.log(b.gray(" No widget types found in widgets directory"));return}if(t.key){let s=n.filter(a=>a.key===t.key);if(s.length===0)throw new Error(`Widget type with key "${t.key}" not found in widgets directory`);n=s,console.log(b.gray(` Deploying single widget type: ${t.key}`))}else console.log(b.gray(` Found ${n.length} widget types to deploy`));for(let s of n)try{console.log(""),console.log(b.blue(`================ ${s.key} =================`)),await Q(e,{name:s.key,dryRun:t.dryRun})}catch(a){if(console.log(a),console.error(b.red(` \u274C Failed to publish widget ${s.key}:`),a.message),t.key)throw a}}function Z(e){let t=[];if(!O(e))return t;let r=le(e,{withFileTypes:!0});for(let o of r){let n=I.join(e,o.name);if(o.isDirectory()){if(o.name==="node_modules"||o.name===".git"||o.name==="dist")continue;t.push(...Z(n))}else if(o.isFile()&&I.extname(o.name)===".ts"){let a=I.parse(o.name).name,i=I.join(e,`${a}.vue`);O(i)&&t.push({name:a,tsFile:n,vueFile:i,dir:e})}}return t}function we(e,t){if(!O(t))return null;let r=le(t,{withFileTypes:!0});for(let o of r){let n=I.join(t,o.name);if(o.isDirectory()){let s=we(e,n);if(s)return s}else if(o.isFile()&&I.parse(o.name).name===e){let a=I.extname(o.name),i=a===".ts"?n:I.join(I.dirname(n),`${e}.ts`),l=a===".vue"?n:I.join(I.dirname(n),`${e}.vue`);if(O(i)&&O(l))return{tsFile:i,vueFile:l,widgetDir:I.dirname(n)}}}return null}function He(e){let t=[],r=/import\s+(?:(\w+)(?:\s*,\s*\{([^}]+)\})?|{([^}]+)})\s+from\s+['"]([^'"]+)['"]/g,o;for(;(o=r.exec(e))!==null;){let n=o[1],s=o[2],a=o[3],i=o[4];n&&i&&t.push({name:n,path:i,isDefault:!0});let l=s||a;l&&i&&l.split(",").map(m=>m.trim()).forEach(m=>{t.push({name:m,path:i,isDefault:!1})})}return t}function Ke(e,t){if(e.startsWith("./")||e.startsWith("../")){let r=I.resolve(t,e),o=[".vue",".ts",".js"];for(let n of o){let s=r+n;if(O(s))return s}return r}return null}async function Xe(e,t,r,o){let n;try{let l=[];r&&l.push("typescript"),o&&l.push("jsx"),n=me(e,{sourceType:"module",sourceFilename:t.toString(),plugins:l}),ze(n,{CallExpression(d){K.isImport(d.node.callee)&&d.replaceWith(K.callExpression(K.identifier(Ye),d.node.arguments))}})}catch(l){throw console.error(b.red("\u274C Parse script error:"),l),new Error(`Failed to parse script: ${l}`)}let s={jsx:qe,typescript:fe},a=[pe,...s!==void 0?Object.values(s):[]],i=await ge(n,e,{sourceMaps:!1,plugins:a,presets:[Ve.resolve("babel-preset-minify")],babelrc:!1,configFile:!1,highlightCode:!1,compact:!X,comments:X,retainLines:X,minified:!1,sourceType:"module"});if(i===null||i.code==null){let l=`unable to transform script "${t.toString()}"`;throw new Error(l)}return i.code}async function Qe(e,t,r,o){if(e.script||e.scriptSetup){let n=[];r&&n.push("typescript"),o&&n.push("jsx");let s=[];o&&s.push("jsx"),r&&s.push("typescript");let a=Ue(e,{id:t,isProd:!1,inlineTemplate:!1,genDefaultAs:U,babelParserPlugins:s,templateOptions:{ssrCssVars:e.cssVars,compilerOptions:{expressionPlugins:n}}});return[a.content,a.bindings]}else{let n=e.vapor?"__vapor: true":"";return[`
16
+ const ${U} = { ${n} }`,void 0]}}async function Ze(e,t,r,o,n){let s=[];o&&s.push("typescript"),n&&s.push("jsx");let{code:a,errors:i}=je({id:t,isProd:!1,vapor:e.vapor,ast:e.template.ast,source:e.template.content,filename:e.filename,scoped:e.styles.some(d=>d.scoped),slotted:e.slotted,ssrCssVars:e.cssVars,compilerOptions:{bindingMetadata:r,expressionPlugins:s}});if(i.length)return i;let l="render";return a=`
17
+ ${a.replace(/\nexport (function|const) (render|ssrRender)/,`$1 ${l}`)}
18
+ ${U}.${l} = ${l}`,a}function et(e){let t=e.split(`
19
+ `),r=[],o=new Map;for(let i of t){let l=i.trim();if(l.startsWith("import ")&&(l.endsWith(";")||l.endsWith('"')||l.endsWith("'"))){let d=tt(l);if(d){let{path:m,defaultImport:w,namedImports:g}=d;if(!o.has(m))o.set(m,{defaultImport:w,namedImports:new Set(g),path:m});else{let D=o.get(m);D&&(w&&!D.defaultImport&&(D.defaultImport=w),g.forEach(p=>D.namedImports.add(p)))}}}else r.push(i)}let n=[];for(let[i,l]of o){let{defaultImport:d,namedImports:m}=l,w=Array.from(m);d&&w.length>0?n.push(`import ${d}, { ${w.join(", ")} } from '${i}';`):d?n.push(`import ${d} from '${i}';`):w.length>0&&n.push(`import { ${w.join(", ")} } from '${i}';`)}return{code:r.join(`
20
+ `).replace(/^export\s+default\s+__bz__;/gm,"").replace(/^export\s+\{[^}]+\};?/gm,"").replace(/^export\s+default[^;]+;/gm,"").replace(/^export\s+\w+\s+\w+[^;]*;/gm,""),imports:n}}function tt(e){let t=e.replace(/;$/,""),r=/^import\s+(\w+)\s+from\s+['"]([^'"]+)['"]$/,o=t.match(r);if(o&&o[1]&&o[2])return{path:o[2],defaultImport:o[1],namedImports:[]};let n=/^import\s+\{\s*([^}]+)\s*\}\s+from\s+['"]([^'"]+)['"]$/,s=t.match(n);if(s&&s[1]&&s[2]){let m=s[1].split(",").map(w=>w.trim());return{path:s[2],namedImports:m}}let a=/^import\s+(\w+)\s*,\s*\{\s*([^}]+)\s*\}\s+from\s+['"]([^'"]+)['"]$/,i=t.match(a);if(i&&i[1]&&i[2]&&i[3]){let m=i[2].split(",").map(w=>w.trim());return{path:i[3],defaultImport:i[1],namedImports:m}}let l=/^import\s+\*\s+as\s+(\w+)\s+from\s+['"]([^'"]+)['"]$/,d=t.match(l);return d&&d[1]&&d[2]?{path:d[2],defaultImport:d[1],namedImports:[]}:null}async function ot(e,t,r=!1,o=!1){let n=new Set,s="",a=e.styleSource,i=new Map,l=g=>{for(let[D,p]of g)i.has(p.componentName)||(i.set(p.componentName,{scriptSource:p.scriptSource,styleSource:p.styleSource,componentName:p.componentName}),p.dependencies&&p.dependencies.size>0&&l(p.dependencies))};l(e.dependencies);for(let[g,D]of i){let p=`${t}_${D.componentName}`;s+=`// Component: ${D.componentName}
21
+ `,s+=`const ${p} = (function() {
22
+ `,s+=D.scriptSource,s+=`
23
+ return __bz__;`,s+=`
24
+ })();
25
+ `,a+=D.styleSource}s+=`
26
+ // Main Component: ${t}
27
+ `,s+=e.scriptSource;for(let[g,D]of i){let p=`${t}_${D.componentName}`,y=new RegExp(`import\\s*\\{\\s*${g}\\s*\\}\\s*from\\s*['"][^'"]*\\.vue['"]\\s*;?`,"g");s=s.replace(y,`const { ${g} } = ${p}`);let E=new RegExp(`import\\s+${g}\\s+from\\s*['"][^'"]*\\.vue['"]\\s*;?`,"g");s=s.replace(E,`const ${g} = ${p}`)}let{code:d,imports:m}=et(s);return m.forEach(g=>n.add(g)),d=Array.from(n).join(`
28
+ `)+`
29
+ `+d,{scriptSource:await Xe(d,`${t}.js`,r,o),styleSource:a}}async function he(e,t=new Set,r=!1){let o=I.resolve(e);if(t.has(o))return{scriptSource:"",styleSource:"",dependencies:new Map};t.add(o);let n=Y(e,"utf-8"),s=I.basename(e),a=I.dirname(e),{descriptor:i}=ce(n,{filename:s,sourceMap:!0}),l=i.script?.lang||i.scriptSetup?.lang,d=!!(l&&/(\.|\b)tsx?$/.test(l)),m=!!(l&&/(\.|\b)tsx?$/.test(l));if(l&&l!=="js"&&!d&&!m)throw console.error(b.red(`\u274C Unsupported lang "${l}" in <script> blocks.`)),new Error(`Unsupported lang "${l}" in <script> blocks.`);let w=i.script?.content||i.scriptSetup?.content||"",g=He(w),D=new Map;for(let u of g){let T=Ke(u.path,a);if(T&&T.endsWith(".vue"))try{let S=await he(T,t),C=I.basename(T,".vue");D.set(u.name,{scriptSource:S.scriptSource,styleSource:S.styleSource,componentName:C,dependencies:S.dependencies}),console.log(b.gray(` \u2705 Dependency processed: ${C}`))}catch(S){console.warn(b.yellow(` \u26A0\uFE0F Failed to process dependency ${u.path}:`),S)}}let p="",y=Be(s)+Date.now().toString().slice(0,1),E=i.styles.some(u=>u.scoped),[v,f]=await Qe(i,y,d,m);if(p+=v,i.template){let u=await Ze(i,y,f,d,m);if(Array.isArray(u))throw new Error(`Template compilation failed: ${u}`);p+=`;${u}`}E&&(p+=`;
30
+ ${U}.__scopeId = ${JSON.stringify(`data-v-${y}`)}`),p+=`
31
+ ${U}.__file = ${JSON.stringify(s)}`,r&&(p+=`
32
+ export default ${U}`);let $="";for(let u of i.styles){if(u.module)throw console.error(b.red("\u274C <style module> is not supported.")),new Error("<style module> is not supported.");if(!u.scoped)throw console.error(b.red("\u274C Only support <style scoped>.")),new Error("Only support <style scoped>.");let T=await Le({id:y,source:u.content,filename:s,scoped:u.scoped,preprocessLang:u.lang=="scss"?"scss":void 0,modules:!1});if(T.errors.length)throw console.error(b.red("\u274C Build style error.")),console.error(T.errors),new Error(`Build style error: ${T.errors}`);$+=T.code+`
33
+ `}let h=(()=>{if($){let u=new Ge({}).minify($);return u.errors.length?(console.error(b.red("\u274C CleanCSS errors:"),u.errors),""):u.styles}return""})();return{scriptSource:p,styleSource:h,dependencies:D}}import F from"chalk";var st={config:["scopedID","name","type","emailSetting","ticketRegistrationSetting","ticketRSVPSetting","subscriptionSetting","checkoutSetting","contactSetting","authSetting","formFields"],data:["scopedID","name","type","isClosed","emailSetting","ticketRegistrationSetting","ticketRSVPSetting","subscriptionSetting","checkoutSetting","contactSetting","authSetting","formFields"]};async function $e(e,t){let r=e.paths.siteSpec,o=e.paths.siteData;console.log(F.blue("\u{1F4DD} Deploying forms from site config...")),t.dryRun&&console.log(F.yellow("\u26A0\uFE0F DRY RUN MODE: No changes will be applied"));let n=await R(r),s=await R(o),a=n.forms||[];if(a.length===0){console.log(F.gray(" No forms found in config"));return}let i=e.target.site?.slug;if(!i)throw new Error(`Site slug not found for target: ${e.target.name}`);console.log(F.blue("\u{1F50D} Verifying site context..."));let l=await P(e,"GET",`/site?slug=${i}`,void 0);if(!l.items||l.items.length===0)throw new Error(`Site with slug "${i}" not found`);let m=l.items[0].scopedID;console.log(F.gray(` Target: ${e.target.name}`)),console.log(F.gray(` Found ${a.length} forms to deploy`)),console.log(F.gray(` Site scoped ID: ${m}`)),console.log(F.blue("\u{1F50D} Fetching remote forms..."));let g=(await P(e,"GET",`/form?siteScopedID=${m}&pageSize=1000`,void 0)).items||[];console.log(F.gray(` Found ${g.length} existing forms`));let D=new Set;for(let p of a){D.add(p.scopedID);try{console.log(F.blue(` Deploying form: ${p.name}`));let y=g.find(v=>v.scopedID===p.scopedID),E=s.forms?.find(v=>v.scopedID===p.scopedID);if(y){let v=De(y,E||{},p),$={...await Se(v),siteScopedID:m};t.dryRun||await P(e,"PUT","/form",$),console.log(F.gray(` \u2705 Updated form: ${p.name}`))}else{let v=De({},E||{},p),f=await Se(v),$={...f,siteScopedID:m,emailSetting:{senderName:"Breezing",replyToEmail:"noreply@breezing.in",successEmailEnabled:!1,customSuccessEmail:!1,successEmailSubject:"",successEmailBody:"",customInviteEmail:!1,inviteEmailSubject:"",inviteEmailBody:"",...f.emailSetting}};t.dryRun||await P(e,"POST","/form",$),console.log(F.green(` \u2705 Created form: ${p.name}`))}}catch(y){console.error(F.red(` \u274C Failed to deploy form ${p.name}:`),y.message)}}if(g.length>0){let p=g.filter(y=>!D.has(y.scopedID));if(p.length>0)if(console.log(F.yellow(`\u26A0\uFE0F Found ${p.length} unused remote forms.`)),t.prune){console.log(F.yellow(" Marking for deletion/pruning..."));for(let y of p)if(console.log(F.yellow(` - ${y.name} (${y.scopedID})`)),!t.dryRun)try{await P(e,"DELETE",`/form/${y.id}`,void 0),console.log(F.green(` \u2705 Deleted form ${y.name}`))}catch(E){console.error(F.red(` \u274C Failed to delete form ${y.name}:`),E.message)}}else console.log(F.gray(" Use --prune to delete these forms."))}console.log(F.green("\u{1F389} All forms deployed successfully!"))}async function Ie(e,t){let r=e.paths.siteSpec;console.log(F.blue("\u2B07\uFE0F Pulling forms..."));let o=e.target.site?.slug;if(!o)throw new Error(`Site slug not found for target: ${e.target.name}`);console.log(F.blue("\u{1F50D} Resolving site context..."));let n=await P(e,"GET",`/site?slug=${o}`,void 0);if(!n.items||n.items.length===0)throw new Error(`Site with slug "${o}" not found`);let s=n.items[0],a=s.scopedID,i=s.id;console.log(F.gray(`Target: ${e.target.name}`)),console.log(F.gray(`Site slug: ${o}`)),console.log(F.gray(`Site scoped ID: ${a}`)),console.log(F.blue("\u{1F50D} Fetching remote forms..."));let d=(await P(e,"GET",`/form?siteScopedID=${a}&pageSize=1000`,void 0)).items||[];console.log(F.gray(` Found ${d.length} forms`)),console.log(F.blue("\u{1F4DD} Updating site-spec.yml..."));let m=await R(r),w=m.forms||[],g=[];for(let D of d){let p=w.find(v=>v.scopedID===D.scopedID),y={name:D.name,scopedID:D.scopedID,tags:D.tags,...p};st.config.forEach(v=>{D[v]!==void 0&&(y[v]=D[v])}),y=await nt(y,p);let E=q(y);g.push(E)}m.forms=g,await W(r,m,{flowLevel:6}),console.log(F.green("\u2705 site-spec.yml updated with forms")),console.log(F.green("\u{1F389} Pull forms completed successfully!"))}async function Se(e){let t={...e};if(t.emailSetting){let r=Object.keys(t.emailSetting).filter(o=>o.endsWith("EmailBody"));for(let o of r)t.emailSetting[o]&&(t.emailSetting[o]=await V(t.emailSetting[o]))}return t}async function nt(e,t){let r={...e};if(r.emailSetting&&t?.emailSetting){let o=Object.keys(t.emailSetting).filter(n=>n.endsWith("EmailBody"));for(let n of o){let s=t.emailSetting[n];s&&(s.startsWith("file:")||s.startsWith("~~/"))&&(await z(r.emailSetting[n],s),r.emailSetting[n]=s)}}return r}function De(e,t,r){let o={...e,...t,...r};return["id","workspaceID","createTime","updateTime"].forEach(s=>{e[s]!==void 0&&(o[s]=e[s])}),o}it.config();var B=new rt;B.name("artech").description("Artech CLI tool").version("1.0.0");var ee=B.command("site").description("Manage sites");ee.command("pull").description("Pull site from API").option("-t, --target <name>","Target environment","default").option("-c, --config <path>","Config file path").option("--layout-only","Pull layout only").action(async e=>{try{let t=await k({target:e.target,config:e.config});await ie(t,e)}catch(t){console.error(x.red("\u274C Pull site failed:"),t.message),process.exit(1)}});ee.command("deploy").description("Deploy site to API").option("-t, --target <name>","Target environment","default").option("-c, --config <path>","Config file path").option("--data","Deploy data (content)").option("--force","Force deploy").option("--dry-run","Dry run").option("--prune","Prune unused resources").action(async e=>{try{let t=await k({target:e.target,config:e.config});await ae(t,e)}catch(t){console.error(x.red("\u274C Deploy site failed:"),t.message),process.exit(1)}});ee.command("init").description("Initialize a new Artech project").option("--pull","Pull site data after initialization").action(async e=>{try{await re(e)}catch(t){console.error(x.red("\u274C Init failed:"),t.message),process.exit(1)}});var be=B.command("form").description("Manage forms");be.command("pull").description("Pull forms from API").option("-t, --target <name>","Target environment","default").option("-c, --config <path>","Config file path").action(async e=>{try{let t=await k({target:e.target,config:e.config});await Ie(t,e)}catch(t){console.error(x.red("\u274C Pull forms failed:"),t.message),process.exit(1)}});be.command("deploy").description("Deploy forms to API").option("-t, --target <name>","Target environment","default").option("-c, --config <path>","Config file path").option("--dry-run","Dry run").option("--prune","Prune unused forms").action(async e=>{try{let t=await k({target:e.target,config:e.config});await $e(t,e)}catch(t){console.error(x.red("\u274C Deploy forms failed:"),t.message),process.exit(1)}});var Fe=B.command("widget").description("Manage widgets");Fe.command("deploy").description("Deploy a widget instance (single)").requiredOption("-n, --name <name>","Widget name").option("-t, --target <name>","Target environment","default").option("-c, --config <path>","Config file path").option("--dry-run","Dry run").action(async e=>{try{let t=await k({target:e.target,config:e.config});await Q(t,e)}catch(t){console.error(x.red("\u274C Deploy widget failed:"),t.message),process.exit(1)}});var Pe=Fe.command("type").description("Manage widget types");Pe.command("list").description("List all available widget types").option("-d, --dir <path>","Directory to search",".").action(async e=>{try{let t=await k({});await ue(t,{cwd:e.dir})}catch(t){console.error(x.red("\u274C List widget types failed:"),t.message),process.exit(1)}});Pe.command("deploy").description("Deploy widget types").option("-t, --target <name>","Target environment","default").option("--key <key>","Specific widget type key").option("--dry-run","Dry run").action(async e=>{try{let t=await k({target:e.target,config:e.config});await ye(t,e)}catch(t){console.error(x.red("\u274C Deploy widget types failed:"),t.message),process.exit(1)}});B.parse();
34
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/index.ts","../src/cmd/site.ts","../src/helpers/api.ts","../src/helpers/yaml.ts","../src/helpers/context.ts","../src/helpers/file.ts","../src/helpers/field.ts","../src/cmd/widget-type.ts","../src/cmd/form.ts"],"sourcesContent":["#!/usr/bin/env node\n\nimport { Command } from 'commander'\nimport chalk from 'chalk'\nimport env from 'dotenv'\nenv.config()\n\nimport { deploySite, pullSite, initSite } from './cmd/site.js'\nimport { deployWidgetType, deployWidgetTypes, listWidgetTypes } from './cmd/widget-type.js'\nimport { deployForms, pullForms } from './cmd/form.js'\nimport { loadContext } from './helpers/context.js'\n\nconst program = new Command()\nprogram\n .name('artech')\n .description('Artech CLI tool')\n .version('1.0.0')\n\n\n\n// Site Group\nconst siteFn = program.command('site').description('Manage sites')\n\nsiteFn.command('pull')\n .description('Pull site from API')\n .option('-t, --target <name>', 'Target environment', 'default')\n .option('-c, --config <path>', 'Config file path')\n .option('--layout-only', 'Pull layout only')\n .action(async (options) => {\n try {\n const context = await loadContext({ target: options.target, config: options.config })\n await pullSite(context, options)\n } catch (error: any) {\n console.error(chalk.red('❌ Pull site failed:'), error.message)\n process.exit(1)\n }\n })\n\nsiteFn.command('deploy')\n .description('Deploy site to API')\n .option('-t, --target <name>', 'Target environment', 'default')\n .option('-c, --config <path>', 'Config file path')\n .option('--data', 'Deploy data (content)')\n .option('--force', 'Force deploy')\n .option('--dry-run', 'Dry run')\n .option('--prune', 'Prune unused resources')\n .action(async (options) => {\n try {\n const context = await loadContext({ target: options.target, config: options.config })\n await deploySite(context, options)\n } catch (error: any) {\n console.error(chalk.red('❌ Deploy site failed:'), error.message)\n process.exit(1)\n }\n })\n\nsiteFn.command('init')\n .description('Initialize a new Artech project')\n .option('--pull', 'Pull site data after initialization')\n .action(async (options) => {\n try {\n await initSite(options)\n } catch (error: any) {\n console.error(chalk.red('❌ Init failed:'), error.message)\n process.exit(1)\n }\n })\n\n// Form Group\nconst formFn = program.command('form').description('Manage forms')\n\nformFn.command('pull')\n .description('Pull forms from API')\n .option('-t, --target <name>', 'Target environment', 'default')\n .option('-c, --config <path>', 'Config file path')\n .action(async (options) => {\n try {\n const context = await loadContext({ target: options.target, config: options.config })\n await pullForms(context, options)\n } catch (error: any) {\n console.error(chalk.red('❌ Pull forms failed:'), error.message)\n process.exit(1)\n }\n })\n\nformFn.command('deploy')\n .description('Deploy forms to API')\n .option('-t, --target <name>', 'Target environment', 'default')\n .option('-c, --config <path>', 'Config file path')\n .option('--dry-run', 'Dry run')\n .option('--prune', 'Prune unused forms')\n .action(async (options) => {\n try {\n const context = await loadContext({ target: options.target, config: options.config })\n await deployForms(context, options)\n } catch (error: any) {\n console.error(chalk.red('❌ Deploy forms failed:'), error.message)\n process.exit(1)\n }\n })\n\n// Widget Group\nconst widgetFn = program.command('widget').description('Manage widgets')\n\nwidgetFn.command('deploy')\n .description('Deploy a widget instance (single)')\n .requiredOption('-n, --name <name>', 'Widget name')\n .option('-t, --target <name>', 'Target environment', 'default')\n .option('-c, --config <path>', 'Config file path')\n .option('--dry-run', 'Dry run')\n .action(async (options) => {\n try {\n const context = await loadContext({ target: options.target, config: options.config })\n await deployWidgetType(context, options)\n } catch (error: any) {\n console.error(chalk.red('❌ Deploy widget failed:'), error.message)\n process.exit(1)\n }\n })\n\n\n\nconst widgetTypeFn = widgetFn.command('type').description('Manage widget types')\n\nwidgetTypeFn.command('list')\n .description('List all available widget types')\n .option('-d, --dir <path>', 'Directory to search', '.')\n .action(async (options) => {\n try {\n const context = await loadContext({})\n await listWidgetTypes(context, { cwd: options.dir })\n } catch (error: any) {\n console.error(chalk.red('❌ List widget types failed:'), error.message)\n process.exit(1)\n }\n })\n\nwidgetTypeFn.command('deploy')\n .description('Deploy widget types')\n .option('-t, --target <name>', 'Target environment', 'default')\n .option('--key <key>', 'Specific widget type key')\n .option('--dry-run', 'Dry run')\n .action(async (options) => {\n try {\n const context = await loadContext({ target: options.target, config: options.config })\n await deployWidgetTypes(context, options)\n } catch (error: any) {\n console.error(chalk.red('❌ Deploy widget types failed:'), error.message)\n process.exit(1)\n }\n })\n\nprogram.parse()","import fs from 'fs/promises'\nimport { spawn } from 'child_process'\nimport path from 'path'\n\nimport yaml from 'js-yaml'\nimport chalk from 'chalk'\nimport type { Site } from '@artech-global/types'\nimport { apiRequest, loadYaml, saveYaml, loadFileContent, saveFileContent } from '../helpers/index.js'\nimport type { ArtechContext } from '../helpers/context.js'\n\nconst PRESERVED_PROPS = ['formID']\n\n/**\n * Get working directory from SITE_CWD env or fallback to process.cwd()\n */\nfunction getWorkingDir(): string {\n return process.env.SITE_CWD ? path.resolve(process.env.SITE_CWD) : process.cwd()\n}\n\nasync function loadConfig(filePath: string): Promise<any> {\n try {\n const content = await fs.readFile(filePath, 'utf8')\n const config: any = yaml.load(content)\n\n // Handle special logic for config files\n if (config.site?.styleBody) {\n config.site.styleBody = await loadFileContent(config.site.styleBody, getWorkingDir())\n }\n\n // Convert page.widgets to page.widgetScopedIDs and move to global widgets\n if (config.pages) {\n if (!config.widgets) {\n config.widgets = []\n }\n\n for (const page of config.pages) {\n if (page.widgets && Array.isArray(page.widgets)) {\n const pageWidgetScopedIDs = page.widgets.map((w: any) => w.scopedID).filter(Boolean)\n\n page.widgets.forEach((widget: any) => {\n const existingWidget = config.widgets.find((w: any) => w.scopedID === widget.scopedID)\n if (!existingWidget) {\n config.widgets.push(widget)\n }\n })\n\n page.widgetScopedIDs = pageWidgetScopedIDs\n delete page.widgets\n }\n }\n }\n\n return config\n } catch (error: any) {\n throw new Error(`Failed to load ${filePath}: ${error.message}`)\n }\n}\n\n\nconst FIELD_MAPPING = {\n site: {\n config: ['title', 'description', 'keywords', 'favicon', 'socialImage', 'siteTheme', 'updateTime'],\n data: ['title', 'description', 'keywords', 'favicon', 'socialImage', 'siteTheme', 'image', 'published', 'createTime', 'updateTime']\n },\n page: {\n config: ['scopedID', 'name', 'slug', 'type', 'widgetScopedIDs', 'headerScopedID', 'footerScopedID'],\n data: ['scopedID', 'name', 'slug', 'type', 'title', 'description', 'keywords', 'image', 'bodyClass', 'isCustomStyle', 'styleBody', 'widgetScopedIDs', 'headerScopedID', 'footerScopedID', 'status', 'position', 'removable', 'editable']\n },\n widget: {\n config: ['scopedID', 'type', '^background'],\n data: ['scopedID', 'type', 'name', 'domID', 'domClass', 'isCustomStyle', 'styleBody', 'isCustomTemplate', 'templateBody', 'margin', 'padding', 'background', 'props', 'removable', 'editable']\n }\n}\n\nfunction filterFields(obj: any, allowedFields: string[]): any {\n const filtered: any = {}\n for (const field of allowedFields) {\n const isOmitEmpty = field.startsWith('^')\n const actualFieldName = isOmitEmpty ? field.substring(1) : field\n \n if (obj.hasOwnProperty(actualFieldName)) {\n if (isOmitEmpty && (!obj[actualFieldName] || obj[actualFieldName].toString().trim() === '')) {\n continue\n }\n filtered[actualFieldName] = obj[actualFieldName]\n }\n }\n return filtered\n}\n\n/**\n * Parse props safely, handling both string and object formats\n */\nfunction parseProps(props: any): any {\n if (!props) return {}\n return typeof props === 'string' ? JSON.parse(props) : props\n}\n\n/**\n * Merge widget props with proper priority and preserved props logic\n * Priority: config > data > remote\n * Preserved props from remote are always kept\n */\nfunction mergeWidgetProps(remoteProps: any, dataProps: any, configProps: any): any {\n // Parse all props safely\n const remote = parseProps(remoteProps)\n const data = parseProps(dataProps)\n const config = parseProps(configProps)\n\n // Merge with priority: config > data > remote\n const merged = { ...remote, ...data, ...config }\n\n // Preserve specified props from remote widget\n PRESERVED_PROPS.forEach(prop => {\n if (remote[prop] !== undefined) {\n merged[prop] = remote[prop]\n }\n })\n\n return merged\n}\n\n/**\n * Get default props for a new widget by fetching its widget type from API\n */\nasync function getDefaultPropsForNewWidget(context: ArtechContext, widgetConfig: any): Promise<any> {\n try {\n // Get widget type from API to get default props\n const widgetTypeResponse = await apiRequest(context, 'GET', `/widget-type?key=${widgetConfig.type}&pageSize=1000`, undefined)\n const widgetType = widgetTypeResponse.items?.[0]\n\n if (widgetType && widgetType.defaultProps) {\n console.log(chalk.blue(` Creating new widget: ${widgetConfig.scopedID} (${widgetConfig.type})`))\n\n // Parse default props and merge with config props\n const defaultProps = parseProps(widgetType.defaultProps)\n const configProps = parseProps(widgetConfig.props)\n\n return { ...defaultProps, ...configProps }\n } else {\n console.log(chalk.red(`⚠️ Widget type ${widgetConfig.type} not found, creating new widget`))\n }\n } catch (error: any) {\n console.warn(chalk.yellow(` ⚠️ Could not load default props for widget ${widgetConfig.type}: ${error.message}`))\n }\n\n // Fallback to just config props if no default props found\n return parseProps(widgetConfig.props)\n}\n\nasync function deployWidgets(config: any, isProd: boolean) {\n const widgetTypes = config.widgetTypes || []\n\n if (widgetTypes.length === 0) {\n console.log(chalk.gray(' No widget types found in config'))\n return\n }\n\n console.log(chalk.gray(` Found ${widgetTypes.length} widget types to deploy`))\n\n for (const widgetType of widgetTypes) {\n try {\n console.log(chalk.blue(` Deploying widget: ${widgetType.key}`))\n\n await executeDeployWidget(widgetType.key, isProd)\n\n console.log(chalk.green(` ✅ Deployed widget: ${widgetType.key}`))\n } catch (error: any) {\n console.log(error)\n console.error(chalk.red(` ❌ Failed to deploy widget ${widgetType.key}:`), error.message)\n throw error // Exit when a widget fails\n }\n }\n}\n\nfunction executeDeployWidget(widgetName: string, isProd: boolean): Promise<void> {\n return new Promise((resolve, reject) => {\n const workingDir = getWorkingDir()\n const scriptPath = path.resolve(workingDir, 'tool/index.ts')\n const args = ['deploy-widget', '-n', widgetName]\n\n if (isProd) {\n args.push('--prod')\n }\n\n const child = spawn('npx', ['tsx', scriptPath, ...args], {\n stdio: 'pipe',\n env: { ...process.env },\n cwd: workingDir\n })\n\n let stdout = ''\n let stderr = ''\n\n child.stdout?.on('data', (data) => {\n stdout += data.toString()\n // Don't log detailed widget publishing output to main process\n })\n\n child.stderr?.on('data', (data) => {\n stderr += data.toString()\n // Only log errors to main process\n if (data.toString().includes('❌')) {\n console.error(data.toString())\n }\n })\n\n child.on('close', (code) => {\n if (code === 0) {\n resolve()\n } else {\n reject(new Error(`Widget deploying failed with code ${code}. Stderr: ${stderr}`))\n }\n })\n\n child.on('error', (error) => {\n reject(new Error(`Failed to spawn widget deploying process: ${error.message}`))\n })\n })\n}\n\nasync function extractConfig(remoteSite: Site, currentConfig: any, widgets: any[]): Promise<any> {\n const widgetUsageCount: { [key: string]: number } = {}\n\n remoteSite.pages?.forEach(page => {\n page.widgetScopedIDs?.forEach(id => {\n widgetUsageCount[id] = (widgetUsageCount[id] || 0) + 1\n })\n if (page.headerScopedID) widgetUsageCount[page.headerScopedID] = (widgetUsageCount[page.headerScopedID] || 0) + 1\n if (page.footerScopedID) widgetUsageCount[page.footerScopedID] = (widgetUsageCount[page.footerScopedID] || 0) + 1\n })\n\n const commonWidgets = widgets\n .filter(widget => widget.scopedID && widgetUsageCount[widget.scopedID] && widgetUsageCount[widget.scopedID]! > 1)\n .map(widget => filterFields(widget, FIELD_MAPPING.widget.config))\n\n const pagesWithWidgets = remoteSite.pages?.map(page => {\n const pageData = filterFields(page, FIELD_MAPPING.page.config)\n const pageWidgetList = page.widgetScopedIDs?.map(id => {\n const widget = widgets.find(w => w.scopedID === id)\n return widget ? filterFields(widget, FIELD_MAPPING.widget.config) : null\n }).filter(Boolean) || []\n delete pageData.widgetScopedIDs\n\n return { ...pageData, widgets: pageWidgetList }\n }) || []\n\n let styleBody = remoteSite.styleBody\n\n\n if (styleBody) {\n const originalStylePath = currentConfig.site?.styleBody\n let styleFilePath: string | undefined\n\n if (originalStylePath && (originalStylePath.startsWith('~~/') || originalStylePath.startsWith('file:'))) {\n styleFilePath = originalStylePath\n } else {\n console.warn(chalk.yellow(`⚠️ Site style file not specified in config`))\n }\n\n if (styleFilePath) {\n await saveFileContent(styleBody, styleFilePath, getWorkingDir())\n styleBody = styleFilePath\n }\n }\n\n return {\n site: {\n ...filterFields(remoteSite, FIELD_MAPPING.site.config),\n styleBody\n },\n pages: pagesWithWidgets,\n widgets: commonWidgets,\n forms: currentConfig.forms || [],\n }\n}\n\nfunction extractData(apiSite: Site, widgets: any[], existingData?: any): any {\n return {\n site: [filterFields(apiSite, FIELD_MAPPING.site.data)],\n pages: apiSite.pages?.map(page => ({\n ...filterFields(page, FIELD_MAPPING.page.data),\n })) || [],\n widgets: widgets.map(widget => {\n const filteredWidget = filterFields(widget, FIELD_MAPPING.widget.data)\n if (filteredWidget.props && typeof filteredWidget.props === 'string') {\n try {\n filteredWidget.props = JSON.parse(filteredWidget.props)\n } catch (error: any) {\n console.warn(chalk.yellow(`⚠️ Could not parse props for widget ${widget.scopedID}: ${error.message}`))\n }\n }\n return filteredWidget\n }),\n }\n}\n\nexport async function initSite(options: { cwd?: string, pull?: boolean }) {\n const cwd = options.cwd ? path.resolve(options.cwd) : process.cwd()\n \n console.log(chalk.blue('🚀 Initializing Artech project...'))\n\n const files = {\n 'artech.config.yml': {\n siteSpecFile: 'config/site-spec.yml',\n siteDataFile: 'config/site-data.yml',\n targets: {\n default: {\n api: 'env:ARTECH_API_URL',\n token: 'env:ARTECH_API_TOKEN',\n site: {\n slug: 'my-site'\n }\n },\n }\n },\n 'config/site-spec.yml': {\n site: {\n title: 'My Site',\n },\n pages: [],\n widgets: [],\n forms: []\n },\n 'config/site-data.yml': {\n site: {},\n pages: [],\n widgets: [],\n forms: []\n }\n }\n\n // Create generated files\n for (const [filename, content] of Object.entries(files)) {\n const filePath = path.join(cwd, filename)\n try {\n // Ensure directory exists\n const dir = path.dirname(filePath)\n await fs.mkdir(dir, { recursive: true })\n \n await fs.access(filePath)\n console.log(chalk.yellow(`⚠️ ${filename} already exists, skipping.`))\n } catch {\n await saveYaml(filePath, content)\n console.log(chalk.green(`✅ Created ${filename}`))\n }\n }\n\n // Create .env.example\n const envExamplePath = path.join(cwd, '.env.example')\n const envContent = `ARTECH_API_URL=https://api.artech.global\\nARTECH_API_TOKEN=\\n`\n try {\n await fs.access(envExamplePath)\n console.log(chalk.yellow(`⚠️ .env.example already exists, skipping.`))\n } catch {\n await fs.writeFile(envExamplePath, envContent)\n console.log(chalk.green(`✅ Created .env.example`))\n }\n\n console.log(chalk.green('\\n✨ Project initialized successfully!'))\n \n if (options.pull) {\n console.log(chalk.blue('📥 Pulling site data... (Not yet implemented in init --pull)'))\n // TODO: Call pullSite logic here if needed, but might require valid config first?\n // Since we just created dummy config, pulling might fail if user hasn't set tokens.\n // Maybe we warn?\n console.warn(chalk.yellow('⚠️ --pull requested but you need to setup .env and artech.config.yml with valid tokens/slugs first.'))\n }\n}\n\n\nexport async function pullSite(context: ArtechContext, options: { \n target?: string\n layoutOnly?: boolean\n}) {\n const siteSpecPath = context.paths.siteSpec\n const siteDataPath = context.paths.siteData\n\n console.log(chalk.blue('⬇️ Pulling latest site data...'))\n\n const currentSpec = await loadYaml(siteSpecPath)\n // Use resolved siteSlug from context\n const siteSlug = context.target.site?.slug\n\n if (!siteSlug) {\n throw new Error(`Site slug not found for target: ${context.target.name}`)\n }\n\n console.log(chalk.gray(`Target: ${context.target.name}`))\n console.log(chalk.gray(`Site slug: ${siteSlug}`))\n\n console.log(chalk.blue('🔍 Checking site existence...'))\n const sitesResponse = await apiRequest(context, 'GET', `/site?slug=${siteSlug}`, undefined)\n\n if (!sitesResponse.items || sitesResponse.items.length === 0) {\n throw new Error(`Site with slug \"${siteSlug}\" not found`)\n }\n\n const siteId = sitesResponse.items[0].id\n const foundSite = sitesResponse.items[0]\n console.log(chalk.green(`✅ Found site: ${foundSite.name} (ID: ${siteId})`))\n console.log(chalk.gray(` Site: ${foundSite.name} (${foundSite.slug})`))\n console.log(chalk.gray(` Updated: ${new Date(foundSite.updateTime * 1000).toISOString()}`))\n\n if (options.layoutOnly) {\n console.log(chalk.gray(' Skipping data pull (layout only)'))\n console.log(chalk.blue('📄 Fetching site layout data...'))\n const remoteSite: Site = await apiRequest(context, 'GET', `/site/${siteId}`, undefined)\n const widgetsResponse = await apiRequest(context, 'GET', `/widget?siteID=${siteId}`, undefined)\n const remoteWidgets = widgetsResponse.items || []\n\n console.log(chalk.blue('📝 Updating site-spec.yml...'))\n const layoutSpec = await extractConfig(remoteSite, currentSpec, remoteWidgets)\n await saveYaml(siteSpecPath, layoutSpec, { flowLevel: 4 })\n console.log(chalk.green('✅ site-spec.yml updated'))\n } else {\n console.log(chalk.blue('📄 Fetching complete site data...'))\n const remoteSite: Site = await apiRequest(context, 'GET', `/site/${siteId}`, undefined)\n const widgetsResponse = await apiRequest(context, 'GET', `/widget?siteID=${siteId}`, undefined)\n const remoteWidgets = widgetsResponse.items || []\n\n // Sort pages by position right after loading from API\n if (remoteSite.pages) {\n remoteSite.pages.sort((a, b) => {\n const positionA = a.position || 0\n const positionB = b.position || 0\n return positionA - positionB\n })\n }\n\n console.log(chalk.blue('📝 Updating site-spec.yml...'))\n const layoutSpec = await extractConfig(remoteSite, currentSpec, remoteWidgets)\n await saveYaml(siteSpecPath, layoutSpec, { flowLevel: 4 })\n console.log(chalk.green('✅ site-spec.yml updated'))\n\n console.log(chalk.blue('📝 Updating site-data.yml...'))\n const currentData = await loadYaml(siteDataPath)\n const completeData = extractData(remoteSite, remoteWidgets, currentData)\n await saveYaml(siteDataPath, completeData, { flowLevel: 10 })\n console.log(chalk.green('✅ site-data.yml updated'))\n \n console.log(chalk.gray(` Pages: ${remoteSite.pages?.length || 0}, Widgets: ${remoteWidgets.length}`))\n }\n\n console.log(chalk.green('🎉 Pull completed successfully!'))\n}\n\nexport async function deploySite(context: ArtechContext, options: {\n target?: string\n data?: boolean\n force?: boolean\n dryRun?: boolean\n prune?: boolean\n}) {\n const siteSpecPath = context.paths.siteSpec\n const siteDataPath = context.paths.siteData\n\n const mode = options.data ? 'complete' : 'layout'\n console.log(chalk.blue(`🚀 Deploying site (${mode} mode)...`))\n if (options.dryRun) {\n console.log(chalk.yellow('⚠️ DRY RUN MODE: No changes will be applied'))\n }\n\n // Load local files with special handling\n const siteSpec = await loadConfig(siteSpecPath)\n const siteData = options.data ? await loadYaml(siteDataPath) : { site: [], pages: [], widgets: [] }\n\n // Use resolved siteSlug from context\n const siteSlug = context.target.site?.slug\n if (!siteSlug) {\n throw new Error(`Site slug not found for target: ${context.target.name}`)\n }\n\n console.log(chalk.gray(`Target: ${context.target.name}`))\n console.log(chalk.gray(`Site slug: ${siteSlug}`))\n\n // Get current site info from API\n console.log(chalk.blue('🔍 Checking site version...'))\n const sitesResponse = await apiRequest(context, 'GET', `/site?slug=${siteSlug}`, undefined)\n if (!sitesResponse.items || sitesResponse.items.length === 0) {\n throw new Error(`Site with slug \"${siteSlug}\" not found`)\n }\n\n let remoteSite: Site = sitesResponse.items[0]\n const siteID = remoteSite.id\n\n const localUpdateTime = siteSpec.site.updateTime || 0\n const remoteUpdateTime = remoteSite.updateTime || 0\n\n console.log(chalk.gray(` Local version: ${new Date(localUpdateTime * 1000).toISOString()}`))\n console.log(chalk.gray(` Remote version: ${new Date(remoteUpdateTime * 1000).toISOString()}`))\n\n // Check if remote is newer\n if (remoteUpdateTime > localUpdateTime && !options.force) {\n console.log(chalk.yellow('⚠️ Remote version is newer than local version!'))\n console.log(chalk.red('❌ Cannot deploy: Remote has newer changes'))\n console.log(chalk.blue('💡 Please run \"artech site pull\" first to get latest changes'))\n throw new Error('Remote has newer changes')\n } else if (remoteUpdateTime > localUpdateTime && options.force) {\n console.log(chalk.yellow('⚠️ Force mode: Deploying despite remote being newer'))\n } else {\n console.log(chalk.green('✅ Local version is up to date'))\n }\n\n\n // Get current site data for merging\n console.log(chalk.blue('📄 Fetching current site data...'))\n remoteSite = await apiRequest(context, 'GET', `/site/${siteID}`, undefined)\n\n const widgetsResponse = await apiRequest(context, 'GET', `/widget?siteID=${siteID}`, undefined)\n const remoteWidgets = widgetsResponse.items || []\n\n // Merge all data with priority: config > data > API\n console.log(chalk.blue('🔄 Merging data...'))\n\n // Merge site data with priority: config > data > API\n const updateSite = {\n ...remoteSite,\n ...siteData.site?.[0],\n ...siteSpec.site\n }\n\n const updatePages = siteSpec.pages?.map((pageConfig: any, index: number) => {\n\n const pageData = siteData.pages?.find((p: any) => p.scopedID === pageConfig.scopedID)\n const remotePage = remoteSite.pages?.find((p: any) => p.scopedID === pageConfig.scopedID)\n\n const updatePage = {\n ...remotePage,\n ...pageData,\n ...pageConfig,\n position: index + 1\n }\n\n return updatePage\n }) || []\n\n const updateWidgets = await Promise.all((siteSpec.widgets || []).map(async (widgetConfig: any) => {\n const widgetData = siteData.widgets?.find((w: any) => w.scopedID === widgetConfig.scopedID)\n const remoteWidget = remoteWidgets.find((w: any) => w.scopedID === widgetConfig.scopedID)\n\n let updateWidget = { ...widgetConfig }\n\n if (!remoteWidget) {\n updateWidget.props = await getDefaultPropsForNewWidget(context, widgetConfig)\n } else {\n updateWidget = { ...remoteWidget, ...widgetData, ...widgetConfig }\n updateWidget.props = mergeWidgetProps(remoteWidget.props, widgetData?.props, widgetConfig.props)\n }\n\n return updateWidget\n }))\n\n console.log(chalk.blue('📝 Updating site...'))\n if (!options.dryRun) {\n await apiRequest(context, 'PUT', `/site`, updateSite)\n }\n\n if (remoteSite.pages && remoteSite.pages.length > 0) {\n console.log(chalk.blue('🗑️ Checking for unused remote pages...'))\n \n const usedPageScopedIDs = new Set<string>()\n updatePages.forEach((page: any) => {\n if (page.scopedID) {\n usedPageScopedIDs.add(page.scopedID)\n }\n })\n \n const unusedPages = remoteSite.pages.filter((remotePage: any) => {\n return !usedPageScopedIDs.has(remotePage.scopedID) && !remotePage.deleteTime\n })\n \n if (unusedPages.length > 0) {\n console.log(chalk.yellow(`⚠️ Found ${unusedPages.length} unused remote page(s).`))\n if (options.prune) {\n console.log(chalk.yellow(` Marking for deletion...`))\n const currentTime = Math.floor(Date.now() / 1000)\n \n for (const unusedPage of unusedPages) {\n console.log(chalk.yellow(` - ${unusedPage.name} (${unusedPage.scopedID})`))\n \n if (!options.dryRun) {\n try {\n await apiRequest(context, 'PUT', `/page`, {\n ...unusedPage,\n deleteTime: currentTime\n })\n console.log(chalk.green(` ✅ Marked page ${unusedPage.scopedID} for deletion`))\n } catch (error: any) {\n console.log(chalk.red(` ❌ Failed to mark page ${unusedPage.scopedID} for deletion: ${error.message}`))\n }\n }\n }\n } else {\n console.log(chalk.gray(` Use --prune to delete these pages.`))\n }\n } else {\n console.log(chalk.gray(' No unused remote pages found'))\n }\n }\n\n // Update pages\n console.log(chalk.blue('📄 Updating pages...'))\n for (const page of updatePages) {\n if (page.name && page.type && page.scopedID) {\n const existingPage = remoteSite.pages?.find(p => p.scopedID === page.scopedID)\n\n if (existingPage) {\n const pageUpdateData = {\n id: existingPage.id,\n siteID: siteID,\n ...page\n }\n if (!options.dryRun) {\n await apiRequest(context, 'PUT', `/page`, pageUpdateData)\n }\n console.log(chalk.gray(` Updated page: ${page.slug}`))\n } else {\n const pageCreateData = {\n siteID: siteID,\n ...page\n }\n if (!options.dryRun) {\n await apiRequest(context, 'POST', `/page`, pageCreateData)\n }\n console.log(chalk.blue(` Creating new page: ${page.slug}`))\n }\n }\n }\n\n // Mark unused remote widgets for deletion first\n if (remoteWidgets && remoteWidgets.length > 0) {\n console.log(chalk.blue('🗑️ Checking for unused remote widgets...'))\n \n const usedWidgetScopedIDs = new Set<string>()\n \n // Collect used widget scopedIDs from pages\n updatePages.forEach((page: any) => {\n if (page.widgetScopedIDs && Array.isArray(page.widgetScopedIDs)) {\n page.widgetScopedIDs.forEach((scopedID: string) => {\n if (scopedID) usedWidgetScopedIDs.add(scopedID)\n })\n }\n if (page.headerScopedID) {\n usedWidgetScopedIDs.add(page.headerScopedID)\n }\n if (page.footerScopedID) {\n usedWidgetScopedIDs.add(page.footerScopedID)\n }\n })\n \n const unusedRemoteWidgets = remoteWidgets.filter((remoteWidget: any) => {\n return !usedWidgetScopedIDs.has(remoteWidget.scopedID) && !remoteWidget.deleteTime\n })\n \n if (unusedRemoteWidgets.length > 0) {\n console.log(chalk.yellow(`⚠️ Found ${unusedRemoteWidgets.length} unused remote widget(s).`))\n if (options.prune) {\n console.log(chalk.yellow(` Marking for deletion...`))\n const currentTime = Math.floor(Date.now() / 1000)\n \n // Print widgets to delete\n unusedRemoteWidgets.forEach((unusedWidget: any) => {\n console.log(chalk.yellow(` - ${unusedWidget.name} (${unusedWidget.scopedID})`))\n })\n \n if (!options.dryRun) {\n const widgetsToDelete = unusedRemoteWidgets.map((widget: any) => ({\n ...widget,\n deleteTime: currentTime\n }))\n \n try {\n await apiRequest(context, 'PUT', `/widget-multiple`, {\n siteID: siteID,\n widgets: widgetsToDelete,\n upsert: false \n })\n console.log(chalk.green(` ✅ Marked ${unusedRemoteWidgets.length} unused widgets for deletion`))\n } catch (error: any) {\n console.log(chalk.red(` ❌ Failed to mark unused widgets for deletion: ${error.message}`))\n }\n }\n } else {\n console.log(chalk.gray(` Use --prune to delete these widgets.`))\n }\n } else {\n console.log(chalk.gray(' No unused remote widgets found'))\n }\n }\n\n // Update widgets\n if (updateWidgets && updateWidgets.length > 0) {\n console.log(chalk.blue('🧩 Updating widgets...'))\n \n const usedWidgetScopedIDs = new Set<string>()\n \n updatePages.forEach((page: any) => {\n if (page.widgetScopedIDs && Array.isArray(page.widgetScopedIDs)) {\n page.widgetScopedIDs.forEach((scopedID: string) => {\n if (scopedID) usedWidgetScopedIDs.add(scopedID)\n })\n }\n if (page.headerScopedID) {\n usedWidgetScopedIDs.add(page.headerScopedID)\n }\n if (page.footerScopedID) {\n usedWidgetScopedIDs.add(page.footerScopedID)\n }\n })\n \n const currentTime = Math.floor(Date.now() / 1000) // Unix timestamp in seconds\n const widgetUpdates = updateWidgets.map((widget: any) => {\n const isUsed = usedWidgetScopedIDs.has(widget.scopedID)\n \n return {\n scopedID: widget.scopedID,\n type: widget.type,\n name: widget.name,\n domID: widget.domID,\n domClass: widget.domClass,\n background: widget.background,\n styleBody: widget.styleBody,\n margin: widget.margin,\n padding: widget.padding,\n props: typeof widget.props === 'string' ? widget.props : JSON.stringify(widget.props),\n deleteTime: isUsed ? undefined : currentTime\n }\n })\n\n const unusedWidgets = widgetUpdates.filter(w => w.deleteTime)\n const usedCount = widgetUpdates.length - unusedWidgets.length\n \n console.log(chalk.gray(` Updating ${usedCount} active widgets`))\n if (unusedWidgets.length > 0) {\n if (!options.prune) {\n console.log(chalk.yellow(` ${unusedWidgets.length} widgets in config are not used in pages.`))\n } else {\n console.log(chalk.yellow(` Marking ${unusedWidgets.length} unused widgets (from config) for deletion`))\n }\n }\n\n if (!options.dryRun) {\n // Filter out deleteTime if prune is false\n const finalWidgetUpdates = widgetUpdates.map(w => {\n if (w.deleteTime && !options.prune) {\n const { deleteTime, ...rest } = w\n return rest\n }\n return w\n })\n\n await apiRequest(context, 'PUT', `/widget-multiple`, {\n siteID: siteID,\n widgets: finalWidgetUpdates,\n upsert: true\n })\n \n console.log(chalk.gray(` ✅ Widget update completed`))\n }\n }\n\n\n console.log(chalk.green(`✅ Site deployed successfully (${mode} mode)!`))\n}","import axios from 'axios'\nimport chalk from 'chalk'\nimport type { ArtechContext } from './context.js'\n\nexport async function apiRequest(context: ArtechContext, method: string, endpoint: string, data?: any): Promise<any> {\n const baseUrl = context.target?.api\n const token = context.target?.token\n\n if (!baseUrl || !token) {\n throw new Error(`API configuration missing in context (target: ${context.target?.name})`)\n }\n\n try {\n const response = await axios({\n method,\n url: `${baseUrl}${endpoint}`,\n headers: {\n 'Authorization': `Bearer ${token}`,\n 'Content-Type': 'application/json'\n },\n ...(data && { data })\n })\n return response.data\n } catch (error: any) {\n // Log response data for 422 status codes\n if (error.response?.status === 422) {\n console.log(chalk.red('❌ 422 Validation Error Response Data:'))\n console.log(JSON.stringify(error.response.data, null, 2))\n }\n throw new Error(`API request failed: ${error.response?.data?.message || error.message}`)\n }\n}\n","import fs from 'fs/promises'\nimport yaml from 'js-yaml'\n\nexport async function loadYaml(filePath: string): Promise<any> {\n try {\n const content = await fs.readFile(filePath, 'utf8')\n return yaml.load(content)\n } catch (error: any) {\n throw new Error(`Failed to load ${filePath}: ${error.message}`)\n }\n}\n\nexport async function saveYaml(filePath: string, data: any, options: { flowLevel?: number } = {}): Promise<void> {\n try {\n const orderedData: any = {}\n if (data.site) orderedData.site = data.site\n if (data.pages) orderedData.pages = data.pages\n if (data.widgets) orderedData.widgets = data.widgets\n if (data.widgetTypes) orderedData.widgetTypes = data.widgetTypes\n if (data.forms) orderedData.forms = data.forms\n if (data.environments) orderedData.environments = data.environments\n\n let yamlContent = yaml.dump(orderedData, {\n indent: 4,\n lineWidth: 200,\n noRefs: true,\n sortKeys: false,\n flowLevel: options.flowLevel || 4\n })\n\n yamlContent = yamlContent\n .replace(/\\n(pages):/g, '\\n\\n$1:')\n .replace(/\\n(widgets):/g, '\\n\\n$1:')\n .replace(/\\n(widgetTypes):/g, '\\n\\n$1:')\n .replace(/\\n(forms):/g, '\\n\\n$1:')\n .replace(/\\n(environments):/g, '\\n\\n$1:')\n .replace(/^\\n/, '')\n\n await fs.writeFile(filePath, yamlContent)\n } catch (error: any) {\n throw new Error(`Failed to save ${filePath}: ${error.message}`)\n }\n}","import fs from 'fs/promises'\nimport path from 'path'\nimport yaml from 'js-yaml'\nimport dotenv from 'dotenv'\nimport chalk from 'chalk'\n\ntype Target = {\n name: string\n api: string\n token: string\n site?: {\n slug: string\n }\n}\n\nexport interface ArtechConfig {\n siteSpecFile: string\n siteDataFile: string\n targets?: {\n [key: string]: Target\n }\n}\n\nexport interface ArtechContext {\n cwd: string\n target: Target\n config: ArtechConfig\n paths: {\n siteSpec: string\n siteData: string\n }\n}\n\nexport async function loadContext(options: {\n cwd?: string\n config?: string\n target?: string\n} = {}): Promise<ArtechContext> {\n const cwd = options.cwd ? path.resolve(options.cwd) : process.cwd()\n const configPath = options.config \n ? path.resolve(cwd, options.config) \n : path.join(cwd, 'artech.config.yml')\n\n // 1. Load .env file if it exists\n const envPath = path.join(cwd, '.env')\n try {\n dotenv.config({ path: envPath })\n } catch (e) {\n // ignore\n }\n\n // 2. Load artech.config.yml\n let config: ArtechConfig = {\n siteSpecFile: 'config/site-spec.yml',\n siteDataFile: 'config/site-data.yml',\n targets: {}\n }\n try {\n const content = await fs.readFile(configPath, 'utf8')\n config = yaml.load(content) as ArtechConfig\n } catch (error: any) {\n if (options.config || error.code !== 'ENOENT') {\n console.warn(chalk.yellow(`⚠️ Could not load config file: ${configPath}`))\n }\n }\n\n // 3. Resolve Target\n const targetName = options.target || 'default'\n const targetConfig = config.targets?.[targetName]\n\n // 4. Resolve Paths\n const siteSpecPath = path.resolve(cwd, config.siteSpecFile)\n const siteDataPath = path.resolve(cwd, config.siteDataFile)\n\n // 5. Resolve API & Token\n let api = ''\n let token = ''\n let siteSlug = ''\n\n if (targetConfig) {\n if (targetConfig.api) {\n let apiVal = targetConfig.api\n if (apiVal.startsWith('env:')) {\n const envVar = apiVal.substring(4)\n apiVal = process.env[envVar] || ''\n }\n api = apiVal\n }\n \n if (targetConfig.token) {\n let tokenVal = targetConfig.token\n if (tokenVal.startsWith('env:')) {\n const envVar = tokenVal.substring(4)\n tokenVal = process.env[envVar] || ''\n }\n token = tokenVal\n }\n \n if (targetConfig.site?.slug) {\n siteSlug = targetConfig.site.slug\n }\n }\n\n return {\n cwd,\n target: {\n name: targetName,\n api,\n token,\n site: targetConfig?.site,\n },\n config,\n paths: {\n siteSpec: siteSpecPath,\n siteData: siteDataPath\n }\n }\n}\n","import fs from 'fs/promises'\nimport path from 'path'\nimport chalk from 'chalk'\n\n/**\n * Load content from file if the string starts with 'file:' or '~~/'\n */\nexport async function loadFileContent(content: string, cwd: string = process.cwd()): Promise<string> {\n if (!content || typeof content !== 'string') return content\n\n if (content.startsWith('file:') || content.startsWith('~~/')) {\n const cleanPath = content.replace(/^(file:|~~)(\\/|\\\\)?/, '')\n const filePath = path.resolve(cwd, cleanPath)\n try {\n return await fs.readFile(filePath, 'utf8')\n } catch (error: any) {\n console.warn(chalk.yellow(`⚠️ Could not load file: ${filePath}`))\n return content\n }\n }\n return content\n}\n\n/**\n * Save content to file if the target path starts with 'file:' or '~~/'\n */\nexport async function saveFileContent(content: string, targetPath: string, cwd: string = process.cwd()): Promise<void> {\n if (!targetPath || (!targetPath.startsWith('file:') && !targetPath.startsWith('~~/'))) {\n return\n }\n\n const cleanPath = targetPath.replace(/^(file:|~~)(\\/|\\\\)?/, '')\n const filePath = path.resolve(cwd, cleanPath)\n\n try {\n console.log(chalk.gray(` Saving file to: ${filePath}`))\n await fs.mkdir(path.dirname(filePath), { recursive: true })\n await fs.writeFile(filePath, content, 'utf8')\n console.log(chalk.green(`✅ Content saved to: ${targetPath}`))\n } catch (error: any) {\n console.warn(chalk.yellow(`⚠️ Could not save file: ${filePath}`))\n }\n}\n","\nexport function filterEmptyFields(obj: any): any {\n if (!obj || typeof obj !== 'object') return obj\n \n if (Array.isArray(obj)) {\n return obj.map(v => filterEmptyFields(v)).filter(v => v !== null && v !== undefined && v !== '')\n }\n\n const result: any = {}\n for (const key in obj) {\n const value = obj[key]\n if (value !== null && value !== undefined && value !== '') {\n if (typeof value === 'object') {\n const filtered = filterEmptyFields(value)\n // If object is empty after filtering, don't include it (unless it was essentially empty but we want to keep it? User said filter empty field)\n // Let's keep it simple: if it's an empty object, maybe we should keep it if the original wasn't empty?\n // But for \"settings\", usually we want to drop empty settings.\n if (Object.keys(filtered).length > 0) {\n result[key] = filtered\n }\n } else {\n result[key] = value\n }\n }\n }\n return result\n}\n","import { readFileSync, existsSync, readdirSync } from 'fs';\nimport * as path from 'path';\nimport { parse, compileScript, compileTemplate, type CompilerOptions, type SFCDescriptor, type BindingMetadata, type SFCScriptCompileOptions, compileStyleAsync } from \"@vue/compiler-sfc\";\nimport hash from 'hash-sum';\nimport LeanCss from 'clean-css'\nimport chalk from 'chalk'\nimport { apiRequest } from '../helpers/index.js'\nimport type { ArtechContext } from '../helpers/context.js'\nimport { createRequire } from 'module';\nconst require = createRequire(import.meta.url);\n\n// @ts-ignore\nimport babelPluginTransformModulesCommonjs from '@babel/plugin-transform-modules-commonjs'\nimport {\n transformFromAstAsync as babel_transformFromAstAsync,\n types as t,\n traverse,\n} from '@babel/core';\nimport {\n parse as babel_parse,\n type ParserOptions,\n} from '@babel/parser';\nimport babelPlugin_jsx from '@vue/babel-plugin-jsx'\n// @ts-ignore\nimport babelPlugin_typescript from '@babel/plugin-transform-typescript'\n\n\nconst COMP_IDENTIFIER = `__bz__`;\nconst IMPORT_IDENTIFIER = `__bz_import__`;\nconst devMode = false;\n\n\nexport async function listWidgetTypes(context: ArtechContext, options: {\n cwd?: string\n}) {\n const searchDir = options.cwd ? path.resolve(options.cwd) : (context.cwd || process.cwd());\n console.log(chalk.blue(`Creating list of widget types in: ${searchDir}...`));\n\n const widgetTypes = findAllWidgetTypes(searchDir);\n\n if (widgetTypes.length === 0) {\n console.log(chalk.yellow('No widget types found.'));\n return;\n }\n\n console.log(chalk.green(`Found ${widgetTypes.length} widget types:`));\n for (const wt of widgetTypes) {\n const relPath = path.relative(searchDir, wt.dir);\n console.log(`- ${chalk.cyan(wt.name)} (${relPath})`);\n }\n}\n\n// Helper to load and execute TypeScript files (for widget descriptors)\nasync function loadTsFile(filePath: string): Promise<any> {\n const source = readFileSync(filePath, 'utf-8');\n \n // Parse AST first\n const ast = babel_parse(source, {\n sourceType: 'module',\n sourceFilename: filePath,\n plugins: ['typescript']\n });\n \n // Using existing babel transform from the file\n const { code } = await babel_transformFromAstAsync(ast, source, {\n filename: filePath,\n presets: [], \n plugins: [\n babelPlugin_typescript,\n babelPluginTransformModulesCommonjs\n ],\n babelrc: false,\n configFile: false,\n }) || { code: '' };\n\n const module = { exports: {} as any };\n // Reuse the require created above or create a new one relative to the file if needed.\n // Ideally, for node modules imports inside the TS file to work, we need a require relative to that file.\n const fileRequire = createRequire(filePath);\n \n // Execute the code\n const fun = new Function('module', 'exports', 'require', code!);\n fun(module, module.exports, fileRequire);\n\n return module.exports.default || module.exports;\n}\n\nexport async function deployWidgetType(context: ArtechContext, options: {\n name: string\n dryRun?: boolean,\n}) {\n const fileName = options.name;\n\n if (options.dryRun) {\n console.log(chalk.yellow('⚠️ DRY RUN MODE: No changes will be applied'))\n }\n\n // Use context.cwd or fallback\n const searchDir = context.cwd ? path.resolve(context.cwd, 'widgets') : path.resolve(process.cwd(), 'widgets');\n\n // Find the widget files\n const widgetFiles = findWidgetFiles(fileName, searchDir);\n\n if (!widgetFiles) {\n throw new Error(`Widget \"${fileName}\" not found in \"${searchDir}\" or its subdirectories. Make sure both \"${fileName}.ts\" and \"${fileName}.vue\" files exist.`);\n }\n\n const { tsFile, vueFile, widgetDir } = widgetFiles;\n console.log(chalk.green(`✅ Found widget files:`));\n console.log(chalk.gray(` TS: ${tsFile}`));\n console.log(chalk.gray(` Vue: ${vueFile}`));\n console.log(chalk.gray(` Directory: ${widgetDir}`));\n\n // Process the main component and all its dependencies\n console.log(chalk.blue(`🔄 Processing component and dependencies...`));\n const componentResult = await processComponent(vueFile, new Set(), true);\n\n // Determine script language for transformation\n const fileContent = readFileSync(vueFile, 'utf-8');\n const { descriptor } = parse(fileContent, {\n filename: path.basename(vueFile),\n sourceMap: true,\n });\n const scriptLang = descriptor.script?.lang || descriptor.scriptSetup?.lang;\n const isTS = !!(scriptLang && /(\\.|\\b)tsx?$/.test(scriptLang));\n const isJSX = !!(scriptLang && /(\\.|\\b)tsx?$/.test(scriptLang));\n\n // Bundle all components together\n const bundledResult = await bundleComponents(componentResult, fileName, isTS, isJSX);\n\n console.log(chalk.green(`✅ Build module successfully (${bundledResult.scriptSource.length} + ${bundledResult.styleSource.length} bytes).`));\n\n const widgetType = await loadTsFile(tsFile);\n widgetType.sfcSource = readFileSync(vueFile, 'utf-8');\n widgetType.scriptSource = bundledResult.scriptSource;\n widgetType.styleSource = bundledResult.styleSource;\n\n const response = await apiRequest(context, 'GET', `/widget-type?key=${widgetType.key}`, undefined);\n\n console.log(chalk.green(`✅ Fetch ${widgetType.key} widget successfully.`));\n\n const data = response;\n let method = \"\";\n let originWidgetType: any = {};\n\n if (!data || !data.items || !data.items[0]) {\n console.log(chalk.blue(`The widget type \"${widgetType.key}\" does not exist. Creating new...`));\n method = \"POST\";\n } else {\n method = \"PUT\";\n originWidgetType = data.items[0];\n if (originWidgetType.key != widgetType.key) {\n throw new Error(`The key \"${widgetType.key}\" != \"${originWidgetType.key}\".`);\n }\n }\n\n if (!options.dryRun) {\n await apiRequest(context, method, '/widget-type', {\n ...originWidgetType,\n ...widgetType,\n });\n console.log(chalk.green(`✅ Widget ${widgetType.key} deployed successfully.`));\n } else {\n console.log(chalk.yellow(`✅ DRY RUN: Widget ${widgetType.key} deployed successfully (simulated).`));\n }\n}\n\n\nexport async function deployWidgetTypes(context: ArtechContext, options: {\n dryRun?: boolean\n target?: string\n key?: string\n}) {\n\n\n console.log(chalk.blue('🧩 Deploying widget types...'))\n if (options.dryRun) {\n console.log(chalk.yellow('⚠️ DRY RUN MODE: No changes will be applied'))\n }\n\n // Use context.cwd or fallback\n const searchDir = context.cwd ? path.resolve(context.cwd, 'widgets') : path.resolve(process.cwd(), 'widgets');\n const foundWidgets = findAllWidgetTypes(searchDir)\n let widgetTypes = foundWidgets.map(w => ({ key: w.name }))\n\n if (widgetTypes.length === 0) {\n console.log(chalk.gray(' No widget types found in widgets directory'))\n return\n }\n\n if (options.key) {\n const filtered = widgetTypes.filter((wt: any) => wt.key === options.key)\n if (filtered.length === 0) {\n throw new Error(`Widget type with key \"${options.key}\" not found in widgets directory`)\n }\n widgetTypes = filtered\n console.log(chalk.gray(` Deploying single widget type: ${options.key}`))\n } else {\n console.log(chalk.gray(` Found ${widgetTypes.length} widget types to deploy`))\n }\n\n for (const widgetType of widgetTypes) {\n try {\n console.log('')\n console.log(chalk.blue(`================ ${widgetType.key} =================`))\n\n await deployWidgetType(context, {\n name: widgetType.key,\n dryRun: options.dryRun\n })\n\n } catch (error: any) {\n console.log(error)\n console.error(chalk.red(` ❌ Failed to publish widget ${widgetType.key}:`), error.message)\n if (options.key) throw error // Fail hard if single widget specified\n }\n }\n}\n\n\n// helper function\nfunction findAllWidgetTypes(searchDirectory: string): Array<{ name: string; tsFile: string; vueFile: string; dir: string }> {\n const widgetTypes: Array<{ name: string; tsFile: string; vueFile: string; dir: string }> = [];\n\n if (!existsSync(searchDirectory)) {\n return widgetTypes;\n }\n\n const items = readdirSync(searchDirectory, { withFileTypes: true });\n\n for (const item of items) {\n const fullPath = path.join(searchDirectory, item.name);\n\n if (item.isDirectory()) {\n if (item.name === 'node_modules' || item.name === '.git' || item.name === 'dist') {\n continue;\n }\n widgetTypes.push(...findAllWidgetTypes(fullPath));\n } else if (item.isFile()) {\n const ext = path.extname(item.name);\n if (ext === '.ts') {\n const name = path.parse(item.name).name;\n // Check for corresponding .vue file in the same directory\n const vueFile = path.join(searchDirectory, `${name}.vue`);\n\n // The requirement is \"[widget-key].ts + [widget-key].vue\"\n if (existsSync(vueFile)) {\n widgetTypes.push({\n name,\n tsFile: fullPath,\n vueFile,\n dir: searchDirectory\n });\n }\n }\n }\n }\n\n return widgetTypes;\n}\n\nfunction findWidgetFiles(widgetName: string, searchDirectory: string): { tsFile: string; vueFile: string; widgetDir: string } | null {\n if (!existsSync(searchDirectory)) {\n return null;\n }\n\n const items = readdirSync(searchDirectory, { withFileTypes: true });\n\n for (const item of items) {\n const fullPath = path.join(searchDirectory, item.name);\n\n if (item.isDirectory()) {\n // Recursively search subdirectories\n const result = findWidgetFiles(widgetName, fullPath);\n if (result) {\n return result;\n }\n } else if (item.isFile()) {\n // Check if this is the widget file we're looking for\n const nameWithoutExt = path.parse(item.name).name;\n if (nameWithoutExt === widgetName) {\n const ext = path.extname(item.name);\n const tsFile = ext === '.ts' ? fullPath : path.join(path.dirname(fullPath), `${widgetName}.ts`);\n const vueFile = ext === '.vue' ? fullPath : path.join(path.dirname(fullPath), `${widgetName}.vue`);\n\n // Verify both files exist\n if (existsSync(tsFile) && existsSync(vueFile)) {\n return {\n tsFile,\n vueFile,\n widgetDir: path.dirname(fullPath)\n };\n }\n }\n }\n }\n\n return null;\n}\n\n// Function to extract import statements from script content\nfunction extractImports(scriptContent: string): Array<{ name: string; path: string; isDefault: boolean }> {\n const imports: Array<{ name: string; path: string; isDefault: boolean }> = [];\n\n // Match import statements\n const importRegex = /import\\s+(?:(\\w+)(?:\\s*,\\s*\\{([^}]+)\\})?|{([^}]+)})\\s+from\\s+['\"]([^'\"]+)['\"]/g;\n let match;\n\n while ((match = importRegex.exec(scriptContent)) !== null) {\n const defaultImport = match[1];\n const namedImports1 = match[2];\n const namedImports2 = match[3];\n const importPath = match[4];\n\n if (defaultImport && importPath) {\n imports.push({ name: defaultImport, path: importPath, isDefault: true });\n }\n\n const namedImports = namedImports1 || namedImports2;\n if (namedImports && importPath) {\n const names = namedImports.split(',').map(name => name.trim());\n names.forEach(name => {\n imports.push({ name, path: importPath, isDefault: false });\n });\n }\n }\n\n return imports;\n}\n\n// Function to resolve relative import paths to absolute paths\nfunction resolveImportPath(importPath: string, baseDir: string): string | null {\n // Handle relative imports\n if (importPath.startsWith('./') || importPath.startsWith('../')) {\n const resolvedPath = path.resolve(baseDir, importPath);\n\n // Try different extensions\n const extensions = ['.vue', '.ts', '.js'];\n for (const ext of extensions) {\n const fullPath = resolvedPath + ext;\n if (existsSync(fullPath)) {\n return fullPath;\n }\n }\n\n // If no extension found, return the path as is\n return resolvedPath;\n }\n\n return null;\n}\n\nasync function transformJS(source: string, filename: string, isTs: boolean, isJsx: boolean): Promise<string> {\n let ast: t.File;\n try {\n const plugins: ParserOptions[\"plugins\"] = []\n if (isTs) plugins.push('typescript')\n if (isJsx) plugins.push('jsx')\n\n ast = babel_parse(source, {\n sourceType: 'module',\n sourceFilename: filename.toString(),\n plugins: plugins,\n });\n\n // rename dynamic import\n traverse(ast, {\n CallExpression(path: any) {\n if (t.isImport(path.node.callee))\n path.replaceWith(t.callExpression(t.identifier(IMPORT_IDENTIFIER), path.node.arguments))\n }\n });\n } catch (ex) {\n console.error(chalk.red('❌ Parse script error:'), ex);\n throw new Error(`Failed to parse script: ${ex}`);\n }\n\n const additionalBabelPlugins =\n {\n 'jsx': babelPlugin_jsx,\n 'typescript': babelPlugin_typescript\n }\n\n const pluginList = [\n babelPluginTransformModulesCommonjs,\n ...additionalBabelPlugins !== undefined ? Object.values(additionalBabelPlugins) : [],\n ]\n\n const transformedScript = await babel_transformFromAstAsync(ast, source, {\n sourceMaps: false,\n plugins: pluginList,\n presets: [require.resolve('babel-preset-minify')],\n babelrc: false,\n configFile: false,\n highlightCode: false,\n compact: !devMode,\n comments: devMode,\n retainLines: devMode,\n minified: false,\n sourceType: 'module',\n });\n\n if (transformedScript === null || transformedScript.code == null) {\n const msg = `unable to transform script \"${filename.toString()}\"`;\n throw new Error(msg)\n }\n return transformedScript.code;\n}\n\nasync function doCompileScript(\n descriptor: SFCDescriptor,\n id: string,\n isTS: boolean,\n isJSX: boolean\n): Promise<[string, Record<string, any> | undefined]> {\n if (descriptor.script || descriptor.scriptSetup) {\n\n const expressionPlugins: CompilerOptions[\"expressionPlugins\"] = [];\n if (isTS) expressionPlugins.push('typescript');\n if (isJSX) expressionPlugins.push('jsx');\n\n const parserPlugins: SFCScriptCompileOptions[\"babelParserPlugins\"] = [];\n if (isJSX) parserPlugins.push(\"jsx\");\n if (isTS) parserPlugins.push(\"typescript\");\n\n const compiledScript = compileScript(descriptor, {\n id,\n isProd: false,\n inlineTemplate: false,\n genDefaultAs: COMP_IDENTIFIER,\n babelParserPlugins: parserPlugins,\n templateOptions: {\n ssrCssVars: descriptor.cssVars,\n compilerOptions: {\n expressionPlugins,\n },\n },\n });\n\n let source = compiledScript.content;\n return [source, compiledScript.bindings];\n } else {\n // @ts-expect-error\n const vaporFlag = descriptor.vapor ? '__vapor: true' : '';\n return [`\\nconst ${COMP_IDENTIFIER} = { ${vaporFlag} }`, undefined];\n }\n}\n\nasync function doCompileTemplate(\n descriptor: SFCDescriptor,\n id: string,\n bindingMetadata: BindingMetadata | undefined,\n isTS: boolean,\n isJSX: boolean,\n) {\n const expressionPlugins: CompilerOptions['expressionPlugins'] = []\n if (isTS) {\n expressionPlugins.push('typescript')\n }\n if (isJSX) {\n expressionPlugins.push('jsx')\n }\n\n let { code, errors } = compileTemplate({\n id,\n isProd: false,\n // @ts-expect-error\n vapor: descriptor.vapor,\n ast: descriptor.template!.ast,\n source: descriptor.template!.content,\n filename: descriptor.filename,\n scoped: descriptor.styles.some((s) => s.scoped),\n slotted: descriptor.slotted,\n ssrCssVars: descriptor.cssVars,\n compilerOptions: {\n bindingMetadata,\n expressionPlugins,\n },\n })\n if (errors.length) {\n return errors\n }\n\n const fnName = `render`\n code =\n `\\n${code.replace(\n /\\nexport (function|const) (render|ssrRender)/,\n `$1 ${fnName}`,\n )}` + `\\n${COMP_IDENTIFIER}.${fnName} = ${fnName}`\n\n return code\n}\n\nfunction extractAndRemoveImports(code: string): { code: string; imports: string[] } {\n const lines = code.split('\\n');\n const filteredLines: string[] = [];\n const importMap = new Map<string, { defaultImport?: string; namedImports: Set<string>; path: string }>();\n\n for (const line of lines) {\n const trimmedLine = line.trim();\n if (trimmedLine.startsWith('import ') && (trimmedLine.endsWith(';') || trimmedLine.endsWith('\"') || trimmedLine.endsWith(\"'\"))) {\n // Parse the import statement\n const importInfo = parseImportStatement(trimmedLine);\n if (importInfo) {\n const { path, defaultImport, namedImports } = importInfo;\n\n if (!importMap.has(path)) {\n importMap.set(path, { defaultImport, namedImports: new Set(namedImports), path });\n } else {\n // Merge with existing import\n const existing = importMap.get(path);\n if (existing) {\n if (defaultImport && !existing.defaultImport) {\n existing.defaultImport = defaultImport;\n }\n namedImports.forEach(name => existing.namedImports.add(name));\n }\n }\n }\n } else {\n filteredLines.push(line);\n }\n }\n\n // Convert import map back to import statements\n const resolvedImports: string[] = [];\n for (const [path, importInfo] of importMap) {\n const { defaultImport, namedImports } = importInfo;\n const namedImportsArray = Array.from(namedImports);\n\n if (defaultImport && namedImportsArray.length > 0) {\n // Both default and named imports\n resolvedImports.push(`import ${defaultImport}, { ${namedImportsArray.join(', ')} } from '${path}';`);\n } else if (defaultImport) {\n // Only default import\n resolvedImports.push(`import ${defaultImport} from '${path}';`);\n } else if (namedImportsArray.length > 0) {\n // Only named imports\n resolvedImports.push(`import { ${namedImportsArray.join(', ')} } from '${path}';`);\n }\n }\n\n const filteredCode = filteredLines.join('\\n');\n\n const codeWithoutExports = filteredCode\n .replace(/^export\\s+default\\s+__bz__;/gm, '')\n .replace(/^export\\s+\\{[^}]+\\};?/gm, '')\n .replace(/^export\\s+default[^;]+;/gm, '')\n .replace(/^export\\s+\\w+\\s+\\w+[^;]*;/gm, '');\n\n return { code: codeWithoutExports, imports: resolvedImports };\n}\n\n// Helper function to parse import statements\nfunction parseImportStatement(importLine: string): { path: string; defaultImport?: string; namedImports: string[] } | null {\n // Remove semicolon if present\n const cleanLine = importLine.replace(/;$/, '');\n\n // Pattern 1: import defaultExport from 'module'\n const defaultImportPattern = /^import\\s+(\\w+)\\s+from\\s+['\"]([^'\"]+)['\"]$/;\n const defaultMatch = cleanLine.match(defaultImportPattern);\n if (defaultMatch && defaultMatch[1] && defaultMatch[2]) {\n return {\n path: defaultMatch[2],\n defaultImport: defaultMatch[1],\n namedImports: []\n };\n }\n\n // Pattern 2: import { named1, named2 } from 'module'\n const namedImportPattern = /^import\\s+\\{\\s*([^}]+)\\s*\\}\\s+from\\s+['\"]([^'\"]+)['\"]$/;\n const namedMatch = cleanLine.match(namedImportPattern);\n if (namedMatch && namedMatch[1] && namedMatch[2]) {\n const namedImports = namedMatch[1].split(',').map(name => name.trim());\n return {\n path: namedMatch[2],\n namedImports\n };\n }\n\n // Pattern 3: import defaultExport, { named1, named2 } from 'module'\n const combinedPattern = /^import\\s+(\\w+)\\s*,\\s*\\{\\s*([^}]+)\\s*\\}\\s+from\\s+['\"]([^'\"]+)['\"]$/;\n const combinedMatch = cleanLine.match(combinedPattern);\n if (combinedMatch && combinedMatch[1] && combinedMatch[2] && combinedMatch[3]) {\n const namedImports = combinedMatch[2].split(',').map(name => name.trim());\n return {\n path: combinedMatch[3],\n defaultImport: combinedMatch[1],\n namedImports\n };\n }\n\n // Pattern 4: import * as namespace from 'module'\n const namespacePattern = /^import\\s+\\*\\s+as\\s+(\\w+)\\s+from\\s+['\"]([^'\"]+)['\"]$/;\n const namespaceMatch = cleanLine.match(namespacePattern);\n if (namespaceMatch && namespaceMatch[1] && namespaceMatch[2]) {\n return {\n path: namespaceMatch[2],\n defaultImport: namespaceMatch[1],\n namedImports: []\n };\n }\n\n return null;\n}\n\n// Function to bundle all components into a single script\nasync function bundleComponents(\n mainComponent: { scriptSource: string; styleSource: string; dependencies: Map<string, any> },\n componentName: string,\n isTS: boolean = false,\n isJSX: boolean = false\n): Promise<{ scriptSource: string; styleSource: string }> {\n let allImports = new Set<string>();\n let bundledScript = '';\n let bundledStyle = mainComponent.styleSource;\n\n const allDependencies = new Map<string, { scriptSource: string; styleSource: string; componentName: string }>();\n\n const collectAllDependencies = (deps: Map<string, any>) => {\n for (const [importName, dep] of deps) {\n if (!allDependencies.has(dep.componentName)) {\n allDependencies.set(dep.componentName, {\n scriptSource: dep.scriptSource,\n styleSource: dep.styleSource,\n componentName: dep.componentName,\n });\n\n if (dep.dependencies && dep.dependencies.size > 0) {\n collectAllDependencies(dep.dependencies);\n }\n }\n }\n };\n\n collectAllDependencies(mainComponent.dependencies);\n\n\n // Add all dependencies\n for (const [depName, dep] of allDependencies) {\n const depComponentName = `${componentName}_${dep.componentName}`;\n bundledScript += `// Component: ${dep.componentName}\\n`;\n bundledScript += `const ${depComponentName} = (function() {\\n`;\n bundledScript += dep.scriptSource;\n bundledScript += `\\nreturn __bz__;`;\n bundledScript += `\\n})();\\n`;\n bundledStyle += dep.styleSource;\n }\n\n // Add main component with import replacements\n bundledScript += `\\n// Main Component: ${componentName}\\n`;\n bundledScript += mainComponent.scriptSource;\n\n // Replace relative imports with bundled component references\n for (const [importName, dep] of allDependencies) {\n const depComponentName = `${componentName}_${dep.componentName}`;\n\n const importPattern = new RegExp(`import\\\\s*\\\\{\\\\s*${importName}\\\\s*\\\\}\\\\s*from\\\\s*['\"][^'\"]*\\\\.vue['\"]\\\\s*;?`, 'g');\n bundledScript = bundledScript.replace(importPattern, `const { ${importName} } = ${depComponentName}`);\n\n const defaultImportPattern = new RegExp(`import\\\\s+${importName}\\\\s+from\\\\s*['\"][^'\"]*\\\\.vue['\"]\\\\s*;?`, 'g');\n bundledScript = bundledScript.replace(defaultImportPattern, `const ${importName} = ${depComponentName}`);\n }\n\n let { code: finalScript, imports: finalImports } = extractAndRemoveImports(bundledScript);\n finalImports.forEach(i => allImports.add(i));\n\n finalScript = Array.from(allImports).join('\\n') + '\\n' + finalScript;\n\n const transformedScript = await transformJS(finalScript, `${componentName}.js`, isTS, isJSX);\n\n return { scriptSource: transformedScript, styleSource: bundledStyle };\n}\n\n// Function to process a component and its dependencies\nasync function processComponent(vueFilePath: string, processedComponents: Set<string> = new Set(), isMain: boolean = false): Promise<{\n scriptSource: string;\n styleSource: string;\n dependencies: Map<string, { scriptSource: string; styleSource: string; componentName: string; dependencies: Map<string, any> }>;\n}> {\n const componentPath = path.resolve(vueFilePath);\n\n if (processedComponents.has(componentPath)) {\n return { scriptSource: '', styleSource: '', dependencies: new Map() };\n }\n\n processedComponents.add(componentPath);\n\n const fileContent = readFileSync(vueFilePath, 'utf-8');\n const fileName = path.basename(vueFilePath);\n const baseDir = path.dirname(vueFilePath);\n\n const { descriptor } = parse(fileContent, {\n filename: fileName,\n sourceMap: true,\n });\n\n const scriptLang = descriptor.script?.lang || descriptor.scriptSetup?.lang;\n const isTS = !!(scriptLang && /(\\.|\\b)tsx?$/.test(scriptLang));\n const isJSX = !!(scriptLang && /(\\.|\\b)tsx?$/.test(scriptLang));\n\n if (scriptLang && scriptLang !== 'js' && !isTS && !isJSX) {\n console.error(chalk.red(`❌ Unsupported lang \"${scriptLang}\" in <script> blocks.`));\n throw new Error(`Unsupported lang \"${scriptLang}\" in <script> blocks.`);\n }\n\n // Extract imports from script content\n const scriptContent = descriptor.script?.content || descriptor.scriptSetup?.content || '';\n const imports = extractImports(scriptContent);\n\n // Process dependencies\n const dependencies = new Map<string, { scriptSource: string; styleSource: string; componentName: string; dependencies: Map<string, any> }>();\n\n for (const importInfo of imports) {\n const resolvedPath = resolveImportPath(importInfo.path, baseDir);\n if (resolvedPath && resolvedPath.endsWith('.vue')) {\n try {\n const depResult = await processComponent(resolvedPath, processedComponents);\n const componentName = path.basename(resolvedPath, '.vue');\n dependencies.set(importInfo.name, {\n scriptSource: depResult.scriptSource,\n styleSource: depResult.styleSource,\n componentName,\n dependencies: depResult.dependencies\n });\n console.log(chalk.gray(` ✅ Dependency processed: ${componentName}`));\n } catch (error) {\n console.warn(chalk.yellow(` ⚠️ Failed to process dependency ${importInfo.path}:`), error);\n }\n }\n }\n\n let combineScript = \"\"\n const id = hash(fileName) + Date.now().toString().slice(0, 1);\n const hasScoped = descriptor.styles.some((s) => s.scoped)\n\n const [script, bindings] = await doCompileScript(descriptor, id, isTS, isJSX);\n combineScript += script;\n\n if (descriptor.template) {\n const clientTemplateResult = await doCompileTemplate(\n descriptor,\n id,\n bindings,\n isTS,\n isJSX,\n )\n if (Array.isArray(clientTemplateResult)) {\n throw new Error(`Template compilation failed: ${clientTemplateResult}`);\n }\n combineScript += `;${clientTemplateResult}`\n }\n\n if (hasScoped) {\n combineScript += `;\\n${COMP_IDENTIFIER}.__scopeId = ${JSON.stringify(`data-v-${id}`)}`\n }\n combineScript +=\n `\\n${COMP_IDENTIFIER}.__file = ${JSON.stringify(fileName)}`\n\n if (isMain) {\n combineScript += `\\nexport default ${COMP_IDENTIFIER}`\n }\n\n let combineStyle = ''\n for (const style of descriptor.styles) {\n if (style.module) {\n console.error(chalk.red(`❌ <style module> is not supported.`));\n throw new Error(`<style module> is not supported.`);\n }\n if (!style.scoped) {\n console.error(chalk.red(`❌ Only support <style scoped>.`));\n throw new Error(`Only support <style scoped>.`);\n }\n\n const styleResult = await compileStyleAsync({\n id,\n source: style.content,\n filename: fileName,\n scoped: style.scoped,\n preprocessLang: style.lang == 'scss' ? 'scss' : undefined,\n modules: false,\n });\n if (styleResult.errors.length) {\n console.error(chalk.red(`❌ Build style error.`));\n console.error(styleResult.errors);\n throw new Error(`Build style error: ${styleResult.errors}`);\n } else {\n combineStyle += styleResult.code + '\\n'\n }\n }\n\n // Don't transform the script here - we'll do it after bundling\n const transformStyle = (() => {\n if (combineStyle) {\n const cleanCss = new LeanCss({}).minify(combineStyle);\n if (cleanCss.errors.length) {\n console.error(chalk.red('❌ CleanCSS errors:'), cleanCss.errors);\n return '';\n }\n return cleanCss.styles;\n }\n return '';\n })();\n\n return {\n scriptSource: combineScript, // Return untransformed script\n styleSource: transformStyle,\n dependencies\n };\n}","import fs from 'fs/promises'\nimport path from 'path'\nimport chalk from 'chalk'\nimport { apiRequest, loadYaml, saveYaml, loadFileContent, saveFileContent, filterEmptyFields } from '../helpers/index.js'\nimport type { ArtechContext } from '../helpers/context.js'\n\n// Form field mapping for config vs data separation\nconst FORM_FIELD_MAPPING = {\n config: ['scopedID', 'name', 'type', 'emailSetting', 'ticketRegistrationSetting', 'ticketRSVPSetting', 'subscriptionSetting', 'checkoutSetting', 'contactSetting', 'authSetting', 'formFields'],\n data: ['scopedID', 'name', 'type', 'isClosed', 'emailSetting', 'ticketRegistrationSetting', 'ticketRSVPSetting', 'subscriptionSetting', 'checkoutSetting', 'contactSetting', 'authSetting', 'formFields']\n}\n\n\nexport async function deployForms(context: ArtechContext, options: { \n target?: string\n dryRun?: boolean\n prune?: boolean\n}) {\n const siteSpecPath = context.paths.siteSpec\n const siteDataPath = context.paths.siteData\n\n console.log(chalk.blue('📝 Deploying forms from site config...'))\n if (options.dryRun) {\n console.log(chalk.yellow('⚠️ DRY RUN MODE: No changes will be applied'))\n }\n\n const siteSpec = await loadYaml(siteSpecPath)\n const siteData = await loadYaml(siteDataPath)\n const forms = siteSpec.forms || []\n\n if (forms.length === 0) {\n console.log(chalk.gray(' No forms found in config'))\n return\n }\n\n // Resolve Site Info from Context\n const siteSlug = context.target.site?.slug\n if (!siteSlug) {\n throw new Error(`Site slug not found for target: ${context.target.name}`)\n }\n\n console.log(chalk.blue('🔍 Verifying site context...'))\n const sitesResponse = await apiRequest(context, 'GET', `/site?slug=${siteSlug}`, undefined)\n if (!sitesResponse.items || sitesResponse.items.length === 0) {\n throw new Error(`Site with slug \"${siteSlug}\" not found`)\n }\n const site = sitesResponse.items[0]\n const siteScopedID = site.scopedID\n\n console.log(chalk.gray(` Target: ${context.target.name}`))\n console.log(chalk.gray(` Found ${forms.length} forms to deploy`))\n console.log(chalk.gray(` Site scoped ID: ${siteScopedID}`))\n\n // Get all remote forms for this site\n console.log(chalk.blue('🔍 Fetching remote forms...'))\n const remoteFormsResponse = await apiRequest(context, 'GET', `/form?siteScopedID=${siteScopedID}&pageSize=1000`, undefined)\n const remoteForms = remoteFormsResponse.items || []\n console.log(chalk.gray(` Found ${remoteForms.length} existing forms`))\n\n const usedFormScopedIDs = new Set<string>()\n\n for (const formConfig of forms) {\n usedFormScopedIDs.add(formConfig.scopedID)\n try {\n console.log(chalk.blue(` Deploying form: ${formConfig.name}`))\n\n // Find existing form by scopedID\n const existingForm = remoteForms.find((form: any) => form.scopedID === formConfig.scopedID)\n \n // Find form data by scopedID\n const formData = siteData.forms?.find((form: any) => form.scopedID === formConfig.scopedID)\n \n if (existingForm) {\n // Update existing form with merged data (config > data > remote)\n const mergedFormData = mergeFormData(existingForm, formData || {}, formConfig)\n \n // Load email file fields from config\n const formWithFiles = await loadEmailFileFields(mergedFormData)\n \n const formUpdateData = {\n ...formWithFiles,\n siteScopedID: siteScopedID\n }\n if (!options.dryRun) {\n await apiRequest(context, 'PUT', `/form`, formUpdateData)\n }\n console.log(chalk.gray(` ✅ Updated form: ${formConfig.name}`))\n } else {\n // Create new form with merged data and default settings\n const mergedFormData = mergeFormData({}, formData || {}, formConfig)\n \n // Load email file fields from config\n const formWithFiles = await loadEmailFileFields(mergedFormData)\n \n const formCreateData = {\n ...formWithFiles,\n siteScopedID: siteScopedID,\n emailSetting: {\n senderName: 'Breezing',\n replyToEmail: 'noreply@breezing.in',\n successEmailEnabled: false,\n customSuccessEmail: false,\n successEmailSubject: '',\n successEmailBody: '',\n customInviteEmail: false,\n inviteEmailSubject: '',\n inviteEmailBody: '',\n ...formWithFiles.emailSetting // Merge with any existing email settings\n }\n }\n \n \n if (!options.dryRun) {\n await apiRequest(context, 'POST', `/form`, formCreateData)\n }\n console.log(chalk.green(` ✅ Created form: ${formConfig.name}`))\n }\n } catch (error: any) {\n console.error(chalk.red(` ❌ Failed to deploy form ${formConfig.name}:`), error.message)\n }\n }\n\n // Prune unused forms\n if (remoteForms.length > 0) {\n const unusedForms = remoteForms.filter((remoteForm: any) => !usedFormScopedIDs.has(remoteForm.scopedID))\n \n if (unusedForms.length > 0) {\n console.log(chalk.yellow(`⚠️ Found ${unusedForms.length} unused remote forms.`))\n \n if (options.prune) {\n console.log(chalk.yellow(` Marking for deletion/pruning...`))\n for (const unusedForm of unusedForms) {\n console.log(chalk.yellow(` - ${unusedForm.name} (${unusedForm.scopedID})`))\n if (!options.dryRun) {\n try {\n await apiRequest(context, 'DELETE', `/form/${unusedForm.id}`, undefined)\n console.log(chalk.green(` ✅ Deleted form ${unusedForm.name}`))\n } catch (e: any) {\n console.error(chalk.red(` ❌ Failed to delete form ${unusedForm.name}:`), e.message)\n }\n }\n }\n } else {\n console.log(chalk.gray(` Use --prune to delete these forms.`))\n }\n }\n }\n\n console.log(chalk.green('🎉 All forms deployed successfully!'))\n}\n\nexport async function pullForms(context: ArtechContext, options: { \n target?: string \n}) {\n const siteSpecPath = context.paths.siteSpec\n\n console.log(chalk.blue('⬇️ Pulling forms...'))\n\n // Resolve Site Info from Context\n const siteSlug = context.target.site?.slug\n if (!siteSlug) {\n throw new Error(`Site slug not found for target: ${context.target.name}`)\n }\n\n console.log(chalk.blue('🔍 Resolving site context...'))\n const sitesResponse = await apiRequest(context, 'GET', `/site?slug=${siteSlug}`, undefined)\n if (!sitesResponse.items || sitesResponse.items.length === 0) {\n throw new Error(`Site with slug \"${siteSlug}\" not found`)\n }\n const site = sitesResponse.items[0]\n const siteScopedID = site.scopedID\n const siteId = site.id\n\n console.log(chalk.gray(`Target: ${context.target.name}`))\n console.log(chalk.gray(`Site slug: ${siteSlug}`))\n console.log(chalk.gray(`Site scoped ID: ${siteScopedID}`))\n\n console.log(chalk.blue('🔍 Fetching remote forms...'))\n const remoteFormsResponse = await apiRequest(context, 'GET', `/form?siteScopedID=${siteScopedID}&pageSize=1000`, undefined)\n const remoteForms = remoteFormsResponse.items || []\n\n console.log(chalk.gray(` Found ${remoteForms.length} forms`))\n\n console.log(chalk.blue('📝 Updating site-spec.yml...'))\n const siteSpec = await loadYaml(siteSpecPath)\n \n // Update forms in spec (merge with existing)\n const existingForms = siteSpec.forms || []\n const newForms = []\n for (const form of remoteForms) {\n // Check if form exists in config to preserve extra props?\n // The original logic just mapped fields.\n const existingConfig = existingForms.find((f: any) => f.scopedID === form.scopedID)\n \n // Config only fields\n let formConfig: any = {\n name: form.name,\n scopedID: form.scopedID,\n tags: form.tags,\n // Preserve existing specific props\n ...existingConfig\n }\n \n // Map remote fields to config\n FORM_FIELD_MAPPING.config.forEach(field => {\n if (form[field] !== undefined) {\n formConfig[field] = form[field]\n }\n })\n\n // Save email file fields\n formConfig = await saveEmailFileFields(formConfig, existingConfig)\n \n // Filter empty fields\n const filteredConfig = filterEmptyFields(formConfig)\n\n newForms.push(filteredConfig)\n }\n \n siteSpec.forms = newForms\n await saveYaml(siteSpecPath, siteSpec, { flowLevel: 6 })\n \n console.log(chalk.green('✅ site-spec.yml updated with forms'))\n console.log(chalk.green('🎉 Pull forms completed successfully!'))\n}\n\nfunction filterFields(obj: any, allowedFields: string[]): any {\n const filtered: any = {}\n for (const field of allowedFields) {\n if (obj.hasOwnProperty(field)) {\n filtered[field] = obj[field]\n }\n }\n return filtered\n}\n\n\n\n/**\n * Handle email file fields that start with \"file:\" or \"~~/\" - load content from files\n */\nasync function loadEmailFileFields(form: any): Promise<any> {\n const updatedForm = { ...form }\n \n if (updatedForm.emailSetting) {\n // Find all fields that end with \"EmailBody\"\n const emailFields = Object.keys(updatedForm.emailSetting).filter(field => \n field.endsWith('EmailBody')\n )\n \n for (const field of emailFields) {\n if (updatedForm.emailSetting[field]) {\n updatedForm.emailSetting[field] = await loadFileContent(updatedForm.emailSetting[field])\n }\n }\n }\n \n return updatedForm\n}\n\n/**\n * Handle email file fields that start with \"file:\" or \"~~/\" - save content to files\n */\nasync function saveEmailFileFields(form: any, originalForm: any): Promise<any> {\n const updatedForm = { ...form }\n \n if (updatedForm.emailSetting && originalForm?.emailSetting) {\n // Find all fields that end with \"EmailBody\"\n const emailFields = Object.keys(originalForm.emailSetting).filter(field => \n field.endsWith('EmailBody')\n )\n \n for (const field of emailFields) {\n const originalField = originalForm.emailSetting[field]\n if (originalField && (originalField.startsWith('file:') || originalField.startsWith('~~/'))) {\n // Save content to file\n await saveFileContent(updatedForm.emailSetting[field], originalField)\n // Revert field in form object to file reference\n updatedForm.emailSetting[field] = originalField\n }\n }\n }\n \n return updatedForm\n}\n\n/**\n * Merge form data with proper priority logic\n * Priority: config > data > remote\n * Preserved props from remote are always kept\n */\nfunction mergeFormData(remoteForm: any, dataForm: any, configForm: any): any {\n // Merge with priority: config > data > remote\n const merged = { ...remoteForm, ...dataForm, ...configForm }\n\n // Preserve important fields from remote form\n const PRESERVED_FIELDS = ['id', 'workspaceID', 'createTime', 'updateTime']\n PRESERVED_FIELDS.forEach(field => {\n if (remoteForm[field] !== undefined) {\n merged[field] = remoteForm[field]\n }\n })\n\n return merged\n}"],"mappings":"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","names":["Command","chalk","env","fs","path","yaml","chalk","axios","chalk","apiRequest","context","method","endpoint","data","baseUrl","token","error","fs","yaml","loadYaml","filePath","content","error","saveYaml","data","options","orderedData","yamlContent","fs","path","yaml","dotenv","chalk","loadContext","options","cwd","configPath","envPath","config","content","error","targetName","targetConfig","siteSpecPath","siteDataPath","api","token","siteSlug","apiVal","envVar","tokenVal","fs","path","chalk","loadFileContent","content","cwd","cleanPath","filePath","saveFileContent","targetPath","filterEmptyFields","obj","v","result","key","value","filtered","PRESERVED_PROPS","getWorkingDir","path","loadConfig","filePath","content","fs","config","yaml","loadFileContent","page","pageWidgetScopedIDs","w","widget","error","FIELD_MAPPING","filterFields","obj","allowedFields","filtered","field","isOmitEmpty","actualFieldName","parseProps","props","mergeWidgetProps","remoteProps","dataProps","configProps","remote","data","merged","prop","getDefaultPropsForNewWidget","context","widgetConfig","widgetType","apiRequest","chalk","defaultProps","extractConfig","remoteSite","currentConfig","widgets","widgetUsageCount","page","id","commonWidgets","widget","filterFields","FIELD_MAPPING","pagesWithWidgets","pageData","pageWidgetList","w","styleBody","originalStylePath","styleFilePath","chalk","saveFileContent","getWorkingDir","extractData","apiSite","existingData","filteredWidget","error","initSite","options","cwd","path","files","filename","content","filePath","dir","fs","saveYaml","envExamplePath","envContent","pullSite","context","siteSpecPath","siteDataPath","currentSpec","loadYaml","siteSlug","sitesResponse","apiRequest","siteId","foundSite","remoteWidgets","layoutSpec","a","b","positionA","positionB","currentData","completeData","deploySite","mode","siteSpec","loadConfig","siteData","siteID","localUpdateTime","remoteUpdateTime","updateSite","updatePages","pageConfig","index","p","updateWidgets","widgetConfig","widgetData","remoteWidget","updateWidget","mergeWidgetProps","getDefaultPropsForNewWidget","usedPageScopedIDs","unusedPages","remotePage","currentTime","unusedPage","existingPage","pageUpdateData","pageCreateData","usedWidgetScopedIDs","scopedID","unusedRemoteWidgets","unusedWidget","widgetsToDelete","widgetUpdates","isUsed","unusedWidgets","usedCount","finalWidgetUpdates","deleteTime","rest","readFileSync","existsSync","readdirSync","path","parse","compileScript","compileTemplate","compileStyleAsync","hash","LeanCss","chalk","createRequire","babelPluginTransformModulesCommonjs","babel_transformFromAstAsync","t","traverse","babel_parse","babelPlugin_jsx","babelPlugin_typescript","require","COMP_IDENTIFIER","IMPORT_IDENTIFIER","devMode","listWidgetTypes","context","options","searchDir","chalk","widgetTypes","findAllWidgetTypes","wt","relPath","loadTsFile","filePath","source","readFileSync","ast","code","module","fileRequire","deployWidgetType","fileName","widgetFiles","findWidgetFiles","tsFile","vueFile","widgetDir","componentResult","processComponent","fileContent","descriptor","parse","scriptLang","isTS","isJSX","bundledResult","bundleComponents","widgetType","response","apiRequest","data","method","originWidgetType","deployWidgetTypes","w","filtered","error","searchDirectory","existsSync","items","readdirSync","item","fullPath","name","widgetName","result","ext","extractImports","scriptContent","imports","importRegex","match","defaultImport","namedImports1","namedImports2","importPath","namedImports","resolveImportPath","baseDir","resolvedPath","extensions","transformJS","filename","isTs","isJsx","plugins","path","ex","additionalBabelPlugins","pluginList","transformedScript","msg","doCompileScript","id","expressionPlugins","parserPlugins","compiledScript","compileScript","vaporFlag","doCompileTemplate","bindingMetadata","errors","compileTemplate","s","fnName","extractAndRemoveImports","lines","filteredLines","importMap","line","trimmedLine","importInfo","parseImportStatement","existing","resolvedImports","namedImportsArray","importLine","cleanLine","defaultImportPattern","defaultMatch","namedImportPattern","namedMatch","combinedPattern","combinedMatch","namespacePattern","namespaceMatch","mainComponent","componentName","allImports","bundledScript","bundledStyle","allDependencies","collectAllDependencies","deps","importName","dep","depName","depComponentName","importPattern","finalScript","finalImports","i","vueFilePath","processedComponents","isMain","componentPath","dependencies","depResult","combineScript","hash","hasScoped","script","bindings","clientTemplateResult","combineStyle","style","styleResult","compileStyleAsync","transformStyle","cleanCss","LeanCss","chalk","FORM_FIELD_MAPPING","deployForms","context","options","siteSpecPath","siteDataPath","chalk","siteSpec","loadYaml","siteData","forms","siteSlug","sitesResponse","apiRequest","siteScopedID","remoteForms","usedFormScopedIDs","formConfig","existingForm","form","formData","mergedFormData","mergeFormData","formUpdateData","loadEmailFileFields","formWithFiles","formCreateData","error","unusedForms","remoteForm","unusedForm","e","pullForms","site","siteId","existingForms","newForms","existingConfig","f","field","saveEmailFileFields","filteredConfig","filterEmptyFields","saveYaml","loadEmailFileFields","form","updatedForm","emailFields","field","loadFileContent","saveEmailFileFields","originalForm","originalField","saveFileContent","mergeFormData","remoteForm","dataForm","configForm","merged","env","program","Command","siteFn","options","context","loadContext","pullSite","error","chalk","deploySite","initSite","formFn","pullForms","deployForms","widgetFn","deployWidgetType","widgetTypeFn","listWidgetTypes","deployWidgetTypes"]}
package/package.json ADDED
@@ -0,0 +1,57 @@
1
+ {
2
+ "name": "@artech-global/cli",
3
+ "version": "1.0.1",
4
+ "description": "CLI tool for Artech platform",
5
+ "bin": {
6
+ "artech": "./dist/index.js"
7
+ },
8
+ "scripts": {
9
+ "build": "tsup",
10
+ "dev": "tsup --watch",
11
+ "start": "node dist/index.js",
12
+ "lint": "eslint src/**/*.ts"
13
+ },
14
+ "files": [
15
+ "dist",
16
+ "README.md"
17
+ ],
18
+ "keywords": [
19
+ "cli",
20
+ "artech"
21
+ ],
22
+ "author": "",
23
+ "license": "MIT",
24
+ "dependencies": {
25
+ "babel-helper-vue-jsx-merge-props": "^2.0.3",
26
+ "babel-plugin-syntax-jsx": "^6.18.0",
27
+ "babel-plugin-transform-vue-jsx": "^3.7.0",
28
+ "babel-preset-env": "^1.7.0",
29
+ "babel-preset-minify": "^0.5.2",
30
+ "@babel/core": "^7.28.5",
31
+ "@babel/parser": "^7.28.5",
32
+ "@babel/plugin-transform-modules-commonjs": "^7.27.1",
33
+ "@babel/plugin-transform-typescript": "^7.28.5",
34
+ "@clack/prompts": "^0.7.0",
35
+ "@types/babel__core": "^7.20.5",
36
+ "@types/clean-css": "^4.2.11",
37
+ "@types/hash-sum": "^1.0.2",
38
+ "@types/js-yaml": "^4.0.9",
39
+ "@vue/babel-plugin-jsx": "^2.0.1",
40
+ "@vue/compiler-sfc": "^3.5.26",
41
+ "axios": "^1.13.2",
42
+ "chalk": "^5.3.0",
43
+ "clean-css": "^5.3.3",
44
+ "commander": "^11.1.0",
45
+ "dotenv": "^16.4.1",
46
+ "hash-sum": "^2.0.0",
47
+ "js-yaml": "^4.1.1",
48
+ "sass": "^1.97.2",
49
+ "typescript": "^5.3.3"
50
+ },
51
+ "devDependencies": {
52
+ "@types/node": "^20.11.16",
53
+ "tsup": "^8.0.1",
54
+ "@artech-global/types": "^1.0.1"
55
+ },
56
+ "type": "module"
57
+ }