@lahat-group/cli 2.1.3 → 2.1.5
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/dist/index.js +49 -48
- package/package.json +2 -1
- package/skill/SKILL.md +121 -115
- package/skill/staff.md +59 -0
package/dist/index.js
CHANGED
|
@@ -1,90 +1,91 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import { createRequire as __cr } from 'module'; const require = __cr(import.meta.url);
|
|
3
|
-
var
|
|
4
|
-
`).replace(/^/gm," ".repeat(o))}let l=[`Usage: ${t.commandUsage(e)}`,""],d=t.commandDescription(e);d.length>0&&(l=l.concat([t.wrap(d,i,0),""]));let f=t.visibleArguments(e).map(y=>c(t.argumentTerm(y),t.argumentDescription(y)));f.length>0&&(l=l.concat(["Arguments:",a(f),""]));let v=t.visibleOptions(e).map(y=>c(t.optionTerm(y),t.optionDescription(y)));if(v.length>0&&(l=l.concat(["Options:",a(v),""])),this.showGlobalOptions){let y=t.visibleGlobalOptions(e).map(
|
|
3
|
+
var cn=Object.create;var Ie=Object.defineProperty;var un=Object.getOwnPropertyDescriptor;var ln=Object.getOwnPropertyNames;var dn=Object.getPrototypeOf,hn=Object.prototype.hasOwnProperty;var V=(r=>typeof require<"u"?require:typeof Proxy<"u"?new Proxy(r,{get:(e,t)=>(typeof require<"u"?require:e)[t]}):r)(function(r){if(typeof require<"u")return require.apply(this,arguments);throw Error('Dynamic require of "'+r+'" is not supported')});var mn=(r,e)=>()=>(r&&(e=r(r=0)),e);var R=(r,e)=>()=>(e||r((e={exports:{}}).exports,e),e.exports);var pn=(r,e,t,n)=>{if(e&&typeof e=="object"||typeof e=="function")for(let i of ln(e))!hn.call(r,i)&&i!==t&&Ie(r,i,{get:()=>e[i],enumerable:!(n=un(e,i))||n.enumerable});return r};var fn=(r,e,t)=>(t=r!=null?cn(dn(r)):{},pn(e||!r||!r.__esModule?Ie(t,"default",{value:r,enumerable:!0}):t,r));import gr from"path";import{fileURLToPath as yr}from"url";var u=mn(()=>{"use strict"});var F=R(ie=>{"use strict";u();var J=class extends Error{constructor(e,t,n){super(n),Error.captureStackTrace(this,this.constructor),this.name=this.constructor.name,this.code=t,this.exitCode=e,this.nestedError=void 0}},re=class extends J{constructor(e){super(1,"commander.invalidArgument",e),Error.captureStackTrace(this,this.constructor),this.name=this.constructor.name}};ie.CommanderError=J;ie.InvalidArgumentError=re});var z=R(se=>{"use strict";u();var{InvalidArgumentError:gn}=F(),oe=class{constructor(e,t){switch(this.description=t||"",this.variadic=!1,this.parseArg=void 0,this.defaultValue=void 0,this.defaultValueDescription=void 0,this.argChoices=void 0,e[0]){case"<":this.required=!0,this._name=e.slice(1,-1);break;case"[":this.required=!1,this._name=e.slice(1,-1);break;default:this.required=!0,this._name=e;break}this._name.length>3&&this._name.slice(-3)==="..."&&(this.variadic=!0,this._name=this._name.slice(0,-3))}name(){return this._name}_concatValue(e,t){return t===this.defaultValue||!Array.isArray(t)?[e]:t.concat(e)}default(e,t){return this.defaultValue=e,this.defaultValueDescription=t,this}argParser(e){return this.parseArg=e,this}choices(e){return this.argChoices=e.slice(),this.parseArg=(t,n)=>{if(!this.argChoices.includes(t))throw new gn(`Allowed choices are ${this.argChoices.join(", ")}.`);return this.variadic?this._concatValue(t,n):t},this}argRequired(){return this.required=!0,this}argOptional(){return this.required=!1,this}};function bn(r){let e=r.name()+(r.variadic===!0?"...":"");return r.required?"<"+e+">":"["+e+"]"}se.Argument=oe;se.humanReadableArgName=bn});var ce=R(De=>{"use strict";u();var{humanReadableArgName:yn}=z(),ae=class{constructor(){this.helpWidth=void 0,this.sortSubcommands=!1,this.sortOptions=!1,this.showGlobalOptions=!1}visibleCommands(e){let t=e.commands.filter(i=>!i._hidden),n=e._getHelpCommand();return n&&!n._hidden&&t.push(n),this.sortSubcommands&&t.sort((i,o)=>i.name().localeCompare(o.name())),t}compareOptions(e,t){let n=i=>i.short?i.short.replace(/^-/,""):i.long.replace(/^--/,"");return n(e).localeCompare(n(t))}visibleOptions(e){let t=e.options.filter(i=>!i.hidden),n=e._getHelpOption();if(n&&!n.hidden){let i=n.short&&e._findOption(n.short),o=n.long&&e._findOption(n.long);!i&&!o?t.push(n):n.long&&!o?t.push(e.createOption(n.long,n.description)):n.short&&!i&&t.push(e.createOption(n.short,n.description))}return this.sortOptions&&t.sort(this.compareOptions),t}visibleGlobalOptions(e){if(!this.showGlobalOptions)return[];let t=[];for(let n=e.parent;n;n=n.parent){let i=n.options.filter(o=>!o.hidden);t.push(...i)}return this.sortOptions&&t.sort(this.compareOptions),t}visibleArguments(e){return e._argsDescription&&e.registeredArguments.forEach(t=>{t.description=t.description||e._argsDescription[t.name()]||""}),e.registeredArguments.find(t=>t.description)?e.registeredArguments:[]}subcommandTerm(e){let t=e.registeredArguments.map(n=>yn(n)).join(" ");return e._name+(e._aliases[0]?"|"+e._aliases[0]:"")+(e.options.length?" [options]":"")+(t?" "+t:"")}optionTerm(e){return e.flags}argumentTerm(e){return e.name()}longestSubcommandTermLength(e,t){return t.visibleCommands(e).reduce((n,i)=>Math.max(n,t.subcommandTerm(i).length),0)}longestOptionTermLength(e,t){return t.visibleOptions(e).reduce((n,i)=>Math.max(n,t.optionTerm(i).length),0)}longestGlobalOptionTermLength(e,t){return t.visibleGlobalOptions(e).reduce((n,i)=>Math.max(n,t.optionTerm(i).length),0)}longestArgumentTermLength(e,t){return t.visibleArguments(e).reduce((n,i)=>Math.max(n,t.argumentTerm(i).length),0)}commandUsage(e){let t=e._name;e._aliases[0]&&(t=t+"|"+e._aliases[0]);let n="";for(let i=e.parent;i;i=i.parent)n=i.name()+" "+n;return n+t+" "+e.usage()}commandDescription(e){return e.description()}subcommandDescription(e){return e.summary()||e.description()}optionDescription(e){let t=[];return e.argChoices&&t.push(`choices: ${e.argChoices.map(n=>JSON.stringify(n)).join(", ")}`),e.defaultValue!==void 0&&(e.required||e.optional||e.isBoolean()&&typeof e.defaultValue=="boolean")&&t.push(`default: ${e.defaultValueDescription||JSON.stringify(e.defaultValue)}`),e.presetArg!==void 0&&e.optional&&t.push(`preset: ${JSON.stringify(e.presetArg)}`),e.envVar!==void 0&&t.push(`env: ${e.envVar}`),t.length>0?`${e.description} (${t.join(", ")})`:e.description}argumentDescription(e){let t=[];if(e.argChoices&&t.push(`choices: ${e.argChoices.map(n=>JSON.stringify(n)).join(", ")}`),e.defaultValue!==void 0&&t.push(`default: ${e.defaultValueDescription||JSON.stringify(e.defaultValue)}`),t.length>0){let n=`(${t.join(", ")})`;return e.description?`${e.description} ${n}`:n}return e.description}formatHelp(e,t){let n=t.padWidth(e,t),i=t.helpWidth||80,o=2,s=2;function c(y,S){if(S){let ne=`${y.padEnd(n+s)}${S}`;return t.wrap(ne,i-o,n+s)}return y}function a(y){return y.join(`
|
|
4
|
+
`).replace(/^/gm," ".repeat(o))}let l=[`Usage: ${t.commandUsage(e)}`,""],d=t.commandDescription(e);d.length>0&&(l=l.concat([t.wrap(d,i,0),""]));let f=t.visibleArguments(e).map(y=>c(t.argumentTerm(y),t.argumentDescription(y)));f.length>0&&(l=l.concat(["Arguments:",a(f),""]));let v=t.visibleOptions(e).map(y=>c(t.optionTerm(y),t.optionDescription(y)));if(v.length>0&&(l=l.concat(["Options:",a(v),""])),this.showGlobalOptions){let y=t.visibleGlobalOptions(e).map(S=>c(t.optionTerm(S),t.optionDescription(S)));y.length>0&&(l=l.concat(["Global Options:",a(y),""]))}let k=t.visibleCommands(e).map(y=>c(t.subcommandTerm(y),t.subcommandDescription(y)));return k.length>0&&(l=l.concat(["Commands:",a(k),""])),l.join(`
|
|
5
5
|
`)}padWidth(e,t){return Math.max(t.longestOptionTermLength(e,t),t.longestGlobalOptionTermLength(e,t),t.longestSubcommandTermLength(e,t),t.longestArgumentTermLength(e,t))}wrap(e,t,n,i=40){let o=" \\f\\t\\v\xA0\u1680\u2000-\u200A\u202F\u205F\u3000\uFEFF",s=new RegExp(`[\\n][${o}]+`);if(e.match(s))return e;let c=t-n;if(c<i)return e;let a=e.slice(0,n),l=e.slice(n).replace(`\r
|
|
6
6
|
`,`
|
|
7
|
-
`),d=" ".repeat(n),v="\\s\u200B",
|
|
8
|
-
|.{1,${c-1}}([${v}]|$)|[^${v}]+?([${v}]|$)`,"g"),y=l.match(
|
|
9
|
-
`?"":(ne>0?d:"")+
|
|
10
|
-
`)}};
|
|
7
|
+
`),d=" ".repeat(n),v="\\s\u200B",k=new RegExp(`
|
|
8
|
+
|.{1,${c-1}}([${v}]|$)|[^${v}]+?([${v}]|$)`,"g"),y=l.match(k)||[];return a+y.map((S,ne)=>S===`
|
|
9
|
+
`?"":(ne>0?d:"")+S.trimEnd()).join(`
|
|
10
|
+
`)}};De.Help=ae});var he=R(de=>{"use strict";u();var{InvalidArgumentError:wn}=F(),ue=class{constructor(e,t){this.flags=e,this.description=t||"",this.required=e.includes("<"),this.optional=e.includes("["),this.variadic=/\w\.\.\.[>\]]$/.test(e),this.mandatory=!1;let n=jn(e);this.short=n.shortFlag,this.long=n.longFlag,this.negate=!1,this.long&&(this.negate=this.long.startsWith("--no-")),this.defaultValue=void 0,this.defaultValueDescription=void 0,this.presetArg=void 0,this.envVar=void 0,this.parseArg=void 0,this.hidden=!1,this.argChoices=void 0,this.conflictsWith=[],this.implied=void 0}default(e,t){return this.defaultValue=e,this.defaultValueDescription=t,this}preset(e){return this.presetArg=e,this}conflicts(e){return this.conflictsWith=this.conflictsWith.concat(e),this}implies(e){let t=e;return typeof e=="string"&&(t={[e]:!0}),this.implied=Object.assign(this.implied||{},t),this}env(e){return this.envVar=e,this}argParser(e){return this.parseArg=e,this}makeOptionMandatory(e=!0){return this.mandatory=!!e,this}hideHelp(e=!0){return this.hidden=!!e,this}_concatValue(e,t){return t===this.defaultValue||!Array.isArray(t)?[e]:t.concat(e)}choices(e){return this.argChoices=e.slice(),this.parseArg=(t,n)=>{if(!this.argChoices.includes(t))throw new wn(`Allowed choices are ${this.argChoices.join(", ")}.`);return this.variadic?this._concatValue(t,n):t},this}name(){return this.long?this.long.replace(/^--/,""):this.short.replace(/^-/,"")}attributeName(){return _n(this.name().replace(/^no-/,""))}is(e){return this.short===e||this.long===e}isBoolean(){return!this.required&&!this.optional&&!this.negate}},le=class{constructor(e){this.positiveOptions=new Map,this.negativeOptions=new Map,this.dualOptions=new Set,e.forEach(t=>{t.negate?this.negativeOptions.set(t.attributeName(),t):this.positiveOptions.set(t.attributeName(),t)}),this.negativeOptions.forEach((t,n)=>{this.positiveOptions.has(n)&&this.dualOptions.add(n)})}valueFromOption(e,t){let n=t.attributeName();if(!this.dualOptions.has(n))return!0;let i=this.negativeOptions.get(n).presetArg,o=i!==void 0?i:!1;return t.negate===(o===e)}};function _n(r){return r.split("-").reduce((e,t)=>e+t[0].toUpperCase()+t.slice(1))}function jn(r){let e,t,n=r.split(/[ |,]+/);return n.length>1&&!/^[[<]/.test(n[1])&&(e=n.shift()),t=n.shift(),!e&&/^-[^-]$/.test(t)&&(e=t,t=void 0),{shortFlag:e,longFlag:t}}de.Option=ue;de.DualOptions=le});var Ve=R(He=>{"use strict";u();function vn(r,e){if(Math.abs(r.length-e.length)>3)return Math.max(r.length,e.length);let t=[];for(let n=0;n<=r.length;n++)t[n]=[n];for(let n=0;n<=e.length;n++)t[0][n]=n;for(let n=1;n<=e.length;n++)for(let i=1;i<=r.length;i++){let o=1;r[i-1]===e[n-1]?o=0:o=1,t[i][n]=Math.min(t[i-1][n]+1,t[i][n-1]+1,t[i-1][n-1]+o),i>1&&n>1&&r[i-1]===e[n-2]&&r[i-2]===e[n-1]&&(t[i][n]=Math.min(t[i][n],t[i-2][n-2]+1))}return t[r.length][e.length]}function On(r,e){if(!e||e.length===0)return"";e=Array.from(new Set(e));let t=r.startsWith("--");t&&(r=r.slice(2),e=e.map(s=>s.slice(2)));let n=[],i=3,o=.4;return e.forEach(s=>{if(s.length<=1)return;let c=vn(r,s),a=Math.max(r.length,s.length);(a-c)/a>o&&(c<i?(i=c,n=[s]):c===i&&n.push(s))}),n.sort((s,c)=>s.localeCompare(c)),t&&(n=n.map(s=>`--${s}`)),n.length>1?`
|
|
11
11
|
(Did you mean one of ${n.join(", ")}?)`:n.length===1?`
|
|
12
|
-
(Did you mean ${n[0]}?)`:""}
|
|
13
|
-
- specify the name in Command constructor or using .name()`);return t=t||{},t.isDefault&&(this._defaultCommandName=e._name),(t.noHelp||t.hidden)&&(e._hidden=!0),this._registerCommand(e),e.parent=this,e._checkForBrokenPassThrough(),this}createArgument(e,t){return new
|
|
14
|
-
Expecting one of '${n.join("', '")}'`);return this._lifeCycleHooks[e]?this._lifeCycleHooks[e].push(t):this._lifeCycleHooks[e]=[t],this}exitOverride(e){return e?this._exitCallback=e:this._exitCallback=t=>{if(t.code!=="commander.executeSubCommandAsync")throw t},this}_exit(e,t,n){this._exitCallback&&this._exitCallback(new fe(e,t,n)),g.exit(e)}action(e){let t=n=>{let i=this.registeredArguments.length,o=n.slice(0,i);return this._storeOptionsAsProperties?o[i]=this:o[i]=this.opts(),o.push(this),e.apply(this,o)};return this._actionHandler=t,this}createOption(e,t){return new
|
|
15
|
-
- already used by option '${t.flags}'`)}this.options.push(e)}_registerCommand(e){let t=i=>[i.name()].concat(i.aliases()),n=t(e).find(i=>this._findCommand(i));if(n){let i=t(this._findCommand(n)).join("|"),o=t(e).join("|");throw new Error(`cannot add command '${o}' as already have command '${i}'`)}this.commands.push(e)}addOption(e){this._registerOption(e);let t=e.name(),n=e.attributeName();if(e.negate){let o=e.long.replace(/^--no-/,"--");this._findOption(o)||this.setOptionValueWithSource(n,e.defaultValue===void 0?!0:e.defaultValue,"default")}else e.defaultValue!==void 0&&this.setOptionValueWithSource(n,e.defaultValue,"default");let i=(o,s,c)=>{o==null&&e.presetArg!==void 0&&(o=e.presetArg);let a=this.getOptionValue(n);o!==null&&e.parseArg?o=this._callParseArg(e,o,a,s):o!==null&&e.variadic&&(o=e._concatValue(o,a)),o==null&&(e.negate?o=!1:e.isBoolean()||e.optional?o=!0:o=""),this.setOptionValueWithSource(n,o,c)};return this.on("option:"+t,o=>{let s=`error: option '${e.flags}' argument '${o}' is invalid.`;i(o,s,"cli")}),e.envVar&&this.on("optionEnv:"+t,o=>{let s=`error: option '${e.flags}' value '${o}' from env '${e.envVar}' is invalid.`;i(o,s,"env")}),this}_optionEx(e,t,n,i,o){if(typeof t=="object"&&t instanceof
|
|
12
|
+
(Did you mean ${n[0]}?)`:""}He.suggestSimilar=On});var Ue=R(Be=>{"use strict";u();var xn=V("events").EventEmitter,me=V("child_process"),$=V("path"),pe=V("fs"),g=V("process"),{Argument:$n,humanReadableArgName:Cn}=z(),{CommanderError:fe}=F(),{Help:An}=ce(),{Option:Fe,DualOptions:Sn}=he(),{suggestSimilar:Le}=Ve(),ge=class r extends xn{constructor(e){super(),this.commands=[],this.options=[],this.parent=null,this._allowUnknownOption=!1,this._allowExcessArguments=!0,this.registeredArguments=[],this._args=this.registeredArguments,this.args=[],this.rawArgs=[],this.processedArgs=[],this._scriptPath=null,this._name=e||"",this._optionValues={},this._optionValueSources={},this._storeOptionsAsProperties=!1,this._actionHandler=null,this._executableHandler=!1,this._executableFile=null,this._executableDir=null,this._defaultCommandName=null,this._exitCallback=null,this._aliases=[],this._combineFlagAndOptionalValue=!0,this._description="",this._summary="",this._argsDescription=void 0,this._enablePositionalOptions=!1,this._passThroughOptions=!1,this._lifeCycleHooks={},this._showHelpAfterError=!1,this._showSuggestionAfterError=!0,this._outputConfiguration={writeOut:t=>g.stdout.write(t),writeErr:t=>g.stderr.write(t),getOutHelpWidth:()=>g.stdout.isTTY?g.stdout.columns:void 0,getErrHelpWidth:()=>g.stderr.isTTY?g.stderr.columns:void 0,outputError:(t,n)=>n(t)},this._hidden=!1,this._helpOption=void 0,this._addImplicitHelpCommand=void 0,this._helpCommand=void 0,this._helpConfiguration={}}copyInheritedSettings(e){return this._outputConfiguration=e._outputConfiguration,this._helpOption=e._helpOption,this._helpCommand=e._helpCommand,this._helpConfiguration=e._helpConfiguration,this._exitCallback=e._exitCallback,this._storeOptionsAsProperties=e._storeOptionsAsProperties,this._combineFlagAndOptionalValue=e._combineFlagAndOptionalValue,this._allowExcessArguments=e._allowExcessArguments,this._enablePositionalOptions=e._enablePositionalOptions,this._showHelpAfterError=e._showHelpAfterError,this._showSuggestionAfterError=e._showSuggestionAfterError,this}_getCommandAndAncestors(){let e=[];for(let t=this;t;t=t.parent)e.push(t);return e}command(e,t,n){let i=t,o=n;typeof i=="object"&&i!==null&&(o=i,i=null),o=o||{};let[,s,c]=e.match(/([^ ]+) *(.*)/),a=this.createCommand(s);return i&&(a.description(i),a._executableHandler=!0),o.isDefault&&(this._defaultCommandName=a._name),a._hidden=!!(o.noHelp||o.hidden),a._executableFile=o.executableFile||null,c&&a.arguments(c),this._registerCommand(a),a.parent=this,a.copyInheritedSettings(this),i?this:a}createCommand(e){return new r(e)}createHelp(){return Object.assign(new An,this.configureHelp())}configureHelp(e){return e===void 0?this._helpConfiguration:(this._helpConfiguration=e,this)}configureOutput(e){return e===void 0?this._outputConfiguration:(Object.assign(this._outputConfiguration,e),this)}showHelpAfterError(e=!0){return typeof e!="string"&&(e=!!e),this._showHelpAfterError=e,this}showSuggestionAfterError(e=!0){return this._showSuggestionAfterError=!!e,this}addCommand(e,t){if(!e._name)throw new Error(`Command passed to .addCommand() must have a name
|
|
13
|
+
- specify the name in Command constructor or using .name()`);return t=t||{},t.isDefault&&(this._defaultCommandName=e._name),(t.noHelp||t.hidden)&&(e._hidden=!0),this._registerCommand(e),e.parent=this,e._checkForBrokenPassThrough(),this}createArgument(e,t){return new $n(e,t)}argument(e,t,n,i){let o=this.createArgument(e,t);return typeof n=="function"?o.default(i).argParser(n):o.default(n),this.addArgument(o),this}arguments(e){return e.trim().split(/ +/).forEach(t=>{this.argument(t)}),this}addArgument(e){let t=this.registeredArguments.slice(-1)[0];if(t&&t.variadic)throw new Error(`only the last argument can be variadic '${t.name()}'`);if(e.required&&e.defaultValue!==void 0&&e.parseArg===void 0)throw new Error(`a default value for a required argument is never used: '${e.name()}'`);return this.registeredArguments.push(e),this}helpCommand(e,t){if(typeof e=="boolean")return this._addImplicitHelpCommand=e,this;e=e??"help [command]";let[,n,i]=e.match(/([^ ]+) *(.*)/),o=t??"display help for command",s=this.createCommand(n);return s.helpOption(!1),i&&s.arguments(i),o&&s.description(o),this._addImplicitHelpCommand=!0,this._helpCommand=s,this}addHelpCommand(e,t){return typeof e!="object"?(this.helpCommand(e,t),this):(this._addImplicitHelpCommand=!0,this._helpCommand=e,this)}_getHelpCommand(){return this._addImplicitHelpCommand??(this.commands.length&&!this._actionHandler&&!this._findCommand("help"))?(this._helpCommand===void 0&&this.helpCommand(void 0,void 0),this._helpCommand):null}hook(e,t){let n=["preSubcommand","preAction","postAction"];if(!n.includes(e))throw new Error(`Unexpected value for event passed to hook : '${e}'.
|
|
14
|
+
Expecting one of '${n.join("', '")}'`);return this._lifeCycleHooks[e]?this._lifeCycleHooks[e].push(t):this._lifeCycleHooks[e]=[t],this}exitOverride(e){return e?this._exitCallback=e:this._exitCallback=t=>{if(t.code!=="commander.executeSubCommandAsync")throw t},this}_exit(e,t,n){this._exitCallback&&this._exitCallback(new fe(e,t,n)),g.exit(e)}action(e){let t=n=>{let i=this.registeredArguments.length,o=n.slice(0,i);return this._storeOptionsAsProperties?o[i]=this:o[i]=this.opts(),o.push(this),e.apply(this,o)};return this._actionHandler=t,this}createOption(e,t){return new Fe(e,t)}_callParseArg(e,t,n,i){try{return e.parseArg(t,n)}catch(o){if(o.code==="commander.invalidArgument"){let s=`${i} ${o.message}`;this.error(s,{exitCode:o.exitCode,code:o.code})}throw o}}_registerOption(e){let t=e.short&&this._findOption(e.short)||e.long&&this._findOption(e.long);if(t){let n=e.long&&this._findOption(e.long)?e.long:e.short;throw new Error(`Cannot add option '${e.flags}'${this._name&&` to command '${this._name}'`} due to conflicting flag '${n}'
|
|
15
|
+
- already used by option '${t.flags}'`)}this.options.push(e)}_registerCommand(e){let t=i=>[i.name()].concat(i.aliases()),n=t(e).find(i=>this._findCommand(i));if(n){let i=t(this._findCommand(n)).join("|"),o=t(e).join("|");throw new Error(`cannot add command '${o}' as already have command '${i}'`)}this.commands.push(e)}addOption(e){this._registerOption(e);let t=e.name(),n=e.attributeName();if(e.negate){let o=e.long.replace(/^--no-/,"--");this._findOption(o)||this.setOptionValueWithSource(n,e.defaultValue===void 0?!0:e.defaultValue,"default")}else e.defaultValue!==void 0&&this.setOptionValueWithSource(n,e.defaultValue,"default");let i=(o,s,c)=>{o==null&&e.presetArg!==void 0&&(o=e.presetArg);let a=this.getOptionValue(n);o!==null&&e.parseArg?o=this._callParseArg(e,o,a,s):o!==null&&e.variadic&&(o=e._concatValue(o,a)),o==null&&(e.negate?o=!1:e.isBoolean()||e.optional?o=!0:o=""),this.setOptionValueWithSource(n,o,c)};return this.on("option:"+t,o=>{let s=`error: option '${e.flags}' argument '${o}' is invalid.`;i(o,s,"cli")}),e.envVar&&this.on("optionEnv:"+t,o=>{let s=`error: option '${e.flags}' value '${o}' from env '${e.envVar}' is invalid.`;i(o,s,"env")}),this}_optionEx(e,t,n,i,o){if(typeof t=="object"&&t instanceof Fe)throw new Error("To add an Option object use addOption() instead of option() or requiredOption()");let s=this.createOption(t,n);if(s.makeOptionMandatory(!!e.mandatory),typeof i=="function")s.default(o).argParser(i);else if(i instanceof RegExp){let c=i;i=(a,l)=>{let d=c.exec(a);return d?d[0]:l},s.default(o).argParser(i)}else s.default(i);return this.addOption(s)}option(e,t,n,i){return this._optionEx({},e,t,n,i)}requiredOption(e,t,n,i){return this._optionEx({mandatory:!0},e,t,n,i)}combineFlagAndOptionalValue(e=!0){return this._combineFlagAndOptionalValue=!!e,this}allowUnknownOption(e=!0){return this._allowUnknownOption=!!e,this}allowExcessArguments(e=!0){return this._allowExcessArguments=!!e,this}enablePositionalOptions(e=!0){return this._enablePositionalOptions=!!e,this}passThroughOptions(e=!0){return this._passThroughOptions=!!e,this._checkForBrokenPassThrough(),this}_checkForBrokenPassThrough(){if(this.parent&&this._passThroughOptions&&!this.parent._enablePositionalOptions)throw new Error(`passThroughOptions cannot be used for '${this._name}' without turning on enablePositionalOptions for parent command(s)`)}storeOptionsAsProperties(e=!0){if(this.options.length)throw new Error("call .storeOptionsAsProperties() before adding options");if(Object.keys(this._optionValues).length)throw new Error("call .storeOptionsAsProperties() before setting option values");return this._storeOptionsAsProperties=!!e,this}getOptionValue(e){return this._storeOptionsAsProperties?this[e]:this._optionValues[e]}setOptionValue(e,t){return this.setOptionValueWithSource(e,t,void 0)}setOptionValueWithSource(e,t,n){return this._storeOptionsAsProperties?this[e]=t:this._optionValues[e]=t,this._optionValueSources[e]=n,this}getOptionValueSource(e){return this._optionValueSources[e]}getOptionValueSourceWithGlobals(e){let t;return this._getCommandAndAncestors().forEach(n=>{n.getOptionValueSource(e)!==void 0&&(t=n.getOptionValueSource(e))}),t}_prepareUserArgs(e,t){if(e!==void 0&&!Array.isArray(e))throw new Error("first parameter to parse must be array or undefined");if(t=t||{},e===void 0&&t.from===void 0){g.versions?.electron&&(t.from="electron");let i=g.execArgv??[];(i.includes("-e")||i.includes("--eval")||i.includes("-p")||i.includes("--print"))&&(t.from="eval")}e===void 0&&(e=g.argv),this.rawArgs=e.slice();let n;switch(t.from){case void 0:case"node":this._scriptPath=e[1],n=e.slice(2);break;case"electron":g.defaultApp?(this._scriptPath=e[1],n=e.slice(2)):n=e.slice(1);break;case"user":n=e.slice(0);break;case"eval":n=e.slice(1);break;default:throw new Error(`unexpected parse option { from: '${t.from}' }`)}return!this._name&&this._scriptPath&&this.nameFromFilename(this._scriptPath),this._name=this._name||"program",n}parse(e,t){let n=this._prepareUserArgs(e,t);return this._parseCommand([],n),this}async parseAsync(e,t){let n=this._prepareUserArgs(e,t);return await this._parseCommand([],n),this}_executeSubCommand(e,t){t=t.slice();let n=!1,i=[".js",".ts",".tsx",".mjs",".cjs"];function o(d,f){let v=$.resolve(d,f);if(pe.existsSync(v))return v;if(i.includes($.extname(f)))return;let k=i.find(y=>pe.existsSync(`${v}${y}`));if(k)return`${v}${k}`}this._checkForMissingMandatoryOptions(),this._checkForConflictingOptions();let s=e._executableFile||`${this._name}-${e._name}`,c=this._executableDir||"";if(this._scriptPath){let d;try{d=pe.realpathSync(this._scriptPath)}catch{d=this._scriptPath}c=$.resolve($.dirname(d),c)}if(c){let d=o(c,s);if(!d&&!e._executableFile&&this._scriptPath){let f=$.basename(this._scriptPath,$.extname(this._scriptPath));f!==this._name&&(d=o(c,`${f}-${e._name}`))}s=d||s}n=i.includes($.extname(s));let a;g.platform!=="win32"?n?(t.unshift(s),t=Me(g.execArgv).concat(t),a=me.spawn(g.argv[0],t,{stdio:"inherit"})):a=me.spawn(s,t,{stdio:"inherit"}):(t.unshift(s),t=Me(g.execArgv).concat(t),a=me.spawn(g.execPath,t,{stdio:"inherit"})),a.killed||["SIGUSR1","SIGUSR2","SIGTERM","SIGINT","SIGHUP"].forEach(f=>{g.on(f,()=>{a.killed===!1&&a.exitCode===null&&a.kill(f)})});let l=this._exitCallback;a.on("close",d=>{d=d??1,l?l(new fe(d,"commander.executeSubCommandAsync","(close)")):g.exit(d)}),a.on("error",d=>{if(d.code==="ENOENT"){let f=c?`searched for local subcommand relative to directory '${c}'`:"no directory for search for local subcommand, use .executableDir() to supply a custom directory",v=`'${s}' does not exist
|
|
16
16
|
- if '${e._name}' is not meant to be an executable command, remove description parameter from '.command()' and use '.description()' instead
|
|
17
17
|
- if the default executable name is not suitable, use the executableFile option to supply a custom name or path
|
|
18
18
|
- ${f}`;throw new Error(v)}else if(d.code==="EACCES")throw new Error(`'${s}' not executable`);if(!l)g.exit(1);else{let f=new fe(1,"commander.executeSubCommandAsync","(error)");f.nestedError=d,l(f)}}),this.runningCommand=a}_dispatchSubcommand(e,t,n){let i=this._findCommand(e);i||this.help({error:!0});let o;return o=this._chainOrCallSubCommandHook(o,i,"preSubcommand"),o=this._chainOrCall(o,()=>{if(i._executableHandler)this._executeSubCommand(i,t.concat(n));else return i._parseCommand(t,n)}),o}_dispatchHelpCommand(e){e||this.help();let t=this._findCommand(e);return t&&!t._executableHandler&&t.help(),this._dispatchSubcommand(e,[],[this._getHelpOption()?.long??this._getHelpOption()?.short??"--help"])}_checkNumberOfArguments(){this.registeredArguments.forEach((e,t)=>{e.required&&this.args[t]==null&&this.missingArgument(e.name())}),!(this.registeredArguments.length>0&&this.registeredArguments[this.registeredArguments.length-1].variadic)&&this.args.length>this.registeredArguments.length&&this._excessArguments(this.args)}_processArguments(){let e=(n,i,o)=>{let s=i;if(i!==null&&n.parseArg){let c=`error: command-argument value '${i}' is invalid for argument '${n.name()}'.`;s=this._callParseArg(n,i,o,c)}return s};this._checkNumberOfArguments();let t=[];this.registeredArguments.forEach((n,i)=>{let o=n.defaultValue;n.variadic?i<this.args.length?(o=this.args.slice(i),n.parseArg&&(o=o.reduce((s,c)=>e(n,c,s),n.defaultValue))):o===void 0&&(o=[]):i<this.args.length&&(o=this.args[i],n.parseArg&&(o=e(n,o,n.defaultValue))),t[i]=o}),this.processedArgs=t}_chainOrCall(e,t){return e&&e.then&&typeof e.then=="function"?e.then(()=>t()):t()}_chainOrCallHooks(e,t){let n=e,i=[];return this._getCommandAndAncestors().reverse().filter(o=>o._lifeCycleHooks[t]!==void 0).forEach(o=>{o._lifeCycleHooks[t].forEach(s=>{i.push({hookedCommand:o,callback:s})})}),t==="postAction"&&i.reverse(),i.forEach(o=>{n=this._chainOrCall(n,()=>o.callback(o.hookedCommand,this))}),n}_chainOrCallSubCommandHook(e,t,n){let i=e;return this._lifeCycleHooks[n]!==void 0&&this._lifeCycleHooks[n].forEach(o=>{i=this._chainOrCall(i,()=>o(this,t))}),i}_parseCommand(e,t){let n=this.parseOptions(t);if(this._parseOptionsEnv(),this._parseOptionsImplied(),e=e.concat(n.operands),t=n.unknown,this.args=e.concat(t),e&&this._findCommand(e[0]))return this._dispatchSubcommand(e[0],e.slice(1),t);if(this._getHelpCommand()&&e[0]===this._getHelpCommand().name())return this._dispatchHelpCommand(e[1]);if(this._defaultCommandName)return this._outputHelpIfRequested(t),this._dispatchSubcommand(this._defaultCommandName,e,t);this.commands.length&&this.args.length===0&&!this._actionHandler&&!this._defaultCommandName&&this.help({error:!0}),this._outputHelpIfRequested(n.unknown),this._checkForMissingMandatoryOptions(),this._checkForConflictingOptions();let i=()=>{n.unknown.length>0&&this.unknownOption(n.unknown[0])},o=`command:${this.name()}`;if(this._actionHandler){i(),this._processArguments();let s;return s=this._chainOrCallHooks(s,"preAction"),s=this._chainOrCall(s,()=>this._actionHandler(this.processedArgs)),this.parent&&(s=this._chainOrCall(s,()=>{this.parent.emit(o,e,t)})),s=this._chainOrCallHooks(s,"postAction"),s}if(this.parent&&this.parent.listenerCount(o))i(),this._processArguments(),this.parent.emit(o,e,t);else if(e.length){if(this._findCommand("*"))return this._dispatchSubcommand("*",e,t);this.listenerCount("command:*")?this.emit("command:*",e,t):this.commands.length?this.unknownCommand():(i(),this._processArguments())}else this.commands.length?(i(),this.help({error:!0})):(i(),this._processArguments())}_findCommand(e){if(e)return this.commands.find(t=>t._name===e||t._aliases.includes(e))}_findOption(e){return this.options.find(t=>t.is(e))}_checkForMissingMandatoryOptions(){this._getCommandAndAncestors().forEach(e=>{e.options.forEach(t=>{t.mandatory&&e.getOptionValue(t.attributeName())===void 0&&e.missingMandatoryOptionValue(t)})})}_checkForConflictingLocalOptions(){let e=this.options.filter(n=>{let i=n.attributeName();return this.getOptionValue(i)===void 0?!1:this.getOptionValueSource(i)!=="default"});e.filter(n=>n.conflictsWith.length>0).forEach(n=>{let i=e.find(o=>n.conflictsWith.includes(o.attributeName()));i&&this._conflictingOption(n,i)})}_checkForConflictingOptions(){this._getCommandAndAncestors().forEach(e=>{e._checkForConflictingLocalOptions()})}parseOptions(e){let t=[],n=[],i=t,o=e.slice();function s(a){return a.length>1&&a[0]==="-"}let c=null;for(;o.length;){let a=o.shift();if(a==="--"){i===n&&i.push(a),i.push(...o);break}if(c&&!s(a)){this.emit(`option:${c.name()}`,a);continue}if(c=null,s(a)){let l=this._findOption(a);if(l){if(l.required){let d=o.shift();d===void 0&&this.optionMissingArgument(l),this.emit(`option:${l.name()}`,d)}else if(l.optional){let d=null;o.length>0&&!s(o[0])&&(d=o.shift()),this.emit(`option:${l.name()}`,d)}else this.emit(`option:${l.name()}`);c=l.variadic?l:null;continue}}if(a.length>2&&a[0]==="-"&&a[1]!=="-"){let l=this._findOption(`-${a[1]}`);if(l){l.required||l.optional&&this._combineFlagAndOptionalValue?this.emit(`option:${l.name()}`,a.slice(2)):(this.emit(`option:${l.name()}`),o.unshift(`-${a.slice(2)}`));continue}}if(/^--[^=]+=/.test(a)){let l=a.indexOf("="),d=this._findOption(a.slice(0,l));if(d&&(d.required||d.optional)){this.emit(`option:${d.name()}`,a.slice(l+1));continue}}if(s(a)&&(i=n),(this._enablePositionalOptions||this._passThroughOptions)&&t.length===0&&n.length===0){if(this._findCommand(a)){t.push(a),o.length>0&&n.push(...o);break}else if(this._getHelpCommand()&&a===this._getHelpCommand().name()){t.push(a),o.length>0&&t.push(...o);break}else if(this._defaultCommandName){n.push(a),o.length>0&&n.push(...o);break}}if(this._passThroughOptions){i.push(a),o.length>0&&i.push(...o);break}i.push(a)}return{operands:t,unknown:n}}opts(){if(this._storeOptionsAsProperties){let e={},t=this.options.length;for(let n=0;n<t;n++){let i=this.options[n].attributeName();e[i]=i===this._versionOptionName?this._version:this[i]}return e}return this._optionValues}optsWithGlobals(){return this._getCommandAndAncestors().reduce((e,t)=>Object.assign(e,t.opts()),{})}error(e,t){this._outputConfiguration.outputError(`${e}
|
|
19
19
|
`,this._outputConfiguration.writeErr),typeof this._showHelpAfterError=="string"?this._outputConfiguration.writeErr(`${this._showHelpAfterError}
|
|
20
20
|
`):this._showHelpAfterError&&(this._outputConfiguration.writeErr(`
|
|
21
|
-
`),this.outputHelp({error:!0}));let n=t||{},i=n.exitCode||1,o=n.code||"commander.error";this._exit(i,o,e)}_parseOptionsEnv(){this.options.forEach(e=>{if(e.envVar&&e.envVar in g.env){let t=e.attributeName();(this.getOptionValue(t)===void 0||["default","config","env"].includes(this.getOptionValueSource(t)))&&(e.required||e.optional?this.emit(`optionEnv:${e.name()}`,g.env[e.envVar]):this.emit(`optionEnv:${e.name()}`))}})}_parseOptionsImplied(){let e=new
|
|
22
|
-
`),this._exit(0,"commander.version",e)}),this}description(e,t){return e===void 0&&t===void 0?this._description:(this._description=e,t&&(this._argsDescription=t),this)}summary(e){return e===void 0?this._summary:(this._summary=e,this)}alias(e){if(e===void 0)return this._aliases[0];let t=this;if(this.commands.length!==0&&this.commands[this.commands.length-1]._executableHandler&&(t=this.commands[this.commands.length-1]),e===t._name)throw new Error("Command alias can't be the same as its name");let n=this.parent?._findCommand(e);if(n){let i=[n.name()].concat(n.aliases()).join("|");throw new Error(`cannot add alias '${e}' to command '${this.name()}' as already have command '${i}'`)}return t._aliases.push(e),this}aliases(e){return e===void 0?this._aliases:(e.forEach(t=>this.alias(t)),this)}usage(e){if(e===void 0){if(this._usage)return this._usage;let t=this.registeredArguments.map(n=>
|
|
21
|
+
`),this.outputHelp({error:!0}));let n=t||{},i=n.exitCode||1,o=n.code||"commander.error";this._exit(i,o,e)}_parseOptionsEnv(){this.options.forEach(e=>{if(e.envVar&&e.envVar in g.env){let t=e.attributeName();(this.getOptionValue(t)===void 0||["default","config","env"].includes(this.getOptionValueSource(t)))&&(e.required||e.optional?this.emit(`optionEnv:${e.name()}`,g.env[e.envVar]):this.emit(`optionEnv:${e.name()}`))}})}_parseOptionsImplied(){let e=new Sn(this.options),t=n=>this.getOptionValue(n)!==void 0&&!["default","implied"].includes(this.getOptionValueSource(n));this.options.filter(n=>n.implied!==void 0&&t(n.attributeName())&&e.valueFromOption(this.getOptionValue(n.attributeName()),n)).forEach(n=>{Object.keys(n.implied).filter(i=>!t(i)).forEach(i=>{this.setOptionValueWithSource(i,n.implied[i],"implied")})})}missingArgument(e){let t=`error: missing required argument '${e}'`;this.error(t,{code:"commander.missingArgument"})}optionMissingArgument(e){let t=`error: option '${e.flags}' argument missing`;this.error(t,{code:"commander.optionMissingArgument"})}missingMandatoryOptionValue(e){let t=`error: required option '${e.flags}' not specified`;this.error(t,{code:"commander.missingMandatoryOptionValue"})}_conflictingOption(e,t){let n=s=>{let c=s.attributeName(),a=this.getOptionValue(c),l=this.options.find(f=>f.negate&&c===f.attributeName()),d=this.options.find(f=>!f.negate&&c===f.attributeName());return l&&(l.presetArg===void 0&&a===!1||l.presetArg!==void 0&&a===l.presetArg)?l:d||s},i=s=>{let c=n(s),a=c.attributeName();return this.getOptionValueSource(a)==="env"?`environment variable '${c.envVar}'`:`option '${c.flags}'`},o=`error: ${i(e)} cannot be used with ${i(t)}`;this.error(o,{code:"commander.conflictingOption"})}unknownOption(e){if(this._allowUnknownOption)return;let t="";if(e.startsWith("--")&&this._showSuggestionAfterError){let i=[],o=this;do{let s=o.createHelp().visibleOptions(o).filter(c=>c.long).map(c=>c.long);i=i.concat(s),o=o.parent}while(o&&!o._enablePositionalOptions);t=Le(e,i)}let n=`error: unknown option '${e}'${t}`;this.error(n,{code:"commander.unknownOption"})}_excessArguments(e){if(this._allowExcessArguments)return;let t=this.registeredArguments.length,n=t===1?"":"s",o=`error: too many arguments${this.parent?` for '${this.name()}'`:""}. Expected ${t} argument${n} but got ${e.length}.`;this.error(o,{code:"commander.excessArguments"})}unknownCommand(){let e=this.args[0],t="";if(this._showSuggestionAfterError){let i=[];this.createHelp().visibleCommands(this).forEach(o=>{i.push(o.name()),o.alias()&&i.push(o.alias())}),t=Le(e,i)}let n=`error: unknown command '${e}'${t}`;this.error(n,{code:"commander.unknownCommand"})}version(e,t,n){if(e===void 0)return this._version;this._version=e,t=t||"-V, --version",n=n||"output the version number";let i=this.createOption(t,n);return this._versionOptionName=i.attributeName(),this._registerOption(i),this.on("option:"+i.name(),()=>{this._outputConfiguration.writeOut(`${e}
|
|
22
|
+
`),this._exit(0,"commander.version",e)}),this}description(e,t){return e===void 0&&t===void 0?this._description:(this._description=e,t&&(this._argsDescription=t),this)}summary(e){return e===void 0?this._summary:(this._summary=e,this)}alias(e){if(e===void 0)return this._aliases[0];let t=this;if(this.commands.length!==0&&this.commands[this.commands.length-1]._executableHandler&&(t=this.commands[this.commands.length-1]),e===t._name)throw new Error("Command alias can't be the same as its name");let n=this.parent?._findCommand(e);if(n){let i=[n.name()].concat(n.aliases()).join("|");throw new Error(`cannot add alias '${e}' to command '${this.name()}' as already have command '${i}'`)}return t._aliases.push(e),this}aliases(e){return e===void 0?this._aliases:(e.forEach(t=>this.alias(t)),this)}usage(e){if(e===void 0){if(this._usage)return this._usage;let t=this.registeredArguments.map(n=>Cn(n));return[].concat(this.options.length||this._helpOption!==null?"[options]":[],this.commands.length?"[command]":[],this.registeredArguments.length?t:[]).join(" ")}return this._usage=e,this}name(e){return e===void 0?this._name:(this._name=e,this)}nameFromFilename(e){return this._name=$.basename(e,$.extname(e)),this}executableDir(e){return e===void 0?this._executableDir:(this._executableDir=e,this)}helpInformation(e){let t=this.createHelp();return t.helpWidth===void 0&&(t.helpWidth=e&&e.error?this._outputConfiguration.getErrHelpWidth():this._outputConfiguration.getOutHelpWidth()),t.formatHelp(this,t)}_getHelpContext(e){e=e||{};let t={error:!!e.error},n;return t.error?n=i=>this._outputConfiguration.writeErr(i):n=i=>this._outputConfiguration.writeOut(i),t.write=e.write||n,t.command=this,t}outputHelp(e){let t;typeof e=="function"&&(t=e,e=void 0);let n=this._getHelpContext(e);this._getCommandAndAncestors().reverse().forEach(o=>o.emit("beforeAllHelp",n)),this.emit("beforeHelp",n);let i=this.helpInformation(n);if(t&&(i=t(i),typeof i!="string"&&!Buffer.isBuffer(i)))throw new Error("outputHelp callback must return a string or a Buffer");n.write(i),this._getHelpOption()?.long&&this.emit(this._getHelpOption().long),this.emit("afterHelp",n),this._getCommandAndAncestors().forEach(o=>o.emit("afterAllHelp",n))}helpOption(e,t){return typeof e=="boolean"?(e?this._helpOption=this._helpOption??void 0:this._helpOption=null,this):(e=e??"-h, --help",t=t??"display help for command",this._helpOption=this.createOption(e,t),this)}_getHelpOption(){return this._helpOption===void 0&&this.helpOption(void 0,void 0),this._helpOption}addHelpOption(e){return this._helpOption=e,this}help(e){this.outputHelp(e);let t=g.exitCode||0;t===0&&e&&typeof e!="function"&&e.error&&(t=1),this._exit(t,"commander.help","(outputHelp)")}addHelpText(e,t){let n=["beforeAll","before","after","afterAll"];if(!n.includes(e))throw new Error(`Unexpected value for position to addHelpText.
|
|
23
23
|
Expecting one of '${n.join("', '")}'`);let i=`${e}Help`;return this.on(i,o=>{let s;typeof t=="function"?s=t({error:o.error,command:o.command}):s=t,s&&o.write(`${s}
|
|
24
|
-
`)}),this}_outputHelpIfRequested(e){let t=this._getHelpOption();t&&e.find(i=>t.is(i))&&(this.outputHelp(),this._exit(0,"commander.helpDisplayed","(outputHelp)"))}};function Le(r){return r.map(e=>{if(!e.startsWith("--inspect"))return e;let t,n="127.0.0.1",i="9229",o;return(o=e.match(/^(--inspect(-brk)?)$/))!==null?t=o[1]:(o=e.match(/^(--inspect(-brk|-port)?)=([^:]+)$/))!==null?(t=o[1],/^\d+$/.test(o[3])?i=o[3]:n=o[3]):(o=e.match(/^(--inspect(-brk|-port)?)=([^:]+):(\d+)$/))!==null&&(t=o[1],n=o[3],i=o[4]),t&&i!=="0"?`${t}=${n}:${parseInt(i)+1}`:e})}Me.Command=ge});var ze=k(x=>{"use strict";u();var{Argument:Ue}=z(),{Command:be}=Be(),{CommanderError:An,InvalidArgumentError:We}=F(),{Help:Sn}=ce(),{Option:Je}=he();x.program=new be;x.createCommand=r=>new be(r);x.createOption=(r,e)=>new Je(r,e);x.createArgument=(r,e)=>new Ue(r,e);x.Command=be;x.Option=Je;x.Argument=Ue;x.Help=Sn;x.CommanderError=An;x.InvalidArgumentError=We;x.InvalidOptionArgumentError=We});u();u();var Ge=mn(ze(),1),{program:b,createCommand:Er,createArgument:Pr,createOption:kr,CommanderError:Rr,InvalidArgumentError:Tr,InvalidOptionArgumentError:qr,Command:Nr,Argument:Ir,Option:Dr,Help:Hr}=Ge.default;u();import{existsSync as Wn}from"fs";u();u();u();u();var O=class extends Error{response;request;options;constructor(e,t,n){let i=e.status||e.status===0?e.status:"",o=e.statusText??"",s=`${i} ${o}`.trim(),c=s?`status code ${s}`:"an unknown error";super(`Request failed with ${c}: ${t.method} ${t.url}`),this.name="HTTPError",this.response=e,this.request=t,this.options=n}};u();var D=class extends Error{name="NonError";value;constructor(e){let t="Non-error value was thrown";try{typeof e=="string"?t=e:e&&typeof e=="object"&&"message"in e&&typeof e.message=="string"&&(t=e.message)}catch{}super(t),this.value=e}};u();var H=class extends Error{name="ForceRetryError";customDelay;code;customRequest;constructor(e){let t=e?.cause?e.cause instanceof Error?e.cause:new D(e.cause):void 0;super(e?.code?`Forced retry: ${e.code}`:"Forced retry",t?{cause:t}:void 0),this.customDelay=e?.delay,this.code=e?.code,this.customRequest=e?.request}};u();u();var ye=(()=>{let r=!1,e=!1,t=typeof globalThis.ReadableStream=="function",n=typeof globalThis.Request=="function";if(t&&n)try{e=new globalThis.Request("https://empty.invalid",{body:new globalThis.ReadableStream,method:"POST",get duplex(){return r=!0,"half"}}).headers.has("Content-Type")}catch(i){if(i instanceof Error&&i.message==="unsupported BodyInit type")return!1;throw i}return r&&!e})(),Ke=typeof globalThis.AbortController=="function",G=typeof globalThis.AbortSignal=="function"&&typeof globalThis.AbortSignal.any=="function",Ye=typeof globalThis.ReadableStream=="function",Qe=typeof globalThis.FormData=="function",K=["get","post","put","patch","head","delete"],En=()=>{};En();var Xe={json:"application/json",text:"text/*",formData:"multipart/form-data",arrayBuffer:"*/*",blob:"*/*",bytes:"*/*"},Y=2147483647,Ze=new TextEncoder().encode("------WebKitFormBoundaryaxpyiPgbbPti10Rw").length,Q=Symbol("stop"),L=class{options;constructor(e){this.options=e}},et=r=>new L(r),tt={json:!0,parseJson:!0,stringifyJson:!0,searchParams:!0,prefixUrl:!0,retry:!0,timeout:!0,hooks:!0,throwHttpErrors:!0,onDownloadProgress:!0,onUploadProgress:!0,fetch:!0,context:!0},nt={next:!0},rt={method:!0,headers:!0,body:!0,mode:!0,credentials:!0,cache:!0,redirect:!0,referrer:!0,referrerPolicy:!0,integrity:!0,keepalive:!0,signal:!0,window:!0,duplex:!0};var Pn=r=>{if(!r)return 0;if(r instanceof FormData){let e=0;for(let[t,n]of r)e+=Ze,e+=new TextEncoder().encode(`Content-Disposition: form-data; name="${t}"`).length,e+=typeof n=="string"?new TextEncoder().encode(n).length:n.size;return e}if(r instanceof Blob)return r.size;if(r instanceof ArrayBuffer)return r.byteLength;if(typeof r=="string")return new TextEncoder().encode(r).length;if(r instanceof URLSearchParams)return new TextEncoder().encode(r.toString()).length;if("byteLength"in r)return r.byteLength;if(typeof r=="object"&&r!==null)try{let e=JSON.stringify(r);return new TextEncoder().encode(e).length}catch{return 0}return 0},it=(r,e,t)=>{let n,i=0;return r.pipeThrough(new TransformStream({transform(o,s){if(s.enqueue(o),n){i+=n.byteLength;let c=e===0?0:i/e;c>=1&&(c=1-Number.EPSILON),t?.({percent:c,totalBytes:Math.max(e,i),transferredBytes:i},n)}n=o},flush(){n&&(i+=n.byteLength,t?.({percent:1,totalBytes:Math.max(e,i),transferredBytes:i},n))}}))},ot=(r,e)=>{if(!r.body)return r;if(r.status===204)return new Response(null,{status:r.status,statusText:r.statusText,headers:r.headers});let t=Math.max(0,Number(r.headers.get("content-length"))||0);return new Response(it(r.body,t,e),{status:r.status,statusText:r.statusText,headers:r.headers})},st=(r,e,t)=>{if(!r.body)return r;let n=Pn(t??r.body);return new Request(r,{duplex:"half",body:it(r.body,n,e)})};u();u();var S=r=>r!==null&&typeof r=="object";var M=(...r)=>{for(let e of r)if((!S(e)||Array.isArray(e))&&e!==void 0)throw new TypeError("The `options` argument must be an object");return je({},...r)},we=(r={},e={})=>{let t=new globalThis.Headers(r),n=e instanceof globalThis.Headers,i=new globalThis.Headers(e);for(let[o,s]of i.entries())n&&s==="undefined"||s===void 0?t.delete(o):t.set(o,s);return t};function X(r,e,t){return Object.hasOwn(e,t)&&e[t]===void 0?[]:je(r[t]??[],e[t]??[])}var _e=(r={},e={})=>({beforeRequest:X(r,e,"beforeRequest"),beforeRetry:X(r,e,"beforeRetry"),afterResponse:X(r,e,"afterResponse"),beforeError:X(r,e,"beforeError")}),kn=(r,e)=>{let t=new URLSearchParams;for(let n of[r,e])if(n!==void 0)if(n instanceof URLSearchParams)for(let[i,o]of n.entries())t.append(i,o);else if(Array.isArray(n))for(let i of n){if(!Array.isArray(i)||i.length!==2)throw new TypeError("Array search parameters must be provided in [[key, value], ...] format");t.append(String(i[0]),String(i[1]))}else if(S(n))for(let[i,o]of Object.entries(n))o!==void 0&&t.append(i,String(o));else{let i=new URLSearchParams(n);for(let[o,s]of i.entries())t.append(o,s)}return t},je=(...r)=>{let e={},t={},n={},i,o=[];for(let s of r)if(Array.isArray(s))Array.isArray(e)||(e=[]),e=[...e,...s];else if(S(s)){for(let[c,a]of Object.entries(s)){if(c==="signal"&&a instanceof globalThis.AbortSignal){o.push(a);continue}if(c==="context"){if(a!=null&&(!S(a)||Array.isArray(a)))throw new TypeError("The `context` option must be an object");e={...e,context:a==null?{}:{...e.context,...a}};continue}if(c==="searchParams"){a==null?i=void 0:i=i===void 0?a:kn(i,a);continue}S(a)&&c in e&&(a=je(e[c],a)),e={...e,[c]:a}}S(s.hooks)&&(n=_e(n,s.hooks),e.hooks=n),S(s.headers)&&(t=we(t,s.headers),e.headers=t)}return i!==void 0&&(e.searchParams=i),o.length>0&&(o.length===1?e.signal=o[0]:G?e.signal=AbortSignal.any(o):e.signal=o.at(-1)),e};u();var ct=r=>K.includes(r)?r.toUpperCase():r,Rn=["get","put","head","delete","options","trace"],Tn=[408,413,429,500,502,503,504],qn=[413,429,503],at={limit:2,methods:Rn,statusCodes:Tn,afterStatusCodes:qn,maxRetryAfter:Number.POSITIVE_INFINITY,backoffLimit:Number.POSITIVE_INFINITY,delay:r=>.3*2**(r-1)*1e3,jitter:void 0,retryOnTimeout:!1},ut=(r={})=>{if(typeof r=="number")return{...at,limit:r};if(r.methods&&!Array.isArray(r.methods))throw new Error("retry.methods must be an array");if(r.methods&&=r.methods.map(t=>t.toLowerCase()),r.statusCodes&&!Array.isArray(r.statusCodes))throw new Error("retry.statusCodes must be an array");let e=Object.fromEntries(Object.entries(r).filter(([,t])=>t!==void 0));return{...at,...e}};u();u();var R=class extends Error{request;constructor(e){super(`Request timed out: ${e.method} ${e.url}`),this.name="TimeoutError",this.request=e}};async function ve(r,e,t,n){return new Promise((i,o)=>{let s=setTimeout(()=>{t&&t.abort(),o(new R(r))},n.timeout);n.fetch(r,e).then(i).catch(o).then(()=>{clearTimeout(s)})})}u();async function Oe(r,{signal:e}){return new Promise((t,n)=>{e&&(e.throwIfAborted(),e.addEventListener("abort",i,{once:!0}));function i(){clearTimeout(o),n(e.reason)}let o=setTimeout(()=>{e?.removeEventListener("abort",i),t()},r)})}u();var lt=(r,e)=>{let t={};for(let n in e)Object.hasOwn(e,n)&&!(n in rt)&&!(n in tt)&&(!(n in r)||n in nt)&&(t[n]=e[n]);return t},dt=r=>r===void 0?!1:Array.isArray(r)?r.length>0:r instanceof URLSearchParams?r.size>0:typeof r=="object"?Object.keys(r).length>0:typeof r=="string"?r.trim().length>0:!!r;u();function ht(r){return r instanceof O||r?.name===O.name}function mt(r){return r instanceof R||r?.name===R.name}var B=class r{static create(e,t){let n=new r(e,t),i=async()=>{if(typeof n.#e.timeout=="number"&&n.#e.timeout>Y)throw new RangeError(`The \`timeout\` option cannot be greater than ${Y}`);await Promise.resolve();let s=await n.#b();for(let c of n.#e.hooks.afterResponse){let a=n.#h(s.clone()),l;try{l=await c(n.request,n.#c(),a,{retryCount:n.#n})}catch(f){throw n.#o(a),n.#o(s),f}if(l instanceof L)throw n.#o(a),n.#o(s),new H(l.options);let d=l instanceof globalThis.Response?l:s;a!==d&&n.#o(a),s!==d&&n.#o(s),s=d}if(n.#h(s),!s.ok&&(typeof n.#e.throwHttpErrors=="function"?n.#e.throwHttpErrors(s.status):n.#e.throwHttpErrors)){let c=new O(s,n.request,n.#c());for(let a of n.#e.hooks.beforeError)c=await a(c,{retryCount:n.#n});throw c}if(n.#e.onDownloadProgress){if(typeof n.#e.onDownloadProgress!="function")throw new TypeError("The `onDownloadProgress` option must be a function");if(!Ye)throw new Error("Streams are not supported in your environment. `ReadableStream` is missing.");let c=s.clone();return n.#o(s),ot(c,n.#e.onDownloadProgress)}return s},o=n.#m(i).finally(()=>{let s=n.#s;n.#l(s?.body??void 0),n.#l(n.request.body??void 0)});for(let[s,c]of Object.entries(Xe))s==="bytes"&&typeof globalThis.Response?.prototype?.bytes!="function"||(o[s]=async()=>{n.request.headers.set("accept",n.request.headers.get("accept")||c);let a=await o;if(s==="json"){if(a.status===204)return"";let l=await a.text();return l===""?"":t.parseJson?t.parseJson(l):JSON.parse(l)}return a[s]()});return o}static#f(e){return e&&typeof e=="object"&&!Array.isArray(e)&&!(e instanceof URLSearchParams)?Object.fromEntries(Object.entries(e).filter(([,t])=>t!==void 0)):e}request;#r;#n=0;#t;#e;#s;#i;#a;constructor(e,t={}){if(this.#t=e,this.#e={...t,headers:we(this.#t.headers,t.headers),hooks:_e({beforeRequest:[],beforeRetry:[],beforeError:[],afterResponse:[]},t.hooks),method:ct(t.method??this.#t.method??"GET"),prefixUrl:String(t.prefixUrl||""),retry:ut(t.retry),throwHttpErrors:t.throwHttpErrors??!0,timeout:t.timeout??1e4,fetch:t.fetch??globalThis.fetch.bind(globalThis),context:t.context??{}},typeof this.#t!="string"&&!(this.#t instanceof URL||this.#t instanceof globalThis.Request))throw new TypeError("`input` must be a string, URL, or Request");if(this.#e.prefixUrl&&typeof this.#t=="string"){if(this.#t.startsWith("/"))throw new Error("`input` must not begin with a slash when using `prefixUrl`");this.#e.prefixUrl.endsWith("/")||(this.#e.prefixUrl+="/"),this.#t=this.#e.prefixUrl+this.#t}Ke&&G&&(this.#i=this.#e.signal??this.#t.signal,this.#r=new globalThis.AbortController,this.#e.signal=this.#i?AbortSignal.any([this.#i,this.#r.signal]):this.#r.signal),ye&&(this.#e.duplex="half"),this.#e.json!==void 0&&(this.#e.body=this.#e.stringifyJson?.(this.#e.json)??JSON.stringify(this.#e.json),this.#e.headers.set("content-type",this.#e.headers.get("content-type")??"application/json"));let n=t.headers&&new globalThis.Headers(t.headers).has("content-type");if(this.#t instanceof globalThis.Request&&(Qe&&this.#e.body instanceof globalThis.FormData||this.#e.body instanceof URLSearchParams)&&!n&&this.#e.headers.delete("content-type"),this.request=new globalThis.Request(this.#t,this.#e),dt(this.#e.searchParams)){let o="?"+(typeof this.#e.searchParams=="string"?this.#e.searchParams.replace(/^\?/,""):new URLSearchParams(r.#f(this.#e.searchParams)).toString()),s=this.request.url.replace(/(?:\?.*?)?(?=#|$)/,o);this.request=new globalThis.Request(s,this.#e)}if(this.#e.onUploadProgress){if(typeof this.#e.onUploadProgress!="function")throw new TypeError("The `onUploadProgress` option must be a function");if(!ye)throw new Error("Request streams are not supported in your environment. The `duplex` option for `Request` is not available.");this.request=this.#p(this.request,this.#e.body??void 0)}}#u(){let e=this.#e.retry.delay(this.#n),t=e;this.#e.retry.jitter===!0?t=Math.random()*e:typeof this.#e.retry.jitter=="function"&&(t=this.#e.retry.jitter(e),(!Number.isFinite(t)||t<0)&&(t=e));let n=this.#e.retry.backoffLimit??Number.POSITIVE_INFINITY;return Math.min(n,t)}async#g(e){if(this.#n++,this.#n>this.#e.retry.limit)throw e;let t=e instanceof Error?e:new D(e);if(t instanceof H)return t.customDelay??this.#u();if(!this.#e.retry.methods.includes(this.request.method.toLowerCase()))throw e;if(this.#e.retry.shouldRetry!==void 0){let n=await this.#e.retry.shouldRetry({error:t,retryCount:this.#n});if(n===!1)throw e;if(n===!0)return this.#u()}if(mt(e)&&!this.#e.retry.retryOnTimeout)throw e;if(ht(e)){if(!this.#e.retry.statusCodes.includes(e.response.status))throw e;let n=e.response.headers.get("Retry-After")??e.response.headers.get("RateLimit-Reset")??e.response.headers.get("X-RateLimit-Retry-After")??e.response.headers.get("X-RateLimit-Reset")??e.response.headers.get("X-Rate-Limit-Reset");if(n&&this.#e.retry.afterStatusCodes.includes(e.response.status)){let i=Number(n)*1e3;Number.isNaN(i)?i=Date.parse(n)-Date.now():i>=Date.parse("2024-01-01")&&(i-=Date.now());let o=this.#e.retry.maxRetryAfter??i;return i<o?i:o}if(e.response.status===413)throw e}return this.#u()}#h(e){return this.#e.parseJson&&(e.json=async()=>this.#e.parseJson(await e.text())),e}#l(e){e&&e.cancel().catch(()=>{})}#o(e){this.#l(e.body??void 0)}async#m(e){try{return await e()}catch(t){let n=Math.min(await this.#g(t),Y);if(this.#n<1)throw t;if(await Oe(n,this.#i?{signal:this.#i}:{}),t instanceof H&&t.customRequest){let i=this.#e.signal?new globalThis.Request(t.customRequest,{signal:this.#e.signal}):new globalThis.Request(t.customRequest);this.#d(i)}for(let i of this.#e.hooks.beforeRetry){let o=await i({request:this.request,options:this.#c(),error:t,retryCount:this.#n});if(o instanceof globalThis.Request){this.#d(o);break}if(o instanceof globalThis.Response)return o;if(o===Q)return}return this.#m(e)}}async#b(){this.#r?.signal.aborted&&(this.#r=new globalThis.AbortController,this.#e.signal=this.#i?AbortSignal.any([this.#i,this.#r.signal]):this.#r.signal,this.request=new globalThis.Request(this.request,{signal:this.#e.signal}));for(let t of this.#e.hooks.beforeRequest){let n=await t(this.request,this.#c(),{retryCount:this.#n});if(n instanceof Response)return n;if(n instanceof globalThis.Request){this.#d(n);break}}let e=lt(this.request,this.#e);return this.#s=this.request,this.request=this.#s.clone(),this.#e.timeout===!1?this.#e.fetch(this.#s,e):ve(this.#s,e,this.#r,this.#e)}#c(){if(!this.#a){let{hooks:e,...t}=this.#e;this.#a=Object.freeze(t)}return this.#a}#d(e){this.#a=void 0,this.request=this.#p(e)}#p(e,t){return!this.#e.onUploadProgress||!e.body?e:st(e,this.#e.onUploadProgress,t??this.#e.body??void 0)}};var xe=r=>{let e=(t,n)=>B.create(t,M(r,n));for(let t of K)e[t]=(n,i)=>B.create(n,M(r,i,{method:t}));return e.create=t=>xe(M(t)),e.extend=t=>(typeof t=="function"&&(t=t(r??{})),xe(M(r,t))),e.stop=Q,e.retry=et,e},Nn=xe(),U=Nn;var In="https://pro.lahat.group/api";function $e(){return process.env.WARDROBE_API_URL??In}function j(r){if(!r)throw new Error("Not authenticated. Run `wardrobe login` first.");return U.create({prefixUrl:$e(),headers:{Authorization:`Bearer ${r}`},retry:0})}u();import{readFileSync as Dn,writeFileSync as Hn,mkdirSync as Vn,rmSync as Fn,existsSync as Ln}from"fs";import{homedir as Mn}from"os";import{join as pt}from"path";function ft(){return process.env.WARDROBE_CONFIG_DIR??pt(Mn(),".config","wardrobe")}function Ce(){return pt(ft(),"config.json")}function _(){let r=Ce();if(!Ln(r))return null;try{return JSON.parse(Dn(r,"utf8"))}catch{return null}}function gt(r){Vn(ft(),{recursive:!0,mode:448}),Hn(Ce(),JSON.stringify(r,null,2),{mode:384})}function bt(){Fn(Ce(),{force:!0})}u();import{readFileSync as Bn}from"fs";function Un(){return new Promise((r,e)=>{let t="";process.stdin.setEncoding("utf8"),process.stdin.on("data",n=>t+=n),process.stdin.on("end",()=>r(t)),process.stdin.on("error",e)})}async function C(r){let e=r==="-"?await Un():Bn(r,"utf8");try{return JSON.parse(e)}catch(t){throw new Error(`Failed to parse JSON input: ${t.message}`)}}function h(r,e,t){e?process.stdout.write(JSON.stringify(r,null,2)+`
|
|
25
|
-
`):t()}function Ae(){return j(_()?.accessToken??null)}async function
|
|
26
|
-
`)}async function
|
|
24
|
+
`)}),this}_outputHelpIfRequested(e){let t=this._getHelpOption();t&&e.find(i=>t.is(i))&&(this.outputHelp(),this._exit(0,"commander.helpDisplayed","(outputHelp)"))}};function Me(r){return r.map(e=>{if(!e.startsWith("--inspect"))return e;let t,n="127.0.0.1",i="9229",o;return(o=e.match(/^(--inspect(-brk)?)$/))!==null?t=o[1]:(o=e.match(/^(--inspect(-brk|-port)?)=([^:]+)$/))!==null?(t=o[1],/^\d+$/.test(o[3])?i=o[3]:n=o[3]):(o=e.match(/^(--inspect(-brk|-port)?)=([^:]+):(\d+)$/))!==null&&(t=o[1],n=o[3],i=o[4]),t&&i!=="0"?`${t}=${n}:${parseInt(i)+1}`:e})}Be.Command=ge});var Ge=R(x=>{"use strict";u();var{Argument:We}=z(),{Command:be}=Ue(),{CommanderError:En,InvalidArgumentError:Je}=F(),{Help:Pn}=ce(),{Option:ze}=he();x.program=new be;x.createCommand=r=>new be(r);x.createOption=(r,e)=>new ze(r,e);x.createArgument=(r,e)=>new We(r,e);x.Command=be;x.Option=ze;x.Argument=We;x.Help=Pn;x.CommanderError=En;x.InvalidArgumentError=Je;x.InvalidOptionArgumentError=Je});u();u();var Ke=fn(Ge(),1),{program:b,createCommand:Nr,createArgument:qr,createOption:Ir,CommanderError:Dr,InvalidArgumentError:Hr,InvalidOptionArgumentError:Vr,Command:Fr,Argument:Lr,Option:Mr,Help:Br}=Ke.default;u();import{existsSync as zn}from"fs";u();u();u();u();var O=class extends Error{response;request;options;constructor(e,t,n){let i=e.status||e.status===0?e.status:"",o=e.statusText??"",s=`${i} ${o}`.trim(),c=s?`status code ${s}`:"an unknown error";super(`Request failed with ${c}: ${t.method} ${t.url}`),this.name="HTTPError",this.response=e,this.request=t,this.options=n}};u();var D=class extends Error{name="NonError";value;constructor(e){let t="Non-error value was thrown";try{typeof e=="string"?t=e:e&&typeof e=="object"&&"message"in e&&typeof e.message=="string"&&(t=e.message)}catch{}super(t),this.value=e}};u();var H=class extends Error{name="ForceRetryError";customDelay;code;customRequest;constructor(e){let t=e?.cause?e.cause instanceof Error?e.cause:new D(e.cause):void 0;super(e?.code?`Forced retry: ${e.code}`:"Forced retry",t?{cause:t}:void 0),this.customDelay=e?.delay,this.code=e?.code,this.customRequest=e?.request}};u();u();var ye=(()=>{let r=!1,e=!1,t=typeof globalThis.ReadableStream=="function",n=typeof globalThis.Request=="function";if(t&&n)try{e=new globalThis.Request("https://empty.invalid",{body:new globalThis.ReadableStream,method:"POST",get duplex(){return r=!0,"half"}}).headers.has("Content-Type")}catch(i){if(i instanceof Error&&i.message==="unsupported BodyInit type")return!1;throw i}return r&&!e})(),Ye=typeof globalThis.AbortController=="function",G=typeof globalThis.AbortSignal=="function"&&typeof globalThis.AbortSignal.any=="function",Qe=typeof globalThis.ReadableStream=="function",Xe=typeof globalThis.FormData=="function",K=["get","post","put","patch","head","delete"],kn=()=>{};kn();var Ze={json:"application/json",text:"text/*",formData:"multipart/form-data",arrayBuffer:"*/*",blob:"*/*",bytes:"*/*"},Y=2147483647,et=new TextEncoder().encode("------WebKitFormBoundaryaxpyiPgbbPti10Rw").length,Q=Symbol("stop"),L=class{options;constructor(e){this.options=e}},tt=r=>new L(r),nt={json:!0,parseJson:!0,stringifyJson:!0,searchParams:!0,prefixUrl:!0,retry:!0,timeout:!0,hooks:!0,throwHttpErrors:!0,onDownloadProgress:!0,onUploadProgress:!0,fetch:!0,context:!0},rt={next:!0},it={method:!0,headers:!0,body:!0,mode:!0,credentials:!0,cache:!0,redirect:!0,referrer:!0,referrerPolicy:!0,integrity:!0,keepalive:!0,signal:!0,window:!0,duplex:!0};var Rn=r=>{if(!r)return 0;if(r instanceof FormData){let e=0;for(let[t,n]of r)e+=et,e+=new TextEncoder().encode(`Content-Disposition: form-data; name="${t}"`).length,e+=typeof n=="string"?new TextEncoder().encode(n).length:n.size;return e}if(r instanceof Blob)return r.size;if(r instanceof ArrayBuffer)return r.byteLength;if(typeof r=="string")return new TextEncoder().encode(r).length;if(r instanceof URLSearchParams)return new TextEncoder().encode(r.toString()).length;if("byteLength"in r)return r.byteLength;if(typeof r=="object"&&r!==null)try{let e=JSON.stringify(r);return new TextEncoder().encode(e).length}catch{return 0}return 0},ot=(r,e,t)=>{let n,i=0;return r.pipeThrough(new TransformStream({transform(o,s){if(s.enqueue(o),n){i+=n.byteLength;let c=e===0?0:i/e;c>=1&&(c=1-Number.EPSILON),t?.({percent:c,totalBytes:Math.max(e,i),transferredBytes:i},n)}n=o},flush(){n&&(i+=n.byteLength,t?.({percent:1,totalBytes:Math.max(e,i),transferredBytes:i},n))}}))},st=(r,e)=>{if(!r.body)return r;if(r.status===204)return new Response(null,{status:r.status,statusText:r.statusText,headers:r.headers});let t=Math.max(0,Number(r.headers.get("content-length"))||0);return new Response(ot(r.body,t,e),{status:r.status,statusText:r.statusText,headers:r.headers})},at=(r,e,t)=>{if(!r.body)return r;let n=Rn(t??r.body);return new Request(r,{duplex:"half",body:ot(r.body,n,e)})};u();u();var E=r=>r!==null&&typeof r=="object";var M=(...r)=>{for(let e of r)if((!E(e)||Array.isArray(e))&&e!==void 0)throw new TypeError("The `options` argument must be an object");return je({},...r)},we=(r={},e={})=>{let t=new globalThis.Headers(r),n=e instanceof globalThis.Headers,i=new globalThis.Headers(e);for(let[o,s]of i.entries())n&&s==="undefined"||s===void 0?t.delete(o):t.set(o,s);return t};function X(r,e,t){return Object.hasOwn(e,t)&&e[t]===void 0?[]:je(r[t]??[],e[t]??[])}var _e=(r={},e={})=>({beforeRequest:X(r,e,"beforeRequest"),beforeRetry:X(r,e,"beforeRetry"),afterResponse:X(r,e,"afterResponse"),beforeError:X(r,e,"beforeError")}),Tn=(r,e)=>{let t=new URLSearchParams;for(let n of[r,e])if(n!==void 0)if(n instanceof URLSearchParams)for(let[i,o]of n.entries())t.append(i,o);else if(Array.isArray(n))for(let i of n){if(!Array.isArray(i)||i.length!==2)throw new TypeError("Array search parameters must be provided in [[key, value], ...] format");t.append(String(i[0]),String(i[1]))}else if(E(n))for(let[i,o]of Object.entries(n))o!==void 0&&t.append(i,String(o));else{let i=new URLSearchParams(n);for(let[o,s]of i.entries())t.append(o,s)}return t},je=(...r)=>{let e={},t={},n={},i,o=[];for(let s of r)if(Array.isArray(s))Array.isArray(e)||(e=[]),e=[...e,...s];else if(E(s)){for(let[c,a]of Object.entries(s)){if(c==="signal"&&a instanceof globalThis.AbortSignal){o.push(a);continue}if(c==="context"){if(a!=null&&(!E(a)||Array.isArray(a)))throw new TypeError("The `context` option must be an object");e={...e,context:a==null?{}:{...e.context,...a}};continue}if(c==="searchParams"){a==null?i=void 0:i=i===void 0?a:Tn(i,a);continue}E(a)&&c in e&&(a=je(e[c],a)),e={...e,[c]:a}}E(s.hooks)&&(n=_e(n,s.hooks),e.hooks=n),E(s.headers)&&(t=we(t,s.headers),e.headers=t)}return i!==void 0&&(e.searchParams=i),o.length>0&&(o.length===1?e.signal=o[0]:G?e.signal=AbortSignal.any(o):e.signal=o.at(-1)),e};u();var ut=r=>K.includes(r)?r.toUpperCase():r,Nn=["get","put","head","delete","options","trace"],qn=[408,413,429,500,502,503,504],In=[413,429,503],ct={limit:2,methods:Nn,statusCodes:qn,afterStatusCodes:In,maxRetryAfter:Number.POSITIVE_INFINITY,backoffLimit:Number.POSITIVE_INFINITY,delay:r=>.3*2**(r-1)*1e3,jitter:void 0,retryOnTimeout:!1},lt=(r={})=>{if(typeof r=="number")return{...ct,limit:r};if(r.methods&&!Array.isArray(r.methods))throw new Error("retry.methods must be an array");if(r.methods&&=r.methods.map(t=>t.toLowerCase()),r.statusCodes&&!Array.isArray(r.statusCodes))throw new Error("retry.statusCodes must be an array");let e=Object.fromEntries(Object.entries(r).filter(([,t])=>t!==void 0));return{...ct,...e}};u();u();var T=class extends Error{request;constructor(e){super(`Request timed out: ${e.method} ${e.url}`),this.name="TimeoutError",this.request=e}};async function ve(r,e,t,n){return new Promise((i,o)=>{let s=setTimeout(()=>{t&&t.abort(),o(new T(r))},n.timeout);n.fetch(r,e).then(i).catch(o).then(()=>{clearTimeout(s)})})}u();async function Oe(r,{signal:e}){return new Promise((t,n)=>{e&&(e.throwIfAborted(),e.addEventListener("abort",i,{once:!0}));function i(){clearTimeout(o),n(e.reason)}let o=setTimeout(()=>{e?.removeEventListener("abort",i),t()},r)})}u();var dt=(r,e)=>{let t={};for(let n in e)Object.hasOwn(e,n)&&!(n in it)&&!(n in nt)&&(!(n in r)||n in rt)&&(t[n]=e[n]);return t},ht=r=>r===void 0?!1:Array.isArray(r)?r.length>0:r instanceof URLSearchParams?r.size>0:typeof r=="object"?Object.keys(r).length>0:typeof r=="string"?r.trim().length>0:!!r;u();function mt(r){return r instanceof O||r?.name===O.name}function pt(r){return r instanceof T||r?.name===T.name}var B=class r{static create(e,t){let n=new r(e,t),i=async()=>{if(typeof n.#e.timeout=="number"&&n.#e.timeout>Y)throw new RangeError(`The \`timeout\` option cannot be greater than ${Y}`);await Promise.resolve();let s=await n.#b();for(let c of n.#e.hooks.afterResponse){let a=n.#h(s.clone()),l;try{l=await c(n.request,n.#c(),a,{retryCount:n.#n})}catch(f){throw n.#o(a),n.#o(s),f}if(l instanceof L)throw n.#o(a),n.#o(s),new H(l.options);let d=l instanceof globalThis.Response?l:s;a!==d&&n.#o(a),s!==d&&n.#o(s),s=d}if(n.#h(s),!s.ok&&(typeof n.#e.throwHttpErrors=="function"?n.#e.throwHttpErrors(s.status):n.#e.throwHttpErrors)){let c=new O(s,n.request,n.#c());for(let a of n.#e.hooks.beforeError)c=await a(c,{retryCount:n.#n});throw c}if(n.#e.onDownloadProgress){if(typeof n.#e.onDownloadProgress!="function")throw new TypeError("The `onDownloadProgress` option must be a function");if(!Qe)throw new Error("Streams are not supported in your environment. `ReadableStream` is missing.");let c=s.clone();return n.#o(s),st(c,n.#e.onDownloadProgress)}return s},o=n.#m(i).finally(()=>{let s=n.#s;n.#l(s?.body??void 0),n.#l(n.request.body??void 0)});for(let[s,c]of Object.entries(Ze))s==="bytes"&&typeof globalThis.Response?.prototype?.bytes!="function"||(o[s]=async()=>{n.request.headers.set("accept",n.request.headers.get("accept")||c);let a=await o;if(s==="json"){if(a.status===204)return"";let l=await a.text();return l===""?"":t.parseJson?t.parseJson(l):JSON.parse(l)}return a[s]()});return o}static#f(e){return e&&typeof e=="object"&&!Array.isArray(e)&&!(e instanceof URLSearchParams)?Object.fromEntries(Object.entries(e).filter(([,t])=>t!==void 0)):e}request;#r;#n=0;#t;#e;#s;#i;#a;constructor(e,t={}){if(this.#t=e,this.#e={...t,headers:we(this.#t.headers,t.headers),hooks:_e({beforeRequest:[],beforeRetry:[],beforeError:[],afterResponse:[]},t.hooks),method:ut(t.method??this.#t.method??"GET"),prefixUrl:String(t.prefixUrl||""),retry:lt(t.retry),throwHttpErrors:t.throwHttpErrors??!0,timeout:t.timeout??1e4,fetch:t.fetch??globalThis.fetch.bind(globalThis),context:t.context??{}},typeof this.#t!="string"&&!(this.#t instanceof URL||this.#t instanceof globalThis.Request))throw new TypeError("`input` must be a string, URL, or Request");if(this.#e.prefixUrl&&typeof this.#t=="string"){if(this.#t.startsWith("/"))throw new Error("`input` must not begin with a slash when using `prefixUrl`");this.#e.prefixUrl.endsWith("/")||(this.#e.prefixUrl+="/"),this.#t=this.#e.prefixUrl+this.#t}Ye&&G&&(this.#i=this.#e.signal??this.#t.signal,this.#r=new globalThis.AbortController,this.#e.signal=this.#i?AbortSignal.any([this.#i,this.#r.signal]):this.#r.signal),ye&&(this.#e.duplex="half"),this.#e.json!==void 0&&(this.#e.body=this.#e.stringifyJson?.(this.#e.json)??JSON.stringify(this.#e.json),this.#e.headers.set("content-type",this.#e.headers.get("content-type")??"application/json"));let n=t.headers&&new globalThis.Headers(t.headers).has("content-type");if(this.#t instanceof globalThis.Request&&(Xe&&this.#e.body instanceof globalThis.FormData||this.#e.body instanceof URLSearchParams)&&!n&&this.#e.headers.delete("content-type"),this.request=new globalThis.Request(this.#t,this.#e),ht(this.#e.searchParams)){let o="?"+(typeof this.#e.searchParams=="string"?this.#e.searchParams.replace(/^\?/,""):new URLSearchParams(r.#f(this.#e.searchParams)).toString()),s=this.request.url.replace(/(?:\?.*?)?(?=#|$)/,o);this.request=new globalThis.Request(s,this.#e)}if(this.#e.onUploadProgress){if(typeof this.#e.onUploadProgress!="function")throw new TypeError("The `onUploadProgress` option must be a function");if(!ye)throw new Error("Request streams are not supported in your environment. The `duplex` option for `Request` is not available.");this.request=this.#p(this.request,this.#e.body??void 0)}}#u(){let e=this.#e.retry.delay(this.#n),t=e;this.#e.retry.jitter===!0?t=Math.random()*e:typeof this.#e.retry.jitter=="function"&&(t=this.#e.retry.jitter(e),(!Number.isFinite(t)||t<0)&&(t=e));let n=this.#e.retry.backoffLimit??Number.POSITIVE_INFINITY;return Math.min(n,t)}async#g(e){if(this.#n++,this.#n>this.#e.retry.limit)throw e;let t=e instanceof Error?e:new D(e);if(t instanceof H)return t.customDelay??this.#u();if(!this.#e.retry.methods.includes(this.request.method.toLowerCase()))throw e;if(this.#e.retry.shouldRetry!==void 0){let n=await this.#e.retry.shouldRetry({error:t,retryCount:this.#n});if(n===!1)throw e;if(n===!0)return this.#u()}if(pt(e)&&!this.#e.retry.retryOnTimeout)throw e;if(mt(e)){if(!this.#e.retry.statusCodes.includes(e.response.status))throw e;let n=e.response.headers.get("Retry-After")??e.response.headers.get("RateLimit-Reset")??e.response.headers.get("X-RateLimit-Retry-After")??e.response.headers.get("X-RateLimit-Reset")??e.response.headers.get("X-Rate-Limit-Reset");if(n&&this.#e.retry.afterStatusCodes.includes(e.response.status)){let i=Number(n)*1e3;Number.isNaN(i)?i=Date.parse(n)-Date.now():i>=Date.parse("2024-01-01")&&(i-=Date.now());let o=this.#e.retry.maxRetryAfter??i;return i<o?i:o}if(e.response.status===413)throw e}return this.#u()}#h(e){return this.#e.parseJson&&(e.json=async()=>this.#e.parseJson(await e.text())),e}#l(e){e&&e.cancel().catch(()=>{})}#o(e){this.#l(e.body??void 0)}async#m(e){try{return await e()}catch(t){let n=Math.min(await this.#g(t),Y);if(this.#n<1)throw t;if(await Oe(n,this.#i?{signal:this.#i}:{}),t instanceof H&&t.customRequest){let i=this.#e.signal?new globalThis.Request(t.customRequest,{signal:this.#e.signal}):new globalThis.Request(t.customRequest);this.#d(i)}for(let i of this.#e.hooks.beforeRetry){let o=await i({request:this.request,options:this.#c(),error:t,retryCount:this.#n});if(o instanceof globalThis.Request){this.#d(o);break}if(o instanceof globalThis.Response)return o;if(o===Q)return}return this.#m(e)}}async#b(){this.#r?.signal.aborted&&(this.#r=new globalThis.AbortController,this.#e.signal=this.#i?AbortSignal.any([this.#i,this.#r.signal]):this.#r.signal,this.request=new globalThis.Request(this.request,{signal:this.#e.signal}));for(let t of this.#e.hooks.beforeRequest){let n=await t(this.request,this.#c(),{retryCount:this.#n});if(n instanceof Response)return n;if(n instanceof globalThis.Request){this.#d(n);break}}let e=dt(this.request,this.#e);return this.#s=this.request,this.request=this.#s.clone(),this.#e.timeout===!1?this.#e.fetch(this.#s,e):ve(this.#s,e,this.#r,this.#e)}#c(){if(!this.#a){let{hooks:e,...t}=this.#e;this.#a=Object.freeze(t)}return this.#a}#d(e){this.#a=void 0,this.request=this.#p(e)}#p(e,t){return!this.#e.onUploadProgress||!e.body?e:at(e,this.#e.onUploadProgress,t??this.#e.body??void 0)}};var xe=r=>{let e=(t,n)=>B.create(t,M(r,n));for(let t of K)e[t]=(n,i)=>B.create(n,M(r,i,{method:t}));return e.create=t=>xe(M(t)),e.extend=t=>(typeof t=="function"&&(t=t(r??{})),xe(M(r,t))),e.stop=Q,e.retry=tt,e},Dn=xe(),U=Dn;var Hn="https://pro.lahat.group/api";function $e(){return process.env.WARDROBE_API_URL??Hn}function j(r){if(!r)throw new Error("Not authenticated. Run `lahat-pro login` first.");return U.create({prefixUrl:$e(),headers:{Authorization:`Bearer ${r}`},retry:0})}u();import{readFileSync as Vn,writeFileSync as Fn,mkdirSync as Ln,rmSync as Mn,existsSync as Bn}from"fs";import{homedir as Un}from"os";import{join as ft}from"path";function gt(){return process.env.WARDROBE_CONFIG_DIR??ft(Un(),".config","wardrobe")}function Ce(){return ft(gt(),"config.json")}function _(){let r=Ce();if(!Bn(r))return null;try{return JSON.parse(Vn(r,"utf8"))}catch{return null}}function bt(r){Ln(gt(),{recursive:!0,mode:448}),Fn(Ce(),JSON.stringify(r,null,2),{mode:384})}function yt(){Mn(Ce(),{force:!0})}u();import{readFileSync as Wn}from"fs";function Jn(){return new Promise((r,e)=>{let t="";process.stdin.setEncoding("utf8"),process.stdin.on("data",n=>t+=n),process.stdin.on("end",()=>r(t)),process.stdin.on("error",e)})}async function C(r){let e=r==="-"?await Jn():Wn(r,"utf8");try{return JSON.parse(e)}catch(t){throw new Error(`Failed to parse JSON input: ${t.message}`)}}function h(r,e,t){e?process.stdout.write(JSON.stringify(r,null,2)+`
|
|
25
|
+
`):t()}function Ae(){return j(_()?.accessToken??null)}async function wt(r={}){let e={};for(let n of["width","height","ceiling","depth","position"])r[n]!==void 0&&(e[n]=r[n]);let t=await Ae().get("configs/init",{searchParams:e}).json();process.stdout.write(JSON.stringify(t.config,null,2)+`
|
|
26
|
+
`)}async function _t(r,e={}){let t=await C(r),n=await Ae().post("configs/validate",{json:{config:t}}).json();h(n,!!e.json,()=>{if(n.valid)process.stdout.write(`valid
|
|
27
27
|
`);else for(let i of n.errors)process.stdout.write(`${i.severity}: ${i.path} \u2014 ${i.message}
|
|
28
|
-
`)}),n.valid||(process.exitCode=1)}async function
|
|
28
|
+
`)}),n.valid||(process.exitCode=1)}async function jt(r,e={}){let t=Ae(),n=r==="-"||zn(r)?await C(r):(await t.get(`designs/${r}`).json()).config,i=await t.post("configs/describe",{json:{config:n,locale:e.locale??"en"}}).json();h(i.lines,!!e.json,()=>process.stdout.write(i.lines.join(`
|
|
29
29
|
`)+`
|
|
30
|
-
`))}u();import{spawn as
|
|
30
|
+
`))}u();import{spawn as Gn}from"child_process";import{setTimeout as Kn}from"timers/promises";function Yn(r){let e=process.platform==="darwin"?"open":process.platform==="win32"?"start":"xdg-open";try{Gn(e,[r],{stdio:"ignore",detached:!0}).unref()}catch{}}async function vt(r={}){let e=$e(),t=await U.post(`${e}/auth/device/code`,{retry:0}).json(),n=`${t.verification_uri}?code=${encodeURIComponent(t.user_code)}`;r.json||(process.stdout.write(`
|
|
31
31
|
To authorize this CLI, visit:
|
|
32
32
|
${t.verification_uri}
|
|
33
33
|
`),process.stdout.write(`and enter code: ${t.user_code}
|
|
34
34
|
|
|
35
|
-
`),
|
|
36
|
-
`));return}catch(s){let a=(s instanceof O?await s.response.json().catch(()=>({})):{}).error;if(a==="authorization_pending")continue;if(a==="slow_down"||s instanceof O&&s.response.status===429){i+=5;continue}throw new Error(`Login failed: ${a??s.message}`)}}throw new Error("Login timed out. Run `
|
|
35
|
+
`),Yn(n));let i=t.interval,o=Date.now()+t.expires_in*1e3;for(;Date.now()<o;){await Kn(i*1e3);try{let s=await U.post(`${e}/auth/device/token`,{json:{device_code:t.device_code},retry:0}).json();bt({..._(),accessToken:s.access_token,apiUrl:e}),h({status:"authorized",scopes:s.scopes},!!r.json,()=>process.stdout.write(`Authorized. Agent key saved.
|
|
36
|
+
`));return}catch(s){let a=(s instanceof O?await s.response.json().catch(()=>({})):{}).error;if(a==="authorization_pending")continue;if(a==="slow_down"||s instanceof O&&s.response.status===429){i+=5;continue}throw new Error(`Login failed: ${a??s.message}`)}}throw new Error("Login timed out. Run `lahat-pro login` again.")}u();async function Ot(r={}){let t=await j(_()?.accessToken??null).get("auth/me").json();h(t,!!r.json,()=>{process.stdout.write(`${t.displayName} <${t.email}> \u2014 account role: ${t.role}
|
|
37
37
|
`),t.agent&&process.stdout.write(`Agent key scopes: ${t.agent.scopes.join(", ")}
|
|
38
|
-
`)})}function
|
|
39
|
-
`))}u();u();u();function
|
|
38
|
+
`)})}function xt(r={}){yt(),h({status:"logged_out"},!!r.json,()=>process.stdout.write(`Logged out.
|
|
39
|
+
`))}u();u();u();function N(r){let e=r?.response?.status;return typeof e=="number"?e:void 0}async function $t(r){try{let e=r.response,t=await(e?.clone?e.clone().json():e?.json());return t&&typeof t=="object"?t:{}}catch{return{}}}import{writeFileSync as Se}from"fs";function w(){return j(_()?.accessToken??null)}function Ee(r){let e=(r??"").replace(/\D/g,"");return e.startsWith("00")&&(e=e.slice(2)),e.startsWith("972")&&(e=e.slice(3)),e.replace(/^0+/,"")}async function Ct(r,e={}){let t=await w().get(`projects/${r}`).json();h(t,!!e.json,()=>{process.stdout.write(`${t.id} ${t.name}
|
|
40
40
|
`),t.customer&&process.stdout.write(`customer: ${t.customer.customerName??"\u2014"} ${t.customer.phoneNumber??""}
|
|
41
41
|
`),t.createdBy&&process.stdout.write(`designer: ${t.createdBy.displayName??"\u2014"} (${t.createdBy.id??""})
|
|
42
|
-
`)})}async function
|
|
43
|
-
`)})}async function
|
|
44
|
-
`)})}async function
|
|
45
|
-
`))}async function
|
|
46
|
-
`)})}async function
|
|
42
|
+
`)})}async function At(r,e={}){let t=await w().get(`projects/${r}/members`).json();h(t.members,!!e.json,()=>{for(let n of t.members)process.stdout.write(`${n.userId} ${n.role} ${n.displayName??n.email??""}
|
|
43
|
+
`)})}async function St(r={}){let e=await w().get("customers").json();h(e.customers,!!r.json,()=>{for(let t of e.customers)process.stdout.write(`${t.id} ${t.customerName??""} ${t.phoneNumber??""}
|
|
44
|
+
`)})}async function Et(r,e={}){let t=await w().get(`customers/${r}`).json();h(t,!!e.json,()=>process.stdout.write(`${t.id} ${t.customerName??""} ${t.phoneNumber??""} ${t.email??""}
|
|
45
|
+
`))}async function Pt(r,e={}){let n=(await w().get(`customers/${r}/projects`).json()).projects??[];h(n,!!e.json,()=>{for(let i of n)process.stdout.write(`${i.id} ${i.name}
|
|
46
|
+
`)})}async function kt(r={}){if(r.open&&!r.project)throw new Error("--open requires --project <id>.");let e,t=null;if(r.project)r.open?(t=(await w().get("orders/open",{searchParams:{projectId:r.project}}).json()).order,e=t?[t]:[]):e=(await w().get("orders",{searchParams:{projectId:r.project}}).json()).orders??[];else{let n={};r.limit!==void 0&&(n.limit=r.limit),r.since!==void 0&&(n.updatedSince=r.since),e=(await w().get("orders",{searchParams:n}).json()).orders??[]}h(r.open?{order:t}:e,!!r.json,()=>{if(e.length===0){process.stdout.write(`no orders
|
|
47
47
|
`);return}for(let n of e){let i=n.totalPrice!==void 0?`${n.totalPrice} ${n.currency??"NIS"}`:"";process.stdout.write(`${n.id??""} #${n.orderNumber??"\u2014"} rev${n.revisionNumber??1} ${n.status??""} ${i}
|
|
48
|
-
`)}})}async function
|
|
48
|
+
`)}})}async function Rt(r,e={}){let t=await w().get(`orders/${r}`).json();h(t,!!e.json,()=>{let n=t.totalPrice!==void 0?`${t.totalPrice} ${t.currency??"NIS"}`:"";process.stdout.write(`${t.id??""} #${t.orderNumber??"\u2014"} rev${t.revisionNumber??1} ${t.status??""} ${n}
|
|
49
49
|
`),process.stdout.write(`project: ${t.projectId??""}
|
|
50
50
|
`),process.stdout.write(`customer: ${t.customerName??""} ${t.phoneNumber??""}
|
|
51
51
|
`);for(let c of t.items??[])process.stdout.write(`design: ${c.designId} ${c.designName}
|
|
52
52
|
`);let i=t.customerDetails;if(i?.deliveryPreference){let c=i.deliveryPreference==="scheduled"&&i.requestedDeliveryDate?`scheduled ${i.requestedDeliveryDate}`:"immediate";process.stdout.write(`delivery: ${c}
|
|
53
53
|
`)}let o=t.statusHistory??[],s=o[o.length-1];s&&process.stdout.write(`last transition: -> ${s.to} ${s.at}
|
|
54
|
-
`)})}async function
|
|
55
|
-
`))}async function
|
|
54
|
+
`)})}async function Tt(r,e={}){let t=e.out??`order-${r}.pdf`,n=Buffer.from(await w().get(`orders/${r}/pdf`).arrayBuffer());Se(t,n),h({path:t,bytes:n.length},!!e.json,()=>process.stdout.write(`${t} ${n.length} bytes
|
|
55
|
+
`))}async function Nt(r,e={}){let t=await w().get(`designs/${r}`).json();if(e.config){process.stdout.write(JSON.stringify(t.config,null,2)+`
|
|
56
56
|
`);return}h(t,!!e.json,()=>{let{width:n,height:i,depth:o}=t.config,s=t.nisTotal==null?"?":t.nisTotal;process.stdout.write(`${t.id} ${t.name??""} ${n??"?"}x${i??"?"}x${o??"?"}cm ${s} NIS v${t.version??"?"}
|
|
57
57
|
`)})}async function qt(r,e={}){let t=e.revision;t===void 0&&(t=(await w().get(`quotations/project/${r}`).json()).revisionNumber);let n=e.out??`quotation-${r}-rev${t}.pdf`,i=Buffer.from(await w().get(`quotations/project/${r}/revisions/${t}/pdf`).arrayBuffer());Se(n,i),h({path:n,bytes:i.length},!!e.json,()=>process.stdout.write(`${n} ${i.length} bytes
|
|
58
|
-
`))}async function
|
|
59
|
-
`))}async function
|
|
58
|
+
`))}async function It(r,e={}){let t=e.out??`design-${r}.jpg`,n=w(),i=async()=>{try{await n.post(`designs/${r}/thumbnail/render`,{timeout:12e4})}catch(s){throw N(s)===503?new Error("The image renderer is not available right now \u2014 try again in a minute."):s}};e.render&&await i();let o;try{o=Buffer.from(await n.get(`designs/${r}/thumbnail`).arrayBuffer())}catch(s){if(e.render||N(s)!==404)throw s;await i(),o=Buffer.from(await n.get(`designs/${r}/thumbnail`).arrayBuffer())}Se(t,o),h({path:t,bytes:o.length},!!e.json,()=>process.stdout.write(`${t} ${o.length} bytes
|
|
59
|
+
`))}async function Dt(r={}){let e={};r.limit!==void 0&&(e.limit=r.limit),r.since!==void 0&&(e.createdSince=r.since),r.before!==void 0&&(e.createdBefore=r.before),r.role!==void 0&&(e.role=r.role);let t=await w().get("users",{searchParams:e}).json();h(t.users,!!r.json,()=>{if(t.users.length===0){process.stdout.write(`no users
|
|
60
60
|
`);return}for(let n of t.users)process.stdout.write(`${n.id??""} ${n.email??""} ${n.displayName??""} ${n.role??""} ${n.createdAt??""} ${n.phone??""} ${n.approvedAt??""}
|
|
61
|
-
`)})}async function
|
|
61
|
+
`)})}async function Ht(r,e={}){if(!r)throw new Error("phone is required.");let t=await w().get("users/by-phone",{searchParams:{phone:r}}).json();h(t.users,!!e.json,()=>{if(t.users.length===0){process.stdout.write(`no matching user
|
|
62
62
|
`);return}for(let n of t.users)process.stdout.write(`${n.id??""} ${n.email??""} ${n.displayName??""} ${n.role??""} ${n.phone??""}
|
|
63
|
-
`)})}async function
|
|
64
|
-
`))}function W(){return j(_()?.accessToken??null)}async function
|
|
65
|
-
`))}async function
|
|
63
|
+
`)})}async function Vt(r={}){let e=await w().get("help-texts").json();h(e,!!r.json,()=>process.stdout.write(`${Object.keys(e).length} help text(s)
|
|
64
|
+
`))}function W(){return j(_()?.accessToken??null)}async function Ft(r,e={}){let t=await C(r),n=await W().post("price",{json:{config:t}}).json();h(n,!!e.json,()=>process.stdout.write(`${n.total} ${n.currency}
|
|
65
|
+
`))}async function Lt(r={}){let e={};r.project?e.projectId=r.project:(r.limit!==void 0&&(e.limit=r.limit),r.since!==void 0&&(e.updatedSince=r.since));let t=await W().get("designs",{searchParams:e}).json();h(t.designs,!!r.json,()=>{if(t.designs.length===0){process.stdout.write(`no designs
|
|
66
66
|
`);return}for(let n of t.designs){let i=r.project?"":` ${n.projectId??""}`;process.stdout.write(`${n.id} ${n.name}${i}
|
|
67
|
-
`)}})}async function
|
|
67
|
+
`)}})}async function Mt(r={}){if(r.project){let n=await W().get(`quotations/project/${r.project}`).json();h(n,!!r.json,()=>{process.stdout.write(`quote #${n.quoteNumber}, ${n.revisionNumber} revision(s)
|
|
68
68
|
`);for(let i of n.revisions)process.stdout.write(`rev${i.revisionNumber} ${i.totalPrice+i.serviceTotal} ${i.currency} ${i.at}
|
|
69
69
|
`)});return}let e={};r.limit!==void 0&&(e.limit=r.limit),r.since!==void 0&&(e.updatedSince=r.since);let t=await W().get("quotations",{searchParams:e}).json();h(t.quotations,!!r.json,()=>{if(t.quotations.length===0){process.stdout.write(`no quotations
|
|
70
70
|
`);return}for(let n of t.quotations){let i=n.totalPrice!==null?`${n.totalPrice+(n.serviceTotal??0)} ${n.currency??"NIS"}`:"";process.stdout.write(`${n.projectId} quote #${n.quoteNumber} rev${n.revisionNumber} ${i} ${n.generatedAt??""}
|
|
71
|
-
`)}})}async function
|
|
72
|
-
`)}})}u();import{writeFileSync as
|
|
71
|
+
`)}})}async function Bt(r={}){let t=(await W().get("projects").json()).projects;if(r.phone){let n=Ee(r.phone);t=t.filter(i=>Ee(i.customer?.phoneNumber)===n)}if(r.designer){let n=r.designer.toLowerCase();t=t.filter(i=>i.createdBy?.id===r.designer||(i.createdBy?.displayName??"").toLowerCase().includes(n))}h(t,!!r.json,()=>{for(let n of t){let i=n.createdBy?.displayName?` ${n.createdBy.displayName}`:"",o=n.customer?.customerName?` ${n.customer.customerName}`:"";process.stdout.write(`${n.id} ${n.name}${o}${i}
|
|
72
|
+
`)}})}u();import{writeFileSync as Qn}from"fs";u();function Z(r){let e={};return r.assembly!==void 0&&(e.includeAssembly=r.assembly),r.transport!==void 0&&(e.includeTransport=r.transport),r.measurement!==void 0&&(e.includeMeasurement=r.measurement),Object.keys(e).length>0?e:void 0}function q(){return j(_()?.accessToken??null)}async function Ut(r,e={}){let t=await C(r),n=await q().post("price",{json:{config:t},searchParams:{preview:"bom"}}).json();h(n,!!e.json,()=>{process.stdout.write(`${n.total} ${n.currency}
|
|
73
73
|
`);for(let i of n.bomPreview?.lines??[])process.stdout.write(` ${i.qty}\xD7 ${i.part} (${i.sku}) ${i.widthMm}\xD7${i.heightMm}mm
|
|
74
74
|
`)})}async function Pe(r,e={}){if(!e.project)throw new Error("--project <id> is required.");let t=await C(r),n=Z(e),i=await q().post("designs",{json:{projectId:e.project,name:e.name??"CLI design",config:t,...n?{serviceOptions:n}:{}}}).json();h(i,!!e.json,()=>process.stdout.write(`${i.id}
|
|
75
|
-
`))}async function
|
|
76
|
-
`))}async function
|
|
77
|
-
`))}async function
|
|
78
|
-
`))}async function
|
|
79
|
-
`))}async function
|
|
75
|
+
`))}async function Wt(r,e={}){let t=Z(e);if(!e.file&&!e.name&&!t)throw new Error("Nothing to update \u2014 pass --file <config>, --name <name> and/or a service flag (--assembly/--no-assembly, --transport/--no-transport, --measurement/--no-measurement).");let n=q(),i=await n.get(`designs/${r}`).json(),o={};e.file&&(o.config=await C(e.file)),e.name&&(o.name=e.name),t&&(o.serviceOptions=t),i.version!==void 0&&(o.version=i.version);let s=await n.put(`designs/${r}`,{json:o}).json();h(s,!!e.json,()=>process.stdout.write(`${s.id} v${s.version??"?"}
|
|
76
|
+
`))}async function Jt(r,e={}){let t=await q().post("quotations/pdf",{json:{projectId:r},timeout:12e4}),n=Number(t.headers.get("x-quote-number")),i=Number(t.headers.get("x-quote-revision")),o=t.headers.get("x-quote-minted")==="true",s=e.out??`quotation-${r}-rev${i}.pdf`,c=Buffer.from(await t.arrayBuffer());Qn(s,c),h({path:s,bytes:c.length,quoteNumber:n,revision:i,minted:o},!!e.json,()=>process.stdout.write(`${s} quote ${n} rev ${i} ${o?"new revision minted":"price unchanged \u2014 existing revision re-served"}
|
|
77
|
+
`))}async function zt(r,e={}){if(!e.yes)throw new Error(`Refusing to archive design ${r} without --yes. Archiving cannot be undone from the app.`);try{await q().delete(`designs/${r}`)}catch(t){throw N(t)===423?new Error(`Design ${r} is in a project that already has an order, so it is frozen \u2014 a person must revise the order first.`):t}h({id:r,archived:!0},!!e.json,()=>process.stdout.write(`archived ${r}
|
|
78
|
+
`))}async function Gt(r,e={}){let t=q(),{project:n,name:i}=e;if(!n||!i){let c=await t.get(`designs/${r}`).json();n??=c.projectId,i??=`${c.name} \u05E2\u05D5\u05EA\u05E7`}let o=await t.post(`designs/${r}/duplicate`,{json:{projectId:n,name:i}}).json(),s=Z(e);s&&await t.put(`designs/${o.id}`,{json:{serviceOptions:s}}).json(),h(o,!!e.json,()=>process.stdout.write(`${o.id}
|
|
79
|
+
`))}async function Kt(r,e,t={}){let n=await q().post(`orders/${r}/agent-transition`,{json:{to:e,...t.dryRun?{dryRun:!0}:{},...t.note?{note:t.note}:{}}}).json();h(n,!!t.json,()=>{n.dryRun?process.stdout.write(`dry run: ${n.from} -> ${n.to} is allowed
|
|
80
80
|
`):n.changed?process.stdout.write(`${n.from} -> ${n.to}
|
|
81
81
|
`):process.stdout.write(`already ${n.status}; nothing changed
|
|
82
|
-
`)})}u();function
|
|
83
|
-
`),
|
|
82
|
+
`)})}u();function Xn(){return j(_()?.accessToken??null)}var P=(...r)=>process.stdout.write(`${r.filter(e=>e!==void 0).join(" ")}
|
|
83
|
+
`),Yt={materials:{path:"configs/materials",render:r=>{for(let e of r.materials)P(e.id,e.surface,e.label)}},handles:{path:"handles",render:r=>{for(let e of r.rows)P(e.sku,e.name,e.isDefault?"(default)":void 0)}},"aluminum-fronts":{path:"aluminum-fronts",render:r=>{let e=new Map(r.colors.map(n=>[n.frontId,n.label])),t=new Map(r.shades.map(n=>[n.frontId,n.label]));P("profile","colorId","shadeId","names");for(let n of r.combos)P(n.profile,n.colorId,n.shadeId,`${e.get(n.colorId)??""} / ${t.get(n.shadeId)??""}`)}},"material-limits":{path:"material-limits",render:r=>{for(let e of r.rows)P(e.key,`${e.maxPartLengthMm}\xD7${e.maxPartWidthMm} mm`)}},"service-pricing":{path:"service-pricing",render:r=>{P("currency",r.currency),P("vatRate",r.vatRate);for(let[e,t]of Object.entries(r.rates))P(e,t)}}},ke=Object.keys(Yt);async function Qt(r,e={}){let t=Yt[r];if(!t)throw new Error(`Unknown catalog "${r}". Choose one of: ${ke.join(", ")}.`);let n=await Xn().get(t.path).json();h(n,!!e.json,()=>t.render(n))}u();import{writeFileSync as Xt}from"fs";var Zt=1e3;async function en(r,e,t={}){if(e.length>Zt)throw new Error(`The prompt is ${e.length} characters; the limit is ${Zt}. Shorten it.`);let n=j(_()?.accessToken??null),i;try{i=await n.post("design-prompt",{json:{projectId:r,prompt:e,locale:t.locale??"he"},timeout:12e4}).json()}catch(s){let c=N(s),a=c?await $t(s):{};throw c===423?new Error("This project already has an order, so it is frozen \u2014 a draft cannot be saved into it."):c===429&&a.error==="design_prompt_quota"?new Error(`The daily AI limit for this key is reached (${a.limit}). Try again tomorrow.`):c===424?new Error("The model could not turn that into a design \u2014 rephrase it or retry."):c===503?new Error("Design-by-prompt is not available right now."):s}if(t.json){t.out&&Xt(t.out,JSON.stringify(i.config,null,2)),h(i,!0,()=>{});return}let o=t.out??`prompt-${new Date().toISOString().replace(/[:.]/g,"-")}.json`;Xt(o,JSON.stringify(i.config,null,2)),h(i,!1,()=>{process.stdout.write(`draft config: ${o}
|
|
84
84
|
`);for(let s of i.assumptions)process.stdout.write(`assumed: ${s}
|
|
85
85
|
`);for(let s of i.adjustments)process.stdout.write(`adjusted: ${typeof s=="string"?s:JSON.stringify(s)}
|
|
86
86
|
`);for(let s of i.warnings)process.stdout.write(`warning: ${s}
|
|
87
|
-
`)})}u();import{fileURLToPath as
|
|
88
|
-
`),process.stdout.write(`
|
|
89
|
-
`)})}u();async function ar(r){if(!(r instanceof O))return null;try{return await r.response.json()}catch{return null}}async function nn(r,e){let t=await ar(r);if(e)return JSON.stringify(t?{error:t.error??"request_failed",...t}:{error:r.message},null,2);if(!t)return`Error: ${r.message}`;let n=[t.error??"Request failed"];return t.detail&&n.push(t.detail),t.fix_hint&&n.push(`fix: ${t.fix_hint}`),t.issues&&n.push(JSON.stringify(t.issues)),`Error: ${n.join(" \u2014 ")}`}u();var rn="2.1.3";function ee(r){return r.option("--assembly","buy assembly for this design").option("--no-assembly","do not buy assembly").option("--transport","buy transport for this design").option("--no-transport","do not buy transport").option("--measurement","buy a measurement visit for this design").option("--no-measurement","do not buy a measurement visit")}b.name("wardrobe").description("Wardrobe configurator CLI").version(rn);b.command("login").description("Authenticate via the OAuth device flow").option("--json","machine-readable output").action(r=>jt(r));b.command("whoami").description("Show the authenticated user").option("--json","machine-readable output").action(r=>vt(r));b.command("logout").description("Remove the stored agent key").option("--json","machine-readable output").action(r=>Ot(r));b.command("init").description("Emit a fresh, valid WardrobeConfig JSON (via the API)").option("--width <cm>","total width in cm, as measured on the wall (gross; a niche: its opening)",r=>Number(r)).option("--height <cm>","wardrobe height in cm (the ceiling follows, 3 cm above)",r=>Number(r)).option("--ceiling <cm>","room ceiling height in cm (the wardrobe stands 3 cm under it)",r=>Number(r)).option("--depth <cm>","depth in cm, doors included (default 60)",r=>Number(r)).option("--position <pos>","right-corner (default) | left-corner | niche | freestanding").action(r=>yt(r));b.command("validate <file>").description("Validate a config against the live rules (file or - for stdin)").option("--json","machine-readable output").action((r,e)=>wt(r,e));b.command("describe <idOrFile>").description("Describe a config (local file/-) or saved design (id), via the API").option("--locale <locale>","en or he","en").option("--json","machine-readable output").action((r,e)=>_t(r,e));b.command("catalog <kind>").description(`List what a config may name, from the live catalogs: ${ke.join(" | ")}. Read this before choosing a colour, handle or aluminium front \u2014 never invent ids`).option("--json","machine-readable output").action((r,e)=>Yt(r,e));b.command("prompt <projectId> <text>").description("Describe a wardrobe in words (he/en) and get a draft config file + the assumptions made. Saves nothing; counts against a daily per-key limit; takes 10-30 s").option("--locale <locale>","he or en","he").option("--out <file>","where to write the draft config (default ./prompt-<timestamp>.json)").option("--json","print the whole response (config, assumptions, adjustments, warnings) instead of writing a file").action((r,e,t)=>Zt(r,e,t));b.command("price <file>").description("Price a config via the API (file or - for stdin)").option("--json","machine-readable output").action((r,e)=>Vt(r,e));b.command("plan <file>").description("Dry-run: price a config + BOM preview (mutates nothing)").option("--json","machine-readable output").action((r,e)=>Bt(r,e));ee(b.command("apply <file>").description("Save a config as a design (file or - for stdin)").requiredOption("--project <id>","project id").option("--name <name>","design name").option("--json","machine-readable output")).action((r,e)=>Pe(r,e));var I=b.command("designs").description("Manage saved designs");I.command("list").description("List designs in a project, or the newest across every project with --project omitted").option("--project <id>","project id").option("--limit <n>","cross-project mode only: max rows (default 20, max 100)",r=>Number(r)).option("--since <iso>","cross-project mode only: only designs updated at/after this ISO 8601 timestamp").option("--json","machine-readable output").action(r=>Ft(r));ee(I.command("create <file>").description("Save a config as a new design in a project (same as `apply`)").requiredOption("--project <id>","project id").option("--name <name>","design name").option("--json","machine-readable output")).action((r,e)=>Pe(r,e));I.command("get <id>").description("Show one saved design with its stored config \u2014 read this before `designs update`, which replaces the whole config").option("--config","print only the bare config: exactly what `designs update --file` accepts").option("--json","machine-readable output: id, projectId, name, version, nisTotal, serviceTotal, config").action((r,e)=>Tt(r,e));ee(I.command("update <id>").description("Revise a saved design (config, name and/or services). Services you do not mention keep their current value").option("--file <file>","new config JSON (file or - for stdin)").option("--name <name>","new design name").option("--json","machine-readable output")).action((r,e)=>Ut(r,e));ee(I.command("duplicate <id>").description("Copy a design (into the same project unless --project is given). Services are not copied \u2014 pass the flags to set them").option("--project <id>","target project (default: the source design's project)").option("--name <name>",'name of the copy (default: "<name> \u05E2\u05D5\u05EA\u05E7")').option("--json","machine-readable output")).action((r,e)=>zt(r,e));I.command("delete <id>").description("Archive a design (soft delete; there is no restore in the app). Requires --yes").option("--yes","confirm the archive").option("--json","machine-readable output").action((r,e)=>Jt(r,e));I.command("thumbnail <id>").description("Download a design's thumbnail image; renders it on the server first if none exists yet").option("--out <file>","destination path").option("--render","re-render on the server even if a thumbnail exists").option("--json","machine-readable output").action((r,e)=>Nt(r,e));var Re=b.command("projects").description("Manage projects");Re.command("list").description("List accessible projects").option("--phone <number>","filter by the customer's phone number").option("--designer <idOrName>","filter by the designer who owns the project").option("--json","machine-readable output").action(r=>Mt(r));Re.command("get <id>").description("Show one project").option("--json","machine-readable output").action((r,e)=>$t(r,e));Re.command("members <id>").description("List a project's owner and members").option("--json","machine-readable output").action((r,e)=>Ct(r,e));var Te=b.command("customers").description("Read customers");Te.command("list").description("List your customers").option("--json","machine-readable output").action(r=>At(r));Te.command("get <id>").description("Show one customer").option("--json","machine-readable output").action((r,e)=>St(r,e));Te.command("projects <id>").description("List a customer's projects").option("--json","machine-readable output").action((r,e)=>Et(r,e));var te=b.command("orders").description("Read orders, or move one along the workflow (orders:transition, office accounts only)");te.command("list").description("List a project's orders, or the newest-updated across every project with --project omitted").option("--project <id>","project id").option("--open","only the project's active (non-cancelled) order (requires --project)").option("--limit <n>","cross-project mode only: max rows (default 20, max 100)",r=>Number(r)).option("--since <iso>","cross-project mode only: only orders updated at/after this ISO 8601 timestamp").option("--json","machine-readable output").action(r=>Pt(r));te.command("get <id>").description("Show one order, with its designs embedded").option("--json","machine-readable output").action((r,e)=>kt(r,e));te.command("pdf <id>").description("Download an order PDF").option("--out <file>","destination path").option("--json","machine-readable output").action((r,e)=>Rt(r,e));te.command("set-status <id> <status>").description("Move an order to its next status (e.g. paid, pending_assembly); only legal steps, never cancelled").option("--dry-run","check the step is allowed without changing anything").option("--note <text>","kept on the order's status history (e.g. a receipt number)").option("--json","machine-readable output").action((r,e,t)=>Gt(r,e,t));var qe=b.command("quotations").description("Read quotations (quotations:read), or mint a revision (quotations:write)");qe.command("list").description("Show a project's quote history, or the newest-generated across every project with --project omitted").option("--project <id>","project id").option("--limit <n>","cross-project mode only: max rows (default 20, max 100)",r=>Number(r)).option("--since <iso>","cross-project mode only: only quotations generated at/after this ISO 8601 timestamp").option("--json","machine-readable output").action(r=>Lt(r));qe.command("pdf <projectId>").description("Download a quotation PDF (default: the project's current revision) \u2014 never mints a new one").option("--revision <n>","a specific historical revision instead of the current one",r=>Number(r)).option("--out <file>","destination path").option("--json","machine-readable output").action((r,e)=>qt(r,e));qe.command("mint <projectId>").description("File the project's quotation at its current price and download the PDF \u2014 unlike `pdf`, this can mint a new revision (requires quotations:write)").option("--out <file>","destination path").option("--json","machine-readable output: path, bytes, quoteNumber, revision, minted").action((r,e)=>Wt(r,e));var on=b.command("users").description("Read registered accounts (requires staff:read)");on.command("list").description("List registered users, newest-registered first").option("--limit <n>","max rows (default 20, max 100)",r=>Number(r)).option("--since <iso>","only users registered at/after this ISO 8601 timestamp").option("--before <iso>","only users registered before this ISO 8601 timestamp (page back with the last row's createdAt)").option("--role <role>","only users with this role: admin, support, designer, client").option("--json","machine-readable output").action(r=>It(r));on.command("by-phone <phone>").description("Find the account(s) whose own phone is this number (+972\u2026 and 05\u2026 forms match)").option("--json","machine-readable output").action((r,e)=>Dt(r,e));b.command("help-texts").description("Read the help-text table").option("--json","machine-readable output").action(r=>Ht(r));var cr=b.command("skill").description("Manage the bundled Claude Skill");cr.command("install").description("Install the wardrobe-configurator Skill for Claude Code").option("--project","install into ./.claude/skills instead of ~/.claude/skills").option("--json","machine-readable output").action(r=>tn(r));b.parseAsync().catch(async r=>{let e=await nn(r,process.argv.includes("--json"));process.stderr.write(`${e}
|
|
87
|
+
`)})}u();import{fileURLToPath as Zn}from"url";import{dirname as Re,join as A}from"path";import{homedir as er}from"os";import{existsSync as tn,mkdirSync as tr,readdirSync as nr,copyFileSync as rr,statSync as ir,readFileSync as or,rmSync as sr}from"fs";function ar(){let r=Re(Zn(import.meta.url));for(let e=0;e<6;e++){let t=A(r,"skill");if(tn(A(t,"SKILL.md")))return t;r=Re(r)}throw new Error("Bundled SKILL.md not found next to the CLI package")}var nn="lahat-pro",cr="wardrobe-configurator";function ur(r){let e=r?A(process.cwd(),".claude"):A(er(),".claude");return A(e,"skills",nn)}function lr(r){let e=A(Re(r),cr),t=A(e,"SKILL.md");if(!(e===r||!tn(t)))return/^name:\s*wardrobe-configurator\s*$/m.test(or(t,"utf8"))?e:void 0}function dr(r={}){let e=r.sourceDir??ar(),t=r.targetDir??ur(!!r.project);tr(t,{recursive:!0});let n=[];for(let o of nr(e)){let s=A(e,o);ir(s).isFile()&&(rr(s,A(t,o)),n.push(o))}let i=lr(t);return i&&sr(i,{recursive:!0}),{target:t,files:n,...i?{removed:i}:{}}}function rn(r){let e=dr({project:r.project});h(e,!!r.json,()=>{process.stdout.write(`Installed ${e.files.length} file(s) to ${e.target}
|
|
88
|
+
`),e.removed&&process.stdout.write(`Removed the old skill at ${e.removed}
|
|
89
|
+
`),process.stdout.write(`Restart Claude Code, then invoke /${nn}
|
|
90
|
+
`)})}u();async function hr(r){if(!(r instanceof O))return null;try{return await r.response.json()}catch{return null}}async function on(r,e){let t=await hr(r);if(e)return JSON.stringify(t?{error:t.error??"request_failed",...t}:{error:r.message},null,2);if(!t)return`Error: ${r.message}`;let n=[t.error??"Request failed"];return t.detail&&n.push(t.detail),t.fix_hint&&n.push(`fix: ${t.fix_hint}`),t.issues&&n.push(JSON.stringify(t.issues)),`Error: ${n.join(" \u2014 ")}`}u();var sn="2.1.5";function ee(r){return r.option("--assembly","buy assembly for this design").option("--no-assembly","do not buy assembly").option("--transport","buy transport for this design").option("--no-transport","do not buy transport").option("--measurement","buy a measurement visit for this design").option("--no-measurement","do not buy a measurement visit")}b.name("lahat-pro").description("Lahat Pro wardrobe CLI (also runs as `wardrobe`)").version(sn);b.command("login").description("Authenticate via the OAuth device flow").option("--json","machine-readable output").action(r=>vt(r));b.command("whoami").description("Show the authenticated user").option("--json","machine-readable output").action(r=>Ot(r));b.command("logout").description("Remove the stored agent key").option("--json","machine-readable output").action(r=>xt(r));b.command("init").description("Emit a fresh, valid WardrobeConfig JSON (via the API)").option("--width <cm>","total width in cm, as measured on the wall (gross; a niche: its opening)",r=>Number(r)).option("--height <cm>","wardrobe height in cm (the ceiling follows, 3 cm above)",r=>Number(r)).option("--ceiling <cm>","room ceiling height in cm (the wardrobe stands 3 cm under it)",r=>Number(r)).option("--depth <cm>","depth in cm, doors included (default 60)",r=>Number(r)).option("--position <pos>","right-corner (default) | left-corner | niche | freestanding").action(r=>wt(r));b.command("validate <file>").description("Validate a config against the live rules (file or - for stdin)").option("--json","machine-readable output").action((r,e)=>_t(r,e));b.command("describe <idOrFile>").description("Describe a config (local file/-) or saved design (id), via the API").option("--locale <locale>","en or he","en").option("--json","machine-readable output").action((r,e)=>jt(r,e));b.command("catalog <kind>").description(`List what a config may name, from the live catalogs: ${ke.join(" | ")}. Read this before choosing a colour, handle or aluminium front \u2014 never invent ids`).option("--json","machine-readable output").action((r,e)=>Qt(r,e));b.command("prompt <projectId> <text>").description("Describe a wardrobe in words (he/en) and get a draft config file + the assumptions made. Saves nothing; counts against a daily per-key limit; takes 10-30 s").option("--locale <locale>","he or en","he").option("--out <file>","where to write the draft config (default ./prompt-<timestamp>.json)").option("--json","print the whole response (config, assumptions, adjustments, warnings) instead of writing a file").action((r,e,t)=>en(r,e,t));b.command("price <file>").description("Price a config via the API (file or - for stdin)").option("--json","machine-readable output").action((r,e)=>Ft(r,e));b.command("plan <file>").description("Dry-run: price a config + BOM preview (mutates nothing)").option("--json","machine-readable output").action((r,e)=>Ut(r,e));ee(b.command("apply <file>").description("Save a config as a design (file or - for stdin)").requiredOption("--project <id>","project id").option("--name <name>","design name").option("--json","machine-readable output")).action((r,e)=>Pe(r,e));var I=b.command("designs").description("Manage saved designs");I.command("list").description("List designs in a project, or the newest across every project with --project omitted").option("--project <id>","project id").option("--limit <n>","cross-project mode only: max rows (default 20, max 100)",r=>Number(r)).option("--since <iso>","cross-project mode only: only designs updated at/after this ISO 8601 timestamp").option("--json","machine-readable output").action(r=>Lt(r));ee(I.command("create <file>").description("Save a config as a new design in a project (same as `apply`)").requiredOption("--project <id>","project id").option("--name <name>","design name").option("--json","machine-readable output")).action((r,e)=>Pe(r,e));I.command("get <id>").description("Show one saved design with its stored config \u2014 read this before `designs update`, which replaces the whole config").option("--config","print only the bare config: exactly what `designs update --file` accepts").option("--json","machine-readable output: id, projectId, name, version, nisTotal, serviceTotal, config").action((r,e)=>Nt(r,e));ee(I.command("update <id>").description("Revise a saved design (config, name and/or services). Services you do not mention keep their current value").option("--file <file>","new config JSON (file or - for stdin)").option("--name <name>","new design name").option("--json","machine-readable output")).action((r,e)=>Wt(r,e));ee(I.command("duplicate <id>").description("Copy a design (into the same project unless --project is given). Services are not copied \u2014 pass the flags to set them").option("--project <id>","target project (default: the source design's project)").option("--name <name>",'name of the copy (default: "<name> \u05E2\u05D5\u05EA\u05E7")').option("--json","machine-readable output")).action((r,e)=>Gt(r,e));I.command("delete <id>").description("Archive a design (soft delete; there is no restore in the app). Requires --yes").option("--yes","confirm the archive").option("--json","machine-readable output").action((r,e)=>zt(r,e));I.command("thumbnail <id>").description("Download a design's thumbnail image; renders it on the server first if none exists yet").option("--out <file>","destination path").option("--render","re-render on the server even if a thumbnail exists").option("--json","machine-readable output").action((r,e)=>It(r,e));var Te=b.command("projects").description("Manage projects");Te.command("list").description("List accessible projects").option("--phone <number>","filter by the customer's phone number").option("--designer <idOrName>","filter by the designer who owns the project").option("--json","machine-readable output").action(r=>Bt(r));Te.command("get <id>").description("Show one project").option("--json","machine-readable output").action((r,e)=>Ct(r,e));Te.command("members <id>").description("List a project's owner and members").option("--json","machine-readable output").action((r,e)=>At(r,e));var Ne=b.command("customers").description("Read customers");Ne.command("list").description("List your customers").option("--json","machine-readable output").action(r=>St(r));Ne.command("get <id>").description("Show one customer").option("--json","machine-readable output").action((r,e)=>Et(r,e));Ne.command("projects <id>").description("List a customer's projects").option("--json","machine-readable output").action((r,e)=>Pt(r,e));var te=b.command("orders").description("Read orders, or move one along the workflow (orders:transition, office accounts only)");te.command("list").description("List a project's orders, or the newest-updated across every project with --project omitted").option("--project <id>","project id").option("--open","only the project's active (non-cancelled) order (requires --project)").option("--limit <n>","cross-project mode only: max rows (default 20, max 100)",r=>Number(r)).option("--since <iso>","cross-project mode only: only orders updated at/after this ISO 8601 timestamp").option("--json","machine-readable output").action(r=>kt(r));te.command("get <id>").description("Show one order, with its designs embedded").option("--json","machine-readable output").action((r,e)=>Rt(r,e));te.command("pdf <id>").description("Download an order PDF").option("--out <file>","destination path").option("--json","machine-readable output").action((r,e)=>Tt(r,e));te.command("set-status <id> <status>").description("Move an order to its next status (e.g. paid, pending_assembly); only legal steps, never cancelled").option("--dry-run","check the step is allowed without changing anything").option("--note <text>","kept on the order's status history (e.g. a receipt number)").option("--json","machine-readable output").action((r,e,t)=>Kt(r,e,t));var qe=b.command("quotations").description("Read quotations (quotations:read), or mint a revision (quotations:write)");qe.command("list").description("Show a project's quote history, or the newest-generated across every project with --project omitted").option("--project <id>","project id").option("--limit <n>","cross-project mode only: max rows (default 20, max 100)",r=>Number(r)).option("--since <iso>","cross-project mode only: only quotations generated at/after this ISO 8601 timestamp").option("--json","machine-readable output").action(r=>Mt(r));qe.command("pdf <projectId>").description("Download a quotation PDF (default: the project's current revision) \u2014 never mints a new one").option("--revision <n>","a specific historical revision instead of the current one",r=>Number(r)).option("--out <file>","destination path").option("--json","machine-readable output").action((r,e)=>qt(r,e));qe.command("mint <projectId>").description("File the project's quotation at its current price and download the PDF \u2014 unlike `pdf`, this can mint a new revision (requires quotations:write)").option("--out <file>","destination path").option("--json","machine-readable output: path, bytes, quoteNumber, revision, minted").action((r,e)=>Jt(r,e));var an=b.command("users").description("Read registered accounts (requires staff:read)");an.command("list").description("List registered users, newest-registered first").option("--limit <n>","max rows (default 20, max 100)",r=>Number(r)).option("--since <iso>","only users registered at/after this ISO 8601 timestamp").option("--before <iso>","only users registered before this ISO 8601 timestamp (page back with the last row's createdAt)").option("--role <role>","only users with this role: admin, support, designer, client").option("--json","machine-readable output").action(r=>Dt(r));an.command("by-phone <phone>").description("Find the account(s) whose own phone is this number (+972\u2026 and 05\u2026 forms match)").option("--json","machine-readable output").action((r,e)=>Ht(r,e));b.command("help-texts").description("Read the help-text table").option("--json","machine-readable output").action(r=>Vt(r));var mr=b.command("skill").description("Manage the bundled Claude Skill");mr.command("install").description("Install the lahat-pro Skill for Claude Code").option("--project","install into ./.claude/skills instead of ~/.claude/skills").option("--json","machine-readable output").action(r=>rn(r));b.parseAsync().catch(async r=>{let e=await on(r,process.argv.includes("--json"));process.stderr.write(`${e}
|
|
90
91
|
`),process.exit(1)});
|
package/package.json
CHANGED
|
@@ -1,10 +1,11 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@lahat-group/cli",
|
|
3
|
-
"version": "2.1.
|
|
3
|
+
"version": "2.1.5",
|
|
4
4
|
"description": "CLI + Claude Skill to build, validate, price, and save wardrobe designs.",
|
|
5
5
|
"license": "UNLICENSED",
|
|
6
6
|
"type": "module",
|
|
7
7
|
"bin": {
|
|
8
|
+
"lahat-pro": "dist/index.js",
|
|
8
9
|
"wardrobe": "dist/index.js"
|
|
9
10
|
},
|
|
10
11
|
"files": [
|
package/skill/SKILL.md
CHANGED
|
@@ -1,14 +1,19 @@
|
|
|
1
1
|
---
|
|
2
|
-
name:
|
|
3
|
-
description: Use when
|
|
2
|
+
name: lahat-pro
|
|
3
|
+
description: Use when a designer (or office staff) wants to design, price, revise or quote a Lahat Pro wardrobe/closet from the terminal — phrases like "design a wardrobe for my customer", "a 2.4 m wardrobe with drawers", "price this design", "make it 3 m wide", "send the customer a quote", "validate my wardrobe config" — OR to look up their own projects, customers, designs, orders and quotations and their PDFs, e.g. "find the customer with phone 05x", "who is on this project", "what is the status of this order", "download the order PDF". Office staff keys can also look up registered users and other designers' projects (staff.md). Drives the `lahat-pro` CLI (HTTP client over the configurator API); a WardrobeConfig JSON file on disk is the unit of work for design verbs, and every lookup verb is read-only.
|
|
4
4
|
---
|
|
5
5
|
|
|
6
|
-
#
|
|
6
|
+
# Lahat Pro CLI
|
|
7
7
|
|
|
8
8
|
Build, validate, price, save, and stage wardrobe designs from the terminal via the
|
|
9
|
-
`
|
|
9
|
+
`lahat-pro` CLI. A **`WardrobeConfig` JSON file on disk is the unit of work**. The
|
|
10
10
|
agent loop is: **init → edit → validate → price → plan → apply**.
|
|
11
11
|
|
|
12
|
+
**Start with `lahat-pro whoami --json`.** It tells you who you work for (`role`) and what
|
|
13
|
+
the key may do (`agent.scopes`). This file is everything a designer needs. If the scopes
|
|
14
|
+
include `staff:read` or `orders:transition`, the key belongs to office staff — also read
|
|
15
|
+
[staff.md](staff.md) for the extra verbs; otherwise don't reach for them.
|
|
16
|
+
|
|
12
17
|
## Never invent an id — read the catalog
|
|
13
18
|
|
|
14
19
|
A config names colours, a handle and (optionally) aluminium door fronts by **id**, and
|
|
@@ -18,53 +23,85 @@ quietly substituting a default colour. So before choosing one, read the live lis
|
|
|
18
23
|
|
|
19
24
|
| Verb | Gives you |
|
|
20
25
|
|---|---|
|
|
21
|
-
| `
|
|
22
|
-
| `
|
|
23
|
-
| `
|
|
24
|
-
| `
|
|
26
|
+
| `lahat-pro catalog materials` | Current exterior + interior colours: `id`, surface, Hebrew name, supplier code. Use the `id` in `materialExternal` / `materialInternal` (and a table column's `table.material`) |
|
|
27
|
+
| `lahat-pro catalog handles` | Handle `sku` + Hebrew name (`(default)` marks the one used when `handleSku` is omitted) → `handleSku` |
|
|
28
|
+
| `lahat-pro catalog aluminum-fronts` | Every valid `profile` × `colorId` × `shadeId` triple for a column's `doorFront`, with names. Use the `colorId`/`shadeId` printed here — they are **not** the long database ids |
|
|
29
|
+
| `lahat-pro catalog material-limits` / `service-pricing` | Max part sizes per material / the public service rates |
|
|
25
30
|
|
|
26
31
|
Old ids you may remember (`white-melamine`, `oak-veneer`, `interior-eco-white`) are
|
|
27
32
|
retired — they are not in `catalog materials`, so don't use them.
|
|
28
33
|
|
|
34
|
+
**Ask for the exterior colour and the handle** before you save a design for a customer.
|
|
35
|
+
They are the two visible choices with no business default: left out, the design gets the
|
|
36
|
+
catalog's placeholder colour (turquoise) and whichever handle the catalog marks
|
|
37
|
+
`(default)`, which is rarely what anyone wanted.
|
|
38
|
+
|
|
29
39
|
## Prerequisites
|
|
30
40
|
|
|
31
41
|
- Install the CLI: `npm install -g @lahat-group/cli` (or run ad-hoc via `npx @lahat-group/cli <verb>`).
|
|
42
|
+
The command is `lahat-pro`; the older name `wardrobe` still works and does the same.
|
|
32
43
|
It ships as a self-contained binary — no build step, no extra dependencies. It holds
|
|
33
44
|
no domain logic of its own; the rules live in the API.
|
|
34
45
|
- **Authenticate first — every verb needs it.** The CLI is a thin HTTP client: `init`,
|
|
35
46
|
`validate` and `describe` are served by the API just as `price` and `apply` are, so
|
|
36
|
-
none of them work offline. `Not authenticated. Run \`
|
|
47
|
+
none of them work offline. `Not authenticated. Run \`lahat-pro login\` first.` means
|
|
37
48
|
exactly that.
|
|
38
|
-
- `
|
|
49
|
+
- `lahat-pro login` runs the OAuth device flow — it prints a
|
|
39
50
|
user code, opens `/activate` in the browser, and stores a scoped agent key at
|
|
40
|
-
`~/.config/wardrobe/config.json` (chmod 600). Confirm with `
|
|
51
|
+
`~/.config/wardrobe/config.json` (chmod 600). Confirm with `lahat-pro whoami`.
|
|
41
52
|
- The CLI targets the **production** API by default. Set `WARDROBE_API_URL` to override
|
|
42
53
|
(e.g. `http://localhost:3001/api` for a local dev server).
|
|
43
54
|
- Every verb accepts `--json` for machine-readable output. Read those; don't scrape prose.
|
|
44
55
|
|
|
56
|
+
## Where a design goes — customers, projects and your Play room
|
|
57
|
+
|
|
58
|
+
Every design is saved into a **project**, and every project belongs to a **customer**.
|
|
59
|
+
`lahat-pro projects list` shows yours with each one's customer; `--phone <number>` finds a
|
|
60
|
+
customer's project by their number.
|
|
61
|
+
|
|
62
|
+
- **The CLI cannot create a customer or a project.** For a new customer, ask the user to
|
|
63
|
+
add the customer in the web app and open them (that gives the customer their project),
|
|
64
|
+
then `lahat-pro projects list` to get its id.
|
|
65
|
+
- **Your Play room** is the project whose customer is you (your own name on both). It is a
|
|
66
|
+
sandbox for trying things out — save experiments there, never a real customer's design,
|
|
67
|
+
and archive what you no longer need.
|
|
68
|
+
- A customer invited into a project is a **member** (`lahat-pro projects members <id>`) and
|
|
69
|
+
sees every design saved there. Don't save drafts or experiments into a customer's project.
|
|
70
|
+
|
|
45
71
|
## The loop
|
|
46
72
|
|
|
47
|
-
1. **init** — `
|
|
73
|
+
1. **init** — `lahat-pro init [--width <cm>] [--position <pos>] [--height <cm> | --ceiling <cm>] [--depth <cm>] > wardrobe.json`
|
|
48
74
|
emits a fresh, valid `WardrobeConfig` on the Lahat Pro defaults below (full-width,
|
|
49
75
|
split into columns). `--width` is the **gross** wall measurement; the server turns it
|
|
50
76
|
into the net width for `--position`, and sets the height/ceiling pair.
|
|
51
77
|
2. **edit** — modify `wardrobe.json` directly (see shape below).
|
|
52
|
-
3. **validate** — `
|
|
53
|
-
**live** constraint pipeline server-side — the same rules `
|
|
78
|
+
3. **validate** — `lahat-pro validate wardrobe.json` (or `-` for stdin). Runs the
|
|
79
|
+
**live** constraint pipeline server-side — the same rules `lahat-pro price` enforces,
|
|
54
80
|
so a config `validate` approves can never be one `price` rejects.
|
|
55
81
|
Exit 0 = valid; exit 1 + structured errors otherwise. Do this after every edit.
|
|
56
|
-
4. **price** — `
|
|
57
|
-
the API's unified area×rate engine.
|
|
58
|
-
5. **plan** — `
|
|
82
|
+
4. **price** — `lahat-pro price wardrobe.json` → authoritative total in **NIS** from
|
|
83
|
+
the API's unified area×rate engine — **before VAT** (see below).
|
|
84
|
+
5. **plan** — `lahat-pro plan wardrobe.json` → dry-run price **plus a BOM preview**.
|
|
59
85
|
Mutates nothing. Use this to preview before applying.
|
|
60
|
-
6. **apply** — `
|
|
86
|
+
6. **apply** — `lahat-pro apply wardrobe.json --project <id> [--name <name>]` → saves
|
|
61
87
|
the config as a design in that project and prints its `{id}`. **`--project` is
|
|
62
|
-
required.** `
|
|
88
|
+
required.** `lahat-pro designs create <file> --project <id>` is the same verb under
|
|
63
89
|
the `designs` group, if that reads more clearly in context.
|
|
64
90
|
|
|
91
|
+
### Prices are before VAT
|
|
92
|
+
|
|
93
|
+
Every number the CLI prints — `price`, `plan`, `designs get` (`nisTotal`, `serviceTotal`)
|
|
94
|
+
— is **before VAT**. The web app, the quotation PDF and the customer all see it **with
|
|
95
|
+
VAT, rounded to whole shekels**: `round(price × (1 + vatRate))`, where `vatRate` comes
|
|
96
|
+
from `lahat-pro catalog service-pricing` (0.18 today). A design that prices at 5,052.94
|
|
97
|
+
here shows as **5,962** on the website. When you tell the user a price, say which one it
|
|
98
|
+
is — and use the VAT-inclusive figure for anything the customer will see. Services
|
|
99
|
+
(`serviceTotal`) are separate and also before VAT; the project total the customer pays is
|
|
100
|
+
the designs plus the services they bought, with VAT.
|
|
101
|
+
|
|
65
102
|
### Lahat Pro defaults — apply them unless the user says otherwise
|
|
66
103
|
|
|
67
|
-
`init`, `
|
|
104
|
+
`init`, `lahat-pro prompt` and the web wizard all start from these; keep to them when you
|
|
68
105
|
edit a config by hand.
|
|
69
106
|
|
|
70
107
|
- **Width is gross.** Every width the user gives is what they measure on the wall (a niche:
|
|
@@ -80,7 +117,7 @@ edit a config by hand.
|
|
|
80
117
|
- **Interior colour:** warm oak mix (אלון חם מיקס, `interior-kh62-dt`) unless asked.
|
|
81
118
|
- **Drawers:** "one drawer" → a pair of small (15 cm) drawers; "two drawers" → two large
|
|
82
119
|
(33.5 cm) drawers; both on the **second level from the bottom**. A size the user names
|
|
83
|
-
wins. `
|
|
120
|
+
wins. `lahat-pro prompt` and the wizard place them; editing modules, leave one level free
|
|
84
121
|
under the stack.
|
|
85
122
|
- **Hanging rail:** one level below the highest position (one shelf above it), back at the
|
|
86
123
|
top only when it would not clear the drawers. A standard rail — a pull-down rail
|
|
@@ -90,9 +127,9 @@ edit a config by hand.
|
|
|
90
127
|
|
|
91
128
|
If the user describes what they want instead of giving dimensions —
|
|
92
129
|
"a 2.4 m wardrobe, drawers in the middle, glass doors on the first column" — use
|
|
93
|
-
`
|
|
130
|
+
`lahat-pro prompt <projectId> "<their words>" [--locale he|en] [--out draft.json]`. It
|
|
94
131
|
writes a draft config to a file (default `./prompt-<timestamp>.json`) and prints the
|
|
95
|
-
**assumptions** it made (e.g. "assumed
|
|
132
|
+
**assumptions** it made (e.g. "assumed a right corner"), plus any adjustments and warnings.
|
|
96
133
|
Saves nothing. Then: **show the user the assumptions and ask them to confirm** → `validate`
|
|
97
134
|
→ `price` → `apply`. Treat the draft as a starting point, never as a finished design.
|
|
98
135
|
|
|
@@ -112,7 +149,7 @@ services they asked for, so pass the flags rather than assuming.
|
|
|
112
149
|
|
|
113
150
|
## Revising a saved design
|
|
114
151
|
|
|
115
|
-
`
|
|
152
|
+
`lahat-pro designs update <id> [--file <config>] [--name <name>] [service flags]` revises a
|
|
116
153
|
design in place — pass any of them. Prefer this over creating a second design when the user
|
|
117
154
|
is iterating; a project accumulating `CLI design`, `CLI design 2`, `CLI design 3` is
|
|
118
155
|
almost always a bug in how the agent worked, not what the user wanted.
|
|
@@ -122,12 +159,12 @@ config, so a resize built from a description instead of the saved design wipes i
|
|
|
122
159
|
layout, materials and hardware. The safe loop for "make it 3 m wide" is:
|
|
123
160
|
|
|
124
161
|
```bash
|
|
125
|
-
|
|
162
|
+
lahat-pro designs get <id> --config > cfg.json # the bare config, exactly what update reads back
|
|
126
163
|
# edit ONLY what was asked in cfg.json (a column is at most 120 cm: widen column widths)
|
|
127
|
-
|
|
164
|
+
lahat-pro validate cfg.json && lahat-pro price cfg.json
|
|
128
165
|
# show the user "from 2.77 m to 3.00 m, price X → Y" and wait for a yes
|
|
129
|
-
|
|
130
|
-
|
|
166
|
+
lahat-pro designs update <id> --file cfg.json
|
|
167
|
+
lahat-pro designs get <id> --json # nisTotal = the new price
|
|
131
168
|
```
|
|
132
169
|
|
|
133
170
|
`designs get <id>` alone prints one line (name, size, price, version); `--json` prints
|
|
@@ -143,72 +180,66 @@ Two refusals to expect, neither of which is retryable:
|
|
|
143
180
|
user's intent on top, and tell them it changed underneath you. **Never** loop.
|
|
144
181
|
- **`423 projectLocked`** — the project has a live (non-cancelled) order, which froze
|
|
145
182
|
its designs. No design in it can be created, updated or deleted, and no new quotation
|
|
146
|
-
revision minted, until a human cancels that order —
|
|
147
|
-
|
|
148
|
-
`
|
|
183
|
+
revision minted, until a human cancels that order — whoever's key it is. Say so; don't
|
|
184
|
+
try another design or another verb. (Check
|
|
185
|
+
`lahat-pro orders list --project <id> --open` first to tell the user *why* before trying.)
|
|
149
186
|
|
|
150
187
|
Note that updating a config **clears the design's thumbnail** (the stored image was of
|
|
151
|
-
the old config); the web app re-captures it on next view, and `
|
|
188
|
+
the old config); the web app re-captures it on next view, and `lahat-pro designs thumbnail
|
|
152
189
|
<id>` renders a fresh one on the server on demand. That is expected, not an error.
|
|
153
190
|
|
|
154
191
|
### Copying and removing a design
|
|
155
192
|
|
|
156
|
-
- `
|
|
193
|
+
- `lahat-pro designs duplicate <id> [--project <id>] [--name <name>] [service flags]` copies
|
|
157
194
|
a design — into the same project, named `<name> עותק`, unless told otherwise. **Services
|
|
158
195
|
are not copied**; pass the flags to set them on the copy. Prints the new id.
|
|
159
|
-
- `
|
|
196
|
+
- `lahat-pro designs delete <id> --yes` **archives** a design. There is no restore in the
|
|
160
197
|
app, so it refuses without `--yes` — and you should only pass `--yes` when the user has
|
|
161
198
|
clearly asked for this design to be deleted. A project with an order answers `423`.
|
|
162
199
|
|
|
163
|
-
`
|
|
200
|
+
`lahat-pro describe <idOrFile>` gives a human-readable summary of a local file/`-`
|
|
164
201
|
or a saved design id.
|
|
165
202
|
|
|
166
203
|
## Reading what exists
|
|
167
204
|
|
|
168
|
-
Every read the key can reach has a verb
|
|
169
|
-
customers,
|
|
170
|
-
|
|
171
|
-
`
|
|
172
|
-
answer `403 insufficient_scope` whoever signed in).
|
|
205
|
+
Every read the key can reach has a verb, and they are all reads — the CLI can read
|
|
206
|
+
customers, projects and orders but never create or change them (only office staff can
|
|
207
|
+
move an order along; see staff.md). Quotations are the one other thing you can write:
|
|
208
|
+
`quotations mint`.
|
|
173
209
|
|
|
174
210
|
| Verb | Shows |
|
|
175
211
|
|---|---|
|
|
176
|
-
| `
|
|
177
|
-
| `
|
|
178
|
-
| `
|
|
179
|
-
| `
|
|
180
|
-
| `
|
|
181
|
-
| `
|
|
182
|
-
| `
|
|
183
|
-
| `
|
|
184
|
-
| `
|
|
185
|
-
| `
|
|
186
|
-
| `
|
|
187
|
-
| `
|
|
188
|
-
| `
|
|
189
|
-
| `
|
|
190
|
-
| `
|
|
191
|
-
| `
|
|
192
|
-
| `
|
|
193
|
-
| `
|
|
194
|
-
| `
|
|
195
|
-
| `
|
|
196
|
-
| `
|
|
197
|
-
| `
|
|
198
|
-
| `
|
|
199
|
-
| `
|
|
200
|
-
| `
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
`projects list` already returns each project's **customer and owning designer inline** —
|
|
208
|
-
so "who is the customer on each of this designer's projects" is one call plus a filter,
|
|
209
|
-
never one call per project. Prefer `--phone` / `--designer` over fetching and grepping.
|
|
210
|
-
|
|
211
|
-
Every cross-project/cross-tenant list (`designs`, `orders`, `quotations`, `users`) takes
|
|
212
|
+
| `lahat-pro projects list` | Projects you can access (needed for `--project`) |
|
|
213
|
+
| `lahat-pro projects list --phone <number>` | Only projects whose **customer** has that number |
|
|
214
|
+
| `lahat-pro projects get <id>` | One project: customer + owning designer |
|
|
215
|
+
| `lahat-pro projects members <id>` | Owner plus every invited member, with roles |
|
|
216
|
+
| `lahat-pro customers list` | Your customers |
|
|
217
|
+
| `lahat-pro customers get <id>` | One customer |
|
|
218
|
+
| `lahat-pro customers projects <id>` | That customer's projects |
|
|
219
|
+
| `lahat-pro designs list --project <id>` | Designs saved in a project |
|
|
220
|
+
| `lahat-pro designs list` | The newest designs across every project you can see |
|
|
221
|
+
| `lahat-pro designs list --limit <n>` `--since <ISO>` | Same, paged — `--limit` caps rows (default 20, max 100), `--since` filters by `updatedAt >=` |
|
|
222
|
+
| `lahat-pro designs get <id>` | One design: name, size, live price, version. `--json` adds `projectId`, `nisTotal`, `serviceTotal` and the full `config`; `--config` prints only the bare config (what `designs update --file` reads) |
|
|
223
|
+
| `lahat-pro designs thumbnail <id> --out f.jpg` | The design's rendered thumbnail. A design nobody has opened in a browser has none yet, so the server renders it first (~20 s); `--render` forces a fresh render. `503` means the renderer is down — retry in a minute |
|
|
224
|
+
| `lahat-pro orders list --project <id>` | Every order the project has had |
|
|
225
|
+
| `lahat-pro orders list --project <id> --open` | Only its active (non-cancelled) order |
|
|
226
|
+
| `lahat-pro orders list` | The newest-**updated** orders across every project you can see — "what moved", not "what's new": a status change or a revision surfaces an old order here too |
|
|
227
|
+
| `lahat-pro orders list --limit <n>` `--since <ISO>` | Same, paged (`--since` filters by `updatedAt >=`) |
|
|
228
|
+
| `lahat-pro orders get <id>` | One order, with its designs' frozen config embedded — no second call to `designs` needed. Prints the buyer's delivery choice (`delivery: immediate` or `delivery: scheduled <date>`) once they have verified their details |
|
|
229
|
+
| `lahat-pro orders pdf <id> --out f.pdf` | The order PDF |
|
|
230
|
+
| `lahat-pro quotations list --project <id>` | That project's quote number + full revision history |
|
|
231
|
+
| `lahat-pro quotations list` | Every quotation you can see, **newest-generated first** — this is "latest quotes generation" |
|
|
232
|
+
| `lahat-pro quotations list --limit <n>` `--since <ISO>` | Same, paged (`--since` filters by `updatedAt >=`, i.e. last generated at/after) |
|
|
233
|
+
| `lahat-pro quotations pdf <projectId> --out f.pdf` | The project's **current** quotation revision's PDF — fetches only, never mints one |
|
|
234
|
+
| `lahat-pro quotations pdf <projectId> --revision <n> --out f.pdf` | A specific historical revision's PDF instead |
|
|
235
|
+
| `lahat-pro quotations mint <projectId> --out f.pdf` | File the quotation at the project's **current** price and download it. **Unlike `pdf`, this can mint a new revision** (1, 2, 3…, history kept) when the price moved since the last one; at an unchanged price it re-serves the stored revision. Output says which (`--json`: `minted`). Needs `quotations:write`; refused with `423` once the project has an order. Use it after a `designs update`, never speculatively — a new revision changes the number on the quote the customer holds |
|
|
236
|
+
| `lahat-pro help-texts` | The help-text table |
|
|
237
|
+
|
|
238
|
+
`projects list` already returns each project's **customer inline** — so "who is the
|
|
239
|
+
customer on each of my projects" is one call, never one call per project. Prefer
|
|
240
|
+
`--phone` over fetching and grepping.
|
|
241
|
+
|
|
242
|
+
Every cross-project list (`designs`, `orders`, `quotations`) takes
|
|
212
243
|
`--limit` (1–100, default 20) and a `--since` cursor — pass the last row's timestamp
|
|
213
244
|
back as `--since` to page further instead of guessing an offset. A malformed `--since` or
|
|
214
245
|
an out-of-range `--limit` is a `400`, not a silently-ignored filter — read the error
|
|
@@ -217,39 +248,16 @@ rather than retrying blind.
|
|
|
217
248
|
### What you can see is not what exists
|
|
218
249
|
|
|
219
250
|
The list is bounded by the key, so an empty result is as often a **visibility** answer as
|
|
220
|
-
a data one. `
|
|
221
|
-
|
|
222
|
-
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
- A key approved by an **admin or support** user *and* carrying **`staff:read`** sees
|
|
228
|
-
**every** project, customer, order and quotation in the system — and can use
|
|
229
|
-
`wardrobe users list` / `users by-phone` at all. That scope is granted only to
|
|
230
|
-
staff, only for GETs, and is listed by name on the consent screen. The same approver
|
|
231
|
-
also receives **`staff:write`**, which lets `designs create` / `designs update` land in
|
|
232
|
-
a project the admin does not own. A key logged in before 2026-09-05 lacks `staff:read`
|
|
233
|
-
and before 2026-09-12 lacks `quotations:read` — a `403 insufficient_scope` on
|
|
234
|
-
`quotations list`, or a `403 Forbidden` on a write to someone else's project, means
|
|
235
|
-
`wardrobe login` again.
|
|
251
|
+
a data one. `lahat-pro whoami --json` reports the truth under `agent.scopes` and `role`:
|
|
252
|
+
|
|
253
|
+
- A designer sees **their own** projects, customers, designs, orders and quotations,
|
|
254
|
+
plus projects they were invited to. A project belonging to someone else answers
|
|
255
|
+
`403 Forbidden`, not `404`.
|
|
256
|
+
- `403 insufficient_scope` means the key lacks that permission — either the verb is for
|
|
257
|
+
office staff (staff.md), or the key is older than the feature: `lahat-pro login` again.
|
|
236
258
|
|
|
237
259
|
Never tell a user something does not exist when you only know your key cannot see it.
|
|
238
|
-
Say which it is: `403 Forbidden` means the row is someone else's
|
|
239
|
-
your key isn't staff at all), `404` means it is gone.
|
|
240
|
-
|
|
241
|
-
### `wardrobe users` is a directory lookup, not a customer lookup
|
|
242
|
-
|
|
243
|
-
`users list` / `users by-phone` read the `User` **account** table — designers, admins,
|
|
244
|
-
support and self-serve clients who can sign in — not the per-project `Customer` contact
|
|
245
|
-
card `wardrobe customers` reads. Each row carries the account's own `phone` (empty until
|
|
246
|
-
that user passes the onboarding phone step; staff never do). `users by-phone` matches
|
|
247
|
-
**only** that field: a customer's number never resolves to the designer who serves them,
|
|
248
|
-
so its answer is "who is this person", safe to act on as the caller's identity. Numbers
|
|
249
|
-
match as the national number, so `+972526665153` and `0526665153` are the same. More than
|
|
250
|
-
one row means the number is ambiguous (the field is self-declared, not unique) — say so
|
|
251
|
-
rather than picking one. Zero rows is normal and not an error; for the customer side of
|
|
252
|
-
the same number use `wardrobe projects list --phone <number>`.
|
|
260
|
+
Say which it is: `403 Forbidden` means the row is someone else's, `404` means it is gone.
|
|
253
261
|
|
|
254
262
|
### Not available here
|
|
255
263
|
|
|
@@ -276,7 +284,7 @@ Don't reach for these; they are not CLI verbs and not agent-reachable:
|
|
|
276
284
|
}
|
|
277
285
|
```
|
|
278
286
|
|
|
279
|
-
Prefer generating the skeleton with `
|
|
287
|
+
Prefer generating the skeleton with `lahat-pro init` rather than hand-writing it —
|
|
280
288
|
`init` fills materials, `ruleVersion`, and a valid column layout for you. Column
|
|
281
289
|
`id`s are `nanoid()` and are not stable across rebuilds.
|
|
282
290
|
|
|
@@ -284,12 +292,10 @@ Prefer generating the skeleton with `wardrobe init` rather than hand-writing it
|
|
|
284
292
|
|
|
285
293
|
- **The CLI can read orders but never place one.** Its key carries `profile:read`,
|
|
286
294
|
`projects:read`, `customers:read`, `designs:read`, `designs:write`, `orders:read`,
|
|
287
|
-
`price:read`, `quotations:read`, `quotations:write`
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
`403 insufficient_scope` (a key logged in before 2026-10-02 lacks `quotations:write` —
|
|
292
|
-
`wardrobe login` again). A
|
|
295
|
+
`price:read`, `quotations:read`, `quotations:write` — **every write beyond designs and
|
|
296
|
+
quotations is absent**, and so is every admin scope. `lahat-pro orders list`,
|
|
297
|
+
`orders pdf`, `quotations list`, `quotations pdf` and `quotations mint` work; creating or
|
|
298
|
+
changing an order or a customer answers `403 insufficient_scope`. A
|
|
293
299
|
project that has never been quoted on the web app has no revision to fetch —
|
|
294
300
|
`quotations pdf`/`quotations list --project` answer `404 quotation_not_found`, not an
|
|
295
301
|
empty document — `quotations mint` is how a first revision is filed. Don't attempt
|
|
@@ -307,7 +313,7 @@ Prefer generating the skeleton with `wardrobe init` rather than hand-writing it
|
|
|
307
313
|
## Do not send order-status updates
|
|
308
314
|
|
|
309
315
|
The customer is emailed automatically at every stage of their order (confirmed,
|
|
310
|
-
measurement, production, installation…). `
|
|
316
|
+
measurement, production, installation…). `lahat-pro orders get` tells you where an order
|
|
311
317
|
stands when someone **asks**, but don't proactively message customers about status changes
|
|
312
318
|
— the emails own that, and a second message from you contradicts or duplicates them.
|
|
313
319
|
|
package/skill/staff.md
ADDED
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
# Lahat Pro CLI — staff keys (admin / support)
|
|
2
|
+
|
|
3
|
+
Read this only when `lahat-pro whoami --json` shows `staff:read` (or `orders:transition`)
|
|
4
|
+
under `agent.scopes`. A designer's or client's key has none of these, and every verb
|
|
5
|
+
below answers `403` for it — don't try them.
|
|
6
|
+
|
|
7
|
+
## What a staff key sees and may change
|
|
8
|
+
|
|
9
|
+
- A key approved by an **admin or support** user *and* carrying **`staff:read`** sees
|
|
10
|
+
**every** project, customer, order and quotation in the system — and can use
|
|
11
|
+
`lahat-pro users list` / `users by-phone` at all. That scope is granted only to
|
|
12
|
+
staff, only for GETs, and is listed by name on the consent screen.
|
|
13
|
+
- The same approver also receives **`staff:write`**, which lets `designs create` /
|
|
14
|
+
`designs update` land in a project the admin does not own.
|
|
15
|
+
- **No key bypasses a locked project.** A project with a live order answers
|
|
16
|
+
`423 projectLocked` even to an admin's key with `staff:write` — the API holds agents
|
|
17
|
+
to the rule the web app relaxes for office staff. Revising an ordered design goes
|
|
18
|
+
through the web app.
|
|
19
|
+
- Old keys lack newer scopes: a key logged in before 2026-09-05 lacks `staff:read`,
|
|
20
|
+
before 2026-09-12 `quotations:read`, before 2026-10-02 `quotations:write`. A
|
|
21
|
+
`403 insufficient_scope` on those, or a `403 Forbidden` on a write to someone else's
|
|
22
|
+
project, means `lahat-pro login` again.
|
|
23
|
+
|
|
24
|
+
## Staff-only verbs
|
|
25
|
+
|
|
26
|
+
| Verb | Shows / does |
|
|
27
|
+
|---|---|
|
|
28
|
+
| `lahat-pro projects list --designer <idOrName>` | Only projects owned by that designer |
|
|
29
|
+
| `lahat-pro designs list` / `orders list` / `quotations list` | With `staff:read`, the newest across the **whole tenant**, not just yours |
|
|
30
|
+
| `lahat-pro users list` | Registered accounts, **newest-registered first** |
|
|
31
|
+
| `lahat-pro users list --limit <n>` `--since <ISO>` | Same, paged (`--since` filters by `createdAt >=`) — `--limit 5` with no `--since` is "the latest registered users"; omit both, paging with `--since` off the last row's timestamp, for "every user in the system" |
|
|
32
|
+
| `lahat-pro users by-phone <number>` | The account(s) whose **own** phone is that number (`+972…`, `05…`, `052-…` all match) |
|
|
33
|
+
| `lahat-pro orders set-status <id> <status> [--dry-run] [--note <text>]` | **Office accounts only** (`orders:transition`, admin/support approvers). Moves the order one legal step: `paid`, `pending_measurement`, `sent_to_manufacturing`, `pending_assembly`, `provided` — never `cancelled`. Already there → "nothing changed"; an illegal step answers 409 with the reason (e.g. `pending_assembly` is only reachable from `in_manufacturing` when transport & installation was bought) — report that to a human, don't retry. `--dry-run` checks without changing; `--note` puts a receipt number on the order's history |
|
|
34
|
+
|
|
35
|
+
`projects list` returns each project's **customer and owning designer inline** — so "who
|
|
36
|
+
is the customer on each of this designer's projects" is one call with `--designer`, never
|
|
37
|
+
one call per project.
|
|
38
|
+
|
|
39
|
+
`users list` takes the same `--limit` (1–100, default 20) / `--since` paging as the other
|
|
40
|
+
cross-project lists; a malformed value is a `400`, not an ignored filter.
|
|
41
|
+
|
|
42
|
+
## `lahat-pro users` is a directory lookup, not a customer lookup
|
|
43
|
+
|
|
44
|
+
`users list` / `users by-phone` read the `User` **account** table — designers, admins,
|
|
45
|
+
support and self-serve clients who can sign in — not the per-project `Customer` contact
|
|
46
|
+
card `lahat-pro customers` reads. Each row carries the account's own `phone` (empty until
|
|
47
|
+
that user passes the onboarding phone step; staff never do). `users by-phone` matches
|
|
48
|
+
**only** that field: a customer's number never resolves to the designer who serves them,
|
|
49
|
+
so its answer is "who is this person", safe to act on as the caller's identity. Numbers
|
|
50
|
+
match as the national number, so `+972526665153` and `0526665153` are the same. More than
|
|
51
|
+
one row means the number is ambiguous (the field is self-declared, not unique) — say so
|
|
52
|
+
rather than picking one. Zero rows is normal and not an error; for the customer side of
|
|
53
|
+
the same number use `lahat-pro projects list --phone <number>`.
|
|
54
|
+
|
|
55
|
+
## Still not reachable, even for staff
|
|
56
|
+
|
|
57
|
+
Anything under `/admin` (catalog, rates, users' roles, commissions), invitations and the
|
|
58
|
+
manufacturing-files export stay in the web app — every agent key is barred from them
|
|
59
|
+
(`403 agent_not_permitted`), whatever its scopes.
|