@gadgetinc/ggt 2.2.0 → 3.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +392 -307
- package/dist/action-CF6zatIh.js +64 -0
- package/dist/action-CF6zatIh.js.map +1 -0
- package/dist/action-CrDCeX3F.js +8 -0
- package/dist/action-CrDCeX3F.js.map +1 -0
- package/dist/add-Basu3Gyf.js +1 -0
- package/dist/agent-plugin-CqgwTOk-.js +15 -0
- package/dist/agent-plugin-CqgwTOk-.js.map +1 -0
- package/dist/agent-plugin-DU9G5B1d.js +9 -0
- package/dist/agent-plugin-DU9G5B1d.js.map +1 -0
- package/dist/assert-Bu1E126Z.js +2 -0
- package/dist/assert-Bu1E126Z.js.map +1 -0
- package/dist/chunk-BjEoQXZ0.js +1 -0
- package/dist/collection-C2TCeYqY.js +2 -0
- package/dist/collection-C2TCeYqY.js.map +1 -0
- package/dist/collection-aM0fpch0.js +1 -0
- package/dist/command-2iNTc5dV.js +118 -0
- package/dist/command-2iNTc5dV.js.map +1 -0
- package/dist/completion-D96nxD5n.js +37 -0
- package/dist/completion-D96nxD5n.js.map +1 -0
- package/dist/configure-C8ge-2cK.js +15 -0
- package/dist/configure-C8ge-2cK.js.map +1 -0
- package/dist/debugger-BkYgApKn.js +22 -0
- package/dist/debugger-BkYgApKn.js.map +1 -0
- package/dist/defaults-B_eD7Pia.js +2 -0
- package/dist/defaults-B_eD7Pia.js.map +1 -0
- package/dist/deploy-Da6P2HXS.js +15 -0
- package/dist/deploy-Da6P2HXS.js.map +1 -0
- package/dist/dev-DWMSNcLl.js +32 -0
- package/dist/dev-DWMSNcLl.js.map +1 -0
- package/dist/dev-lock-BFanZSu1.js +10 -0
- package/dist/dev-lock-BFanZSu1.js.map +1 -0
- package/dist/directory-CNL03L6c.js +9 -0
- package/dist/directory-CNL03L6c.js.map +1 -0
- package/dist/env-DoWNvHzW.js +62 -0
- package/dist/env-DoWNvHzW.js.map +1 -0
- package/dist/esm-B25i6Etq.js +12 -0
- package/dist/esm-B25i6Etq.js.map +1 -0
- package/dist/esm-CJocZrdd.js +2 -0
- package/dist/esm-CJocZrdd.js.map +1 -0
- package/dist/eval-BceZMSd5.js +27 -0
- package/dist/eval-BceZMSd5.js.map +1 -0
- package/dist/execAsync-DrhcEHLd.js +2 -0
- package/dist/execAsync-DrhcEHLd.js.map +1 -0
- package/dist/filesync-De6asZeR.js +61 -0
- package/dist/filesync-De6asZeR.js.map +1 -0
- package/dist/getMachineId-bsd-Cch8Z6pV.js +2 -0
- package/dist/getMachineId-bsd-Cch8Z6pV.js.map +1 -0
- package/dist/getMachineId-darwin-kbQWK54o.js +3 -0
- package/dist/getMachineId-darwin-kbQWK54o.js.map +1 -0
- package/dist/getMachineId-linux-DdIel6zr.js +2 -0
- package/dist/getMachineId-linux-DdIel6zr.js.map +1 -0
- package/dist/getMachineId-unsupported-Bvmsh30k.js +2 -0
- package/dist/getMachineId-unsupported-Bvmsh30k.js.map +1 -0
- package/dist/getMachineId-win-BteHZe8j.js +2 -0
- package/dist/getMachineId-win-BteHZe8j.js.map +1 -0
- package/dist/ggt-B3HQjQRM.js +3 -0
- package/dist/ggt-B3HQjQRM.js.map +1 -0
- package/dist/handler-DZyG8Sel.js +4 -0
- package/dist/handler-DZyG8Sel.js.map +1 -0
- package/dist/http-CY3lPMkt.js +320 -0
- package/dist/http-CY3lPMkt.js.map +1 -0
- package/dist/indent-string-BVm-4tyL.js +2 -0
- package/dist/indent-string-BVm-4tyL.js.map +1 -0
- package/dist/list-lQKWZ6ZI.js +10 -0
- package/dist/list-lQKWZ6ZI.js.map +1 -0
- package/dist/login-Ce0tByNd.js +1 -0
- package/dist/logout-_sTWeaiQ.js +5 -0
- package/dist/logout-_sTWeaiQ.js.map +1 -0
- package/dist/logs-DbhJzz4M.js +9 -0
- package/dist/logs-DbhJzz4M.js.map +1 -0
- package/dist/main.js +2 -2
- package/dist/main.js.map +1 -7
- package/dist/model-CBiMKY0P.js +11 -0
- package/dist/model-CBiMKY0P.js.map +1 -0
- package/dist/ms-B7sMc0pR.js +2 -0
- package/dist/ms-B7sMc0pR.js.map +1 -0
- package/dist/open-CSsA4B-l.js +38 -0
- package/dist/open-CSsA4B-l.js.map +1 -0
- package/dist/p-map-DE0acmRv.js +2 -0
- package/dist/p-map-DE0acmRv.js.map +1 -0
- package/dist/problems-BMLsmxd4.js +11 -0
- package/dist/problems-BMLsmxd4.js.map +1 -0
- package/dist/prompt-C9nwJW0G.js +2 -0
- package/dist/prompt-C9nwJW0G.js.map +1 -0
- package/dist/pull-DpizmJGk.js +12 -0
- package/dist/pull-DpizmJGk.js.map +1 -0
- package/dist/push-67KBCw6c.js +12 -0
- package/dist/push-67KBCw6c.js.map +1 -0
- package/dist/root-D_UnUsp7.js +28 -0
- package/dist/root-D_UnUsp7.js.map +1 -0
- package/dist/select-Dey_sjjd.js +4 -0
- package/dist/select-Dey_sjjd.js.map +1 -0
- package/dist/session-BmzGF1t7.js +2 -0
- package/dist/session-BmzGF1t7.js.map +1 -0
- package/dist/spinner-BVmbgIil.js +8 -0
- package/dist/spinner-BVmbgIil.js.map +1 -0
- package/dist/src-DxCC1MV4.js +6 -0
- package/dist/src-DxCC1MV4.js.map +1 -0
- package/dist/status-P_RFQ7J0.js +13 -0
- package/dist/status-P_RFQ7J0.js.map +1 -0
- package/dist/subscribeToEnvironmentLogs-CUicaiw_.js +2 -0
- package/dist/subscribeToEnvironmentLogs-CUicaiw_.js.map +1 -0
- package/dist/sync-json-V52OzeCz.js +112 -0
- package/dist/sync-json-V52OzeCz.js.map +1 -0
- package/dist/table-MrBbxMay.js +11 -0
- package/dist/table-MrBbxMay.js.map +1 -0
- package/dist/update-CfxiL08e.js +12 -0
- package/dist/update-CfxiL08e.js.map +1 -0
- package/dist/update-iyhnL9-M.js +1 -0
- package/dist/var-ByWcufFt.js +59 -0
- package/dist/var-ByWcufFt.js.map +1 -0
- package/dist/version-B_9GB4u3.js +9 -0
- package/dist/version-B_9GB4u3.js.map +1 -0
- package/dist/whoami-BNcXIfz7.js +5 -0
- package/dist/whoami-BNcXIfz7.js.map +1 -0
- package/package.json +19 -23
- package/assets/favicon-128@4x.png +0 -0
- package/dist/add-TWLGKL2T.js +0 -82
- package/dist/add-TWLGKL2T.js.map +0 -7
- package/dist/agent-plugin-TN24O7FB.js +0 -10
- package/dist/agent-plugin-TN24O7FB.js.map +0 -7
- package/dist/chunk-2742UPMB.js +0 -10
- package/dist/chunk-2742UPMB.js.map +0 -7
- package/dist/chunk-3OM5WM7E.js +0 -2
- package/dist/chunk-3OM5WM7E.js.map +0 -7
- package/dist/chunk-442CSROP.js +0 -66
- package/dist/chunk-442CSROP.js.map +0 -7
- package/dist/chunk-7DYQUG5M.js +0 -2
- package/dist/chunk-7DYQUG5M.js.map +0 -7
- package/dist/chunk-DR4CXBD6.js +0 -11
- package/dist/chunk-DR4CXBD6.js.map +0 -7
- package/dist/chunk-F255O64V.js +0 -2
- package/dist/chunk-F255O64V.js.map +0 -7
- package/dist/chunk-GFQYFEEH.js +0 -2
- package/dist/chunk-GFQYFEEH.js.map +0 -7
- package/dist/chunk-GJGBTM5Y.js +0 -2
- package/dist/chunk-GJGBTM5Y.js.map +0 -7
- package/dist/chunk-HCULGPBH.js +0 -2
- package/dist/chunk-HCULGPBH.js.map +0 -7
- package/dist/chunk-J232VCIM.js +0 -2
- package/dist/chunk-J232VCIM.js.map +0 -7
- package/dist/chunk-JG2QCDK2.js +0 -118
- package/dist/chunk-JG2QCDK2.js.map +0 -7
- package/dist/chunk-JKZNSRLU.js +0 -8
- package/dist/chunk-JKZNSRLU.js.map +0 -7
- package/dist/chunk-JYE5LLIF.js +0 -9
- package/dist/chunk-JYE5LLIF.js.map +0 -7
- package/dist/chunk-KKIL22RY.js +0 -2
- package/dist/chunk-KKIL22RY.js.map +0 -7
- package/dist/chunk-L2XBSR7G.js +0 -2
- package/dist/chunk-L2XBSR7G.js.map +0 -7
- package/dist/chunk-MW6MXMSN.js +0 -2
- package/dist/chunk-MW6MXMSN.js.map +0 -7
- package/dist/chunk-OUIZQC4D.js +0 -12
- package/dist/chunk-OUIZQC4D.js.map +0 -7
- package/dist/chunk-R6KJLEKY.js +0 -28
- package/dist/chunk-R6KJLEKY.js.map +0 -7
- package/dist/chunk-SIR6HLN3.js +0 -69
- package/dist/chunk-SIR6HLN3.js.map +0 -7
- package/dist/chunk-SVWK2NXG.js +0 -2
- package/dist/chunk-SVWK2NXG.js.map +0 -7
- package/dist/chunk-T6UHSWMT.js +0 -2
- package/dist/chunk-T6UHSWMT.js.map +0 -7
- package/dist/chunk-WB6O2V5D.js +0 -11
- package/dist/chunk-WB6O2V5D.js.map +0 -7
- package/dist/chunk-XC4F2TLW.js +0 -113
- package/dist/chunk-XC4F2TLW.js.map +0 -7
- package/dist/chunk-YFUOXDPK.js +0 -10
- package/dist/chunk-YFUOXDPK.js.map +0 -7
- package/dist/chunk-ZSREFZXV.js +0 -211
- package/dist/chunk-ZSREFZXV.js.map +0 -7
- package/dist/chunk-ZYDMXS5R.js +0 -6
- package/dist/chunk-ZYDMXS5R.js.map +0 -7
- package/dist/configure-UJS7V2JX.js +0 -12
- package/dist/configure-UJS7V2JX.js.map +0 -7
- package/dist/debugger-QN2MCLBL.js +0 -41
- package/dist/debugger-QN2MCLBL.js.map +0 -7
- package/dist/deploy-J74PHPQA.js +0 -25
- package/dist/deploy-J74PHPQA.js.map +0 -7
- package/dist/dev-GGUSOOYP.js +0 -59
- package/dist/dev-GGUSOOYP.js.map +0 -7
- package/dist/esm-D77XRR65.js +0 -38
- package/dist/esm-D77XRR65.js.map +0 -7
- package/dist/eval-L6WHUFLU.js +0 -54
- package/dist/eval-L6WHUFLU.js.map +0 -7
- package/dist/getMachineId-bsd-QUXN4NKS.js +0 -2
- package/dist/getMachineId-bsd-QUXN4NKS.js.map +0 -7
- package/dist/getMachineId-darwin-TCXBAX22.js +0 -3
- package/dist/getMachineId-darwin-TCXBAX22.js.map +0 -7
- package/dist/getMachineId-linux-IJ3LYIOX.js +0 -2
- package/dist/getMachineId-linux-IJ3LYIOX.js.map +0 -7
- package/dist/getMachineId-unsupported-IKXBUCYY.js +0 -2
- package/dist/getMachineId-unsupported-IKXBUCYY.js.map +0 -7
- package/dist/getMachineId-win-6CX7VSFF.js +0 -2
- package/dist/getMachineId-win-6CX7VSFF.js.map +0 -7
- package/dist/ggt-5XNRJZSW.js +0 -44
- package/dist/ggt-5XNRJZSW.js.map +0 -7
- package/dist/list-756D46N5.js +0 -11
- package/dist/list-756D46N5.js.map +0 -7
- package/dist/login-GMWQRH7V.js +0 -2
- package/dist/login-GMWQRH7V.js.map +0 -7
- package/dist/logout-LQABTJFD.js +0 -7
- package/dist/logout-LQABTJFD.js.map +0 -7
- package/dist/logs-AQZB272X.js +0 -28
- package/dist/logs-AQZB272X.js.map +0 -7
- package/dist/open-OMZWPQ66.js +0 -74
- package/dist/open-OMZWPQ66.js.map +0 -7
- package/dist/problems-FZJKH52E.js +0 -14
- package/dist/problems-FZJKH52E.js.map +0 -7
- package/dist/pull-XYCYN7QN.js +0 -28
- package/dist/pull-XYCYN7QN.js.map +0 -7
- package/dist/push-3QM7ZFTC.js +0 -2
- package/dist/push-3QM7ZFTC.js.map +0 -7
- package/dist/status-PWAXNK5G.js +0 -14
- package/dist/status-PWAXNK5G.js.map +0 -7
- package/dist/update-QIQFJFRQ.js +0 -2
- package/dist/update-QIQFJFRQ.js.map +0 -7
- package/dist/var-N4WGGJXZ.js +0 -159
- package/dist/var-N4WGGJXZ.js.map +0 -7
- package/dist/version-AJKSJJDC.js +0 -11
- package/dist/version-AJKSJJDC.js.map +0 -7
- package/dist/whoami-KJYDSQSD.js +0 -7
- package/dist/whoami-KJYDSQSD.js.map +0 -7
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
import{r as e}from"./prompt-C9nwJW0G.js";import{$ as t,Q as n,U as r,V as i,W as a,Z as o,d as s,et as c,gt as l,j as u,tt as d,u as f}from"./http-CY3lPMkt.js";import{E as p,c as m,mt as h,n as g,s as _}from"./command-2iNTc5dV.js";import{t as v,u as y}from"./filesync-De6asZeR.js";import{a as b}from"./collection-C2TCeYqY.js";import{n as x,r as S,t as C,u as w}from"./sync-json-V52OzeCz.js";import{t as T}from"./select-Dey_sjjd.js";const E=()=>{let e=new Date,t=e=>String(e).padStart(2,`0`);return`env-${`${e.getUTCFullYear()}${t(e.getUTCMonth()+1)}${t(e.getUTCDate())}`}-${`${t(e.getUTCHours())}${t(e.getUTCMinutes())}${t(e.getUTCSeconds())}`}`},D=async(e,{syncJson:t,name:r})=>{try{await t.edit.mutate({mutation:n,variables:{environment:{slug:r,sourceSlug:t.environment.name}}})}catch(e){throw e instanceof i?new F(e):e}return{name:r}},O=async(e,{envName:t,command:n})=>{let r=await C.load(e,{command:n,flags:{_:[],"--application":void 0,"--allow-unknown-directory":void 0,"--allow-different-app":void 0,"--environment":t},directory:await S(process.cwd())});if(!r)return;let i=new v(r),a=await i.hashes(e);if(a.environmentChangesToPull.size===0){m({ensureEmptyLineAbove:!0,content:`Nothing to pull.`});return}a.localChangesToPush.size>0&&await i.print(e,{hashes:a}),await i.pull(e,{hashes:a,force:!0})},k=e=>{let t=[],n=[];for(let r of e){let e=/^(.*):+(.*)$/.exec(r);!e||e.length!==3||!e[1]||!e[2]?t.push(p`${r} is not a valid field definition`):n.push({name:e[1].replace(/:+/g,``),fieldType:e[2]})}return[n,t]},A=e=>{let t=e.split(`/`),n=[];if(!t[1])return{modelApiIdentifier:``,fieldName:``,fieldType:``,problems:[`Missing field definition`]};let[r,i]=k([t[1]]);return n.push(...i),n.length>0||r.length===0?{modelApiIdentifier:``,fieldName:``,fieldType:``,problems:n}:{modelApiIdentifier:t[0],fieldName:r[0]?.name??``,fieldType:r[0]?.fieldType??``,problems:[]}},j=async(e,{syncJson:n,filesync:r,modelApiIdentifier:a,fields:o})=>{let s;try{s=(await n.edit.mutate({mutation:t,variables:{path:a,fields:o.map(e=>({name:e.name,fieldType:e.fieldType}))}})).createModelFields}catch(e){throw e instanceof i?new F(e):e}return await r.writeToLocalFilesystem(e,{filesVersion:s.remoteFilesVersion,files:s.changed,delete:[]}),{fieldName:o[0]?.name??``,remoteFilesVersion:s.remoteFilesVersion,changed:s.changed}},M=async(e,{syncJson:t,filesync:n,modelApiIdentifier:r,fields:a=[]})=>{let o;try{o=(await t.edit.mutate({mutation:c,variables:{path:r,fields:a.map(e=>({name:e.name,fieldType:e.fieldType}))}})).createModel}catch(e){throw e instanceof i?new F(e):e}return await n.writeToLocalFilesystem(e,{filesVersion:o.remoteFilesVersion,files:o.changed,delete:[]}),{modelApiIdentifier:r,remoteFilesVersion:o.remoteFilesVersion,changed:o.changed}},N=async(e,{syncJson:t,filesync:n,method:r,path:a})=>{let o;try{o=(await t.edit.mutate({mutation:d,variables:{method:r,path:a}})).createRoute}catch(e){throw e instanceof i?new F(e):e}return await n.writeToLocalFilesystem(e,{filesVersion:o.remoteFilesVersion,files:o.changed,delete:[]}),{method:r,path:a,remoteFilesVersion:o.remoteFilesVersion,changed:o.changed}},P=async(t,n,r)=>{let i=await S(process.cwd()),a=await C.load(t,{command:n,flags:r,directory:i});if(!a)throw new w({command:n,flags:r,directory:i});let o=new v(a),s=await o.hashes(t,{silent:!0});return s.inSync||await o.merge(t,{hashes:s,printEnvironmentChangesOptions:{limit:5},printLocalChangesOptions:{limit:5},silent:!0}),m({ensureEmptyLineAbove:!0,content:`${_.created(e.tick)} Sync completed ${y()}`}),{filesync:o,syncJson:a}};var F=class extends r{isBug=a.NO;constructor(e){let t=``;t=h(e.cause)?p`
|
|
2
|
+
${b(e.cause.map(e=>e.message)).flatMap(e=>e.split(`
|
|
3
|
+
`)).map(e=>e.startsWith(`• `)?e:`\u2022 ${e}`).join(`
|
|
4
|
+
`)}
|
|
5
|
+
`:p`${e.cause}`,super(t)}render(){return p`
|
|
6
|
+
${_.deleted(e.cross)} Failed to add:
|
|
7
|
+
${this.message}
|
|
8
|
+
`}},I=g({name:`add`,description:`Add resources to your app`,details:p`
|
|
9
|
+
Syncs local files with the environment before adding the resource, ensuring the
|
|
10
|
+
environment is up to date. If there are conflicts, they must be resolved before the
|
|
11
|
+
resource can be added.
|
|
12
|
+
`,sections:[{title:`Resource Syntax`,content:p`
|
|
13
|
+
ggt add model <model_name> [field_name:field_type ...]
|
|
14
|
+
Fields are optional. Each field is a name:type pair (e.g. title:string).
|
|
15
|
+
|
|
16
|
+
ggt add action <context>/<action_name>
|
|
17
|
+
context is either "model/<model_name>" for model actions or "action" for global actions.
|
|
18
|
+
|
|
19
|
+
ggt add route <method> <route_path>
|
|
20
|
+
method is an HTTP verb: GET, POST, PUT, PATCH, or DELETE.
|
|
21
|
+
|
|
22
|
+
ggt add field <model_name>/<field_name>:<field_type>
|
|
23
|
+
Adds a field to an existing model.
|
|
24
|
+
`}],examples:[`ggt add model post`,`ggt add model post title:string body:string`,`ggt add field post/published:boolean`,`ggt add action model/post/publish`,`ggt add action action/audit`,`ggt add route GET /hello`,`ggt add environment staging`],flags:x,subcommands:t=>({model:t({description:`Add a new data model`,details:p`
|
|
25
|
+
Creates the model on your environment and pulls the generated files to your
|
|
26
|
+
local directory. Optionally include field definitions as ${_.subdued(`name:type`)} pairs
|
|
27
|
+
after the model name. Supported types include string, number, boolean,
|
|
28
|
+
datetime, json, email, url, vector, richtext, file, enum, and color.
|
|
29
|
+
`,examples:[`ggt add model post`,`ggt add model post title:string body:string`,`ggt add model user name:string email:string`],positionals:[{name:`model`,required:!0,description:`API identifier for the new model`,details:`Becomes the API identifier in your client code (e.g. api.post). Must be unique within the app.`},{name:`field:type ...`,description:`Optional field definitions (name:type pairs)`,details:`Each field is a name:type pair separated by a colon (e.g. title:string).`}],run:async(t,n)=>{let{filesync:r,syncJson:i}=await P(t,`add`,n),a=n._[0],o=[];if(n._.length>1){let[e,t]=k(n._.slice(1));if(t.length>0)throw new u(p`
|
|
30
|
+
Failed to add model:
|
|
31
|
+
|
|
32
|
+
${t.map(e=>`• ${e}`).join(`
|
|
33
|
+
`)}
|
|
34
|
+
`,{usageHint:!1});o=e}await M(t,{syncJson:i,filesync:r,modelApiIdentifier:a,fields:o});let s=l.isSupported?l(a,`https://${i.environment.application.primaryDomain}/edit/${i.environment.name}/model/${a}/schema`):a;m({ensureEmptyLineAbove:!0,content:_.subdued(`New model created in environment.`)}),m({ensureEmptyLineAbove:!0,content:`${_.created(e.tick)} Model ${_.code(s)} added successfully.`})}}),action:t({description:`Add an action to a model or as a global action`,details:p`
|
|
35
|
+
The path determines whether the action is added to a model or as a global
|
|
36
|
+
action. Use ${_.subdued(`model/<model>/<action>`)} for model actions or
|
|
37
|
+
${_.subdued(`action/<action>`)} for global actions. If the path is ambiguous because
|
|
38
|
+
a model and action namespace share the same name, you'll be prompted to
|
|
39
|
+
choose.
|
|
40
|
+
`,examples:[`ggt add action model/post/publish`,`ggt add action action/audit`,`ggt add action model/user/sendEmail`],positionals:[{name:`path`,required:!0,description:`Action path (e.g. model/post/publish or action/audit)`,details:`If the path is ambiguous because a model and action namespace share the same name, you'll be prompted to choose.`}],run:async(e,t)=>{let{filesync:n,syncJson:r}=await P(e,`add`,t),i=t._[0];await R(e,{syncJson:r,filesync:n,path:(await L(i,await s(e,r.environment),await f(e,r.environment))).path}),m({ensureEmptyLineAbove:!0,content:`Action ${_.code(i)} added successfully.`})}}),route:t({description:`Add an HTTP route`,details:p`
|
|
41
|
+
Creates the route handler file on the environment and pulls it to your
|
|
42
|
+
local directory. Supported methods are GET, POST, PUT, PATCH, and DELETE.
|
|
43
|
+
`,examples:[`ggt add route GET /hello`,`ggt add route POST /webhooks/stripe`,`ggt add route DELETE /posts/:id`,`ggt add route PUT /users/:id`],positionals:[{name:`method`,required:!0,description:`HTTP method (GET, POST, PUT, PATCH, DELETE)`,details:`Case-insensitive.`},{name:`path`,required:!0,description:`Route path`,details:`The URL path for the route handler (e.g. /hello, /webhooks/stripe). Leading slash is required.`}],run:async(e,t)=>{let{filesync:n,syncJson:r}=await P(e,`add`,t),i=t._[0],a=t._[1];await N(e,{syncJson:r,filesync:n,method:i,path:a}),m({ensureEmptyLineAbove:!0,content:`Route ${_.code(a)} added successfully.`})}}),field:t({description:`Add a field to an existing model`,details:p`
|
|
44
|
+
Uses the format ${_.subdued(`model/field:type`)} to identify the target model and the
|
|
45
|
+
field to add. Supported types include string, number, boolean, datetime,
|
|
46
|
+
json, email, url, vector, richtext, file, enum, and color.
|
|
47
|
+
`,examples:[`ggt add field post/published:boolean`,`ggt add field user/age:number`,`ggt add field post/title:string`,`ggt add field user/email:email`],positionals:[{name:`model/field:type`,required:!0,description:`Model path and field definition`,details:`Format is model/field:type (e.g. post/published:boolean).`}],run:async(e,t)=>{let{filesync:n,syncJson:r}=await P(e,`add`,t),i=t._[0],a=A(i);if(a.problems.includes(`Missing field definition`))throw new u(`Failed to add field, invalid field definition`,{usageHint:!1});if(a.problems.length>0)throw new u(p`
|
|
48
|
+
Failed to add field:
|
|
49
|
+
|
|
50
|
+
${a.problems.map(e=>`• ${e}`).join(`
|
|
51
|
+
`)}
|
|
52
|
+
`,{usageHint:!1});await j(e,{syncJson:r,filesync:n,modelApiIdentifier:a.modelApiIdentifier,fields:[{name:a.fieldName,fieldType:a.fieldType}]}),m({ensureEmptyLineAbove:!0,content:`Field ${_.code(a.fieldName)} added successfully.`})}}),environment:t({aliases:[`env`],description:`Create a new environment by cloning`,details:p`
|
|
53
|
+
Clones the current environment's data and schema into a new environment.
|
|
54
|
+
If no name is given, one is auto-generated. After creation, automatically
|
|
55
|
+
pulls from the new environment to switch your local directory to it.
|
|
56
|
+
|
|
57
|
+
For more control (e.g. choosing the source environment or skipping the
|
|
58
|
+
auto-switch), use ${_.subdued(`ggt env create`)} instead.
|
|
59
|
+
`,examples:[`ggt add environment staging`,`ggt add environment`],positionals:[{name:`name`,description:`Name for the new environment (auto-generated if omitted)`,details:`The name is lowercased automatically. If omitted, a timestamped name is generated (e.g. env-20260303-142530).`}],run:async(e,t)=>{let{syncJson:n}=await P(e,`add`,t),r=t._[0];r||=E(),await D(e,{syncJson:n,name:r}),m({ensureEmptyLineAbove:!0,content:`Environment ${_.code(r)} added successfully.`}),await O(e,{envName:r,command:`pull`})}})})});const L=async(t,n,r)=>{let i=t.split(`/`),a=i.length>1?i.slice(0,i.length-1):i,o=i[i.length-1],s=n.find(e=>{let t=a[a.length-1];return e.apiIdentifier.toUpperCase()===t.toUpperCase()&&e.namespace?.join(`/`)===a.slice(0,a.length-1).join(`/`)}),c=r.find(e=>e.namespace?.join(`/`)===a.join(`/`));if(s&&c){let n=a.join(`/`),r=await T({choices:[`models`,`actions`],content:p`
|
|
60
|
+
${_.header(`Namespace Conflict:`)} The action '${o}.js' cannot be automatically added due to a namespace conflict.
|
|
61
|
+
|
|
62
|
+
How would you like to proceed?:
|
|
63
|
+
`,formatChoice:e=>{switch(e){case`models`:return`As a Model action in ${_.subdued(`models/${n}/${o}.js`)}`;case`actions`:return`As an Action in ${_.subdued(`actions/${n}/${o}.js`)}`}}});return m({ensureEmptyLineAbove:!0,content:p`${_.renamed(e.info)} You can override the context of the action by specifying the context in the path. For example: ${_.subdued(`ggt add action ${r}/${t}`)}`}),{path:`${r}/${t}`,overrideContextAction:r}}return{path:t}},R=async(e,{syncJson:t,filesync:n,path:r})=>{let a;try{a=(await t.edit.mutate({mutation:o,variables:{path:r}})).createAction}catch(e){throw e instanceof i?new F(e):e}return await n.writeToLocalFilesystem(e,{filesVersion:a.remoteFilesVersion,files:a.changed,delete:[]}),{path:r,remoteFilesVersion:a.remoteFilesVersion,changed:a.changed}};export{M as a,P as i,F as n,k as o,I as r,R as t};
|
|
64
|
+
//# sourceMappingURL=action-CF6zatIh.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"action-CF6zatIh.js","names":["colors","colors","colors"],"sources":["../src/services/add/environment.ts","../src/services/add/field.ts","../src/services/add/model.ts","../src/services/add/route.ts","../src/services/filesync/setup-sync.ts","../src/commands/add.ts","../src/services/add/action.ts"],"sourcesContent":["import { AddClientError } from \"../../commands/add.ts\";\nimport { CREATE_ENVIRONMENT_MUTATION } from \"../app/edit/operation.ts\";\nimport { ClientError } from \"../app/error.ts\";\nimport type { Context } from \"../command/context.ts\";\nimport { FileSync } from \"../filesync/filesync.ts\";\nimport { loadSyncJsonDirectory, SyncJson } from \"../filesync/sync-json.ts\";\nimport type { SyncJson as SyncJsonType } from \"../filesync/sync-json.ts\";\nimport { println } from \"../output/print.ts\";\n\nexport type AddEnvironmentResult = {\n name: string;\n};\n\n/**\n * Generate a default environment name based on the current timestamp.\n */\nexport const generateDefaultEnvName = (): string => {\n const now = new Date();\n const pad = (n: number): string => String(n).padStart(2, \"0\");\n const date = `${now.getUTCFullYear()}${pad(now.getUTCMonth() + 1)}${pad(now.getUTCDate())}`;\n const time = `${pad(now.getUTCHours())}${pad(now.getUTCMinutes())}${pad(now.getUTCSeconds())}`;\n return `env-${date}-${time}`;\n};\n\n/**\n * Create a new environment by cloning the current one.\n */\nexport const addEnvironment = async (\n ctx: Context,\n {\n syncJson,\n name,\n }: {\n syncJson: SyncJsonType;\n name: string;\n },\n): Promise<AddEnvironmentResult> => {\n try {\n await syncJson.edit.mutate({\n mutation: CREATE_ENVIRONMENT_MUTATION,\n variables: { environment: { slug: name, sourceSlug: syncJson.environment.name } },\n });\n } catch (error) {\n if (error instanceof ClientError) {\n throw new AddClientError(error);\n } else {\n throw error;\n }\n }\n\n return { name };\n};\n\n/**\n * Switch to a newly created environment by pulling from it.\n */\nexport const switchToNewEnvironment = async (\n ctx: Context,\n {\n envName,\n command,\n }: {\n envName: string;\n command: string;\n },\n): Promise<void> => {\n const pullFromNewEnvSyncJson = await SyncJson.load(ctx, {\n command: command as \"pull\",\n flags: {\n _: [],\n \"--application\": undefined,\n \"--allow-unknown-directory\": undefined,\n \"--allow-different-app\": undefined,\n \"--environment\": envName,\n },\n directory: await loadSyncJsonDirectory(process.cwd()),\n });\n\n if (!pullFromNewEnvSyncJson) {\n return;\n }\n\n const filesync = new FileSync(pullFromNewEnvSyncJson);\n const hashes = await filesync.hashes(ctx);\n\n if (hashes.environmentChangesToPull.size === 0) {\n println({ ensureEmptyLineAbove: true, content: \"Nothing to pull.\" });\n return;\n }\n\n if (hashes.localChangesToPush.size > 0) {\n await filesync.print(ctx, { hashes });\n }\n\n await filesync.pull(ctx, { hashes, force: true });\n};\n","import type { CreateModelFieldsMutation } from \"../../__generated__/graphql.ts\";\nimport { AddClientError } from \"../../commands/add.ts\";\nimport { CREATE_MODEL_FIELDS_MUTATION } from \"../app/edit/operation.ts\";\nimport { ClientError } from \"../app/error.ts\";\nimport type { Context } from \"../command/context.ts\";\nimport type { FileSync } from \"../filesync/filesync.ts\";\nimport type { SyncJson } from \"../filesync/sync-json.ts\";\nimport { sprint } from \"../output/sprint.ts\";\n\n/**\n * Parse field definitions like \"name:string\" into { name, fieldType } objects.\n */\nexport const parseFieldValues = (fields: string[]): [{ name: string; fieldType: string }[], problems: string[]] => {\n const problems: string[] = [];\n const modelFields: { name: string; fieldType: string }[] = [];\n\n for (const field of fields) {\n const matches = /^(.*):+(.*)$/.exec(field);\n if (!matches || matches.length !== 3 || !matches[1] || !matches[2]) {\n problems.push(sprint`${field} is not a valid field definition`);\n } else {\n modelFields.push({ name: matches[1].replace(/:+/g, \"\"), fieldType: matches[2] });\n }\n }\n\n return [modelFields, problems];\n};\n\nexport type AddFieldsResult = {\n fieldName: string;\n remoteFilesVersion: string;\n changed: CreateModelFieldsMutation[\"createModelFields\"][\"changed\"];\n};\n\n/**\n * Parse a field target string like \"modelA/fieldB:string\" into its components.\n */\nexport const parseFieldTarget = (\n input: string,\n): { modelApiIdentifier: string; fieldName: string; fieldType: string; problems: string[] } => {\n const splitPathAndField = input.split(\"/\");\n const problems: string[] = [];\n\n if (!splitPathAndField[1]) {\n return { modelApiIdentifier: \"\", fieldName: \"\", fieldType: \"\", problems: [\"Missing field definition\"] };\n }\n\n const [modelFields, parseProblems] = parseFieldValues([splitPathAndField[1]]);\n problems.push(...parseProblems);\n\n if (problems.length > 0 || modelFields.length === 0) {\n return { modelApiIdentifier: \"\", fieldName: \"\", fieldType: \"\", problems };\n }\n\n return {\n modelApiIdentifier: splitPathAndField[0],\n fieldName: modelFields[0]?.name ?? \"\",\n fieldType: modelFields[0]?.fieldType ?? \"\",\n problems: [],\n };\n};\n\n/**\n * Add fields to an existing model.\n */\nexport const addFields = async (\n ctx: Context,\n {\n syncJson,\n filesync,\n modelApiIdentifier,\n fields,\n }: {\n syncJson: SyncJson;\n filesync: FileSync;\n modelApiIdentifier: string;\n fields: Array<{ name: string; fieldType: string }>;\n },\n): Promise<AddFieldsResult> => {\n let result;\n\n try {\n result = (\n await syncJson.edit.mutate({\n mutation: CREATE_MODEL_FIELDS_MUTATION,\n variables: {\n path: modelApiIdentifier,\n fields: fields.map((f) => ({ name: f.name, fieldType: f.fieldType })),\n },\n })\n ).createModelFields;\n } catch (error) {\n if (error instanceof ClientError) {\n throw new AddClientError(error);\n } else {\n throw error;\n }\n }\n\n await filesync.writeToLocalFilesystem(ctx, { filesVersion: result.remoteFilesVersion, files: result.changed, delete: [] });\n\n return {\n fieldName: fields[0]?.name ?? \"\",\n remoteFilesVersion: result.remoteFilesVersion,\n changed: result.changed,\n };\n};\n","import type { CreateModelMutation } from \"../../__generated__/graphql.ts\";\nimport { AddClientError } from \"../../commands/add.ts\";\nimport { CREATE_MODEL_MUTATION } from \"../app/edit/operation.ts\";\nimport { ClientError } from \"../app/error.ts\";\nimport type { Context } from \"../command/context.ts\";\nimport type { FileSync } from \"../filesync/filesync.ts\";\nimport type { SyncJson } from \"../filesync/sync-json.ts\";\n\nexport type AddModelResult = {\n modelApiIdentifier: string;\n remoteFilesVersion: string;\n changed: CreateModelMutation[\"createModel\"][\"changed\"];\n};\n\n/**\n * Add a model to the app.\n */\nexport const addModel = async (\n ctx: Context,\n {\n syncJson,\n filesync,\n modelApiIdentifier,\n fields = [],\n }: {\n syncJson: SyncJson;\n filesync: FileSync;\n modelApiIdentifier: string;\n fields?: Array<{ name: string; fieldType: string }>;\n },\n): Promise<AddModelResult> => {\n let result;\n\n try {\n result = (\n await syncJson.edit.mutate({\n mutation: CREATE_MODEL_MUTATION,\n variables: {\n path: modelApiIdentifier,\n fields: fields.map((f) => ({ name: f.name, fieldType: f.fieldType })),\n },\n })\n ).createModel;\n } catch (error) {\n if (error instanceof ClientError) {\n throw new AddClientError(error);\n } else {\n throw error;\n }\n }\n\n await filesync.writeToLocalFilesystem(ctx, { filesVersion: result.remoteFilesVersion, files: result.changed, delete: [] });\n\n return {\n modelApiIdentifier,\n remoteFilesVersion: result.remoteFilesVersion,\n changed: result.changed,\n };\n};\n","import type { CreateRouteMutation } from \"../../__generated__/graphql.ts\";\nimport { AddClientError } from \"../../commands/add.ts\";\nimport { CREATE_ROUTE_MUTATION } from \"../app/edit/operation.ts\";\nimport { ClientError } from \"../app/error.ts\";\nimport type { Context } from \"../command/context.ts\";\nimport type { FileSync } from \"../filesync/filesync.ts\";\nimport type { SyncJson } from \"../filesync/sync-json.ts\";\n\nexport type AddRouteResult = {\n method: string;\n path: string;\n remoteFilesVersion: string;\n changed: CreateRouteMutation[\"createRoute\"][\"changed\"];\n};\n\n/**\n * Add a route to the app.\n */\nexport const addRoute = async (\n ctx: Context,\n {\n syncJson,\n filesync,\n method,\n path,\n }: {\n syncJson: SyncJson;\n filesync: FileSync;\n method: string;\n path: string;\n },\n): Promise<AddRouteResult> => {\n let result;\n\n try {\n result = (\n await syncJson.edit.mutate({\n mutation: CREATE_ROUTE_MUTATION,\n variables: { method, path },\n })\n ).createRoute;\n } catch (error) {\n if (error instanceof ClientError) {\n throw new AddClientError(error);\n } else {\n throw error;\n }\n }\n\n await filesync.writeToLocalFilesystem(ctx, { filesVersion: result.remoteFilesVersion, files: result.changed, delete: [] });\n\n return {\n method,\n path,\n remoteFilesVersion: result.remoteFilesVersion,\n changed: result.changed,\n };\n};\n","import type { Command } from \"../command/command.ts\";\nimport type { Context } from \"../command/context.ts\";\nimport type { FlagsResult } from \"../command/flag.ts\";\nimport colors from \"../output/colors.ts\";\nimport { println } from \"../output/print.ts\";\nimport { symbol } from \"../output/symbols.ts\";\nimport { ts } from \"../output/timestamp.ts\";\nimport { UnknownDirectoryError } from \"./error.ts\";\nimport { FileSync } from \"./filesync.ts\";\nimport { SyncJson, type SyncJsonFlags, loadSyncJsonDirectory } from \"./sync-json.ts\";\n\nexport const setupCommandSync = async (\n ctx: Context,\n command: Command,\n flags: FlagsResult<typeof SyncJsonFlags>,\n): Promise<{ filesync: FileSync; syncJson: SyncJson }> => {\n const directory = await loadSyncJsonDirectory(process.cwd());\n const syncJson = await SyncJson.load(ctx, { command, flags, directory });\n if (!syncJson) {\n throw new UnknownDirectoryError({ command, flags, directory });\n }\n\n const filesync = new FileSync(syncJson);\n const hashes = await filesync.hashes(ctx, { silent: true });\n\n if (!hashes.inSync) {\n await filesync.merge(ctx, {\n hashes,\n printEnvironmentChangesOptions: { limit: 5 },\n printLocalChangesOptions: { limit: 5 },\n silent: true,\n });\n }\n\n println({ ensureEmptyLineAbove: true, content: `${colors.created(symbol.tick)} Sync completed ${ts()}` });\n\n return { filesync, syncJson };\n};\n","import terminalLink from \"terminal-link\";\n\nimport { addAction, resolveActionPath } from \"../services/add/action.ts\";\nimport { addEnvironment, generateDefaultEnvName, switchToNewEnvironment } from \"../services/add/environment.ts\";\nimport { addFields, parseFieldTarget, parseFieldValues } from \"../services/add/field.ts\";\nimport { addModel } from \"../services/add/model.ts\";\nimport { addRoute } from \"../services/add/route.ts\";\nimport { getGlobalActions, getModels } from \"../services/app/app.ts\";\nimport { ClientError } from \"../services/app/error.ts\";\nimport { defineCommand } from \"../services/command/command.ts\";\nimport { FlagError } from \"../services/command/flag.ts\";\nimport { setupCommandSync } from \"../services/filesync/setup-sync.ts\";\nimport { SyncJsonFlags } from \"../services/filesync/sync-json.ts\";\nimport colors from \"../services/output/colors.ts\";\nimport { println } from \"../services/output/print.ts\";\nimport { GGTError, IsBug } from \"../services/output/report.ts\";\nimport { sprint } from \"../services/output/sprint.ts\";\nimport { symbol } from \"../services/output/symbols.ts\";\nimport { uniq } from \"../services/util/collection.ts\";\nimport { isGraphQLErrors } from \"../services/util/is.ts\";\n\nexport class AddClientError extends GGTError {\n isBug = IsBug.NO;\n\n constructor(error: ClientError) {\n let template = \"\";\n\n if (isGraphQLErrors(error.cause)) {\n const errors = uniq(error.cause.map((x) => x.message));\n template = sprint`\n ${errors\n .flatMap((e) => e.split(\"\\n\"))\n .map((line) => (line.startsWith(\"\\u2022 \") ? line : `\\u2022 ${line}`))\n .join(\"\\n\")}\n `;\n } else {\n template = sprint`${error.cause}`;\n }\n\n super(template);\n }\n\n protected override render(): string {\n return sprint`\n ${colors.deleted(symbol.cross)} Failed to add:\n ${this.message}\n `;\n }\n}\n\nexport default defineCommand({\n name: \"add\",\n description: \"Add resources to your app\",\n details: sprint`\n Syncs local files with the environment before adding the resource, ensuring the\n environment is up to date. If there are conflicts, they must be resolved before the\n resource can be added.\n `,\n sections: [\n {\n title: \"Resource Syntax\",\n content: sprint`\n ggt add model <model_name> [field_name:field_type ...]\n Fields are optional. Each field is a name:type pair (e.g. title:string).\n\n ggt add action <context>/<action_name>\n context is either \"model/<model_name>\" for model actions or \"action\" for global actions.\n\n ggt add route <method> <route_path>\n method is an HTTP verb: GET, POST, PUT, PATCH, or DELETE.\n\n ggt add field <model_name>/<field_name>:<field_type>\n Adds a field to an existing model.\n `,\n },\n ],\n examples: [\n \"ggt add model post\",\n \"ggt add model post title:string body:string\",\n \"ggt add field post/published:boolean\",\n \"ggt add action model/post/publish\",\n \"ggt add action action/audit\",\n \"ggt add route GET /hello\",\n \"ggt add environment staging\",\n ],\n flags: SyncJsonFlags,\n subcommands: (sub) => ({\n model: sub({\n description: \"Add a new data model\",\n details: sprint`\n Creates the model on your environment and pulls the generated files to your\n local directory. Optionally include field definitions as ${colors.subdued(\"name:type\")} pairs\n after the model name. Supported types include string, number, boolean,\n datetime, json, email, url, vector, richtext, file, enum, and color.\n `,\n examples: [\"ggt add model post\", \"ggt add model post title:string body:string\", \"ggt add model user name:string email:string\"],\n positionals: [\n {\n name: \"model\",\n required: true,\n description: \"API identifier for the new model\",\n details: \"Becomes the API identifier in your client code (e.g. api.post). Must be unique within the app.\",\n },\n {\n name: \"field:type ...\",\n description: \"Optional field definitions (name:type pairs)\",\n details: \"Each field is a name:type pair separated by a colon (e.g. title:string).\",\n },\n ],\n run: async (ctx, flags) => {\n const { filesync, syncJson } = await setupCommandSync(ctx, \"add\", flags);\n // oxlint-disable-next-line no-non-null-assertion -- framework validates required positional\n const modelApiIdentifier = flags._[0]!;\n\n let modelFieldsList: { name: string; fieldType: string }[] = [];\n if (flags._.length > 1) {\n const [modelFields, problems] = parseFieldValues(flags._.slice(1));\n\n if (problems.length > 0) {\n throw new FlagError(\n sprint`\n Failed to add model:\n\n ${problems.map((p) => `• ${p}`).join(\"\\n\")}\n `,\n { usageHint: false },\n );\n }\n\n modelFieldsList = modelFields;\n }\n\n await addModel(ctx, {\n syncJson,\n filesync,\n modelApiIdentifier,\n fields: modelFieldsList,\n });\n\n const modelPrintout = terminalLink.isSupported\n ? terminalLink(\n modelApiIdentifier,\n `https://${syncJson.environment.application.primaryDomain}/edit/${syncJson.environment.name}/model/${modelApiIdentifier}/schema`,\n )\n : modelApiIdentifier;\n\n println({ ensureEmptyLineAbove: true, content: colors.subdued(\"New model created in environment.\") });\n println({\n ensureEmptyLineAbove: true,\n content: `${colors.created(symbol.tick)} Model ${colors.code(modelPrintout)} added successfully.`,\n });\n },\n }),\n action: sub({\n description: \"Add an action to a model or as a global action\",\n details: sprint`\n The path determines whether the action is added to a model or as a global\n action. Use ${colors.subdued(\"model/<model>/<action>\")} for model actions or\n ${colors.subdued(\"action/<action>\")} for global actions. If the path is ambiguous because\n a model and action namespace share the same name, you'll be prompted to\n choose.\n `,\n examples: [\"ggt add action model/post/publish\", \"ggt add action action/audit\", \"ggt add action model/user/sendEmail\"],\n positionals: [\n {\n name: \"path\",\n required: true,\n description: \"Action path (e.g. model/post/publish or action/audit)\",\n details: \"If the path is ambiguous because a model and action namespace share the same name, you'll be prompted to choose.\",\n },\n ],\n run: async (ctx, flags) => {\n const { filesync, syncJson } = await setupCommandSync(ctx, \"add\", flags);\n // oxlint-disable-next-line no-non-null-assertion -- framework validates required positional\n const path = flags._[0]!;\n\n const models = await getModels(ctx, syncJson.environment);\n const globalActions = await getGlobalActions(ctx, syncJson.environment);\n\n const resolved = await resolveActionPath(path, models, globalActions);\n\n await addAction(ctx, {\n syncJson,\n filesync,\n path: resolved.path,\n });\n\n println({ ensureEmptyLineAbove: true, content: `Action ${colors.code(path)} added successfully.` });\n },\n }),\n route: sub({\n description: \"Add an HTTP route\",\n details: sprint`\n Creates the route handler file on the environment and pulls it to your\n local directory. Supported methods are GET, POST, PUT, PATCH, and DELETE.\n `,\n examples: [\n \"ggt add route GET /hello\",\n \"ggt add route POST /webhooks/stripe\",\n \"ggt add route DELETE /posts/:id\",\n \"ggt add route PUT /users/:id\",\n ],\n positionals: [\n {\n name: \"method\",\n required: true,\n description: \"HTTP method (GET, POST, PUT, PATCH, DELETE)\",\n details: \"Case-insensitive.\",\n },\n {\n name: \"path\",\n required: true,\n description: \"Route path\",\n details: \"The URL path for the route handler (e.g. /hello, /webhooks/stripe). Leading slash is required.\",\n },\n ],\n run: async (ctx, flags) => {\n const { filesync, syncJson } = await setupCommandSync(ctx, \"add\", flags);\n // oxlint-disable-next-line no-non-null-assertion -- framework validates required positional\n const routeMethod = flags._[0]!;\n // oxlint-disable-next-line no-non-null-assertion -- framework validates required positional\n const routePath = flags._[1]!;\n\n await addRoute(ctx, {\n syncJson,\n filesync,\n method: routeMethod,\n path: routePath,\n });\n\n println({ ensureEmptyLineAbove: true, content: `Route ${colors.code(routePath)} added successfully.` });\n },\n }),\n field: sub({\n description: \"Add a field to an existing model\",\n details: sprint`\n Uses the format ${colors.subdued(\"model/field:type\")} to identify the target model and the\n field to add. Supported types include string, number, boolean, datetime,\n json, email, url, vector, richtext, file, enum, and color.\n `,\n examples: [\n \"ggt add field post/published:boolean\",\n \"ggt add field user/age:number\",\n \"ggt add field post/title:string\",\n \"ggt add field user/email:email\",\n ],\n positionals: [\n {\n name: \"model/field:type\",\n required: true,\n description: \"Model path and field definition\",\n details: \"Format is model/field:type (e.g. post/published:boolean).\",\n },\n ],\n run: async (ctx, flags) => {\n const { filesync, syncJson } = await setupCommandSync(ctx, \"add\", flags);\n\n // oxlint-disable-next-line no-non-null-assertion -- framework validates required positional\n const input = flags._[0]!;\n\n const parsed = parseFieldTarget(input);\n\n // Handle missing field definition case with original error message\n if (parsed.problems.includes(\"Missing field definition\")) {\n throw new FlagError(\"Failed to add field, invalid field definition\", { usageHint: false });\n }\n\n if (parsed.problems.length > 0) {\n throw new FlagError(\n sprint`\n Failed to add field:\n\n ${parsed.problems.map((p) => `• ${p}`).join(\"\\n\")}\n `,\n { usageHint: false },\n );\n }\n\n await addFields(ctx, {\n syncJson,\n filesync,\n modelApiIdentifier: parsed.modelApiIdentifier,\n fields: [{ name: parsed.fieldName, fieldType: parsed.fieldType }],\n });\n\n println({ ensureEmptyLineAbove: true, content: `Field ${colors.code(parsed.fieldName)} added successfully.` });\n },\n }),\n environment: sub({\n aliases: [\"env\"],\n description: \"Create a new environment by cloning\",\n details: sprint`\n Clones the current environment's data and schema into a new environment.\n If no name is given, one is auto-generated. After creation, automatically\n pulls from the new environment to switch your local directory to it.\n\n For more control (e.g. choosing the source environment or skipping the\n auto-switch), use ${colors.subdued(\"ggt env create\")} instead.\n `,\n examples: [\"ggt add environment staging\", \"ggt add environment\"],\n positionals: [\n {\n name: \"name\",\n description: \"Name for the new environment (auto-generated if omitted)\",\n details: \"The name is lowercased automatically. If omitted, a timestamped name is generated (e.g. env-20260303-142530).\",\n },\n ],\n run: async (ctx, flags) => {\n const { syncJson } = await setupCommandSync(ctx, \"add\", flags);\n\n let newEnvName = flags._[0];\n if (!newEnvName) {\n newEnvName = generateDefaultEnvName();\n }\n\n await addEnvironment(ctx, {\n syncJson,\n name: newEnvName,\n });\n\n println({ ensureEmptyLineAbove: true, content: `Environment ${colors.code(newEnvName)} added successfully.` });\n\n // Switch to newly made env\n await switchToNewEnvironment(ctx, {\n envName: newEnvName,\n command: \"pull\",\n });\n },\n }),\n }),\n});\n","import type { CreateActionMutation } from \"../../__generated__/graphql.ts\";\nimport { AddClientError } from \"../../commands/add.ts\";\nimport type { ModelApiIdentifier, GlobalActionApiIdentifier } from \"../app/app.ts\";\nimport { CREATE_ACTION_MUTATION } from \"../app/edit/operation.ts\";\nimport { ClientError } from \"../app/error.ts\";\nimport type { Context } from \"../command/context.ts\";\nimport type { FileSync } from \"../filesync/filesync.ts\";\nimport type { SyncJson } from \"../filesync/sync-json.ts\";\nimport colors from \"../output/colors.ts\";\nimport { println } from \"../output/print.ts\";\nimport { select } from \"../output/select.ts\";\nimport { sprint } from \"../output/sprint.ts\";\nimport { symbol } from \"../output/symbols.ts\";\n\nexport type AddActionResult = {\n path: string;\n remoteFilesVersion: string;\n changed: CreateActionMutation[\"createAction\"][\"changed\"];\n};\n\n/**\n * Resolve an action path, handling namespace conflicts between models and global actions.\n */\nexport const resolveActionPath = async (\n path: string,\n models: ModelApiIdentifier[],\n globalActions: GlobalActionApiIdentifier[],\n): Promise<{ path: string; overrideContextAction?: \"models\" | \"actions\" }> => {\n const splitPath = path.split(\"/\");\n const parsedPaths = splitPath.length > 1 ? splitPath.slice(0, splitPath.length - 1) : splitPath;\n const parsedAction = splitPath[splitPath.length - 1];\n\n const conflictingModel = models.find((model) => {\n const modelName = parsedPaths[parsedPaths.length - 1];\n return (\n model.apiIdentifier.toUpperCase() === modelName.toUpperCase() &&\n model.namespace?.join(\"/\") === parsedPaths.slice(0, parsedPaths.length - 1).join(\"/\")\n );\n });\n\n const conflictingActionNamespace = globalActions.find((action) => {\n return action.namespace?.join(\"/\") === parsedPaths.join(\"/\");\n });\n\n if (conflictingModel && conflictingActionNamespace) {\n const joinedParsedPaths = parsedPaths.join(\"/\");\n const overrideContextAction = await select({\n choices: [\"models\", \"actions\"] as const,\n content: sprint`\n ${colors.header(\"Namespace Conflict:\")} The action '${parsedAction}.js' cannot be automatically added due to a namespace conflict.\n\n How would you like to proceed?:\n `,\n formatChoice: (choice) => {\n switch (choice) {\n case \"models\": {\n return `As a Model action in ${colors.subdued(`models/${joinedParsedPaths}/${parsedAction}.js`)}`;\n }\n case \"actions\": {\n return `As an Action in ${colors.subdued(`actions/${joinedParsedPaths}/${parsedAction}.js`)}`;\n }\n }\n },\n });\n\n println({\n ensureEmptyLineAbove: true,\n content: sprint`${colors.renamed(symbol.info)} You can override the context of the action by specifying the context in the path. For example: ${colors.subdued(`ggt add action ${overrideContextAction}/${path}`)}`,\n });\n\n return { path: `${overrideContextAction}/${path}`, overrideContextAction };\n }\n\n return { path };\n};\n\n/**\n * Add an action to the app.\n */\nexport const addAction = async (\n ctx: Context,\n {\n syncJson,\n filesync,\n path,\n }: {\n syncJson: SyncJson;\n filesync: FileSync;\n path: string;\n },\n): Promise<AddActionResult> => {\n let result;\n\n try {\n result = (\n await syncJson.edit.mutate({\n mutation: CREATE_ACTION_MUTATION,\n variables: { path },\n })\n ).createAction;\n } catch (error) {\n if (error instanceof ClientError) {\n throw new AddClientError(error);\n } else {\n throw error;\n }\n }\n\n await filesync.writeToLocalFilesystem(ctx, { filesVersion: result.remoteFilesVersion, files: result.changed, delete: [] });\n\n return {\n path,\n remoteFilesVersion: result.remoteFilesVersion,\n changed: result.changed,\n };\n};\n"],"mappings":"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"}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import"./ms-B7sMc0pR.js";import"./src-DxCC1MV4.js";import"./prompt-C9nwJW0G.js";import"./http-CY3lPMkt.js";import{E as e,c as t,n,s as r}from"./command-2iNTc5dV.js";import"./filesync-De6asZeR.js";import"./collection-C2TCeYqY.js";import"./directory-CNL03L6c.js";import"./session-BmzGF1t7.js";import{n as i}from"./sync-json-V52OzeCz.js";import"./select-Dey_sjjd.js";import"./spinner-BVmbgIil.js";import"./table-MrBbxMay.js";import{i as a,t as o}from"./action-CF6zatIh.js";var s=n({name:`action`,description:`Add and manage actions`,details:e`
|
|
2
|
+
Actions run server-side code in your app. Add global actions for reusable
|
|
3
|
+
logic, or add model actions that run in the context of a specific model.
|
|
4
|
+
`,examples:[`ggt action add sendWelcomeEmail`,`ggt action add notifications/sendWelcomeEmail`,`ggt action add publish --model post`,`ggt action add fulfill --model shopifyOrder`],flags:i,subcommands:n=>({add:n({description:`Add an action to your app`,details:e`
|
|
5
|
+
Without ${r.subdued(`--model`)}, adds a global action. With ${r.subdued(`--model`)},
|
|
6
|
+
adds an action to an existing model.
|
|
7
|
+
`,examples:[`ggt action add sendWelcomeEmail`,`ggt action add notifications/sendWelcomeEmail`,`ggt action add publish --model post`,`ggt action add fulfill --model shopifyOrder`],positionals:[{name:`name`,required:!0,description:`Action API identifier`,details:`Can include namespaces as folders (for example notifications/sendWelcomeEmail).`}],flags:{"--model":{type:String,description:`Add a model action to the specified model`,details:`Model API identifier. Can include namespaces (for example billing/invoice).`}},run:async(e,n)=>{let{filesync:i,syncJson:s}=await a(e,`action`,n),c=n._[0],l=n[`--model`];await o(e,{syncJson:s,filesync:i,path:l?`model/${l}/${c}`:c}),t({ensureEmptyLineAbove:!0,content:`Action ${r.code(c)} added successfully.`})}})})});export{s as default};
|
|
8
|
+
//# sourceMappingURL=action-CrDCeX3F.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"action-CrDCeX3F.js","names":["colors"],"sources":["../src/commands/action.ts"],"sourcesContent":["import { addAction } from \"../services/add/action.ts\";\nimport { defineCommand } from \"../services/command/command.ts\";\nimport { setupCommandSync } from \"../services/filesync/setup-sync.ts\";\nimport { SyncJsonFlags } from \"../services/filesync/sync-json.ts\";\nimport colors from \"../services/output/colors.ts\";\nimport { println } from \"../services/output/print.ts\";\nimport { sprint } from \"../services/output/sprint.ts\";\n\nexport default defineCommand({\n name: \"action\",\n description: \"Add and manage actions\",\n details: sprint`\n Actions run server-side code in your app. Add global actions for reusable\n logic, or add model actions that run in the context of a specific model.\n `,\n examples: [\n \"ggt action add sendWelcomeEmail\",\n \"ggt action add notifications/sendWelcomeEmail\",\n \"ggt action add publish --model post\",\n \"ggt action add fulfill --model shopifyOrder\",\n ],\n flags: SyncJsonFlags,\n subcommands: (sub) => ({\n add: sub({\n description: \"Add an action to your app\",\n details: sprint`\n Without ${colors.subdued(\"--model\")}, adds a global action. With ${colors.subdued(\"--model\")},\n adds an action to an existing model.\n `,\n examples: [\n \"ggt action add sendWelcomeEmail\",\n \"ggt action add notifications/sendWelcomeEmail\",\n \"ggt action add publish --model post\",\n \"ggt action add fulfill --model shopifyOrder\",\n ],\n positionals: [\n {\n name: \"name\",\n required: true,\n description: \"Action API identifier\",\n details: \"Can include namespaces as folders (for example notifications/sendWelcomeEmail).\",\n },\n ],\n flags: {\n \"--model\": {\n type: String,\n description: \"Add a model action to the specified model\",\n details: \"Model API identifier. Can include namespaces (for example billing/invoice).\",\n },\n },\n run: async (ctx, flags) => {\n const { filesync, syncJson } = await setupCommandSync(ctx, \"action\", flags);\n\n // oxlint-disable-next-line no-non-null-assertion -- framework validates required positional\n const actionName = flags._[0]!;\n\n const modelApiIdentifier = flags[\"--model\"];\n const path = modelApiIdentifier ? `model/${modelApiIdentifier}/${actionName}` : actionName;\n\n await addAction(ctx, {\n syncJson,\n filesync,\n path,\n });\n\n println({ ensureEmptyLineAbove: true, content: `Action ${colors.code(actionName)} added successfully.` });\n },\n }),\n }),\n});\n"],"mappings":"sdAQA,IAAA,EAAe,EAAc,CAC3B,KAAM,SACN,YAAa,yBACb,QAAS,CAAM;;;IAIf,SAAU,CACR,kCACA,gDACA,sCACA,8CACD,CACD,MAAO,EACP,YAAc,IAAS,CACrB,IAAK,EAAI,CACP,YAAa,4BACb,QAAS,CAAM;kBACHA,EAAO,QAAQ,UAAU,CAAC,+BAA+BA,EAAO,QAAQ,UAAU,CAAC;;QAG/F,SAAU,CACR,kCACA,gDACA,sCACA,8CACD,CACD,YAAa,CACX,CACE,KAAM,OACN,SAAU,GACV,YAAa,wBACb,QAAS,kFACV,CACF,CACD,MAAO,CACL,UAAW,CACT,KAAM,OACN,YAAa,4CACb,QAAS,8EACV,CACF,CACD,IAAK,MAAO,EAAK,IAAU,CACzB,GAAM,CAAE,WAAU,YAAa,MAAM,EAAiB,EAAK,SAAU,EAAM,CAGrE,EAAa,EAAM,EAAE,GAErB,EAAqB,EAAM,WAGjC,MAAM,EAAU,EAAK,CACnB,WACA,WACA,KALW,EAAqB,SAAS,EAAmB,GAAG,IAAe,EAM/E,CAAC,CAEF,EAAQ,CAAE,qBAAsB,GAAM,QAAS,UAAUA,EAAO,KAAK,EAAW,CAAC,sBAAuB,CAAC,EAE5G,CAAC,CACH,EACF,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import"./ms-B7sMc0pR.js";import"./src-DxCC1MV4.js";import"./prompt-C9nwJW0G.js";import"./http-CY3lPMkt.js";import"./command-2iNTc5dV.js";import"./filesync-De6asZeR.js";import"./collection-C2TCeYqY.js";import"./directory-CNL03L6c.js";import"./session-BmzGF1t7.js";import"./sync-json-V52OzeCz.js";import"./select-Dey_sjjd.js";import"./spinner-BVmbgIil.js";import"./table-MrBbxMay.js";import{n as e,r as t}from"./action-CF6zatIh.js";export{e as AddClientError,t as default};
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import{o as e}from"./chunk-BjEoQXZ0.js";import"./ms-B7sMc0pR.js";import"./prompt-C9nwJW0G.js";import{g as t}from"./http-CY3lPMkt.js";import{E as n,H as r,V as i,n as a,s as o}from"./command-2iNTc5dV.js";import"./collection-C2TCeYqY.js";import{t as s}from"./directory-CNL03L6c.js";import"./session-BmzGF1t7.js";import{i as c,r as l}from"./agent-plugin-DU9G5B1d.js";import u from"node:path";var d=e(i(),1);const f=async()=>{let e=process.cwd(),t=await r(`.gadget/sync.json`,{cwd:e}),n=t?u.dirname(u.dirname(t)):e;return s.init(n)};var p=a({name:`agent-plugin`,description:`Manage plugins for AI coding assistants`,details:n`
|
|
2
|
+
Plugins include an ${o.identifier(`AGENTS.md`)} scaffold at the project root and Gadget-specific
|
|
3
|
+
skill files. These help tools like Claude Code and Cursor understand your Gadget
|
|
4
|
+
app's conventions. Must be run from inside a Gadget project directory or its parent.
|
|
5
|
+
`,examples:[`ggt agent-plugin install`,`ggt agent-plugin install --force`,`ggt agent-plugin update`],subcommands:e=>({install:e({description:`Install agent plugins into the current project`,details:n`
|
|
6
|
+
Writes ${o.identifier(`AGENTS.md`)} and Gadget skill files into your project. Existing
|
|
7
|
+
files are skipped unless ${o.hint(`--force`)} is passed to overwrite them. The
|
|
8
|
+
project root is detected from ${o.hint(`.gadget/sync.json`)} or defaults to the
|
|
9
|
+
current directory.
|
|
10
|
+
`,examples:[`ggt agent-plugin install`,`ggt agent-plugin install --force`],flags:{"--force":{type:Boolean,alias:`-f`,description:`Overwrite existing files even if already present`,details:`Overwrites existing AGENTS.md and skill files. Without this flag, existing files are left untouched.`}},run:async(e,t)=>{let n=await f(),r=t[`--force`]??!1;await l({ctx:e,directory:n,force:r}),await c({ctx:e,directory:n,force:r})}}),update:e({description:`Update agent plugins to the latest version`,details:n`
|
|
11
|
+
Overwrites all agent plugin files with their latest versions. Prompts
|
|
12
|
+
before replacing ${o.identifier(`AGENTS.md`)} if it already exists. Skill files are
|
|
13
|
+
always replaced without prompting.
|
|
14
|
+
`,examples:[`ggt agent-plugin update`],run:async e=>{let n=await f();(!await d.default.pathExists(n.absolute(`AGENTS.md`))||await t({exitWhenNo:!1,content:`Overwrite AGENTS.md with latest version?`}))&&await l({ctx:e,directory:n,force:!0}),await c({ctx:e,directory:n,force:!0})}})})});export{p as default};
|
|
15
|
+
//# sourceMappingURL=agent-plugin-CqgwTOk-.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"agent-plugin-CqgwTOk-.js","names":["colors","fs"],"sources":["../src/commands/agent-plugin.ts"],"sourcesContent":["import path from \"node:path\";\n\nimport { findUp } from \"find-up\";\nimport fs from \"fs-extra\";\n\nimport { defineCommand } from \"../services/command/command.ts\";\nimport { Directory } from \"../services/filesync/directory.ts\";\nimport { installAgentsMdScaffold, installGadgetSkillsIntoProject } from \"../services/output/agent-plugin.ts\";\nimport colors from \"../services/output/colors.ts\";\nimport { confirm } from \"../services/output/confirm.ts\";\nimport { sprint } from \"../services/output/sprint.ts\";\n\nconst resolveProjectRoot = async (): Promise<Directory> => {\n const cwd = process.cwd();\n const syncJsonPath = await findUp(\".gadget/sync.json\", { cwd });\n const projectRoot = syncJsonPath ? path.dirname(path.dirname(syncJsonPath)) : cwd;\n return Directory.init(projectRoot);\n};\n\nexport default defineCommand({\n name: \"agent-plugin\",\n description: \"Manage plugins for AI coding assistants\",\n details: sprint`\n Plugins include an ${colors.identifier(\"AGENTS.md\")} scaffold at the project root and Gadget-specific\n skill files. These help tools like Claude Code and Cursor understand your Gadget\n app's conventions. Must be run from inside a Gadget project directory or its parent.\n `,\n examples: [\"ggt agent-plugin install\", \"ggt agent-plugin install --force\", \"ggt agent-plugin update\"],\n subcommands: (sub) => ({\n install: sub({\n description: \"Install agent plugins into the current project\",\n details: sprint`\n Writes ${colors.identifier(\"AGENTS.md\")} and Gadget skill files into your project. Existing\n files are skipped unless ${colors.hint(\"--force\")} is passed to overwrite them. The\n project root is detected from ${colors.hint(\".gadget/sync.json\")} or defaults to the\n current directory.\n `,\n examples: [\"ggt agent-plugin install\", \"ggt agent-plugin install --force\"],\n flags: {\n \"--force\": {\n type: Boolean,\n alias: \"-f\",\n description: \"Overwrite existing files even if already present\",\n details: \"Overwrites existing AGENTS.md and skill files. Without this flag, existing files are left untouched.\",\n },\n },\n run: async (ctx, flags) => {\n const directory = await resolveProjectRoot();\n const force = flags[\"--force\"] ?? false;\n\n await installAgentsMdScaffold({ ctx, directory, force });\n await installGadgetSkillsIntoProject({ ctx, directory, force });\n },\n }),\n update: sub({\n description: \"Update agent plugins to the latest version\",\n details: sprint`\n Overwrites all agent plugin files with their latest versions. Prompts\n before replacing ${colors.identifier(\"AGENTS.md\")} if it already exists. Skill files are\n always replaced without prompting.\n `,\n examples: [\"ggt agent-plugin update\"],\n run: async (ctx) => {\n const directory = await resolveProjectRoot();\n\n const hasAgentsMd = await fs.pathExists(directory.absolute(\"AGENTS.md\"));\n if (!hasAgentsMd || (await confirm({ exitWhenNo: false, content: \"Overwrite AGENTS.md with latest version?\" }))) {\n await installAgentsMdScaffold({ ctx, directory, force: true });\n }\n await installGadgetSkillsIntoProject({ ctx, directory, force: true });\n },\n }),\n }),\n});\n"],"mappings":"oZAYA,MAAM,EAAqB,SAAgC,CACzD,IAAM,EAAM,QAAQ,KAAK,CACnB,EAAe,MAAM,EAAO,oBAAqB,CAAE,MAAK,CAAC,CACzD,EAAc,EAAe,EAAK,QAAQ,EAAK,QAAQ,EAAa,CAAC,CAAG,EAC9E,OAAO,EAAU,KAAK,EAAY,EAGpC,IAAA,EAAe,EAAc,CAC3B,KAAM,eACN,YAAa,0CACb,QAAS,CAAM;yBACQA,EAAO,WAAW,YAAY,CAAC;;;IAItD,SAAU,CAAC,2BAA4B,mCAAoC,0BAA0B,CACrG,YAAc,IAAS,CACrB,QAAS,EAAI,CACX,YAAa,iDACb,QAAS,CAAM;iBACJA,EAAO,WAAW,YAAY,CAAC;mCACbA,EAAO,KAAK,UAAU,CAAC;wCAClBA,EAAO,KAAK,oBAAoB,CAAC;;QAGnE,SAAU,CAAC,2BAA4B,mCAAmC,CAC1E,MAAO,CACL,UAAW,CACT,KAAM,QACN,MAAO,KACP,YAAa,mDACb,QAAS,uGACV,CACF,CACD,IAAK,MAAO,EAAK,IAAU,CACzB,IAAM,EAAY,MAAM,GAAoB,CACtC,EAAQ,EAAM,YAAc,GAElC,MAAM,EAAwB,CAAE,MAAK,YAAW,QAAO,CAAC,CACxD,MAAM,EAA+B,CAAE,MAAK,YAAW,QAAO,CAAC,EAElE,CAAC,CACF,OAAQ,EAAI,CACV,YAAa,6CACb,QAAS,CAAM;;2BAEMA,EAAO,WAAW,YAAY,CAAC;;QAGpD,SAAU,CAAC,0BAA0B,CACrC,IAAK,KAAO,IAAQ,CAClB,IAAM,EAAY,MAAM,GAAoB,EAGxC,CADgB,MAAMC,EAAAA,QAAG,WAAW,EAAU,SAAS,YAAY,CAAC,EACnD,MAAM,EAAQ,CAAE,WAAY,GAAO,QAAS,2CAA4C,CAAC,GAC5G,MAAM,EAAwB,CAAE,MAAK,YAAW,MAAO,GAAM,CAAC,CAEhE,MAAM,EAA+B,CAAE,MAAK,YAAW,MAAO,GAAM,CAAC,EAExE,CAAC,CACH,EACF,CAAC"}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import{o as e}from"./chunk-BjEoQXZ0.js";import{t}from"./ms-B7sMc0pR.js";import{g as n,t as r}from"./http-CY3lPMkt.js";import{E as i,V as a,c as o,d as s,l as c,s as l}from"./command-2iNTc5dV.js";import{t as u}from"./p-map-DE0acmRv.js";import d from"node:os";import f from"node:path";import p from"node:crypto";var m=e(a(),1),h=e(t(),1);const g=`AGENTS.md`,_=`CLAUDE.md`,v=`gadget-best-practices`,y=`gadget-inc/skills`,b=(0,h.default)(`10s`),x=e=>{let t=f.resolve(e.path);return p.createHash(`md5`).update(s.windows?t.toLowerCase():t).digest(`hex`).slice(0,16)},S=(e,t)=>f.join(s.cacheDir,`${t}${x(e)}`),C=e=>f.join(s.cacheDir,`agent-plugin-sha-${x(e)}`),w=async({ctx:e,directory:t,force:n})=>{let a=t.absolute(g),c=t.absolute(_),u=await m.default.pathExists(a),d=await m.default.lstat(c).then(()=>!0,()=>!1);if(!n&&(u||d)){o({content:i`${l.hint(`✓`)} Agent scaffold already exists (reinstall with ${l.code(`ggt agent-plugin install --force`)})`});return}try{let t=await r({context:{ctx:e},method:`GET`,url:`https://raw.githubusercontent.com/gadget-inc/skills/main/agents/AGENTS.md`,headers:{Accept:`text/plain`},timeout:{request:b}}).text();await m.default.outputFile(a,t.endsWith(`
|
|
2
|
+
`)?t:`${t}\n`)}catch{o({ensureEmptyLineAbove:!0,content:i`${l.error(`Failed to install AGENTS.md.`)} Try again: ${l.code(`ggt agent-plugin install`)}`});return}o({content:i`${l.success(`✓`)} AGENTS.md installed`});try{n&&await m.default.remove(c),await m.default.symlink(g,c)}catch{s.windows?o({content:i`To link ${l.code(_)} → ${l.code(g)} on Windows, you may need Developer Mode.
|
|
3
|
+
|
|
4
|
+
Try in PowerShell:
|
|
5
|
+
${l.code(`New-Item -ItemType SymbolicLink -Path ${_} -Target ${g}`)}`}):o({content:i`Couldn't create ${l.code(_)} symlink.
|
|
6
|
+
|
|
7
|
+
Try:
|
|
8
|
+
${l.code(`ln -sf ${g} ${_}`)}`})}},T=async({ctx:e,directory:t})=>{if(!c.isInteractive||s.logFormat===`json`||!await D(t)||await m.default.pathExists(t.absolute(g))||await m.default.lstat(t.absolute(_)).then(()=>!0,()=>!1))return;let r=S(t,`opt_out-agents-md-hint-`);if(!await m.default.pathExists(r)){if(!await n({exitWhenNo:!1,ensureEmptyLineAbove:!0,ensureNewLine:!0,content:`Add ${g} to this project for your coding agent?`})){await m.default.outputFile(r,`1`).catch(()=>void 0);return}await w({ctx:e,directory:t})}},E=async({ctx:e,directory:t,ref:n=`main`,force:a})=>{let s=t.absolute(`.agents/skills`,v,`SKILL.md`);if(!a&&await m.default.pathExists(s)){o({content:i`${l.hint(`✓`)} Gadget skills already installed (reinstall with ${l.code(`ggt agent-plugin install --force`)})`});return}let c,p;try{p=(await r({context:{ctx:e},method:`GET`,url:`https://api.github.com/repos/${y}/commits/${n}`,headers:{Accept:`application/vnd.github+json`},responseType:`json`,resolveBodyOnly:!0,timeout:{request:b}})).sha;let i=`https://api.github.com/repos/${y}/git/trees/${p}?recursive=1`,{tree:a}=await r({context:{ctx:e},method:`GET`,url:i,headers:{Accept:`application/vnd.github+json`},responseType:`json`,resolveBodyOnly:!0,timeout:{request:b}}),o=a.filter(e=>e.type===`blob`&&e.path.startsWith(`skills/gadget/`));if(o.length===0)throw Error(`No skills found in repository.`);let s=new Set;for(let e of o){let t=e.path.slice(14);t.includes(`..`)||t.startsWith(`/`)||s.add(t.split(`/`)[0])}let l=t.absolute(`.agents`,`.tmp-gadget-skills-${Date.now()}`);await m.default.ensureDir(l);try{await u(o,async t=>{let n=t.path.slice(14);if(n.includes(`..`)||n.startsWith(`/`))return;let i=f.join(l,n);if(!f.resolve(i).startsWith(f.resolve(l)))return;let a=`https://raw.githubusercontent.com/${y}/${p}/${t.path}`,o=await r({context:{ctx:e},method:`GET`,url:a,timeout:{request:b}}).text();await m.default.ensureDir(f.dirname(i)),await m.default.writeFile(i,o)},{concurrency:5});let n=t.absolute(`.agents/skills`);for(let e of s){let t=f.join(l,e),r=f.join(n,e);await m.default.remove(r),await m.default.move(t,r,{overwrite:!0})}}finally{await m.default.remove(l).catch(()=>void 0)}c=[...s]}catch(e){o({ensureEmptyLineAbove:!0,content:i`${l.error(`Failed to install skills.`)} ${e instanceof Error?e.message:String(e)}`});return}o({content:i`${l.success(`✓`)} Installed skills: ${c.join(`, `)}`}),p&&await m.default.outputFile(C(t),p).catch(()=>void 0);try{let e=t.absolute(`.claude/skills`);await m.default.ensureDir(e);for(let n of c){let r=t.absolute(`.agents/skills`,n),i=f.join(e,n);try{let e=await m.default.readlink(i);if(f.resolve(f.dirname(i),e)===f.resolve(r))continue}catch{}await m.default.remove(i),d.platform()===`win32`?await m.default.symlink(r,i,`junction`):await m.default.symlink(f.relative(f.dirname(i),r),i)}o({content:i`${l.success(`✓`)} Symlinks created in .claude/skills/`})}catch(e){o({content:i`${l.warning(`⚠`)} Failed to create .claude/skills/ symlinks: ${e instanceof Error?e.message:String(e)}`})}},D=async e=>{try{for await(let t of e.walk())if(!t.startsWith(`.gadget`))return!0}catch{return!1}return!1},O=async({ctx:e,directory:t})=>{if(!c.isInteractive||s.logFormat===`json`||!await D(t)||await m.default.pathExists(t.absolute(`.agents/skills`,v,`SKILL.md`)))return;let r=S(t,`opt_out-gadget-skills-hint-`);if(!await m.default.pathExists(r)){if(!await n({exitWhenNo:!1,ensureEmptyLineAbove:!0,ensureNewLine:!0,content:`Install Gadget agent skills for your coding agent?`})){await m.default.outputFile(r,`1`).catch(()=>void 0);return}await E({ctx:e,directory:t,force:!0})}};export{T as a,E as i,C as n,O as o,w as r,y as t};
|
|
9
|
+
//# sourceMappingURL=agent-plugin-DU9G5B1d.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"agent-plugin-DU9G5B1d.js","names":["fs","colors"],"sources":["../src/services/output/agent-plugin.ts"],"sourcesContent":["import crypto from \"node:crypto\";\nimport os from \"node:os\";\nimport path from \"node:path\";\n\nimport fs from \"fs-extra\";\nimport ms from \"ms\";\nimport pMap from \"p-map\";\n\nimport type { Context } from \"../command/context.ts\";\nimport { config } from \"../config/config.ts\";\nimport { Directory } from \"../filesync/directory.ts\";\nimport { http } from \"../http/http.ts\";\nimport colors from \"./colors.ts\";\nimport { confirm } from \"./confirm.ts\";\nimport { output } from \"./output.ts\";\nimport { println } from \"./print.ts\";\nimport { sprint } from \"./sprint.ts\";\n\nconst AGENTS_FILE = \"AGENTS.md\";\nconst CLAUDE_FILE = \"CLAUDE.md\";\nconst AGENTS_MD_URL = \"https://raw.githubusercontent.com/gadget-inc/skills/main/agents/AGENTS.md\";\n\nconst SENTINEL_SKILL = \"gadget-best-practices\";\nexport const SKILLS_REPO = \"gadget-inc/skills\";\nconst SKILLS_PREFIX = \"skills/gadget/\";\nconst SHA_CACHE_PREFIX = \"agent-plugin-sha-\";\n\nconst HTTP_TIMEOUT = ms(\"10s\");\n\nconst projectHash = (directory: Directory): string => {\n const root = path.resolve(directory.path);\n return crypto\n .createHash(\"md5\")\n .update(config.windows ? root.toLowerCase() : root)\n .digest(\"hex\")\n .slice(0, 16);\n};\n\nconst optOutPath = (directory: Directory, prefix: string): string => {\n return path.join(config.cacheDir, `${prefix}${projectHash(directory)}`);\n};\n\nexport const agentPluginShaPath = (directory: Directory): string => {\n return path.join(config.cacheDir, `${SHA_CACHE_PREFIX}${projectHash(directory)}`);\n};\n\nexport const installAgentsMdScaffold = async ({\n ctx,\n directory,\n force,\n}: {\n ctx: Context;\n directory: Directory;\n force?: boolean;\n}): Promise<void> => {\n const agentsPath = directory.absolute(AGENTS_FILE);\n const claudePath = directory.absolute(CLAUDE_FILE);\n\n const agentsExists = await fs.pathExists(agentsPath);\n const claudeExists = await fs.lstat(claudePath).then(\n () => true,\n () => false,\n );\n\n if (!force && (agentsExists || claudeExists)) {\n println({\n content: sprint`${colors.hint(\"✓\")} Agent scaffold already exists (reinstall with ${colors.code(\"ggt agent-plugin install --force\")})`,\n });\n return;\n }\n\n try {\n const text = await http({\n context: { ctx },\n method: \"GET\",\n url: AGENTS_MD_URL,\n headers: { Accept: \"text/plain\" },\n timeout: { request: HTTP_TIMEOUT },\n }).text();\n await fs.outputFile(agentsPath, text.endsWith(\"\\n\") ? text : `${text}\\n`);\n } catch {\n println({\n ensureEmptyLineAbove: true,\n content: sprint`${colors.error(\"Failed to install AGENTS.md.\")} Try again: ${colors.code(\"ggt agent-plugin install\")}`,\n });\n return;\n }\n\n println({ content: sprint`${colors.success(\"✓\")} AGENTS.md installed` });\n\n try {\n if (force) await fs.remove(claudePath);\n await fs.symlink(AGENTS_FILE, claudePath);\n } catch {\n if (config.windows) {\n println({\n content: sprint`To link ${colors.code(CLAUDE_FILE)} → ${colors.code(AGENTS_FILE)} on Windows, you may need Developer Mode.\n\nTry in PowerShell:\n ${colors.code(`New-Item -ItemType SymbolicLink -Path ${CLAUDE_FILE} -Target ${AGENTS_FILE}`)}`,\n });\n } else {\n println({\n content: sprint`Couldn't create ${colors.code(CLAUDE_FILE)} symlink.\n\nTry:\n ${colors.code(`ln -sf ${AGENTS_FILE} ${CLAUDE_FILE}`)}`,\n });\n }\n }\n};\n\nexport const maybePromptAgentsMd = async ({ ctx, directory }: { ctx: Context; directory: Directory }): Promise<void> => {\n if (!output.isInteractive || config.logFormat === \"json\") return;\n // don't prompt to add AGENTS.md if the directory doesn't contain any user files\n // this means the first sync has not happened so we don't know yet if the user has\n // their own AGENTS.md already\n if (!(await hasNonGadgetFiles(directory))) return;\n if (await fs.pathExists(directory.absolute(AGENTS_FILE))) return;\n if (\n await fs.lstat(directory.absolute(CLAUDE_FILE)).then(\n () => true,\n () => false,\n )\n )\n return;\n\n const optOut = optOutPath(directory, \"opt_out-agents-md-hint-\");\n if (await fs.pathExists(optOut)) return;\n\n const yes = await confirm({\n exitWhenNo: false,\n ensureEmptyLineAbove: true,\n ensureNewLine: true,\n content: `Add ${AGENTS_FILE} to this project for your coding agent?`,\n });\n\n if (!yes) {\n await fs.outputFile(optOut, \"1\").catch(() => undefined);\n return;\n }\n\n await installAgentsMdScaffold({ ctx, directory });\n};\n\ntype GitHubTreeEntry = {\n path: string;\n type: string;\n sha: string;\n};\n\nexport const installGadgetSkillsIntoProject = async ({\n ctx,\n directory,\n ref = \"main\",\n force,\n}: {\n ctx: Context;\n directory: Directory;\n ref?: string;\n force?: boolean;\n}): Promise<void> => {\n const sentinelPath = directory.absolute(\".agents/skills\", SENTINEL_SKILL, \"SKILL.md\");\n\n if (!force && (await fs.pathExists(sentinelPath))) {\n println({\n content: sprint`${colors.hint(\"✓\")} Gadget skills already installed (reinstall with ${colors.code(\"ggt agent-plugin install --force\")})`,\n });\n return;\n }\n\n let skillNames: string[];\n let commitSha: string | undefined;\n\n try {\n const commitData = (await http({\n context: { ctx },\n method: \"GET\",\n url: `https://api.github.com/repos/${SKILLS_REPO}/commits/${ref}`,\n headers: { Accept: \"application/vnd.github+json\" },\n responseType: \"json\",\n resolveBodyOnly: true,\n timeout: { request: HTTP_TIMEOUT },\n })) as { sha: string };\n commitSha = commitData.sha;\n\n const treeUrl = `https://api.github.com/repos/${SKILLS_REPO}/git/trees/${commitSha}?recursive=1`;\n const treeData = await http({\n context: { ctx },\n method: \"GET\",\n url: treeUrl,\n headers: { Accept: \"application/vnd.github+json\" },\n responseType: \"json\",\n resolveBodyOnly: true,\n timeout: { request: HTTP_TIMEOUT },\n });\n\n const { tree } = treeData as { tree: GitHubTreeEntry[] };\n const blobs = tree.filter((e) => e.type === \"blob\" && e.path.startsWith(SKILLS_PREFIX));\n if (blobs.length === 0) {\n throw new Error(\"No skills found in repository.\");\n }\n\n const names = new Set<string>();\n for (const blob of blobs) {\n const relative = blob.path.slice(SKILLS_PREFIX.length);\n if (relative.includes(\"..\") || relative.startsWith(\"/\")) continue;\n names.add(relative.split(\"/\")[0] as string);\n }\n\n const tmpDir = directory.absolute(\".agents\", `.tmp-gadget-skills-${Date.now()}`);\n await fs.ensureDir(tmpDir);\n\n try {\n await pMap(\n blobs,\n async (blob) => {\n const relative = blob.path.slice(SKILLS_PREFIX.length);\n if (relative.includes(\"..\") || relative.startsWith(\"/\")) return;\n\n const destPath = path.join(tmpDir, relative);\n if (!path.resolve(destPath).startsWith(path.resolve(tmpDir))) return;\n\n const rawUrl = `https://raw.githubusercontent.com/${SKILLS_REPO}/${commitSha}/${blob.path}`;\n const text = await http({\n context: { ctx },\n method: \"GET\",\n url: rawUrl,\n timeout: { request: HTTP_TIMEOUT },\n }).text();\n\n await fs.ensureDir(path.dirname(destPath));\n await fs.writeFile(destPath, text);\n },\n { concurrency: 5 },\n );\n\n const skillsDir = directory.absolute(\".agents/skills\");\n for (const name of names) {\n const src = path.join(tmpDir, name);\n const dest = path.join(skillsDir, name);\n await fs.remove(dest);\n await fs.move(src, dest, { overwrite: true });\n }\n } finally {\n await fs.remove(tmpDir).catch(() => undefined);\n }\n\n skillNames = [...names];\n } catch (error) {\n println({\n ensureEmptyLineAbove: true,\n content: sprint`${colors.error(\"Failed to install skills.\")} ${error instanceof Error ? error.message : String(error)}`,\n });\n return;\n }\n\n println({\n content: sprint`${colors.success(\"✓\")} Installed skills: ${skillNames.join(\", \")}`,\n });\n\n if (commitSha) {\n await fs.outputFile(agentPluginShaPath(directory), commitSha).catch(() => undefined);\n }\n\n try {\n const claudeSkillsDir = directory.absolute(\".claude/skills\");\n await fs.ensureDir(claudeSkillsDir);\n\n for (const skillName of skillNames) {\n const target = directory.absolute(\".agents/skills\", skillName);\n const linkPath = path.join(claudeSkillsDir, skillName);\n\n try {\n const existing = await fs.readlink(linkPath);\n if (path.resolve(path.dirname(linkPath), existing) === path.resolve(target)) continue;\n } catch {}\n\n await fs.remove(linkPath);\n\n if (os.platform() === \"win32\") {\n await fs.symlink(target, linkPath, \"junction\");\n } else {\n await fs.symlink(path.relative(path.dirname(linkPath), target), linkPath);\n }\n }\n\n println({\n content: sprint`${colors.success(\"✓\")} Symlinks created in .claude/skills/`,\n });\n } catch (error) {\n println({\n content: sprint`${colors.warning(\"⚠\")} Failed to create .claude/skills/ symlinks: ${error instanceof Error ? error.message : String(error)}`,\n });\n }\n};\n\nconst hasNonGadgetFiles = async (directory: Directory): Promise<boolean> => {\n try {\n for await (const normalizedPath of directory.walk()) {\n if (!normalizedPath.startsWith(\".gadget\")) {\n return true;\n }\n }\n } catch {\n // on error, skip the prompt\n return false;\n }\n\n return false;\n};\n\nexport const maybePromptGadgetSkills = async ({ ctx, directory }: { ctx: Context; directory: Directory }): Promise<void> => {\n if (!output.isInteractive || config.logFormat === \"json\") return;\n // don't prompt to add skills if the directory doesn't contain any user files\n // this means the first sync has not happened so we don't know yet if the user has\n // their own skills already\n if (!(await hasNonGadgetFiles(directory))) return;\n if (await fs.pathExists(directory.absolute(\".agents/skills\", SENTINEL_SKILL, \"SKILL.md\"))) return;\n\n const optOut = optOutPath(directory, \"opt_out-gadget-skills-hint-\");\n if (await fs.pathExists(optOut)) return;\n\n const yes = await confirm({\n exitWhenNo: false,\n ensureEmptyLineAbove: true,\n ensureNewLine: true,\n content: \"Install Gadget agent skills for your coding agent?\",\n });\n\n if (!yes) {\n await fs.outputFile(optOut, \"1\").catch(() => undefined);\n return;\n }\n\n await installGadgetSkillsIntoProject({ ctx, directory, force: true });\n};\n"],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"assert-Bu1E126Z.js","names":[],"sources":["../src/services/util/assert.ts"],"sourcesContent":["/* oxlint-disable func-style */\n\n/**\n * Throws an error indicating that the code should be unreachable.\n *\n * @param expr - An optional expression to include in the error message.\n * @throws - Always throws an error with the message \"Unreachable code: {expr}\".\n */\nexport function unreachable(expr?: unknown): never {\n // oxlint-disable-next-line restrict-template-expressions\n throw new Error(`Unreachable code: ${expr}`);\n}\n"],"mappings":"AAQA,SAAgB,EAAY,EAAuB,CAEjD,MAAU,MAAM,qBAAqB,IAAO"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{createRequire as e}from"node:module";var t=Object.create,n=Object.defineProperty,r=Object.getOwnPropertyDescriptor,i=Object.getOwnPropertyNames,a=Object.getPrototypeOf,o=Object.prototype.hasOwnProperty,s=(e,t)=>()=>(e&&(t=e(e=0)),t),c=(e,t)=>()=>(t||e((t={exports:{}}).exports,t),t.exports),l=(e,t)=>{let r={};for(var i in e)n(r,i,{get:e[i],enumerable:!0});return t||n(r,Symbol.toStringTag,{value:`Module`}),r},u=(e,t,a,s)=>{if(t&&typeof t==`object`||typeof t==`function`)for(var c=i(t),l=0,u=c.length,d;l<u;l++)d=c[l],!o.call(e,d)&&d!==a&&n(e,d,{get:(e=>t[e]).bind(null,d),enumerable:!(s=r(t,d))||s.enumerable});return e},d=(e,r,i)=>(i=e==null?{}:t(a(e)),u(r||!e||!e.__esModule?n(i,`default`,{value:e,enumerable:!0}):i,e)),f=e=>o.call(e,`module.exports`)?e[`module.exports`]:u(n({},`__esModule`,{value:!0}),e),p=e(import.meta.url);export{f as a,p as i,s as n,d as o,l as r,c as t};
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
import{o as e,t}from"./chunk-BjEoQXZ0.js";import n from"node:assert";var r=t((e=>{e.__esModule=!0,e.distance=e.closest=void 0;var t=new Uint32Array(65536),n=function(e,n){for(var r=e.length,i=n.length,a=1<<r-1,o=-1,s=0,c=r,l=r;l--;)t[e.charCodeAt(l)]|=1<<l;for(l=0;l<i;l++){var u=t[n.charCodeAt(l)],d=u|s;u|=(u&o)+o^o,s|=~(u|o),o&=u,s&a&&c++,o&a&&c--,s=s<<1|1,o=o<<1|~(d|s),s&=d}for(l=r;l--;)t[e.charCodeAt(l)]=0;return c},r=function(e,n){for(var r=n.length,i=e.length,a=[],o=[],s=Math.ceil(r/32),c=Math.ceil(i/32),l=0;l<s;l++)o[l]=-1,a[l]=0;for(var u=0;u<c-1;u++){for(var d=0,f=-1,p=u*32,m=Math.min(32,i)+p,h=p;h<m;h++)t[e.charCodeAt(h)]|=1<<h;for(var l=0;l<r;l++){var g=t[n.charCodeAt(l)],_=o[l/32|0]>>>l&1,v=a[l/32|0]>>>l&1,y=g|d,b=((g|v)&f)+f^f|g|v,x=d|~(b|f),S=f&b;x>>>31^_&&(o[l/32|0]^=1<<l),S>>>31^v&&(a[l/32|0]^=1<<l),x=x<<1|_,S=S<<1|v,f=S|~(y|x),d=x&y}for(var h=p;h<m;h++)t[e.charCodeAt(h)]=0}for(var C=0,w=-1,T=u*32,E=Math.min(32,i-T)+T,h=T;h<E;h++)t[e.charCodeAt(h)]|=1<<h;for(var D=i,l=0;l<r;l++){var g=t[n.charCodeAt(l)],_=o[l/32|0]>>>l&1,v=a[l/32|0]>>>l&1,y=g|C,b=((g|v)&w)+w^w|g|v,x=C|~(b|w),S=w&b;D+=x>>>i-1&1,D-=S>>>i-1&1,x>>>31^_&&(o[l/32|0]^=1<<l),S>>>31^v&&(a[l/32|0]^=1<<l),x=x<<1|_,S=S<<1|v,w=S|~(y|x),C=x&y}for(var h=T;h<E;h++)t[e.charCodeAt(h)]=0;return D},i=function(e,t){if(e.length<t.length){var i=t;t=e,e=i}return t.length===0?e.length:e.length<=32?n(e,t):r(e,t)};e.distance=i,e.closest=function(e,t){for(var n=1/0,r=0,a=0;a<t.length;a++){var o=i(e,t[a]);o<n&&(n=o,r=a)}return t[r]}})),i=e(t(((e,t)=>{(function(){var n;try{n=typeof Intl<`u`&&Intl.Collator!==void 0?Intl.Collator(`generic`,{sensitivity:`base`}):null}catch{console.log(`Collator could not be initialized and wouldn't be used`)}var i=r(),a=[],o=[],s={get:function(e,t,r){if(r&&n&&r.useCollator){var s=e.length,c=t.length;if(s===0)return c;if(c===0)return s;var l,u,d,f,p;for(d=0;d<c;++d)a[d]=d,o[d]=t.charCodeAt(d);a[c]=c;var m;for(d=0;d<s;++d){for(u=d+1,f=0;f<c;++f)l=u,m=n.compare(e.charAt(d),String.fromCharCode(o[f]))===0,u=a[f]+(m?0:1),p=l+1,u>p&&(u=p),p=a[f+1]+1,u>p&&(u=p),a[f]=l;a[f]=u}return u}return i.distance(e,t)}};typeof define<`u`&&define!==null&&define.amd?define(function(){return s}):t!=null&&e!==void 0&&t.exports===e?t.exports=s:typeof self<`u`&&typeof self.postMessage==`function`&&typeof self.importScripts==`function`?self.Levenshtein=s:typeof window<`u`&&window!==null&&(window.Levenshtein=s)})()}))(),1);const a=e=>e.filter(e=>!!e),o=e=>[...new Set(e)],s=(e,t)=>(n(t.length>0,`options must not be empty`),[...t].sort((t,n)=>i.default.get(t,e)-i.default.get(n,e))),c=(e,t)=>s(e,t)[0],l=(e,t)=>t?e.filter(e=>e.startsWith(t)):e;export{o as a,s as i,a as n,l as r,c as t};
|
|
2
|
+
//# sourceMappingURL=collection-C2TCeYqY.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"collection-C2TCeYqY.js","names":["levenshtein"],"sources":["../node_modules/.pnpm/fastest-levenshtein@1.0.16/node_modules/fastest-levenshtein/mod.js","../node_modules/.pnpm/fast-levenshtein@3.0.0/node_modules/fast-levenshtein/levenshtein.js","../src/services/util/collection.ts"],"sourcesContent":["\"use strict\";\nexports.__esModule = true;\nexports.distance = exports.closest = void 0;\nvar peq = new Uint32Array(0x10000);\nvar myers_32 = function (a, b) {\n var n = a.length;\n var m = b.length;\n var lst = 1 << (n - 1);\n var pv = -1;\n var mv = 0;\n var sc = n;\n var i = n;\n while (i--) {\n peq[a.charCodeAt(i)] |= 1 << i;\n }\n for (i = 0; i < m; i++) {\n var eq = peq[b.charCodeAt(i)];\n var xv = eq | mv;\n eq |= ((eq & pv) + pv) ^ pv;\n mv |= ~(eq | pv);\n pv &= eq;\n if (mv & lst) {\n sc++;\n }\n if (pv & lst) {\n sc--;\n }\n mv = (mv << 1) | 1;\n pv = (pv << 1) | ~(xv | mv);\n mv &= xv;\n }\n i = n;\n while (i--) {\n peq[a.charCodeAt(i)] = 0;\n }\n return sc;\n};\nvar myers_x = function (b, a) {\n var n = a.length;\n var m = b.length;\n var mhc = [];\n var phc = [];\n var hsize = Math.ceil(n / 32);\n var vsize = Math.ceil(m / 32);\n for (var i = 0; i < hsize; i++) {\n phc[i] = -1;\n mhc[i] = 0;\n }\n var j = 0;\n for (; j < vsize - 1; j++) {\n var mv_1 = 0;\n var pv_1 = -1;\n var start_1 = j * 32;\n var vlen_1 = Math.min(32, m) + start_1;\n for (var k = start_1; k < vlen_1; k++) {\n peq[b.charCodeAt(k)] |= 1 << k;\n }\n for (var i = 0; i < n; i++) {\n var eq = peq[a.charCodeAt(i)];\n var pb = (phc[(i / 32) | 0] >>> i) & 1;\n var mb = (mhc[(i / 32) | 0] >>> i) & 1;\n var xv = eq | mv_1;\n var xh = ((((eq | mb) & pv_1) + pv_1) ^ pv_1) | eq | mb;\n var ph = mv_1 | ~(xh | pv_1);\n var mh = pv_1 & xh;\n if ((ph >>> 31) ^ pb) {\n phc[(i / 32) | 0] ^= 1 << i;\n }\n if ((mh >>> 31) ^ mb) {\n mhc[(i / 32) | 0] ^= 1 << i;\n }\n ph = (ph << 1) | pb;\n mh = (mh << 1) | mb;\n pv_1 = mh | ~(xv | ph);\n mv_1 = ph & xv;\n }\n for (var k = start_1; k < vlen_1; k++) {\n peq[b.charCodeAt(k)] = 0;\n }\n }\n var mv = 0;\n var pv = -1;\n var start = j * 32;\n var vlen = Math.min(32, m - start) + start;\n for (var k = start; k < vlen; k++) {\n peq[b.charCodeAt(k)] |= 1 << k;\n }\n var score = m;\n for (var i = 0; i < n; i++) {\n var eq = peq[a.charCodeAt(i)];\n var pb = (phc[(i / 32) | 0] >>> i) & 1;\n var mb = (mhc[(i / 32) | 0] >>> i) & 1;\n var xv = eq | mv;\n var xh = ((((eq | mb) & pv) + pv) ^ pv) | eq | mb;\n var ph = mv | ~(xh | pv);\n var mh = pv & xh;\n score += (ph >>> (m - 1)) & 1;\n score -= (mh >>> (m - 1)) & 1;\n if ((ph >>> 31) ^ pb) {\n phc[(i / 32) | 0] ^= 1 << i;\n }\n if ((mh >>> 31) ^ mb) {\n mhc[(i / 32) | 0] ^= 1 << i;\n }\n ph = (ph << 1) | pb;\n mh = (mh << 1) | mb;\n pv = mh | ~(xv | ph);\n mv = ph & xv;\n }\n for (var k = start; k < vlen; k++) {\n peq[b.charCodeAt(k)] = 0;\n }\n return score;\n};\nvar distance = function (a, b) {\n if (a.length < b.length) {\n var tmp = b;\n b = a;\n a = tmp;\n }\n if (b.length === 0) {\n return a.length;\n }\n if (a.length <= 32) {\n return myers_32(a, b);\n }\n return myers_x(a, b);\n};\nexports.distance = distance;\nvar closest = function (str, arr) {\n var min_distance = Infinity;\n var min_index = 0;\n for (var i = 0; i < arr.length; i++) {\n var dist = distance(str, arr[i]);\n if (dist < min_distance) {\n min_distance = dist;\n min_index = i;\n }\n }\n return arr[min_index];\n};\nexports.closest = closest;\n","(function() {\n 'use strict';\n \n var collator;\n try {\n collator = (typeof Intl !== \"undefined\" && typeof Intl.Collator !== \"undefined\") ? Intl.Collator(\"generic\", { sensitivity: \"base\" }) : null;\n } catch (err){\n console.log(\"Collator could not be initialized and wouldn't be used\");\n }\n\n var levenshtein = require('fastest-levenshtein');\n\n // arrays to re-use\n var prevRow = [],\n str2Char = [];\n \n /**\n * Based on the algorithm at http://en.wikipedia.org/wiki/Levenshtein_distance.\n */\n var Levenshtein = {\n /**\n * Calculate levenshtein distance of the two strings.\n *\n * @param str1 String the first string.\n * @param str2 String the second string.\n * @param [options] Additional options.\n * @param [options.useCollator] Use `Intl.Collator` for locale-sensitive string comparison.\n * @return Integer the levenshtein distance (0 and above).\n */\n get: function(str1, str2, options) {\n var useCollator = (options && collator && options.useCollator);\n \n if (useCollator) {\n var str1Len = str1.length,\n str2Len = str2.length;\n \n // base cases\n if (str1Len === 0) return str2Len;\n if (str2Len === 0) return str1Len;\n\n // two rows\n var curCol, nextCol, i, j, tmp;\n\n // initialise previous row\n for (i=0; i<str2Len; ++i) {\n prevRow[i] = i;\n str2Char[i] = str2.charCodeAt(i);\n }\n prevRow[str2Len] = str2Len;\n\n var strCmp;\n // calculate current row distance from previous row using collator\n for (i = 0; i < str1Len; ++i) {\n nextCol = i + 1;\n\n for (j = 0; j < str2Len; ++j) {\n curCol = nextCol;\n\n // substution\n strCmp = 0 === collator.compare(str1.charAt(i), String.fromCharCode(str2Char[j]));\n\n nextCol = prevRow[j] + (strCmp ? 0 : 1);\n\n // insertion\n tmp = curCol + 1;\n if (nextCol > tmp) {\n nextCol = tmp;\n }\n // deletion\n tmp = prevRow[j + 1] + 1;\n if (nextCol > tmp) {\n nextCol = tmp;\n }\n\n // copy current col value into previous (in preparation for next iteration)\n prevRow[j] = curCol;\n }\n\n // copy last col value into previous (in preparation for next iteration)\n prevRow[j] = nextCol;\n }\n return nextCol;\n }\n return levenshtein.distance(str1, str2);\n }\n\n };\n\n // amd\n if (typeof define !== \"undefined\" && define !== null && define.amd) {\n define(function() {\n return Levenshtein;\n });\n }\n // commonjs\n else if (typeof module !== \"undefined\" && module !== null && typeof exports !== \"undefined\" && module.exports === exports) {\n module.exports = Levenshtein;\n }\n // web worker\n else if (typeof self !== \"undefined\" && typeof self.postMessage === 'function' && typeof self.importScripts === 'function') {\n self.Levenshtein = Levenshtein;\n }\n // browser main thread\n else if (typeof window !== \"undefined\" && window !== null) {\n window.Levenshtein = Levenshtein;\n }\n}());\n","import assert from \"node:assert\";\n\nimport levenshtein from \"fast-levenshtein\";\n\n/**\n * Returns a new array with all falsy values removed. The values\n * `false`, `null`, `0`, `\"\"`, `undefined`, and `NaN` are falsy.\n *\n * @param array - The array to compact.\n * @returns A new array with all falsy values removed.\n */\nexport const compact = <T>(array: T[]): NonNullable<T>[] => {\n return array.filter((value): value is NonNullable<T> => Boolean(value));\n};\n\n/**\n * Returns a new array with all duplicate elements removed.\n *\n * @param array - The array to remove duplicates from.\n * @returns A new array with all duplicate elements removed.\n */\nexport const uniq = <T>(array: T[]): T[] => {\n return [...new Set(array)];\n};\n\n/**\n * Sorts an array of strings based on their similarity to a given input\n * string. The closest match is returned as the first element, followed\n * by the sorted array.\n *\n * @param input - The input string to compare against.\n * @param options - The array of strings to be sorted.\n * @returns An array with the closest match as the first element,\n * followed by the sorted array.\n */\nexport const sortBySimilar = (input: string, options: readonly string[]): [closest: string, ...sorted: string[]] => {\n assert(options.length > 0, \"options must not be empty\");\n return [...options].sort((a, b) => levenshtein.get(a, input) - levenshtein.get(b, input)) as [string, ...string[]];\n};\n\n/**\n * Returns the option most similar to the given input string.\n *\n * @throws {AssertionError} if `options` is empty.\n */\nexport const closestMatch = (input: string, options: readonly string[]): string => {\n return sortBySimilar(input, options)[0];\n};\n\n/**\n * Returns elements that start with the given prefix, or all elements\n * if the prefix is empty.\n */\nexport const filterByPrefix = (items: string[], prefix: string): string[] => {\n return prefix ? items.filter((s) => s.startsWith(prefix)) : items;\n};\n"],"x_google_ignoreList":[0,1],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{r as e}from"./collection-C2TCeYqY.js";export{e as filterByPrefix};
|