@gadgetinc/ggt 1.0.1 → 1.0.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (100) hide show
  1. package/README.md +192 -128
  2. package/lib/__generated__/graphql.js.map +1 -1
  3. package/lib/commands/add.js +385 -0
  4. package/lib/commands/add.js.map +1 -0
  5. package/lib/commands/deploy.js +20 -102
  6. package/lib/commands/deploy.js.map +1 -1
  7. package/lib/commands/dev.js +43 -114
  8. package/lib/commands/dev.js.map +1 -1
  9. package/lib/commands/list.js +3 -6
  10. package/lib/commands/list.js.map +1 -1
  11. package/lib/commands/login.js +2 -5
  12. package/lib/commands/login.js.map +1 -1
  13. package/lib/commands/logout.js +2 -5
  14. package/lib/commands/logout.js.map +1 -1
  15. package/lib/commands/open.js +45 -86
  16. package/lib/commands/open.js.map +1 -1
  17. package/lib/commands/pull.js +19 -76
  18. package/lib/commands/pull.js.map +1 -1
  19. package/lib/commands/push.js +19 -76
  20. package/lib/commands/push.js.map +1 -1
  21. package/lib/commands/root.js +4 -3
  22. package/lib/commands/root.js.map +1 -1
  23. package/lib/commands/status.js +3 -8
  24. package/lib/commands/status.js.map +1 -1
  25. package/lib/commands/version.js +6 -5
  26. package/lib/commands/version.js.map +1 -1
  27. package/lib/commands/whoami.js +2 -5
  28. package/lib/commands/whoami.js.map +1 -1
  29. package/lib/ggt.js.map +1 -1
  30. package/lib/main.js.map +1 -1
  31. package/lib/services/app/api/api.js.map +1 -1
  32. package/lib/services/app/api/operation.js +11 -0
  33. package/lib/services/app/api/operation.js.map +1 -1
  34. package/lib/services/app/app.js +21 -2
  35. package/lib/services/app/app.js.map +1 -1
  36. package/lib/services/app/arg.js.map +1 -1
  37. package/lib/services/app/client.js +1 -5
  38. package/lib/services/app/client.js.map +1 -1
  39. package/lib/services/app/edit/edit.js.map +1 -1
  40. package/lib/services/app/edit/operation.js +52 -0
  41. package/lib/services/app/edit/operation.js.map +1 -1
  42. package/lib/services/app/error.js.map +1 -1
  43. package/lib/services/command/arg.js +3 -1
  44. package/lib/services/command/arg.js.map +1 -1
  45. package/lib/services/command/command.js +1 -0
  46. package/lib/services/command/command.js.map +1 -1
  47. package/lib/services/command/context.js.map +1 -1
  48. package/lib/services/config/config.js.map +1 -1
  49. package/lib/services/config/env.js.map +1 -1
  50. package/lib/services/config/package-json.js.map +1 -1
  51. package/lib/services/filesync/changes.js.map +1 -1
  52. package/lib/services/filesync/conflicts.js.map +1 -1
  53. package/lib/services/filesync/directory.js.map +1 -1
  54. package/lib/services/filesync/error.js +1 -0
  55. package/lib/services/filesync/error.js.map +1 -1
  56. package/lib/services/filesync/file.js.map +1 -1
  57. package/lib/services/filesync/filesync.js +179 -174
  58. package/lib/services/filesync/filesync.js.map +1 -1
  59. package/lib/services/filesync/hashes.js.map +1 -1
  60. package/lib/services/filesync/strategy.js.map +1 -1
  61. package/lib/services/filesync/sync-json.js.map +1 -1
  62. package/lib/services/http/auth.js.map +1 -1
  63. package/lib/services/http/http.js.map +1 -1
  64. package/lib/services/output/confirm.js.map +1 -1
  65. package/lib/services/output/footer.js.map +1 -1
  66. package/lib/services/output/log/field.js.map +1 -1
  67. package/lib/services/output/log/format/format.js.map +1 -1
  68. package/lib/services/output/log/format/json.js.map +1 -1
  69. package/lib/services/output/log/format/pretty.js.map +1 -1
  70. package/lib/services/output/log/level.js.map +1 -1
  71. package/lib/services/output/log/logger.js.map +1 -1
  72. package/lib/services/output/log/structured.js.map +1 -1
  73. package/lib/services/output/notify.js.map +1 -1
  74. package/lib/services/output/output.js.map +1 -1
  75. package/lib/services/output/print.js.map +1 -1
  76. package/lib/services/output/problems.js.map +1 -1
  77. package/lib/services/output/prompt.js.map +1 -1
  78. package/lib/services/output/report.js.map +1 -1
  79. package/lib/services/output/select.js.map +1 -1
  80. package/lib/services/output/spinner.js.map +1 -1
  81. package/lib/services/output/sprint.js.map +1 -1
  82. package/lib/services/output/symbols.js.map +1 -1
  83. package/lib/services/output/table.js.map +1 -1
  84. package/lib/services/output/timestamp.js.map +1 -1
  85. package/lib/services/output/update.js.map +1 -1
  86. package/lib/services/user/session.js.map +1 -1
  87. package/lib/services/user/user.js.map +1 -1
  88. package/lib/services/util/assert.js.map +1 -1
  89. package/lib/services/util/boolean.js.map +1 -1
  90. package/lib/services/util/collection.js.map +1 -1
  91. package/lib/services/util/function.js.map +1 -1
  92. package/lib/services/util/is.js.map +1 -1
  93. package/lib/services/util/json.js.map +1 -1
  94. package/lib/services/util/number.js.map +1 -1
  95. package/lib/services/util/object.js.map +1 -1
  96. package/lib/services/util/paths.js.map +1 -1
  97. package/lib/services/util/promise.js.map +1 -1
  98. package/lib/services/util/types.js.map +1 -1
  99. package/npm-shrinkwrap.json +2071 -1684
  100. package/package.json +30 -30
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/commands/whoami.ts"],"sourcesContent":["import type { Command, Usage } from \"../services/command/command.js\";\nimport { println } from \"../services/output/print.js\";\nimport { sprint } from \"../services/output/sprint.js\";\nimport { getUser } from \"../services/user/user.js\";\n\nexport const usage: Usage = () => sprint`\n Show the name and email address of the currently logged in user.\n\n {bold USAGE}\n ggt whoami\n\n {bold EXAMPLES}\n $ ggt whoami\n`;\n\nexport const command: Command = async (ctx) => {\n const user = await getUser(ctx);\n if (!user) {\n println`You are not logged in`;\n return;\n }\n\n if (user.name) {\n println`You are logged in as ${user.name} (${user.email})`;\n } else {\n println`You are logged in as ${user.email}`;\n }\n};\n"],"names":["println","sprint","getUser","usage","command","ctx","user","name","email"],"mappings":"AACA,SAASA,OAAO,QAAQ,8BAA8B;AACtD,SAASC,MAAM,QAAQ,+BAA+B;AACtD,SAASC,OAAO,QAAQ,2BAA2B;AAEnD,OAAO,MAAMC,QAAe,IAAMF,MAAM,CAAC;;;;;;;;AAQzC,CAAC,CAAC;AAEF,OAAO,MAAMG,UAAmB,OAAOC;IACrC,MAAMC,OAAO,MAAMJ,QAAQG;IAC3B,IAAI,CAACC,MAAM;QACTN,OAAO,CAAC,qBAAqB,CAAC;QAC9B;IACF;IAEA,IAAIM,KAAKC,IAAI,EAAE;QACbP,OAAO,CAAC,qBAAqB,EAAEM,KAAKC,IAAI,CAAC,EAAE,EAAED,KAAKE,KAAK,CAAC,CAAC,CAAC;IAC5D,OAAO;QACLR,OAAO,CAAC,qBAAqB,EAAEM,KAAKE,KAAK,CAAC,CAAC;IAC7C;AACF,EAAE"}
1
+ {"version":3,"sources":["../../src/commands/whoami.ts"],"sourcesContent":["import type { Command, Usage } from \"../services/command/command.js\";\nimport { println } from \"../services/output/print.js\";\nimport { sprint } from \"../services/output/sprint.js\";\nimport { getUser } from \"../services/user/user.js\";\n\nexport const usage: Usage = () => sprint`\n Show the name and email address of the currently logged in user.\n\n {gray Usage}\n ggt whoami\n`;\n\nexport const command: Command = async (ctx) => {\n const user = await getUser(ctx);\n if (!user) {\n println`You are not logged in`;\n return;\n }\n\n if (user.name) {\n println`You are logged in as ${user.name} (${user.email})`;\n } else {\n println`You are logged in as ${user.email}`;\n }\n};\n"],"names":["println","sprint","getUser","usage","command","ctx","user","name","email"],"rangeMappings":";;;;;;;;;;;;;;;;;;;;","mappings":"AACA,SAASA,OAAO,QAAQ,8BAA8B;AACtD,SAASC,MAAM,QAAQ,+BAA+B;AACtD,SAASC,OAAO,QAAQ,2BAA2B;AAEnD,OAAO,MAAMC,QAAe,IAAMF,MAAM,CAAC;;;;;AAKzC,CAAC,CAAC;AAEF,OAAO,MAAMG,UAAmB,OAAOC;IACrC,MAAMC,OAAO,MAAMJ,QAAQG;IAC3B,IAAI,CAACC,MAAM;QACTN,OAAO,CAAC,qBAAqB,CAAC;QAC9B;IACF;IAEA,IAAIM,KAAKC,IAAI,EAAE;QACbP,OAAO,CAAC,qBAAqB,EAAEM,KAAKC,IAAI,CAAC,EAAE,EAAED,KAAKE,KAAK,CAAC,CAAC,CAAC;IAC5D,OAAO;QACLR,OAAO,CAAC,qBAAqB,EAAEM,KAAKE,KAAK,CAAC,CAAC;IAC7C;AACF,EAAE"}
package/lib/ggt.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/ggt.ts"],"sourcesContent":["import ms from \"ms\";\nimport * as root from \"./commands/root.js\";\nimport { Context } from \"./services/command/context.js\";\nimport { output } from \"./services/output/output.js\";\nimport { println } from \"./services/output/print.js\";\nimport { installErrorHandlers, reportErrorAndExit } from \"./services/output/report.js\";\nimport { activeSpinner, spin } from \"./services/output/spinner.js\";\nimport { installJsonExtensions } from \"./services/util/json.js\";\n\nexport const ggt = async (ctx = Context.init({ name: \"ggt\" })): Promise<void> => {\n installJsonExtensions();\n installErrorHandlers(ctx);\n\n try {\n let stopping = false;\n\n for (const signal of [\"SIGINT\", \"SIGTERM\"] as const) {\n // eslint-disable-next-line @typescript-eslint/no-misused-promises\n process.on(signal, async () => {\n if (stopping) {\n return;\n }\n\n stopping = true;\n ctx.log.trace(\"received signal\", { signal });\n\n setTimeout(() => {\n // when ggt is run with npx, and the user presses ctrl+c, ggt\n // receives SIGINT twice in quick succession. in order to\n // prevent the second SIGINT from triggering the force exit\n // listener, we wait a bit in this setTimeout before adding it\n process.once(signal, () => {\n println(\" Exiting immediately\");\n process.exit(1);\n });\n }, ms(\"100ms\")).unref();\n\n // ctrl+c was pressed, so we need to clear the line\n output.writeStdout(\"\\n\");\n\n // if there was any sticky text, it needs to be persisted now\n activeSpinner?.clear();\n output.persistFooter();\n\n const spinner = spin({ successSymbol: \"👋\" })`\n Stopping {gray Press Ctrl+C again to force}\n `;\n\n try {\n ctx.abort();\n await ctx.done;\n spinner.succeed(\"Goodbye!\");\n } catch (error) {\n spinner.fail();\n await reportErrorAndExit(ctx, error);\n }\n });\n }\n\n await root.command(ctx);\n } catch (error) {\n await reportErrorAndExit(ctx, error);\n }\n};\n"],"names":["ms","root","Context","output","println","installErrorHandlers","reportErrorAndExit","activeSpinner","spin","installJsonExtensions","ggt","ctx","init","name","stopping","signal","process","on","log","trace","setTimeout","once","exit","unref","writeStdout","clear","persistFooter","spinner","successSymbol","abort","done","succeed","error","fail","command"],"mappings":"AAAA,OAAOA,QAAQ,KAAK;AACpB,YAAYC,UAAU,qBAAqB;AAC3C,SAASC,OAAO,QAAQ,gCAAgC;AACxD,SAASC,MAAM,QAAQ,8BAA8B;AACrD,SAASC,OAAO,QAAQ,6BAA6B;AACrD,SAASC,oBAAoB,EAAEC,kBAAkB,QAAQ,8BAA8B;AACvF,SAASC,aAAa,EAAEC,IAAI,QAAQ,+BAA+B;AACnE,SAASC,qBAAqB,QAAQ,0BAA0B;AAEhE,OAAO,MAAMC,MAAM,OAAOC,MAAMT,QAAQU,IAAI,CAAC;IAAEC,MAAM;AAAM,EAAE;IAC3DJ;IACAJ,qBAAqBM;IAErB,IAAI;QACF,IAAIG,WAAW;QAEf,KAAK,MAAMC,UAAU;YAAC;YAAU;SAAU,CAAW;YACnD,kEAAkE;YAClEC,QAAQC,EAAE,CAACF,QAAQ;gBACjB,IAAID,UAAU;oBACZ;gBACF;gBAEAA,WAAW;gBACXH,IAAIO,GAAG,CAACC,KAAK,CAAC,mBAAmB;oBAAEJ;gBAAO;gBAE1CK,WAAW;oBACT,6DAA6D;oBAC7D,yDAAyD;oBACzD,2DAA2D;oBAC3D,8DAA8D;oBAC9DJ,QAAQK,IAAI,CAACN,QAAQ;wBACnBX,QAAQ;wBACRY,QAAQM,IAAI,CAAC;oBACf;gBACF,GAAGtB,GAAG,UAAUuB,KAAK;gBAErB,mDAAmD;gBACnDpB,OAAOqB,WAAW,CAAC;gBAEnB,6DAA6D;gBAC7DjB,eAAekB;gBACftB,OAAOuB,aAAa;gBAEpB,MAAMC,UAAUnB,KAAK;oBAAEoB,eAAe;gBAAK,EAAE,CAAC;;QAE9C,CAAC;gBAED,IAAI;oBACFjB,IAAIkB,KAAK;oBACT,MAAMlB,IAAImB,IAAI;oBACdH,QAAQI,OAAO,CAAC;gBAClB,EAAE,OAAOC,OAAO;oBACdL,QAAQM,IAAI;oBACZ,MAAM3B,mBAAmBK,KAAKqB;gBAChC;YACF;QACF;QAEA,MAAM/B,KAAKiC,OAAO,CAACvB;IACrB,EAAE,OAAOqB,OAAO;QACd,MAAM1B,mBAAmBK,KAAKqB;IAChC;AACF,EAAE"}
1
+ {"version":3,"sources":["../src/ggt.ts"],"sourcesContent":["import ms from \"ms\";\nimport * as root from \"./commands/root.js\";\nimport { Context } from \"./services/command/context.js\";\nimport { output } from \"./services/output/output.js\";\nimport { println } from \"./services/output/print.js\";\nimport { installErrorHandlers, reportErrorAndExit } from \"./services/output/report.js\";\nimport { activeSpinner, spin } from \"./services/output/spinner.js\";\nimport { installJsonExtensions } from \"./services/util/json.js\";\n\nexport const ggt = async (ctx = Context.init({ name: \"ggt\" })): Promise<void> => {\n installJsonExtensions();\n installErrorHandlers(ctx);\n\n try {\n let stopping = false;\n\n for (const signal of [\"SIGINT\", \"SIGTERM\"] as const) {\n // eslint-disable-next-line @typescript-eslint/no-misused-promises\n process.on(signal, async () => {\n if (stopping) {\n return;\n }\n\n stopping = true;\n ctx.log.trace(\"received signal\", { signal });\n\n setTimeout(() => {\n // when ggt is run with npx, and the user presses ctrl+c, ggt\n // receives SIGINT twice in quick succession. in order to\n // prevent the second SIGINT from triggering the force exit\n // listener, we wait a bit in this setTimeout before adding it\n process.once(signal, () => {\n println(\" Exiting immediately\");\n process.exit(1);\n });\n }, ms(\"100ms\")).unref();\n\n // ctrl+c was pressed, so we need to clear the line\n output.writeStdout(\"\\n\");\n\n // if there was any sticky text, it needs to be persisted now\n activeSpinner?.clear();\n output.persistFooter();\n\n const spinner = spin({ successSymbol: \"👋\" })`\n Stopping {gray Press Ctrl+C again to force}\n `;\n\n try {\n ctx.abort();\n await ctx.done;\n spinner.succeed(\"Goodbye!\");\n } catch (error) {\n spinner.fail();\n await reportErrorAndExit(ctx, error);\n }\n });\n }\n\n await root.command(ctx);\n } catch (error) {\n await reportErrorAndExit(ctx, error);\n }\n};\n"],"names":["ms","root","Context","output","println","installErrorHandlers","reportErrorAndExit","activeSpinner","spin","installJsonExtensions","ggt","ctx","init","name","stopping","signal","process","on","log","trace","setTimeout","once","exit","unref","writeStdout","clear","persistFooter","spinner","successSymbol","abort","done","succeed","error","fail","command"],"rangeMappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;","mappings":"AAAA,OAAOA,QAAQ,KAAK;AACpB,YAAYC,UAAU,qBAAqB;AAC3C,SAASC,OAAO,QAAQ,gCAAgC;AACxD,SAASC,MAAM,QAAQ,8BAA8B;AACrD,SAASC,OAAO,QAAQ,6BAA6B;AACrD,SAASC,oBAAoB,EAAEC,kBAAkB,QAAQ,8BAA8B;AACvF,SAASC,aAAa,EAAEC,IAAI,QAAQ,+BAA+B;AACnE,SAASC,qBAAqB,QAAQ,0BAA0B;AAEhE,OAAO,MAAMC,MAAM,OAAOC,MAAMT,QAAQU,IAAI,CAAC;IAAEC,MAAM;AAAM,EAAE;IAC3DJ;IACAJ,qBAAqBM;IAErB,IAAI;QACF,IAAIG,WAAW;QAEf,KAAK,MAAMC,UAAU;YAAC;YAAU;SAAU,CAAW;YACnD,kEAAkE;YAClEC,QAAQC,EAAE,CAACF,QAAQ;gBACjB,IAAID,UAAU;oBACZ;gBACF;gBAEAA,WAAW;gBACXH,IAAIO,GAAG,CAACC,KAAK,CAAC,mBAAmB;oBAAEJ;gBAAO;gBAE1CK,WAAW;oBACT,6DAA6D;oBAC7D,yDAAyD;oBACzD,2DAA2D;oBAC3D,8DAA8D;oBAC9DJ,QAAQK,IAAI,CAACN,QAAQ;wBACnBX,QAAQ;wBACRY,QAAQM,IAAI,CAAC;oBACf;gBACF,GAAGtB,GAAG,UAAUuB,KAAK;gBAErB,mDAAmD;gBACnDpB,OAAOqB,WAAW,CAAC;gBAEnB,6DAA6D;gBAC7DjB,eAAekB;gBACftB,OAAOuB,aAAa;gBAEpB,MAAMC,UAAUnB,KAAK;oBAAEoB,eAAe;gBAAK,EAAE,CAAC;;QAE9C,CAAC;gBAED,IAAI;oBACFjB,IAAIkB,KAAK;oBACT,MAAMlB,IAAImB,IAAI;oBACdH,QAAQI,OAAO,CAAC;gBAClB,EAAE,OAAOC,OAAO;oBACdL,QAAQM,IAAI;oBACZ,MAAM3B,mBAAmBK,KAAKqB;gBAChC;YACF;QACF;QAEA,MAAM/B,KAAKiC,OAAO,CAACvB;IACrB,EAAE,OAAOqB,OAAO;QACd,MAAM1B,mBAAmBK,KAAKqB;IAChC;AACF,EAAE"}
package/lib/main.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/main.ts"],"sourcesContent":["#!/usr/bin/env node\n\nimport { ggt } from \"./ggt.js\";\n\nawait ggt();\n"],"names":["ggt"],"mappings":";AAEA,SAASA,GAAG,QAAQ,WAAW;AAE/B,MAAMA"}
1
+ {"version":3,"sources":["../src/main.ts"],"sourcesContent":["#!/usr/bin/env node\n\nimport { ggt } from \"./ggt.js\";\n\nawait ggt();\n"],"names":["ggt"],"rangeMappings":";;","mappings":";AAEA,SAASA,GAAG,QAAQ,WAAW;AAE/B,MAAMA"}
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../../src/services/app/api/api.ts"],"sourcesContent":["import type { ExecutionResult } from \"graphql-ws\";\nimport assert from \"node:assert\";\nimport type { Promisable } from \"type-fest\";\nimport type { Context } from \"../../command/context.js\";\nimport type { HttpOptions } from \"../../http/http.js\";\nimport { unthunk, type Thunk } from \"../../util/function.js\";\nimport { Client } from \"../client.js\";\nimport type { GraphQLMutation, GraphQLQuery, GraphQLSubscription } from \"../edit/operation.js\";\nimport { ClientError } from \"../error.js\";\n\nexport class Api {\n /**\n * The {@linkcode Context} that was used to create this instance.\n */\n readonly ctx: Context;\n\n /**\n * The client used to make requests to Gadget's /api/graphql\n * endpoint.\n */\n #client: Client;\n\n constructor(ctx: Context) {\n this.ctx = ctx.child({ name: \"api\" });\n this.#client = new Client(this.ctx, \"/api/graphql\");\n }\n\n /**\n * Execute a GraphQL query.\n *\n * @param request - The query and variables to send to the server.\n * @param request.query - The GraphQL query to execute.\n * @param request.variables - The variables to send to the server.\n * @param request.http - {@linkcode HttpOptions} to pass to http.\n * @returns The data returned by the server.\n */\n async query<Query extends GraphQLQuery>({\n query,\n variables,\n ...options\n }: {\n query: Query;\n variables?: Thunk<Query[\"Variables\"]> | null;\n http?: HttpOptions;\n }): Promise<Query[\"Data\"]> {\n const name = query.match(/query (\\w+)/)?.[1];\n assert(name, \"query name not found\");\n\n const ctx = this.ctx.child({\n fields: { edit: { query: name } },\n devFields: { edit: { query: name, variables: unthunk(variables) } },\n });\n\n ctx.log.info(\"executing graphql query\");\n const response = await this.#client.execute(ctx, {\n operation: query,\n variables,\n ...options,\n http: {\n retry: {\n // queries _should_ be idempotent, so automatically retry them\n methods: [\"POST\"],\n },\n ...options.http,\n },\n });\n\n if (response.errors) {\n throw new ClientError(query, response.errors);\n }\n\n if (!response.data) {\n throw new ClientError(query, \"Query response did not contain data\");\n }\n\n return response.data;\n }\n\n /**\n * Execute a GraphQL mutation.\n *\n * @param request - The query and variables to send to the server.\n * @param request.mutation - The GraphQL mutation to execute.\n * @param request.variables - The variables to send to the server.\n * @param request.http - {@linkcode HttpOptions} to pass to http.\n * @returns The data returned by the server.\n */\n async mutate<Mutation extends GraphQLMutation>({\n mutation,\n variables,\n ...options\n }: {\n mutation: Mutation;\n variables?: Thunk<Mutation[\"Variables\"]> | null;\n http?: HttpOptions;\n }): Promise<Mutation[\"Data\"]> {\n const name = mutation.match(/mutation (\\w+)/)?.[1];\n assert(name, \"mutation name not found\");\n\n const ctx = this.ctx.child({\n fields: { edit: { mutation: name } },\n devFields: { edit: { mutation: name, variables: unthunk(variables) } },\n });\n\n ctx.log.info(\"executing graphql mutation\");\n const response = await this.#client.execute(ctx, { operation: mutation, variables, ...options });\n\n if (response.errors) {\n throw new ClientError(mutation, response.errors);\n }\n\n if (!response.data) {\n throw new ClientError(mutation, \"Mutation response did not contain data\");\n }\n\n return response.data;\n }\n\n /**\n * Subscribe to a GraphQL subscription.\n *\n * @param options - The query and variables to send to the server.\n * @param options.subscription - The GraphQL subscription to subscribe to.\n * @param options.variables - The variables to send to the server.\n * @param options.onData - A callback that will be called when data is received from the server.\n * @param options.onError - A callback that will be called when an error is received from the server.\n * @param options.onComplete - A callback that will be called when the subscription ends.\n * @returns A function to unsubscribe from the subscription.\n */\n subscribe<Subscription extends GraphQLSubscription>({\n onData,\n ...options\n }: {\n subscription: Subscription;\n variables?: Thunk<Subscription[\"Variables\"]> | null;\n onData: (data: Subscription[\"Data\"]) => Promisable<void>;\n onError: (error: ClientError) => Promisable<void>;\n onComplete?: () => Promisable<void>;\n }): EditSubscription<Subscription> {\n const name = options.subscription.match(/subscription (\\w+)/)?.[1];\n assert(name, \"subscription name not found\");\n\n let ctx = this.ctx.child({\n fields: { edit: { subscription: name } },\n devFields: { edit: { subscription: name, variables: unthunk(options.variables) } },\n });\n\n const onResponse = async (response: ExecutionResult<Subscription[\"Data\"], Subscription[\"Extensions\"]>): Promise<void> => {\n if (response.errors) {\n unsubscribe();\n await options.onError(new ClientError(options.subscription, response.errors));\n return;\n }\n\n if (!response.data) {\n unsubscribe();\n await options.onError(new ClientError(options.subscription, \"Subscription response did not contain data\"));\n return;\n }\n\n await onData(response.data);\n };\n\n ctx.log.info(\"subscribing to graphql subscription\");\n let unsubscribe = this.#client.subscribe(ctx, { ...options, onResponse });\n\n return {\n unsubscribe,\n resubscribe: (variables) => {\n unsubscribe();\n\n if (variables !== undefined) {\n options.variables = variables;\n }\n\n ctx = this.ctx.child({\n fields: { edit: { subscription: name } },\n devFields: { edit: { subscription: name, variables: unthunk(options.variables) } },\n });\n\n ctx.log.info(\"re-subscribing to graphql subscription\");\n unsubscribe = this.#client.subscribe(ctx, { ...options, onResponse });\n },\n };\n }\n\n /**\n * Close the client.\n */\n async dispose(): Promise<void> {\n await this.#client.dispose();\n }\n}\n\n/**\n * An object that can be used to unsubscribe and resubscribe to an\n * ongoing Edit GraphQL subscription.\n */\nexport type EditSubscription<Subscription extends GraphQLSubscription> = {\n /**\n * Unsubscribe from the subscription.\n */\n unsubscribe(): void;\n\n /**\n * Resubscribe to the subscription.\n */\n resubscribe(variables?: Thunk<Subscription[\"Variables\"]> | null): void;\n};\n"],"names":["assert","unthunk","Client","ClientError","Api","query","variables","options","name","match","ctx","child","fields","edit","devFields","log","info","response","client","execute","operation","http","retry","methods","errors","data","mutate","mutation","subscribe","onData","subscription","onResponse","unsubscribe","onError","resubscribe","undefined","dispose","constructor"],"mappings":"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"}
1
+ {"version":3,"sources":["../../../../src/services/app/api/api.ts"],"sourcesContent":["import type { ExecutionResult } from \"graphql-ws\";\nimport assert from \"node:assert\";\nimport type { Promisable } from \"type-fest\";\nimport type { Context } from \"../../command/context.js\";\nimport type { HttpOptions } from \"../../http/http.js\";\nimport { unthunk, type Thunk } from \"../../util/function.js\";\nimport { Client } from \"../client.js\";\nimport type { GraphQLMutation, GraphQLQuery, GraphQLSubscription } from \"../edit/operation.js\";\nimport { ClientError } from \"../error.js\";\n\nexport class Api {\n /**\n * The {@linkcode Context} that was used to create this instance.\n */\n readonly ctx: Context;\n\n /**\n * The client used to make requests to Gadget's /api/graphql\n * endpoint.\n */\n #client: Client;\n\n constructor(ctx: Context) {\n this.ctx = ctx.child({ name: \"api\" });\n this.#client = new Client(this.ctx, \"/api/graphql\");\n }\n\n /**\n * Execute a GraphQL query.\n *\n * @param request - The query and variables to send to the server.\n * @param request.query - The GraphQL query to execute.\n * @param request.variables - The variables to send to the server.\n * @param request.http - {@linkcode HttpOptions} to pass to http.\n * @returns The data returned by the server.\n */\n async query<Query extends GraphQLQuery>({\n query,\n variables,\n ...options\n }: {\n query: Query;\n variables?: Thunk<Query[\"Variables\"]> | null;\n http?: HttpOptions;\n }): Promise<Query[\"Data\"]> {\n const name = query.match(/query (\\w+)/)?.[1];\n assert(name, \"query name not found\");\n\n const ctx = this.ctx.child({\n fields: { edit: { query: name } },\n devFields: { edit: { query: name, variables: unthunk(variables) } },\n });\n\n ctx.log.info(\"executing graphql query\");\n const response = await this.#client.execute(ctx, {\n operation: query,\n variables,\n ...options,\n http: {\n retry: {\n // queries _should_ be idempotent, so automatically retry them\n methods: [\"POST\"],\n },\n ...options.http,\n },\n });\n\n if (response.errors) {\n throw new ClientError(query, response.errors);\n }\n\n if (!response.data) {\n throw new ClientError(query, \"Query response did not contain data\");\n }\n\n return response.data;\n }\n\n /**\n * Execute a GraphQL mutation.\n *\n * @param request - The query and variables to send to the server.\n * @param request.mutation - The GraphQL mutation to execute.\n * @param request.variables - The variables to send to the server.\n * @param request.http - {@linkcode HttpOptions} to pass to http.\n * @returns The data returned by the server.\n */\n async mutate<Mutation extends GraphQLMutation>({\n mutation,\n variables,\n ...options\n }: {\n mutation: Mutation;\n variables?: Thunk<Mutation[\"Variables\"]> | null;\n http?: HttpOptions;\n }): Promise<Mutation[\"Data\"]> {\n const name = mutation.match(/mutation (\\w+)/)?.[1];\n assert(name, \"mutation name not found\");\n\n const ctx = this.ctx.child({\n fields: { edit: { mutation: name } },\n devFields: { edit: { mutation: name, variables: unthunk(variables) } },\n });\n\n ctx.log.info(\"executing graphql mutation\");\n const response = await this.#client.execute(ctx, { operation: mutation, variables, ...options });\n\n if (response.errors) {\n throw new ClientError(mutation, response.errors);\n }\n\n if (!response.data) {\n throw new ClientError(mutation, \"Mutation response did not contain data\");\n }\n\n return response.data;\n }\n\n /**\n * Subscribe to a GraphQL subscription.\n *\n * @param options - The query and variables to send to the server.\n * @param options.subscription - The GraphQL subscription to subscribe to.\n * @param options.variables - The variables to send to the server.\n * @param options.onData - A callback that will be called when data is received from the server.\n * @param options.onError - A callback that will be called when an error is received from the server.\n * @param options.onComplete - A callback that will be called when the subscription ends.\n * @returns A function to unsubscribe from the subscription.\n */\n subscribe<Subscription extends GraphQLSubscription>({\n onData,\n ...options\n }: {\n subscription: Subscription;\n variables?: Thunk<Subscription[\"Variables\"]> | null;\n onData: (data: Subscription[\"Data\"]) => Promisable<void>;\n onError: (error: ClientError) => Promisable<void>;\n onComplete?: () => Promisable<void>;\n }): EditSubscription<Subscription> {\n const name = options.subscription.match(/subscription (\\w+)/)?.[1];\n assert(name, \"subscription name not found\");\n\n let ctx = this.ctx.child({\n fields: { edit: { subscription: name } },\n devFields: { edit: { subscription: name, variables: unthunk(options.variables) } },\n });\n\n const onResponse = async (response: ExecutionResult<Subscription[\"Data\"], Subscription[\"Extensions\"]>): Promise<void> => {\n if (response.errors) {\n unsubscribe();\n await options.onError(new ClientError(options.subscription, response.errors));\n return;\n }\n\n if (!response.data) {\n unsubscribe();\n await options.onError(new ClientError(options.subscription, \"Subscription response did not contain data\"));\n return;\n }\n\n await onData(response.data);\n };\n\n ctx.log.info(\"subscribing to graphql subscription\");\n let unsubscribe = this.#client.subscribe(ctx, { ...options, onResponse });\n\n return {\n unsubscribe,\n resubscribe: (variables) => {\n unsubscribe();\n\n if (variables !== undefined) {\n options.variables = variables;\n }\n\n ctx = this.ctx.child({\n fields: { edit: { subscription: name } },\n devFields: { edit: { subscription: name, variables: unthunk(options.variables) } },\n });\n\n ctx.log.info(\"re-subscribing to graphql subscription\");\n unsubscribe = this.#client.subscribe(ctx, { ...options, onResponse });\n },\n };\n }\n\n /**\n * Close the client.\n */\n async dispose(): Promise<void> {\n await this.#client.dispose();\n }\n}\n\n/**\n * An object that can be used to unsubscribe and resubscribe to an\n * ongoing Edit GraphQL subscription.\n */\nexport type EditSubscription<Subscription extends GraphQLSubscription> = {\n /**\n * Unsubscribe from the subscription.\n */\n unsubscribe(): void;\n\n /**\n * Resubscribe to the subscription.\n */\n resubscribe(variables?: Thunk<Subscription[\"Variables\"]> | null): void;\n};\n"],"names":["assert","unthunk","Client","ClientError","Api","query","variables","options","name","match","ctx","child","fields","edit","devFields","log","info","response","client","execute","operation","http","retry","methods","errors","data","mutate","mutation","subscribe","onData","subscription","onResponse","unsubscribe","onError","resubscribe","undefined","dispose","constructor"],"rangeMappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;","mappings":"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"}
@@ -4,6 +4,17 @@ export const GADGET_META_MODELS_QUERY = sprint(/* GraphQL */ `
4
4
  gadgetMeta {
5
5
  models {
6
6
  apiIdentifier
7
+ namespace
8
+ }
9
+ }
10
+ }
11
+ `);
12
+ export const GADGET_GLOBAL_ACTIONS_QUERY = sprint(/* GraphQL */ `
13
+ query GadgetMetaGlobalActions {
14
+ gadgetMeta {
15
+ globalActions {
16
+ apiIdentifier
17
+ namespace
7
18
  }
8
19
  }
9
20
  }
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../../src/services/app/api/operation.ts"],"sourcesContent":["import type { GadgetMetaModelsQuery, GadgetMetaModelsQueryVariables } from \"../../../__generated__/graphql.js\";\nimport { sprint } from \"../../output/sprint.js\";\nimport type { GraphQLQuery } from \"../edit/operation.js\";\n\nexport const GADGET_META_MODELS_QUERY = sprint(/* GraphQL */ `\n query GadgetMetaModels {\n gadgetMeta {\n models {\n apiIdentifier\n }\n }\n }\n`) as GraphQLQuery<GadgetMetaModelsQuery, GadgetMetaModelsQueryVariables>;\n"],"names":["sprint","GADGET_META_MODELS_QUERY"],"mappings":"AACA,SAASA,MAAM,QAAQ,yBAAyB;AAGhD,OAAO,MAAMC,2BAA2BD,OAAO,WAAW,GAAG,CAAC;;;;;;;;AAQ9D,CAAC,EAAyE"}
1
+ {"version":3,"sources":["../../../../src/services/app/api/operation.ts"],"sourcesContent":["import type {\n GadgetMetaGlobalActionsQuery,\n GadgetMetaGlobalActionsQueryVariables,\n GadgetMetaModelsQuery,\n GadgetMetaModelsQueryVariables,\n} from \"../../../__generated__/graphql.js\";\nimport { sprint } from \"../../output/sprint.js\";\nimport type { GraphQLQuery } from \"../edit/operation.js\";\n\nexport const GADGET_META_MODELS_QUERY = sprint(/* GraphQL */ `\n query GadgetMetaModels {\n gadgetMeta {\n models {\n apiIdentifier\n namespace\n }\n }\n }\n`) as GraphQLQuery<GadgetMetaModelsQuery, GadgetMetaModelsQueryVariables>;\n\nexport const GADGET_GLOBAL_ACTIONS_QUERY = sprint(/* GraphQL */ `\n query GadgetMetaGlobalActions {\n gadgetMeta {\n globalActions {\n apiIdentifier\n namespace\n }\n }\n }\n`) as GraphQLQuery<GadgetMetaGlobalActionsQuery, GadgetMetaGlobalActionsQueryVariables>;\n"],"names":["sprint","GADGET_META_MODELS_QUERY","GADGET_GLOBAL_ACTIONS_QUERY"],"rangeMappings":";;;;;;;;;;;;;;;;;;;;","mappings":"AAMA,SAASA,MAAM,QAAQ,yBAAyB;AAGhD,OAAO,MAAMC,2BAA2BD,OAAO,WAAW,GAAG,CAAC;;;;;;;;;AAS9D,CAAC,EAAyE;AAE1E,OAAO,MAAME,8BAA8BF,OAAO,WAAW,GAAG,CAAC;;;;;;;;;AASjE,CAAC,EAAuF"}
@@ -4,7 +4,7 @@ import { config } from "../config/config.js";
4
4
  import { loadAuthHeaders } from "../http/auth.js";
5
5
  import { http } from "../http/http.js";
6
6
  import { Api } from "./api/api.js";
7
- import { GADGET_META_MODELS_QUERY } from "./api/operation.js";
7
+ import { GADGET_GLOBAL_ACTIONS_QUERY, GADGET_META_MODELS_QUERY } from "./api/operation.js";
8
8
  export const EnvironmentType = Object.freeze({
9
9
  Development: "development",
10
10
  Production: "production",
@@ -32,7 +32,12 @@ export const Application = z.object({
32
32
  environments: z.array(Environment)
33
33
  });
34
34
  export const ModelApiIdentifier = z.object({
35
- apiIdentifier: z.string()
35
+ apiIdentifier: z.string(),
36
+ namespace: z.nullable(z.array(z.string())).optional()
37
+ });
38
+ export const GlobalActionApiIdentifier = z.object({
39
+ apiIdentifier: z.string(),
40
+ namespace: z.nullable(z.array(z.string())).optional()
36
41
  });
37
42
  /**
38
43
  * Retrieves a list of apps for the given user. If the user is not
@@ -72,5 +77,19 @@ export const getModels = async (ctx)=>{
72
77
  });
73
78
  return gadgetMeta.models;
74
79
  };
80
+ export const getGlobalActions = async (ctx)=>{
81
+ const headers = loadAuthHeaders();
82
+ if (!headers) {
83
+ return [];
84
+ }
85
+ assert(ctx.user, "must get user before getting models");
86
+ const api = new Api(ctx);
87
+ // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
88
+ const { gadgetMeta } = await api.query({
89
+ query: GADGET_GLOBAL_ACTIONS_QUERY
90
+ });
91
+ // eslint-disable-next-line @typescript-eslint/no-unsafe-return, @typescript-eslint/no-unsafe-member-access
92
+ return gadgetMeta.globalActions;
93
+ };
75
94
 
76
95
  //# sourceMappingURL=app.js.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../src/services/app/app.ts"],"sourcesContent":["import assert from \"node:assert\";\nimport { z } from \"zod\";\nimport type { Context } from \"../command/context.js\";\nimport { config } from \"../config/config.js\";\nimport { loadAuthHeaders } from \"../http/auth.js\";\nimport { http } from \"../http/http.js\";\nimport { Api } from \"./api/api.js\";\nimport { GADGET_META_MODELS_QUERY } from \"./api/operation.js\";\n\nexport const EnvironmentType = Object.freeze({\n Development: \"development\",\n Production: \"production\",\n Test: \"test\",\n});\n\nexport type EnvironmentType = keyof typeof EnvironmentType;\n\nexport const Environment = z.object({\n id: z.union([z.string(), z.number(), z.bigint()]).transform((v) => BigInt(v)),\n name: z.string().transform((name) => name.toLowerCase()),\n type: z.nativeEnum(EnvironmentType),\n});\n\nexport type Environment = z.infer<typeof Environment>;\n\nexport const Application = z.object({\n id: z.union([z.string(), z.number(), z.bigint()]).transform((v) => BigInt(v)),\n slug: z.string(),\n primaryDomain: z.string(),\n hasSplitEnvironments: z.boolean(),\n multiEnvironmentEnabled: z.boolean(),\n environments: z.array(Environment),\n});\n\nexport type Application = z.infer<typeof Application>;\n\nexport const ModelApiIdentifier = z.object({\n apiIdentifier: z.string(),\n});\n\nexport type ModelApiIdentifier = z.infer<typeof ModelApiIdentifier>;\n\n/**\n * Retrieves a list of apps for the given user. If the user is not\n * logged in, an empty array is returned instead.\n *\n * @param ctx - The current context.\n * @returns A promise that resolves to an array of Application objects.\n */\n// TODO: cache this\nexport const getApps = async (ctx: Context): Promise<Application[]> => {\n const headers = loadAuthHeaders();\n if (!headers) {\n return [];\n }\n\n assert(ctx.user, \"must get user before getting apps\");\n\n const json = await http({\n context: { ctx },\n url: `https://${config.domains.services}/auth/api/apps`,\n headers: { ...headers },\n responseType: \"json\",\n resolveBodyOnly: true,\n });\n\n return z.array(Application).parse(json);\n};\n\nexport const getModels = async (ctx: Context): Promise<ModelApiIdentifier[] | []> => {\n const headers = loadAuthHeaders();\n if (!headers) {\n return [];\n }\n\n assert(ctx.user, \"must get user before getting models\");\n\n const api = new Api(ctx);\n const { gadgetMeta } = await api.query({ query: GADGET_META_MODELS_QUERY });\n return gadgetMeta.models;\n};\n"],"names":["assert","z","config","loadAuthHeaders","http","Api","GADGET_META_MODELS_QUERY","EnvironmentType","Object","freeze","Development","Production","Test","Environment","object","id","union","string","number","bigint","transform","v","BigInt","name","toLowerCase","type","nativeEnum","Application","slug","primaryDomain","hasSplitEnvironments","boolean","multiEnvironmentEnabled","environments","array","ModelApiIdentifier","apiIdentifier","getApps","ctx","headers","user","json","context","url","domains","services","responseType","resolveBodyOnly","parse","getModels","api","gadgetMeta","query","models"],"mappings":"AAAA,OAAOA,YAAY,cAAc;AACjC,SAASC,CAAC,QAAQ,MAAM;AAExB,SAASC,MAAM,QAAQ,sBAAsB;AAC7C,SAASC,eAAe,QAAQ,kBAAkB;AAClD,SAASC,IAAI,QAAQ,kBAAkB;AACvC,SAASC,GAAG,QAAQ,eAAe;AACnC,SAASC,wBAAwB,QAAQ,qBAAqB;AAE9D,OAAO,MAAMC,kBAAkBC,OAAOC,MAAM,CAAC;IAC3CC,aAAa;IACbC,YAAY;IACZC,MAAM;AACR,GAAG;AAIH,OAAO,MAAMC,cAAcZ,EAAEa,MAAM,CAAC;IAClCC,IAAId,EAAEe,KAAK,CAAC;QAACf,EAAEgB,MAAM;QAAIhB,EAAEiB,MAAM;QAAIjB,EAAEkB,MAAM;KAAG,EAAEC,SAAS,CAAC,CAACC,IAAMC,OAAOD;IAC1EE,MAAMtB,EAAEgB,MAAM,GAAGG,SAAS,CAAC,CAACG,OAASA,KAAKC,WAAW;IACrDC,MAAMxB,EAAEyB,UAAU,CAACnB;AACrB,GAAG;AAIH,OAAO,MAAMoB,cAAc1B,EAAEa,MAAM,CAAC;IAClCC,IAAId,EAAEe,KAAK,CAAC;QAACf,EAAEgB,MAAM;QAAIhB,EAAEiB,MAAM;QAAIjB,EAAEkB,MAAM;KAAG,EAAEC,SAAS,CAAC,CAACC,IAAMC,OAAOD;IAC1EO,MAAM3B,EAAEgB,MAAM;IACdY,eAAe5B,EAAEgB,MAAM;IACvBa,sBAAsB7B,EAAE8B,OAAO;IAC/BC,yBAAyB/B,EAAE8B,OAAO;IAClCE,cAAchC,EAAEiC,KAAK,CAACrB;AACxB,GAAG;AAIH,OAAO,MAAMsB,qBAAqBlC,EAAEa,MAAM,CAAC;IACzCsB,eAAenC,EAAEgB,MAAM;AACzB,GAAG;AAIH;;;;;;CAMC,GACD,mBAAmB;AACnB,OAAO,MAAMoB,UAAU,OAAOC;IAC5B,MAAMC,UAAUpC;IAChB,IAAI,CAACoC,SAAS;QACZ,OAAO,EAAE;IACX;IAEAvC,OAAOsC,IAAIE,IAAI,EAAE;IAEjB,MAAMC,OAAO,MAAMrC,KAAK;QACtBsC,SAAS;YAAEJ;QAAI;QACfK,KAAK,CAAC,QAAQ,EAAEzC,OAAO0C,OAAO,CAACC,QAAQ,CAAC,cAAc,CAAC;QACvDN,SAAS;YAAE,GAAGA,OAAO;QAAC;QACtBO,cAAc;QACdC,iBAAiB;IACnB;IAEA,OAAO9C,EAAEiC,KAAK,CAACP,aAAaqB,KAAK,CAACP;AACpC,EAAE;AAEF,OAAO,MAAMQ,YAAY,OAAOX;IAC9B,MAAMC,UAAUpC;IAChB,IAAI,CAACoC,SAAS;QACZ,OAAO,EAAE;IACX;IAEAvC,OAAOsC,IAAIE,IAAI,EAAE;IAEjB,MAAMU,MAAM,IAAI7C,IAAIiC;IACpB,MAAM,EAAEa,UAAU,EAAE,GAAG,MAAMD,IAAIE,KAAK,CAAC;QAAEA,OAAO9C;IAAyB;IACzE,OAAO6C,WAAWE,MAAM;AAC1B,EAAE"}
1
+ {"version":3,"sources":["../../../src/services/app/app.ts"],"sourcesContent":["import assert from \"node:assert\";\nimport { z } from \"zod\";\nimport type { Context } from \"../command/context.js\";\nimport { config } from \"../config/config.js\";\nimport { loadAuthHeaders } from \"../http/auth.js\";\nimport { http } from \"../http/http.js\";\nimport { Api } from \"./api/api.js\";\nimport { GADGET_GLOBAL_ACTIONS_QUERY, GADGET_META_MODELS_QUERY } from \"./api/operation.js\";\n\nexport const EnvironmentType = Object.freeze({\n Development: \"development\",\n Production: \"production\",\n Test: \"test\",\n});\n\nexport type EnvironmentType = keyof typeof EnvironmentType;\n\nexport const Environment = z.object({\n id: z.union([z.string(), z.number(), z.bigint()]).transform((v) => BigInt(v)),\n name: z.string().transform((name) => name.toLowerCase()),\n type: z.nativeEnum(EnvironmentType),\n});\n\nexport type Environment = z.infer<typeof Environment>;\n\nexport const Application = z.object({\n id: z.union([z.string(), z.number(), z.bigint()]).transform((v) => BigInt(v)),\n slug: z.string(),\n primaryDomain: z.string(),\n hasSplitEnvironments: z.boolean(),\n multiEnvironmentEnabled: z.boolean(),\n environments: z.array(Environment),\n});\n\nexport type Application = z.infer<typeof Application>;\n\nexport const ModelApiIdentifier = z.object({\n apiIdentifier: z.string(),\n namespace: z.nullable(z.array(z.string())).optional(),\n});\n\nexport type ModelApiIdentifier = z.infer<typeof ModelApiIdentifier>;\n\nexport const GlobalActionApiIdentifier = z.object({\n apiIdentifier: z.string(),\n namespace: z.nullable(z.array(z.string())).optional(),\n});\n\nexport type GlobalActionApiIdentifier = z.infer<typeof GlobalActionApiIdentifier>;\n\n/**\n * Retrieves a list of apps for the given user. If the user is not\n * logged in, an empty array is returned instead.\n *\n * @param ctx - The current context.\n * @returns A promise that resolves to an array of Application objects.\n */\n// TODO: cache this\nexport const getApps = async (ctx: Context): Promise<Application[]> => {\n const headers = loadAuthHeaders();\n if (!headers) {\n return [];\n }\n\n assert(ctx.user, \"must get user before getting apps\");\n\n const json = await http({\n context: { ctx },\n url: `https://${config.domains.services}/auth/api/apps`,\n headers: { ...headers },\n responseType: \"json\",\n resolveBodyOnly: true,\n });\n\n return z.array(Application).parse(json);\n};\n\nexport const getModels = async (ctx: Context): Promise<ModelApiIdentifier[] | []> => {\n const headers = loadAuthHeaders();\n if (!headers) {\n return [];\n }\n\n assert(ctx.user, \"must get user before getting models\");\n\n const api = new Api(ctx);\n const { gadgetMeta } = await api.query({ query: GADGET_META_MODELS_QUERY });\n return gadgetMeta.models;\n};\n\nexport const getGlobalActions = async (ctx: Context): Promise<GlobalActionApiIdentifier[] | []> => {\n const headers = loadAuthHeaders();\n if (!headers) {\n return [];\n }\n\n assert(ctx.user, \"must get user before getting models\");\n\n const api = new Api(ctx);\n // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment\n const { gadgetMeta } = await api.query({ query: GADGET_GLOBAL_ACTIONS_QUERY });\n\n // eslint-disable-next-line @typescript-eslint/no-unsafe-return, @typescript-eslint/no-unsafe-member-access\n return gadgetMeta.globalActions;\n};\n"],"names":["assert","z","config","loadAuthHeaders","http","Api","GADGET_GLOBAL_ACTIONS_QUERY","GADGET_META_MODELS_QUERY","EnvironmentType","Object","freeze","Development","Production","Test","Environment","object","id","union","string","number","bigint","transform","v","BigInt","name","toLowerCase","type","nativeEnum","Application","slug","primaryDomain","hasSplitEnvironments","boolean","multiEnvironmentEnabled","environments","array","ModelApiIdentifier","apiIdentifier","namespace","nullable","optional","GlobalActionApiIdentifier","getApps","ctx","headers","user","json","context","url","domains","services","responseType","resolveBodyOnly","parse","getModels","api","gadgetMeta","query","models","getGlobalActions","globalActions"],"rangeMappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;","mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../src/services/app/arg.ts"],"sourcesContent":["import { ArgError } from \"../command/arg.js\";\nimport { sprint } from \"../output/sprint.js\";\n\n/**\n * Parses the value of an application argument (-a/--app) and returns\n * the application's slug.\n *\n * @param value - The value of the argument.\n * @param name - The name of the argument. e.g. \"-a\" or \"--app\".\n * @returns The application's slug.\n * @throws {ArgError} If the value is not a valid slug or URL.\n */\nexport const AppArg = (value: string, name: string): string => {\n const slug = /^(https:\\/\\/)?(?<slug>[\\w-]+?)(--development)?(\\..*)?$/.exec(value)?.groups?.[\"slug\"];\n if (slug) {\n return slug;\n }\n\n throw new ArgError(\n sprint`\n ${name} must be the application's {bold slug} or {bold URL}\n\n {bold EXAMPLES:}\n ${name} my-app\n ${name} my-app.gadget.app\n ${name} https://my-app.gadget.app\n ${name} https://my-app.gadget.app/edit\n ${name} https://my-app--development.gadget.app/edit\n `,\n );\n};\n"],"names":["ArgError","sprint","AppArg","value","name","slug","exec","groups"],"mappings":"AAAA,SAASA,QAAQ,QAAQ,oBAAoB;AAC7C,SAASC,MAAM,QAAQ,sBAAsB;AAE7C;;;;;;;;CAQC,GACD,OAAO,MAAMC,SAAS,CAACC,OAAeC;IACpC,MAAMC,OAAO,qEAAyDC,IAAI,CAACH,QAAQI,QAAQ,CAAC,OAAO;IACnG,IAAIF,MAAM;QACR,OAAOA;IACT;IAEA,MAAM,IAAIL,SACRC,MAAM,CAAC;MACL,EAAEG,KAAK;;;QAGL,EAAEA,KAAK;QACP,EAAEA,KAAK;QACP,EAAEA,KAAK;QACP,EAAEA,KAAK;QACP,EAAEA,KAAK;IACX,CAAC;AAEL,EAAE"}
1
+ {"version":3,"sources":["../../../src/services/app/arg.ts"],"sourcesContent":["import { ArgError } from \"../command/arg.js\";\nimport { sprint } from \"../output/sprint.js\";\n\n/**\n * Parses the value of an application argument (-a/--app) and returns\n * the application's slug.\n *\n * @param value - The value of the argument.\n * @param name - The name of the argument. e.g. \"-a\" or \"--app\".\n * @returns The application's slug.\n * @throws {ArgError} If the value is not a valid slug or URL.\n */\nexport const AppArg = (value: string, name: string): string => {\n const slug = /^(https:\\/\\/)?(?<slug>[\\w-]+?)(--development)?(\\..*)?$/.exec(value)?.groups?.[\"slug\"];\n if (slug) {\n return slug;\n }\n\n throw new ArgError(\n sprint`\n ${name} must be the application's {bold slug} or {bold URL}\n\n {bold EXAMPLES:}\n ${name} my-app\n ${name} my-app.gadget.app\n ${name} https://my-app.gadget.app\n ${name} https://my-app.gadget.app/edit\n ${name} https://my-app--development.gadget.app/edit\n `,\n );\n};\n"],"names":["ArgError","sprint","AppArg","value","name","slug","exec","groups"],"rangeMappings":";;;;;;;;;;;;;;;;;;;;;;;;;","mappings":"AAAA,SAASA,QAAQ,QAAQ,oBAAoB;AAC7C,SAASC,MAAM,QAAQ,sBAAsB;AAE7C;;;;;;;;CAQC,GACD,OAAO,MAAMC,SAAS,CAACC,OAAeC;IACpC,MAAMC,OAAO,qEAAyDC,IAAI,CAACH,QAAQI,QAAQ,CAAC,OAAO;IACnG,IAAIF,MAAM;QACR,OAAOA;IACT;IAEA,MAAM,IAAIL,SACRC,MAAM,CAAC;MACL,EAAEG,KAAK;;;QAGL,EAAEA,KAAK;QACP,EAAEA,KAAK;QACP,EAAEA,KAAK;QACP,EAAEA,KAAK;QACP,EAAEA,KAAK;IACX,CAAC;AAEL,EAAE"}
@@ -113,12 +113,8 @@ var ConnectionStatus;
113
113
  assert(ctx.app, "app must be set on Client context");
114
114
  assert(ctx.env, "env must be set on Client context");
115
115
  this.endpoint = endpoint;
116
- let subdomain = ctx.app.slug;
117
- if (ctx.app.hasSplitEnvironments) {
118
- subdomain += "--development";
119
- }
120
116
  this._graphqlWsClient = createClient({
121
- url: `wss://${subdomain}.${config.domains.app}/edit/api/graphql-ws`,
117
+ url: `wss://${ctx.app.slug}.${config.domains.app}/edit/api/graphql-ws`,
122
118
  shouldRetry: ()=>true,
123
119
  connectionParams: {
124
120
  environment: ctx.env.name
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../src/services/app/client.ts"],"sourcesContent":["import type { ExecutionResult } from \"graphql-ws\";\nimport { createClient } from \"graphql-ws\";\nimport assert from \"node:assert\";\nimport type { ClientRequestArgs } from \"node:http\";\nimport PQueue from \"p-queue\";\nimport type { Promisable } from \"type-fest\";\nimport WebSocket from \"ws\";\nimport type { Context } from \"../command/context.js\";\nimport { config } from \"../config/config.js\";\nimport { loadAuthHeaders } from \"../http/auth.js\";\nimport { http, type HttpOptions } from \"../http/http.js\";\nimport { noop, unthunk, type Thunk } from \"../util/function.js\";\nimport { isObject } from \"../util/is.js\";\nimport type { GraphQLMutation, GraphQLQuery, GraphQLSubscription } from \"./edit/operation.js\";\nimport { ClientError } from \"./error.js\";\n\nenum ConnectionStatus {\n CONNECTED,\n DISCONNECTED,\n RECONNECTING,\n}\n\n/**\n * Client is a GraphQL client connected to a Gadget application's\n * given endpoint.\n */\nexport class Client {\n // assume the client is going to connect\n status = ConnectionStatus.CONNECTED;\n\n readonly ctx: Context;\n\n readonly endpoint: string;\n\n private _graphqlWsClient: ReturnType<typeof createClient>;\n\n constructor(ctx: Context, endpoint: string) {\n this.ctx = ctx.child({ name: \"client\" });\n assert(ctx.app, \"app must be set on Client context\");\n assert(ctx.env, \"env must be set on Client context\");\n\n this.endpoint = endpoint;\n\n let subdomain = ctx.app.slug;\n if (ctx.app.hasSplitEnvironments) {\n subdomain += \"--development\";\n }\n\n this._graphqlWsClient = createClient({\n url: `wss://${subdomain}.${config.domains.app}/edit/api/graphql-ws`,\n shouldRetry: () => true,\n connectionParams: {\n environment: ctx.env.name,\n },\n webSocketImpl: class extends WebSocket {\n constructor(address: string | URL, protocols?: string | string[], wsOptions?: WebSocket.ClientOptions | ClientRequestArgs) {\n // this cookie should be available since we were given an app which requires a cookie to load\n const headers = loadAuthHeaders();\n\n assert(headers, \"missing headers when connecting to GraphQL API\");\n\n super(address, protocols, {\n signal: ctx.signal,\n ...wsOptions,\n headers: {\n ...wsOptions?.headers,\n \"user-agent\": config.versionFull,\n ...headers,\n },\n });\n }\n },\n on: {\n connecting: () => {\n switch (this.status) {\n case ConnectionStatus.DISCONNECTED:\n this.status = ConnectionStatus.RECONNECTING;\n this.ctx.log.info(\"reconnecting\");\n break;\n case ConnectionStatus.RECONNECTING:\n this.ctx.log.info(\"retrying\");\n break;\n default:\n this.ctx.log.debug(\"connecting\");\n break;\n }\n },\n connected: () => {\n if (this.status === ConnectionStatus.RECONNECTING) {\n this.ctx.log.info(\"reconnected\");\n } else {\n this.ctx.log.debug(\"connected\");\n }\n\n // let the other on connected listeners see what status we're in\n setImmediate(() => (this.status = ConnectionStatus.CONNECTED));\n },\n closed: () => {\n this.status = ConnectionStatus.DISCONNECTED;\n this.ctx.log.debug(\"disconnected\");\n },\n error: (error) => {\n if (this.status === ConnectionStatus.RECONNECTING) {\n this.ctx.log.error(\"failed to reconnect\", { error });\n } else {\n this.ctx.log.error(\"connection error\", { error });\n }\n },\n },\n });\n }\n\n /**\n * Subscribe to a GraphQL subscription.\n */\n subscribe<Subscription extends GraphQLSubscription>(\n ctx: Context,\n {\n subscription,\n variables,\n onResponse,\n onError: optionsOnError,\n onComplete = noop,\n }: {\n subscription: Subscription;\n variables?: Thunk<Subscription[\"Variables\"]> | null;\n onResponse: (response: ExecutionResult<Subscription[\"Data\"], Subscription[\"Extensions\"]>) => Promisable<void>;\n onError: (error: ClientError) => Promisable<void>;\n onComplete?: () => Promisable<void>;\n },\n ): () => void {\n let request = { query: subscription, variables: unthunk(variables) };\n\n const removeConnectedListener = this._graphqlWsClient.on(\"connected\", () => {\n if (this.status === ConnectionStatus.RECONNECTING) {\n request = { query: subscription, variables: unthunk(variables) };\n ctx.log.info(\"re-subscribing to graphql subscription\");\n }\n });\n\n const queue = new PQueue({ concurrency: 1 });\n const onError = (error: unknown): Promisable<void> => optionsOnError(new ClientError(subscription, error));\n\n const unsubscribe = this._graphqlWsClient.subscribe<Subscription[\"Data\"], Subscription[\"Extensions\"]>(request, {\n // eslint-disable-next-line @typescript-eslint/no-misused-promises\n next: (response) => queue.add(() => onResponse(response)).catch(onError),\n // eslint-disable-next-line @typescript-eslint/no-misused-promises\n error: (error) => queue.add(() => onError(error)),\n // eslint-disable-next-line @typescript-eslint/no-misused-promises\n complete: () => queue.add(() => onComplete()).catch(onError),\n });\n\n return () => {\n removeConnectedListener();\n unsubscribe();\n };\n }\n\n /**\n * Execute a GraphQL query or mutation.\n */\n async execute<Operation extends GraphQLQuery | GraphQLMutation>(\n ctx: Context,\n request: {\n operation: Operation;\n variables?: Thunk<Operation[\"Variables\"]> | null;\n http?: HttpOptions;\n },\n ): Promise<ExecutionResult<Operation[\"Data\"], Operation[\"Extensions\"]>> {\n assert(ctx.app, \"missing app when executing GraphQL query\");\n assert(ctx.env, \"missing env when executing GraphQL query\");\n\n const headers = loadAuthHeaders();\n assert(headers, \"missing headers when executing GraphQL request\");\n\n let subdomain = ctx.app.slug;\n if (ctx.app.multiEnvironmentEnabled) {\n subdomain += `--${ctx.env.name}`;\n } else if (ctx.app.hasSplitEnvironments) {\n subdomain += \"--development\";\n }\n\n try {\n const json = await http({\n context: { ctx },\n method: \"POST\",\n url: `https://${subdomain}.${config.domains.app}${this.endpoint}`,\n headers: { ...headers, \"x-gadget-environment\": ctx.env.name },\n json: { query: request.operation, variables: unthunk(request.variables) },\n responseType: \"json\",\n resolveBodyOnly: true,\n throwHttpErrors: false,\n ...request.http,\n });\n\n if (!isObject(json) || (!(\"data\" in json) && !(\"errors\" in json))) {\n ctx.log.error(\"received invalid graphql response\", { error: json });\n throw json;\n }\n\n return json as Operation[\"Response\"];\n } catch (error) {\n throw new ClientError(request.operation, error);\n }\n }\n\n /**\n * Close the connection to the server.\n */\n async dispose(): Promise<void> {\n await this._graphqlWsClient.dispose();\n }\n}\n"],"names":["createClient","assert","PQueue","WebSocket","config","loadAuthHeaders","http","noop","unthunk","isObject","ClientError","ConnectionStatus","Client","subscribe","ctx","subscription","variables","onResponse","onError","optionsOnError","onComplete","request","query","removeConnectedListener","_graphqlWsClient","on","status","log","info","queue","concurrency","error","unsubscribe","next","response","add","catch","complete","execute","app","env","headers","subdomain","slug","multiEnvironmentEnabled","name","hasSplitEnvironments","json","context","method","url","domains","endpoint","operation","responseType","resolveBodyOnly","throwHttpErrors","dispose","constructor","child","shouldRetry","connectionParams","environment","webSocketImpl","address","protocols","wsOptions","signal","versionFull","connecting","debug","connected","setImmediate","closed"],"mappings":"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"}
1
+ {"version":3,"sources":["../../../src/services/app/client.ts"],"sourcesContent":["import type { ExecutionResult } from \"graphql-ws\";\nimport { createClient } from \"graphql-ws\";\nimport assert from \"node:assert\";\nimport type { ClientRequestArgs } from \"node:http\";\nimport PQueue from \"p-queue\";\nimport type { Promisable } from \"type-fest\";\nimport WebSocket from \"ws\";\nimport type { Context } from \"../command/context.js\";\nimport { config } from \"../config/config.js\";\nimport { loadAuthHeaders } from \"../http/auth.js\";\nimport { http, type HttpOptions } from \"../http/http.js\";\nimport { noop, unthunk, type Thunk } from \"../util/function.js\";\nimport { isObject } from \"../util/is.js\";\nimport type { GraphQLMutation, GraphQLQuery, GraphQLSubscription } from \"./edit/operation.js\";\nimport { ClientError } from \"./error.js\";\n\nenum ConnectionStatus {\n CONNECTED,\n DISCONNECTED,\n RECONNECTING,\n}\n\n/**\n * Client is a GraphQL client connected to a Gadget application's\n * given endpoint.\n */\nexport class Client {\n // assume the client is going to connect\n status = ConnectionStatus.CONNECTED;\n\n readonly ctx: Context;\n\n readonly endpoint: string;\n\n private _graphqlWsClient: ReturnType<typeof createClient>;\n\n constructor(ctx: Context, endpoint: string) {\n this.ctx = ctx.child({ name: \"client\" });\n assert(ctx.app, \"app must be set on Client context\");\n assert(ctx.env, \"env must be set on Client context\");\n\n this.endpoint = endpoint;\n\n this._graphqlWsClient = createClient({\n url: `wss://${ctx.app.slug}.${config.domains.app}/edit/api/graphql-ws`,\n shouldRetry: () => true,\n connectionParams: {\n environment: ctx.env.name,\n },\n webSocketImpl: class extends WebSocket {\n constructor(address: string | URL, protocols?: string | string[], wsOptions?: WebSocket.ClientOptions | ClientRequestArgs) {\n // this cookie should be available since we were given an app which requires a cookie to load\n const headers = loadAuthHeaders();\n\n assert(headers, \"missing headers when connecting to GraphQL API\");\n\n super(address, protocols, {\n signal: ctx.signal,\n ...wsOptions,\n headers: {\n ...wsOptions?.headers,\n \"user-agent\": config.versionFull,\n ...headers,\n },\n });\n }\n },\n on: {\n connecting: () => {\n switch (this.status) {\n case ConnectionStatus.DISCONNECTED:\n this.status = ConnectionStatus.RECONNECTING;\n this.ctx.log.info(\"reconnecting\");\n break;\n case ConnectionStatus.RECONNECTING:\n this.ctx.log.info(\"retrying\");\n break;\n default:\n this.ctx.log.debug(\"connecting\");\n break;\n }\n },\n connected: () => {\n if (this.status === ConnectionStatus.RECONNECTING) {\n this.ctx.log.info(\"reconnected\");\n } else {\n this.ctx.log.debug(\"connected\");\n }\n\n // let the other on connected listeners see what status we're in\n setImmediate(() => (this.status = ConnectionStatus.CONNECTED));\n },\n closed: () => {\n this.status = ConnectionStatus.DISCONNECTED;\n this.ctx.log.debug(\"disconnected\");\n },\n error: (error) => {\n if (this.status === ConnectionStatus.RECONNECTING) {\n this.ctx.log.error(\"failed to reconnect\", { error });\n } else {\n this.ctx.log.error(\"connection error\", { error });\n }\n },\n },\n });\n }\n\n /**\n * Subscribe to a GraphQL subscription.\n */\n subscribe<Subscription extends GraphQLSubscription>(\n ctx: Context,\n {\n subscription,\n variables,\n onResponse,\n onError: optionsOnError,\n onComplete = noop,\n }: {\n subscription: Subscription;\n variables?: Thunk<Subscription[\"Variables\"]> | null;\n onResponse: (response: ExecutionResult<Subscription[\"Data\"], Subscription[\"Extensions\"]>) => Promisable<void>;\n onError: (error: ClientError) => Promisable<void>;\n onComplete?: () => Promisable<void>;\n },\n ): () => void {\n let request = { query: subscription, variables: unthunk(variables) };\n\n const removeConnectedListener = this._graphqlWsClient.on(\"connected\", () => {\n if (this.status === ConnectionStatus.RECONNECTING) {\n request = { query: subscription, variables: unthunk(variables) };\n ctx.log.info(\"re-subscribing to graphql subscription\");\n }\n });\n\n const queue = new PQueue({ concurrency: 1 });\n const onError = (error: unknown): Promisable<void> => optionsOnError(new ClientError(subscription, error));\n\n const unsubscribe = this._graphqlWsClient.subscribe<Subscription[\"Data\"], Subscription[\"Extensions\"]>(request, {\n // eslint-disable-next-line @typescript-eslint/no-misused-promises\n next: (response) => queue.add(() => onResponse(response)).catch(onError),\n // eslint-disable-next-line @typescript-eslint/no-misused-promises\n error: (error) => queue.add(() => onError(error)),\n // eslint-disable-next-line @typescript-eslint/no-misused-promises\n complete: () => queue.add(() => onComplete()).catch(onError),\n });\n\n return () => {\n removeConnectedListener();\n unsubscribe();\n };\n }\n\n /**\n * Execute a GraphQL query or mutation.\n */\n async execute<Operation extends GraphQLQuery | GraphQLMutation>(\n ctx: Context,\n request: {\n operation: Operation;\n variables?: Thunk<Operation[\"Variables\"]> | null;\n http?: HttpOptions;\n },\n ): Promise<ExecutionResult<Operation[\"Data\"], Operation[\"Extensions\"]>> {\n assert(ctx.app, \"missing app when executing GraphQL query\");\n assert(ctx.env, \"missing env when executing GraphQL query\");\n\n const headers = loadAuthHeaders();\n assert(headers, \"missing headers when executing GraphQL request\");\n\n let subdomain = ctx.app.slug;\n if (ctx.app.multiEnvironmentEnabled) {\n subdomain += `--${ctx.env.name}`;\n } else if (ctx.app.hasSplitEnvironments) {\n subdomain += \"--development\";\n }\n\n try {\n const json = await http({\n context: { ctx },\n method: \"POST\",\n url: `https://${subdomain}.${config.domains.app}${this.endpoint}`,\n headers: { ...headers, \"x-gadget-environment\": ctx.env.name },\n json: { query: request.operation, variables: unthunk(request.variables) },\n responseType: \"json\",\n resolveBodyOnly: true,\n throwHttpErrors: false,\n ...request.http,\n });\n\n if (!isObject(json) || (!(\"data\" in json) && !(\"errors\" in json))) {\n ctx.log.error(\"received invalid graphql response\", { error: json });\n throw json;\n }\n\n return json as Operation[\"Response\"];\n } catch (error) {\n throw new ClientError(request.operation, error);\n }\n }\n\n /**\n * Close the connection to the server.\n */\n async dispose(): Promise<void> {\n await this._graphqlWsClient.dispose();\n }\n}\n"],"names":["createClient","assert","PQueue","WebSocket","config","loadAuthHeaders","http","noop","unthunk","isObject","ClientError","ConnectionStatus","Client","subscribe","ctx","subscription","variables","onResponse","onError","optionsOnError","onComplete","request","query","removeConnectedListener","_graphqlWsClient","on","status","log","info","queue","concurrency","error","unsubscribe","next","response","add","catch","complete","execute","app","env","headers","subdomain","slug","multiEnvironmentEnabled","name","hasSplitEnvironments","json","context","method","url","domains","endpoint","operation","responseType","resolveBodyOnly","throwHttpErrors","dispose","constructor","child","shouldRetry","connectionParams","environment","webSocketImpl","address","protocols","wsOptions","signal","versionFull","connecting","debug","connected","setImmediate","closed"],"rangeMappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;","mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../../src/services/app/edit/edit.ts"],"sourcesContent":["import type { ExecutionResult } from \"graphql-ws\";\nimport assert from \"node:assert\";\nimport type { Promisable } from \"type-fest\";\nimport type { Context } from \"../../command/context.js\";\nimport { type HttpOptions } from \"../../http/http.js\";\nimport { unthunk, type Thunk } from \"../../util/function.js\";\nimport { Client } from \"../client.js\";\nimport { ClientError } from \"../error.js\";\nimport type { GraphQLMutation, GraphQLQuery, GraphQLSubscription } from \"./operation.js\";\n\nexport class Edit {\n /**\n * The {@linkcode Context} that was used to create this instance.\n */\n readonly ctx: Context;\n\n /**\n * The client used to make requests to Gadget's /edit/api/graphql\n * endpoint.\n */\n #client: Client;\n\n constructor(ctx: Context) {\n this.ctx = ctx.child({ name: \"edit\" });\n this.#client = new Client(this.ctx, \"/edit/api/graphql\");\n }\n\n /**\n * Execute a GraphQL query.\n *\n * @param request - The query and variables to send to the server.\n * @param request.query - The GraphQL query to execute.\n * @param request.variables - The variables to send to the server.\n * @param request.http - {@linkcode HttpOptions} to pass to http.\n * @returns The data returned by the server.\n */\n async query<Query extends GraphQLQuery>({\n query,\n variables,\n ...options\n }: {\n query: Query;\n variables?: Thunk<Query[\"Variables\"]> | null;\n http?: HttpOptions;\n }): Promise<Query[\"Data\"]> {\n const name = query.match(/query (\\w+)/)?.[1];\n assert(name, \"query name not found\");\n\n const ctx = this.ctx.child({\n fields: { edit: { query: name } },\n devFields: { edit: { query: name, variables: unthunk(variables) } },\n });\n\n ctx.log.info(\"executing graphql query\");\n const response = await this.#client.execute(ctx, {\n operation: query,\n variables,\n ...options,\n http: {\n retry: {\n // queries _should_ be idempotent, so automatically retry them\n methods: [\"POST\"],\n },\n ...options.http,\n },\n });\n\n if (response.errors) {\n throw new ClientError(query, response.errors);\n }\n\n if (!response.data) {\n throw new ClientError(query, \"Query response did not contain data\");\n }\n\n return response.data;\n }\n\n /**\n * Execute a GraphQL mutation.\n *\n * @param request - The query and variables to send to the server.\n * @param request.mutation - The GraphQL mutation to execute.\n * @param request.variables - The variables to send to the server.\n * @param request.http - {@linkcode HttpOptions} to pass to http.\n * @returns The data returned by the server.\n */\n async mutate<Mutation extends GraphQLMutation>({\n mutation,\n variables,\n ...options\n }: {\n mutation: Mutation;\n variables?: Thunk<Mutation[\"Variables\"]> | null;\n http?: HttpOptions;\n }): Promise<Mutation[\"Data\"]> {\n const name = mutation.match(/mutation (\\w+)/)?.[1];\n assert(name, \"mutation name not found\");\n\n const ctx = this.ctx.child({\n fields: { edit: { mutation: name } },\n devFields: { edit: { mutation: name, variables: unthunk(variables) } },\n });\n\n ctx.log.info(\"executing graphql mutation\");\n const response = await this.#client.execute(ctx, { operation: mutation, variables, ...options });\n\n if (response.errors) {\n throw new ClientError(mutation, response.errors);\n }\n\n if (!response.data) {\n throw new ClientError(mutation, \"Mutation response did not contain data\");\n }\n\n return response.data;\n }\n\n /**\n * Subscribe to a GraphQL subscription.\n *\n * @param options - The query and variables to send to the server.\n * @param options.subscription - The GraphQL subscription to subscribe to.\n * @param options.variables - The variables to send to the server.\n * @param options.onData - A callback that will be called when data is received from the server.\n * @param options.onError - A callback that will be called when an error is received from the server.\n * @param options.onComplete - A callback that will be called when the subscription ends.\n * @returns A function to unsubscribe from the subscription.\n */\n subscribe<Subscription extends GraphQLSubscription>({\n onData,\n ...options\n }: {\n subscription: Subscription;\n variables?: Thunk<Subscription[\"Variables\"]> | null;\n onData: (data: Subscription[\"Data\"]) => Promisable<void>;\n onError: (error: ClientError) => Promisable<void>;\n onComplete?: () => Promisable<void>;\n }): EditSubscription<Subscription> {\n const name = options.subscription.match(/subscription (\\w+)/)?.[1];\n assert(name, \"subscription name not found\");\n\n let ctx = this.ctx.child({\n fields: { edit: { subscription: name } },\n devFields: { edit: { subscription: name, variables: unthunk(options.variables) } },\n });\n\n const onResponse = async (response: ExecutionResult<Subscription[\"Data\"], Subscription[\"Extensions\"]>): Promise<void> => {\n if (response.errors) {\n unsubscribe();\n await options.onError(new ClientError(options.subscription, response.errors));\n return;\n }\n\n if (!response.data) {\n unsubscribe();\n await options.onError(new ClientError(options.subscription, \"Subscription response did not contain data\"));\n return;\n }\n\n await onData(response.data);\n };\n\n ctx.log.info(\"subscribing to graphql subscription\");\n let unsubscribe = this.#client.subscribe(ctx, { ...options, onResponse });\n\n return {\n unsubscribe,\n resubscribe: (variables) => {\n unsubscribe();\n\n if (variables !== undefined) {\n options.variables = variables;\n }\n\n ctx = this.ctx.child({\n fields: { edit: { subscription: name } },\n devFields: { edit: { subscription: name, variables: unthunk(options.variables) } },\n });\n\n ctx.log.info(\"re-subscribing to graphql subscription\");\n unsubscribe = this.#client.subscribe(ctx, { ...options, onResponse });\n },\n };\n }\n\n /**\n * Close the client.\n */\n async dispose(): Promise<void> {\n await this.#client.dispose();\n }\n}\n\n/**\n * An object that can be used to unsubscribe and resubscribe to an\n * ongoing Edit GraphQL subscription.\n */\nexport type EditSubscription<Subscription extends GraphQLSubscription> = {\n /**\n * Unsubscribe from the subscription.\n */\n unsubscribe(): void;\n\n /**\n * Resubscribe to the subscription.\n */\n resubscribe(variables?: Thunk<Subscription[\"Variables\"]> | null): void;\n};\n"],"names":["assert","unthunk","Client","ClientError","Edit","query","variables","options","name","match","ctx","child","fields","edit","devFields","log","info","response","client","execute","operation","http","retry","methods","errors","data","mutate","mutation","subscribe","onData","subscription","onResponse","unsubscribe","onError","resubscribe","undefined","dispose","constructor"],"mappings":"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"}
1
+ {"version":3,"sources":["../../../../src/services/app/edit/edit.ts"],"sourcesContent":["import type { ExecutionResult } from \"graphql-ws\";\nimport assert from \"node:assert\";\nimport type { Promisable } from \"type-fest\";\nimport type { Context } from \"../../command/context.js\";\nimport { type HttpOptions } from \"../../http/http.js\";\nimport { unthunk, type Thunk } from \"../../util/function.js\";\nimport { Client } from \"../client.js\";\nimport { ClientError } from \"../error.js\";\nimport type { GraphQLMutation, GraphQLQuery, GraphQLSubscription } from \"./operation.js\";\n\nexport class Edit {\n /**\n * The {@linkcode Context} that was used to create this instance.\n */\n readonly ctx: Context;\n\n /**\n * The client used to make requests to Gadget's /edit/api/graphql\n * endpoint.\n */\n #client: Client;\n\n constructor(ctx: Context) {\n this.ctx = ctx.child({ name: \"edit\" });\n this.#client = new Client(this.ctx, \"/edit/api/graphql\");\n }\n\n /**\n * Execute a GraphQL query.\n *\n * @param request - The query and variables to send to the server.\n * @param request.query - The GraphQL query to execute.\n * @param request.variables - The variables to send to the server.\n * @param request.http - {@linkcode HttpOptions} to pass to http.\n * @returns The data returned by the server.\n */\n async query<Query extends GraphQLQuery>({\n query,\n variables,\n ...options\n }: {\n query: Query;\n variables?: Thunk<Query[\"Variables\"]> | null;\n http?: HttpOptions;\n }): Promise<Query[\"Data\"]> {\n const name = query.match(/query (\\w+)/)?.[1];\n assert(name, \"query name not found\");\n\n const ctx = this.ctx.child({\n fields: { edit: { query: name } },\n devFields: { edit: { query: name, variables: unthunk(variables) } },\n });\n\n ctx.log.info(\"executing graphql query\");\n const response = await this.#client.execute(ctx, {\n operation: query,\n variables,\n ...options,\n http: {\n retry: {\n // queries _should_ be idempotent, so automatically retry them\n methods: [\"POST\"],\n },\n ...options.http,\n },\n });\n\n if (response.errors) {\n throw new ClientError(query, response.errors);\n }\n\n if (!response.data) {\n throw new ClientError(query, \"Query response did not contain data\");\n }\n\n return response.data;\n }\n\n /**\n * Execute a GraphQL mutation.\n *\n * @param request - The query and variables to send to the server.\n * @param request.mutation - The GraphQL mutation to execute.\n * @param request.variables - The variables to send to the server.\n * @param request.http - {@linkcode HttpOptions} to pass to http.\n * @returns The data returned by the server.\n */\n async mutate<Mutation extends GraphQLMutation>({\n mutation,\n variables,\n ...options\n }: {\n mutation: Mutation;\n variables?: Thunk<Mutation[\"Variables\"]> | null;\n http?: HttpOptions;\n }): Promise<Mutation[\"Data\"]> {\n const name = mutation.match(/mutation (\\w+)/)?.[1];\n assert(name, \"mutation name not found\");\n\n const ctx = this.ctx.child({\n fields: { edit: { mutation: name } },\n devFields: { edit: { mutation: name, variables: unthunk(variables) } },\n });\n\n ctx.log.info(\"executing graphql mutation\");\n const response = await this.#client.execute(ctx, { operation: mutation, variables, ...options });\n\n if (response.errors) {\n throw new ClientError(mutation, response.errors);\n }\n\n if (!response.data) {\n throw new ClientError(mutation, \"Mutation response did not contain data\");\n }\n\n return response.data;\n }\n\n /**\n * Subscribe to a GraphQL subscription.\n *\n * @param options - The query and variables to send to the server.\n * @param options.subscription - The GraphQL subscription to subscribe to.\n * @param options.variables - The variables to send to the server.\n * @param options.onData - A callback that will be called when data is received from the server.\n * @param options.onError - A callback that will be called when an error is received from the server.\n * @param options.onComplete - A callback that will be called when the subscription ends.\n * @returns A function to unsubscribe from the subscription.\n */\n subscribe<Subscription extends GraphQLSubscription>({\n onData,\n ...options\n }: {\n subscription: Subscription;\n variables?: Thunk<Subscription[\"Variables\"]> | null;\n onData: (data: Subscription[\"Data\"]) => Promisable<void>;\n onError: (error: ClientError) => Promisable<void>;\n onComplete?: () => Promisable<void>;\n }): EditSubscription<Subscription> {\n const name = options.subscription.match(/subscription (\\w+)/)?.[1];\n assert(name, \"subscription name not found\");\n\n let ctx = this.ctx.child({\n fields: { edit: { subscription: name } },\n devFields: { edit: { subscription: name, variables: unthunk(options.variables) } },\n });\n\n const onResponse = async (response: ExecutionResult<Subscription[\"Data\"], Subscription[\"Extensions\"]>): Promise<void> => {\n if (response.errors) {\n unsubscribe();\n await options.onError(new ClientError(options.subscription, response.errors));\n return;\n }\n\n if (!response.data) {\n unsubscribe();\n await options.onError(new ClientError(options.subscription, \"Subscription response did not contain data\"));\n return;\n }\n\n await onData(response.data);\n };\n\n ctx.log.info(\"subscribing to graphql subscription\");\n let unsubscribe = this.#client.subscribe(ctx, { ...options, onResponse });\n\n return {\n unsubscribe,\n resubscribe: (variables) => {\n unsubscribe();\n\n if (variables !== undefined) {\n options.variables = variables;\n }\n\n ctx = this.ctx.child({\n fields: { edit: { subscription: name } },\n devFields: { edit: { subscription: name, variables: unthunk(options.variables) } },\n });\n\n ctx.log.info(\"re-subscribing to graphql subscription\");\n unsubscribe = this.#client.subscribe(ctx, { ...options, onResponse });\n },\n };\n }\n\n /**\n * Close the client.\n */\n async dispose(): Promise<void> {\n await this.#client.dispose();\n }\n}\n\n/**\n * An object that can be used to unsubscribe and resubscribe to an\n * ongoing Edit GraphQL subscription.\n */\nexport type EditSubscription<Subscription extends GraphQLSubscription> = {\n /**\n * Unsubscribe from the subscription.\n */\n unsubscribe(): void;\n\n /**\n * Resubscribe to the subscription.\n */\n resubscribe(variables?: Thunk<Subscription[\"Variables\"]> | null): void;\n};\n"],"names":["assert","unthunk","Client","ClientError","Edit","query","variables","options","name","match","ctx","child","fields","edit","devFields","log","info","response","client","execute","operation","http","retry","methods","errors","data","mutate","mutation","subscribe","onData","subscription","onResponse","unsubscribe","onError","resubscribe","undefined","dispose","constructor"],"rangeMappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;","mappings":"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"}
@@ -99,5 +99,57 @@ export const PUBLISH_STATUS_SUBSCRIPTION = sprint(/* GraphQL */ `
99
99
  }
100
100
  }
101
101
  `);
102
+ export const CREATE_MODEL_MUTATION = sprint(/* GraphQL */ `
103
+ mutation createModel($path: String!, $fields: [CreateModelFieldsInput!]) {
104
+ createModel(path: $path, fields: $fields) {
105
+ remoteFilesVersion
106
+ changed {
107
+ path
108
+ mode
109
+ content
110
+ encoding
111
+ }
112
+ }
113
+ }
114
+ `);
115
+ export const CREATE_ACTION_MUTATION = sprint(/* GraphQL */ `
116
+ mutation createAction($path: String!) {
117
+ createAction(path: $path) {
118
+ remoteFilesVersion
119
+ changed {
120
+ path
121
+ mode
122
+ content
123
+ encoding
124
+ }
125
+ }
126
+ }
127
+ `);
128
+ export const CREATE_ROUTE_MUTATION = sprint(/* GraphQL */ `
129
+ mutation createRoute($method: String!, $path: String!) {
130
+ createRoute(method: $method, path: $path) {
131
+ remoteFilesVersion
132
+ changed {
133
+ path
134
+ mode
135
+ content
136
+ encoding
137
+ }
138
+ }
139
+ }
140
+ `);
141
+ export const CREATE_MODEL_FIELDS_MUTATION = sprint(/* GraphQL */ `
142
+ mutation createModelFields($path: String!, $fields: [CreateModelFieldsInput!]!) {
143
+ createModelFields(path: $path, fields: $fields) {
144
+ remoteFilesVersion
145
+ changed {
146
+ path
147
+ mode
148
+ content
149
+ encoding
150
+ }
151
+ }
152
+ }
153
+ `);
102
154
 
103
155
  //# sourceMappingURL=operation.js.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../../src/services/app/edit/operation.ts"],"sourcesContent":["import type { ExecutionResult } from \"graphql-ws\";\nimport type { JsonObject } from \"type-fest\";\nimport type {\n FileSyncComparisonHashesQuery,\n FileSyncComparisonHashesQueryVariables,\n FileSyncFilesQuery,\n FileSyncFilesQueryVariables,\n FileSyncHashesQuery,\n FileSyncHashesQueryVariables,\n PublishFileSyncEventsMutation,\n PublishFileSyncEventsMutationVariables,\n PublishStatusSubscription,\n PublishStatusSubscriptionVariables,\n RemoteFileSyncEventsSubscription,\n RemoteFileSyncEventsSubscriptionVariables,\n RemoteFilesVersionQuery,\n RemoteFilesVersionQueryVariables,\n} from \"../../../__generated__/graphql.js\";\nimport { sprint } from \"../../output/sprint.js\";\n\n/**\n * A GraphQL query with its associated types.\n *\n * At runtime, this is just a string.\n */\nexport type GraphQLQuery<\n Data extends JsonObject = JsonObject,\n Variables extends JsonObject = JsonObject,\n Extensions extends JsonObject = JsonObject,\n Response extends ExecutionResult<Data, Extensions> = ExecutionResult<Data, Extensions>,\n> = string & {\n type: \"query\";\n Data: Data;\n Variables: Variables;\n Extensions: Extensions;\n Response: Response;\n};\n\n/**\n * A GraphQL mutation with its associated types.\n *\n * At runtime, this is just a string.\n */\nexport type GraphQLMutation<\n Data extends JsonObject = JsonObject,\n Variables extends JsonObject = JsonObject,\n Extensions extends JsonObject = JsonObject,\n Response extends ExecutionResult<Data, Extensions> = ExecutionResult<Data, Extensions>,\n> = string & {\n type: \"mutation\";\n Data: Data;\n Variables: Variables;\n Extensions: Extensions;\n Response: Response;\n};\n\n/**\n * A GraphQL subscription with its associated types.\n *\n * At runtime, this is just a string.\n */\nexport type GraphQLSubscription<\n Data extends JsonObject = JsonObject,\n Variables extends JsonObject = JsonObject,\n Extensions extends JsonObject = JsonObject,\n Response extends ExecutionResult<Data, Extensions> = ExecutionResult<Data, Extensions>,\n> = string & {\n type: \"subscription\";\n Data: Data;\n Variables: Variables;\n Extensions: Extensions;\n Response: Response;\n};\n\nexport const REMOTE_FILE_SYNC_EVENTS_SUBSCRIPTION = sprint(/* GraphQL */ `\n subscription RemoteFileSyncEvents($localFilesVersion: String!) {\n remoteFileSyncEvents(localFilesVersion: $localFilesVersion, encoding: base64) {\n remoteFilesVersion\n changed {\n path\n mode\n content\n encoding\n }\n deleted {\n path\n }\n }\n }\n`) as GraphQLSubscription<RemoteFileSyncEventsSubscription, RemoteFileSyncEventsSubscriptionVariables>;\n\nexport type REMOTE_FILE_SYNC_EVENTS_SUBSCRIPTION = typeof REMOTE_FILE_SYNC_EVENTS_SUBSCRIPTION;\n\nexport const REMOTE_FILES_VERSION_QUERY = sprint(/* GraphQL */ `\n query RemoteFilesVersion {\n remoteFilesVersion\n }\n`) as GraphQLQuery<RemoteFilesVersionQuery, RemoteFilesVersionQueryVariables>;\n\nexport type REMOTE_FILES_VERSION_QUERY = typeof REMOTE_FILES_VERSION_QUERY;\n\nexport const PUBLISH_FILE_SYNC_EVENTS_MUTATION = sprint(/* GraphQL */ `\n mutation PublishFileSyncEvents($input: PublishFileSyncEventsInput!) {\n publishFileSyncEvents(input: $input) {\n remoteFilesVersion\n problems {\n level\n message\n path\n type\n }\n }\n }\n`) as GraphQLMutation<PublishFileSyncEventsMutation, PublishFileSyncEventsMutationVariables>;\n\nexport type PUBLISH_FILE_SYNC_EVENTS_MUTATION = typeof PUBLISH_FILE_SYNC_EVENTS_MUTATION;\n\nexport const FILE_SYNC_FILES_QUERY = sprint(/* GraphQL */ `\n query FileSyncFiles($paths: [String!]!, $filesVersion: String, $encoding: FileSyncEncoding) {\n fileSyncFiles(paths: $paths, filesVersion: $filesVersion, encoding: $encoding) {\n filesVersion\n files {\n path\n mode\n content\n encoding\n }\n }\n }\n`) as GraphQLQuery<FileSyncFilesQuery, FileSyncFilesQueryVariables>;\n\nexport type FILE_SYNC_FILES_QUERY = typeof FILE_SYNC_FILES_QUERY;\n\nexport const FILE_SYNC_HASHES_QUERY = sprint(/* GraphQL */ `\n query FileSyncHashes($filesVersion: String) {\n fileSyncHashes(filesVersion: $filesVersion) {\n filesVersion\n hashes\n }\n }\n`) as GraphQLQuery<FileSyncHashesQuery, FileSyncHashesQueryVariables>;\n\nexport type FILE_SYNC_HASHES_QUERY = typeof FILE_SYNC_HASHES_QUERY;\n\nexport const FILE_SYNC_COMPARISON_HASHES_QUERY = sprint(/* GraphQL */ `\n query FileSyncComparisonHashes($filesVersion: String!) {\n fileSyncComparisonHashes(filesVersion: $filesVersion) {\n filesVersionHashes {\n filesVersion\n hashes\n }\n latestFilesVersionHashes {\n filesVersion\n hashes\n }\n }\n }\n`) as GraphQLQuery<FileSyncComparisonHashesQuery, FileSyncComparisonHashesQueryVariables>;\n\nexport type FILE_SYNC_COMPARISON_HASHES_QUERY = typeof FILE_SYNC_COMPARISON_HASHES_QUERY;\n\nexport const PUBLISH_STATUS_SUBSCRIPTION = sprint(/* GraphQL */ `\n subscription PublishStatus($localFilesVersion: String!, $force: Boolean, $allowCharges: Boolean) {\n publishStatus(localFilesVersion: $localFilesVersion, force: $force, allowCharges: $allowCharges) {\n publishStarted\n remoteFilesVersion\n progress\n issues {\n severity\n message\n node {\n type\n key\n apiIdentifier\n name\n fieldType\n parentKey\n parentApiIdentifier\n }\n nodeLabels {\n type\n identifier\n }\n }\n status {\n code\n message\n output\n }\n }\n }\n`) as GraphQLSubscription<PublishStatusSubscription, PublishStatusSubscriptionVariables>;\n\nexport type PUBLISH_STATUS_SUBSCRIPTION = typeof PUBLISH_STATUS_SUBSCRIPTION;\n"],"names":["sprint","REMOTE_FILE_SYNC_EVENTS_SUBSCRIPTION","REMOTE_FILES_VERSION_QUERY","PUBLISH_FILE_SYNC_EVENTS_MUTATION","FILE_SYNC_FILES_QUERY","FILE_SYNC_HASHES_QUERY","FILE_SYNC_COMPARISON_HASHES_QUERY","PUBLISH_STATUS_SUBSCRIPTION"],"mappings":"AAkBA,SAASA,MAAM,QAAQ,yBAAyB;AAwDhD,OAAO,MAAMC,uCAAuCD,OAAO,WAAW,GAAG,CAAC;;;;;;;;;;;;;;;AAe1E,CAAC,EAAsG;AAIvG,OAAO,MAAME,6BAA6BF,OAAO,WAAW,GAAG,CAAC;;;;AAIhE,CAAC,EAA6E;AAI9E,OAAO,MAAMG,oCAAoCH,OAAO,WAAW,GAAG,CAAC;;;;;;;;;;;;AAYvE,CAAC,EAA4F;AAI7F,OAAO,MAAMI,wBAAwBJ,OAAO,WAAW,GAAG,CAAC;;;;;;;;;;;;AAY3D,CAAC,EAAmE;AAIpE,OAAO,MAAMK,yBAAyBL,OAAO,WAAW,GAAG,CAAC;;;;;;;AAO5D,CAAC,EAAqE;AAItE,OAAO,MAAMM,oCAAoCN,OAAO,WAAW,GAAG,CAAC;;;;;;;;;;;;;AAavE,CAAC,EAAyF;AAI1F,OAAO,MAAMO,8BAA8BP,OAAO,WAAW,GAAG,CAAC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AA8BjE,CAAC,EAAwF"}
1
+ {"version":3,"sources":["../../../../src/services/app/edit/operation.ts"],"sourcesContent":["import type { ExecutionResult } from \"graphql-ws\";\nimport type { JsonObject } from \"type-fest\";\nimport type {\n CreateActionMutation,\n CreateActionMutationVariables,\n CreateModelFieldsMutation,\n CreateModelMutation,\n CreateModelMutationVariables,\n CreateRouteMutation,\n CreateRouteMutationVariables,\n FileSyncComparisonHashesQuery,\n FileSyncComparisonHashesQueryVariables,\n FileSyncFilesQuery,\n FileSyncFilesQueryVariables,\n FileSyncHashesQuery,\n FileSyncHashesQueryVariables,\n PublishFileSyncEventsMutation,\n PublishFileSyncEventsMutationVariables,\n PublishStatusSubscription,\n PublishStatusSubscriptionVariables,\n RemoteFileSyncEventsSubscription,\n RemoteFileSyncEventsSubscriptionVariables,\n RemoteFilesVersionQuery,\n RemoteFilesVersionQueryVariables,\n} from \"../../../__generated__/graphql.js\";\nimport { sprint } from \"../../output/sprint.js\";\n\n/**\n * A GraphQL query with its associated types.\n *\n * At runtime, this is just a string.\n */\nexport type GraphQLQuery<\n Data extends JsonObject = JsonObject,\n Variables extends JsonObject = JsonObject,\n Extensions extends JsonObject = JsonObject,\n Response extends ExecutionResult<Data, Extensions> = ExecutionResult<Data, Extensions>,\n> = string & {\n type: \"query\";\n Data: Data;\n Variables: Variables;\n Extensions: Extensions;\n Response: Response;\n};\n\n/**\n * A GraphQL mutation with its associated types.\n *\n * At runtime, this is just a string.\n */\nexport type GraphQLMutation<\n Data extends JsonObject = JsonObject,\n Variables extends JsonObject = JsonObject,\n Extensions extends JsonObject = JsonObject,\n Response extends ExecutionResult<Data, Extensions> = ExecutionResult<Data, Extensions>,\n> = string & {\n type: \"mutation\";\n Data: Data;\n Variables: Variables;\n Extensions: Extensions;\n Response: Response;\n};\n\n/**\n * A GraphQL subscription with its associated types.\n *\n * At runtime, this is just a string.\n */\nexport type GraphQLSubscription<\n Data extends JsonObject = JsonObject,\n Variables extends JsonObject = JsonObject,\n Extensions extends JsonObject = JsonObject,\n Response extends ExecutionResult<Data, Extensions> = ExecutionResult<Data, Extensions>,\n> = string & {\n type: \"subscription\";\n Data: Data;\n Variables: Variables;\n Extensions: Extensions;\n Response: Response;\n};\n\nexport const REMOTE_FILE_SYNC_EVENTS_SUBSCRIPTION = sprint(/* GraphQL */ `\n subscription RemoteFileSyncEvents($localFilesVersion: String!) {\n remoteFileSyncEvents(localFilesVersion: $localFilesVersion, encoding: base64) {\n remoteFilesVersion\n changed {\n path\n mode\n content\n encoding\n }\n deleted {\n path\n }\n }\n }\n`) as GraphQLSubscription<RemoteFileSyncEventsSubscription, RemoteFileSyncEventsSubscriptionVariables>;\n\nexport type REMOTE_FILE_SYNC_EVENTS_SUBSCRIPTION = typeof REMOTE_FILE_SYNC_EVENTS_SUBSCRIPTION;\n\nexport const REMOTE_FILES_VERSION_QUERY = sprint(/* GraphQL */ `\n query RemoteFilesVersion {\n remoteFilesVersion\n }\n`) as GraphQLQuery<RemoteFilesVersionQuery, RemoteFilesVersionQueryVariables>;\n\nexport type REMOTE_FILES_VERSION_QUERY = typeof REMOTE_FILES_VERSION_QUERY;\n\nexport const PUBLISH_FILE_SYNC_EVENTS_MUTATION = sprint(/* GraphQL */ `\n mutation PublishFileSyncEvents($input: PublishFileSyncEventsInput!) {\n publishFileSyncEvents(input: $input) {\n remoteFilesVersion\n problems {\n level\n message\n path\n type\n }\n }\n }\n`) as GraphQLMutation<PublishFileSyncEventsMutation, PublishFileSyncEventsMutationVariables>;\n\nexport type PUBLISH_FILE_SYNC_EVENTS_MUTATION = typeof PUBLISH_FILE_SYNC_EVENTS_MUTATION;\n\nexport const FILE_SYNC_FILES_QUERY = sprint(/* GraphQL */ `\n query FileSyncFiles($paths: [String!]!, $filesVersion: String, $encoding: FileSyncEncoding) {\n fileSyncFiles(paths: $paths, filesVersion: $filesVersion, encoding: $encoding) {\n filesVersion\n files {\n path\n mode\n content\n encoding\n }\n }\n }\n`) as GraphQLQuery<FileSyncFilesQuery, FileSyncFilesQueryVariables>;\n\nexport type FILE_SYNC_FILES_QUERY = typeof FILE_SYNC_FILES_QUERY;\n\nexport const FILE_SYNC_HASHES_QUERY = sprint(/* GraphQL */ `\n query FileSyncHashes($filesVersion: String) {\n fileSyncHashes(filesVersion: $filesVersion) {\n filesVersion\n hashes\n }\n }\n`) as GraphQLQuery<FileSyncHashesQuery, FileSyncHashesQueryVariables>;\n\nexport type FILE_SYNC_HASHES_QUERY = typeof FILE_SYNC_HASHES_QUERY;\n\nexport const FILE_SYNC_COMPARISON_HASHES_QUERY = sprint(/* GraphQL */ `\n query FileSyncComparisonHashes($filesVersion: String!) {\n fileSyncComparisonHashes(filesVersion: $filesVersion) {\n filesVersionHashes {\n filesVersion\n hashes\n }\n latestFilesVersionHashes {\n filesVersion\n hashes\n }\n }\n }\n`) as GraphQLQuery<FileSyncComparisonHashesQuery, FileSyncComparisonHashesQueryVariables>;\n\nexport type FILE_SYNC_COMPARISON_HASHES_QUERY = typeof FILE_SYNC_COMPARISON_HASHES_QUERY;\n\nexport const PUBLISH_STATUS_SUBSCRIPTION = sprint(/* GraphQL */ `\n subscription PublishStatus($localFilesVersion: String!, $force: Boolean, $allowCharges: Boolean) {\n publishStatus(localFilesVersion: $localFilesVersion, force: $force, allowCharges: $allowCharges) {\n publishStarted\n remoteFilesVersion\n progress\n issues {\n severity\n message\n node {\n type\n key\n apiIdentifier\n name\n fieldType\n parentKey\n parentApiIdentifier\n }\n nodeLabels {\n type\n identifier\n }\n }\n status {\n code\n message\n output\n }\n }\n }\n`) as GraphQLSubscription<PublishStatusSubscription, PublishStatusSubscriptionVariables>;\n\nexport type PUBLISH_STATUS_SUBSCRIPTION = typeof PUBLISH_STATUS_SUBSCRIPTION;\n\nexport const CREATE_MODEL_MUTATION = sprint(/* GraphQL */ `\n mutation createModel($path: String!, $fields: [CreateModelFieldsInput!]) {\n createModel(path: $path, fields: $fields) {\n remoteFilesVersion\n changed {\n path\n mode\n content\n encoding\n }\n }\n }\n`) as GraphQLMutation<CreateModelMutation, CreateModelMutationVariables>;\n\nexport type CREATE_MODEL_MUTATION = typeof CREATE_MODEL_MUTATION;\n\nexport const CREATE_ACTION_MUTATION = sprint(/* GraphQL */ `\n mutation createAction($path: String!) {\n createAction(path: $path) {\n remoteFilesVersion\n changed {\n path\n mode\n content\n encoding\n }\n }\n }\n`) as GraphQLMutation<CreateActionMutation, CreateActionMutationVariables>;\n\nexport type CREATE_ACTION_MUTATION = typeof CREATE_ACTION_MUTATION;\n\nexport const CREATE_ROUTE_MUTATION = sprint(/* GraphQL */ `\n mutation createRoute($method: String!, $path: String!) {\n createRoute(method: $method, path: $path) {\n remoteFilesVersion\n changed {\n path\n mode\n content\n encoding\n }\n }\n }\n`) as GraphQLMutation<CreateRouteMutation, CreateRouteMutationVariables>;\n\nexport type CREATE_ROUTE_MUTATION = typeof CREATE_ROUTE_MUTATION;\n\nexport const CREATE_MODEL_FIELDS_MUTATION = sprint(/* GraphQL */ `\n mutation createModelFields($path: String!, $fields: [CreateModelFieldsInput!]!) {\n createModelFields(path: $path, fields: $fields) {\n remoteFilesVersion\n changed {\n path\n mode\n content\n encoding\n }\n }\n }\n`) as GraphQLMutation<CreateModelFieldsMutation, CreateModelMutationVariables>;\n\nexport type CREATE_MODEL_FIELDS_MUTATION = typeof CREATE_MODEL_FIELDS_MUTATION;\n"],"names":["sprint","REMOTE_FILE_SYNC_EVENTS_SUBSCRIPTION","REMOTE_FILES_VERSION_QUERY","PUBLISH_FILE_SYNC_EVENTS_MUTATION","FILE_SYNC_FILES_QUERY","FILE_SYNC_HASHES_QUERY","FILE_SYNC_COMPARISON_HASHES_QUERY","PUBLISH_STATUS_SUBSCRIPTION","CREATE_MODEL_MUTATION","CREATE_ACTION_MUTATION","CREATE_ROUTE_MUTATION","CREATE_MODEL_FIELDS_MUTATION"],"rangeMappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;","mappings":"AAyBA,SAASA,MAAM,QAAQ,yBAAyB;AAwDhD,OAAO,MAAMC,uCAAuCD,OAAO,WAAW,GAAG,CAAC;;;;;;;;;;;;;;;AAe1E,CAAC,EAAsG;AAIvG,OAAO,MAAME,6BAA6BF,OAAO,WAAW,GAAG,CAAC;;;;AAIhE,CAAC,EAA6E;AAI9E,OAAO,MAAMG,oCAAoCH,OAAO,WAAW,GAAG,CAAC;;;;;;;;;;;;AAYvE,CAAC,EAA4F;AAI7F,OAAO,MAAMI,wBAAwBJ,OAAO,WAAW,GAAG,CAAC;;;;;;;;;;;;AAY3D,CAAC,EAAmE;AAIpE,OAAO,MAAMK,yBAAyBL,OAAO,WAAW,GAAG,CAAC;;;;;;;AAO5D,CAAC,EAAqE;AAItE,OAAO,MAAMM,oCAAoCN,OAAO,WAAW,GAAG,CAAC;;;;;;;;;;;;;AAavE,CAAC,EAAyF;AAI1F,OAAO,MAAMO,8BAA8BP,OAAO,WAAW,GAAG,CAAC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AA8BjE,CAAC,EAAwF;AAIzF,OAAO,MAAMQ,wBAAwBR,OAAO,WAAW,GAAG,CAAC;;;;;;;;;;;;AAY3D,CAAC,EAAwE;AAIzE,OAAO,MAAMS,yBAAyBT,OAAO,WAAW,GAAG,CAAC;;;;;;;;;;;;AAY5D,CAAC,EAA0E;AAI3E,OAAO,MAAMU,wBAAwBV,OAAO,WAAW,GAAG,CAAC;;;;;;;;;;;;AAY3D,CAAC,EAAwE;AAIzE,OAAO,MAAMW,+BAA+BX,OAAO,WAAW,GAAG,CAAC;;;;;;;;;;;;AAYlE,CAAC,EAA8E"}
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../src/services/app/error.ts"],"sourcesContent":["import type { GraphQLError } from \"graphql\";\nimport assert from \"node:assert\";\nimport pluralize from \"pluralize\";\nimport type { CloseEvent, ErrorEvent } from \"ws\";\nimport { GGTError, IsBug } from \"../output/report.js\";\nimport { sprint } from \"../output/sprint.js\";\nimport { uniq } from \"../util/collection.js\";\nimport { isCloseEvent, isError, isErrorEvent, isGraphQLErrors, isString } from \"../util/is.js\";\nimport { serializeError } from \"../util/object.js\";\nimport type { GraphQLMutation, GraphQLQuery, GraphQLSubscription } from \"./edit/operation.js\";\n\nexport class ClientError extends GGTError {\n isBug = IsBug.MAYBE;\n\n override cause: string | Error | readonly GraphQLError[] | CloseEvent | ErrorEvent;\n\n constructor(\n readonly request: GraphQLQuery | GraphQLMutation | GraphQLSubscription,\n cause: unknown,\n ) {\n super(\"An error occurred while communicating with Gadget\");\n\n // ErrorEvent and CloseEvent aren't serializable, so we reconstruct\n // them into an object. We discard the `target` property because\n // it's large and not that useful\n if (isErrorEvent(cause)) {\n this.cause = {\n type: cause.type,\n message: cause.message,\n error: serializeError(cause.error),\n } as ErrorEvent;\n } else if (isCloseEvent(cause)) {\n this.cause = {\n type: cause.type,\n code: cause.code,\n reason: cause.reason,\n wasClean: cause.wasClean,\n } as CloseEvent;\n } else {\n assert(\n isString(cause) || isError(cause) || isGraphQLErrors(cause),\n \"cause must be a string, Error, GraphQLError[], CloseEvent, or ErrorEvent\",\n );\n this.cause = cause;\n }\n }\n\n override render(): string {\n let body = \"\";\n\n switch (true) {\n case isGraphQLErrors(this.cause): {\n const errors = uniq(this.cause.map((x) => x.message));\n body = sprint`\n Gadget responded with the following ${pluralize(\"error\", errors.length, false)}:\n\n • ${errors.join(\"\\n • \")}\n `;\n break;\n }\n case isCloseEvent(this.cause):\n body = \"The connection to Gadget closed unexpectedly.\";\n break;\n case isErrorEvent(this.cause) || isError(this.cause):\n body = this.cause.message;\n break;\n default:\n body = this.cause;\n break;\n }\n\n return this.message + \"\\n\\n\" + body;\n }\n}\n"],"names":["assert","pluralize","GGTError","IsBug","sprint","uniq","isCloseEvent","isError","isErrorEvent","isGraphQLErrors","isString","serializeError","ClientError","render","body","cause","errors","map","x","message","length","join","constructor","request","isBug","MAYBE","type","error","code","reason","wasClean"],"mappings":";AACA,OAAOA,YAAY,cAAc;AACjC,OAAOC,eAAe,YAAY;AAElC,SAASC,QAAQ,EAAEC,KAAK,QAAQ,sBAAsB;AACtD,SAASC,MAAM,QAAQ,sBAAsB;AAC7C,SAASC,IAAI,QAAQ,wBAAwB;AAC7C,SAASC,YAAY,EAAEC,OAAO,EAAEC,YAAY,EAAEC,eAAe,EAAEC,QAAQ,QAAQ,gBAAgB;AAC/F,SAASC,cAAc,QAAQ,oBAAoB;AAGnD,OAAO,MAAMC,oBAAoBV;IAoCtBW,SAAiB;QACxB,IAAIC,OAAO;QAEX,OAAQ;YACN,KAAKL,gBAAgB,IAAI,CAACM,KAAK;gBAAG;oBAChC,MAAMC,SAASX,KAAK,IAAI,CAACU,KAAK,CAACE,GAAG,CAAC,CAACC,IAAMA,EAAEC,OAAO;oBACnDL,OAAOV,MAAM,CAAC;8CACwB,EAAEH,UAAU,SAASe,OAAOI,MAAM,EAAE,OAAO;;cAE3E,EAAEJ,OAAOK,IAAI,CAAC,oBAAoB;QACxC,CAAC;oBACD;gBACF;YACA,KAAKf,aAAa,IAAI,CAACS,KAAK;gBAC1BD,OAAO;gBACP;YACF,KAAKN,aAAa,IAAI,CAACO,KAAK,KAAKR,QAAQ,IAAI,CAACQ,KAAK;gBACjDD,OAAO,IAAI,CAACC,KAAK,CAACI,OAAO;gBACzB;YACF;gBACEL,OAAO,IAAI,CAACC,KAAK;gBACjB;QACJ;QAEA,OAAO,IAAI,CAACI,OAAO,GAAG,SAASL;IACjC;IAxDAQ,YACE,AAASC,OAA6D,EACtER,KAAc,CACd;QACA,KAAK,CAAC;;QARRS,uBAAAA,SAAAA,KAAAA;QAEA,uBAAST,SAAT,KAAA;aAGWQ,UAAAA;aALXC,QAAQrB,MAAMsB,KAAK;QAUjB,mEAAmE;QACnE,gEAAgE;QAChE,iCAAiC;QACjC,IAAIjB,aAAaO,QAAQ;YACvB,IAAI,CAACA,KAAK,GAAG;gBACXW,MAAMX,MAAMW,IAAI;gBAChBP,SAASJ,MAAMI,OAAO;gBACtBQ,OAAOhB,eAAeI,MAAMY,KAAK;YACnC;QACF,OAAO,IAAIrB,aAAaS,QAAQ;YAC9B,IAAI,CAACA,KAAK,GAAG;gBACXW,MAAMX,MAAMW,IAAI;gBAChBE,MAAMb,MAAMa,IAAI;gBAChBC,QAAQd,MAAMc,MAAM;gBACpBC,UAAUf,MAAMe,QAAQ;YAC1B;QACF,OAAO;YACL9B,OACEU,SAASK,UAAUR,QAAQQ,UAAUN,gBAAgBM,QACrD;YAEF,IAAI,CAACA,KAAK,GAAGA;QACf;IACF;AA4BF"}
1
+ {"version":3,"sources":["../../../src/services/app/error.ts"],"sourcesContent":["import type { GraphQLError } from \"graphql\";\nimport assert from \"node:assert\";\nimport pluralize from \"pluralize\";\nimport type { CloseEvent, ErrorEvent } from \"ws\";\nimport { GGTError, IsBug } from \"../output/report.js\";\nimport { sprint } from \"../output/sprint.js\";\nimport { uniq } from \"../util/collection.js\";\nimport { isCloseEvent, isError, isErrorEvent, isGraphQLErrors, isString } from \"../util/is.js\";\nimport { serializeError } from \"../util/object.js\";\nimport type { GraphQLMutation, GraphQLQuery, GraphQLSubscription } from \"./edit/operation.js\";\n\nexport class ClientError extends GGTError {\n isBug = IsBug.MAYBE;\n\n override cause: string | Error | readonly GraphQLError[] | CloseEvent | ErrorEvent;\n\n constructor(\n readonly request: GraphQLQuery | GraphQLMutation | GraphQLSubscription,\n cause: unknown,\n ) {\n super(\"An error occurred while communicating with Gadget\");\n\n // ErrorEvent and CloseEvent aren't serializable, so we reconstruct\n // them into an object. We discard the `target` property because\n // it's large and not that useful\n if (isErrorEvent(cause)) {\n this.cause = {\n type: cause.type,\n message: cause.message,\n error: serializeError(cause.error),\n } as ErrorEvent;\n } else if (isCloseEvent(cause)) {\n this.cause = {\n type: cause.type,\n code: cause.code,\n reason: cause.reason,\n wasClean: cause.wasClean,\n } as CloseEvent;\n } else {\n assert(\n isString(cause) || isError(cause) || isGraphQLErrors(cause),\n \"cause must be a string, Error, GraphQLError[], CloseEvent, or ErrorEvent\",\n );\n this.cause = cause;\n }\n }\n\n override render(): string {\n let body = \"\";\n\n switch (true) {\n case isGraphQLErrors(this.cause): {\n const errors = uniq(this.cause.map((x) => x.message));\n body = sprint`\n Gadget responded with the following ${pluralize(\"error\", errors.length, false)}:\n\n • ${errors.join(\"\\n • \")}\n `;\n break;\n }\n case isCloseEvent(this.cause):\n body = \"The connection to Gadget closed unexpectedly.\";\n break;\n case isErrorEvent(this.cause) || isError(this.cause):\n body = this.cause.message;\n break;\n default:\n body = this.cause;\n break;\n }\n\n return this.message + \"\\n\\n\" + body;\n }\n}\n"],"names":["assert","pluralize","GGTError","IsBug","sprint","uniq","isCloseEvent","isError","isErrorEvent","isGraphQLErrors","isString","serializeError","ClientError","render","body","cause","errors","map","x","message","length","join","constructor","request","isBug","MAYBE","type","error","code","reason","wasClean"],"rangeMappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;","mappings":";AACA,OAAOA,YAAY,cAAc;AACjC,OAAOC,eAAe,YAAY;AAElC,SAASC,QAAQ,EAAEC,KAAK,QAAQ,sBAAsB;AACtD,SAASC,MAAM,QAAQ,sBAAsB;AAC7C,SAASC,IAAI,QAAQ,wBAAwB;AAC7C,SAASC,YAAY,EAAEC,OAAO,EAAEC,YAAY,EAAEC,eAAe,EAAEC,QAAQ,QAAQ,gBAAgB;AAC/F,SAASC,cAAc,QAAQ,oBAAoB;AAGnD,OAAO,MAAMC,oBAAoBV;IAoCtBW,SAAiB;QACxB,IAAIC,OAAO;QAEX,OAAQ;YACN,KAAKL,gBAAgB,IAAI,CAACM,KAAK;gBAAG;oBAChC,MAAMC,SAASX,KAAK,IAAI,CAACU,KAAK,CAACE,GAAG,CAAC,CAACC,IAAMA,EAAEC,OAAO;oBACnDL,OAAOV,MAAM,CAAC;8CACwB,EAAEH,UAAU,SAASe,OAAOI,MAAM,EAAE,OAAO;;cAE3E,EAAEJ,OAAOK,IAAI,CAAC,oBAAoB;QACxC,CAAC;oBACD;gBACF;YACA,KAAKf,aAAa,IAAI,CAACS,KAAK;gBAC1BD,OAAO;gBACP;YACF,KAAKN,aAAa,IAAI,CAACO,KAAK,KAAKR,QAAQ,IAAI,CAACQ,KAAK;gBACjDD,OAAO,IAAI,CAACC,KAAK,CAACI,OAAO;gBACzB;YACF;gBACEL,OAAO,IAAI,CAACC,KAAK;gBACjB;QACJ;QAEA,OAAO,IAAI,CAACI,OAAO,GAAG,SAASL;IACjC;IAxDAQ,YACE,AAASC,OAA6D,EACtER,KAAc,CACd;QACA,KAAK,CAAC;;QARRS,uBAAAA,SAAAA,KAAAA;QAEA,uBAAST,SAAT,KAAA;aAGWQ,UAAAA;aALXC,QAAQrB,MAAMsB,KAAK;QAUjB,mEAAmE;QACnE,gEAAgE;QAChE,iCAAiC;QACjC,IAAIjB,aAAaO,QAAQ;YACvB,IAAI,CAACA,KAAK,GAAG;gBACXW,MAAMX,MAAMW,IAAI;gBAChBP,SAASJ,MAAMI,OAAO;gBACtBQ,OAAOhB,eAAeI,MAAMY,KAAK;YACnC;QACF,OAAO,IAAIrB,aAAaS,QAAQ;YAC9B,IAAI,CAACA,KAAK,GAAG;gBACXW,MAAMX,MAAMW,IAAI;gBAChBE,MAAMb,MAAMa,IAAI;gBAChBC,QAAQd,MAAMc,MAAM;gBACpBC,UAAUf,MAAMe,QAAQ;YAC1B;QACF,OAAO;YACL9B,OACEU,SAASK,UAAUR,QAAQQ,UAAUN,gBAAgBM,QACrD;YAEF,IAAI,CAACA,KAAK,GAAGA;QACf;IACF;AA4BF"}
@@ -1,6 +1,8 @@
1
1
  import { _ as _define_property } from "@swc/helpers/_/_define_property";
2
2
  import arg from "arg";
3
+ import chalk from "chalk";
3
4
  import { GGTError, IsBug, UnexpectedError } from "../output/report.js";
5
+ import { symbol } from "../output/symbols.js";
4
6
  import { isNil } from "../util/is.js";
5
7
  export const parseArgs = (args, options)=>{
6
8
  const spec = {};
@@ -42,7 +44,7 @@ export const parseArgs = (args, options)=>{
42
44
  };
43
45
  export class ArgError extends GGTError {
44
46
  render() {
45
- return this.message;
47
+ return `${chalk.redBright(symbol.cross)} ` + this.message;
46
48
  }
47
49
  constructor(...args){
48
50
  super(...args);
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../src/services/command/arg.ts"],"sourcesContent":["import arg from \"arg\";\nimport type { Simplify } from \"type-fest\";\nimport { GGTError, IsBug, UnexpectedError } from \"../output/report.js\";\nimport { isNil } from \"../util/is.js\";\n\nexport type ArgsDefinition = Record<string, ArgDefinition>;\n\ntype ArgDefinition<Handler extends arg.Handler = arg.Handler> =\n | Handler\n | {\n type: Handler;\n alias?: string | string[];\n default?: ReturnType<Handler>;\n };\n\nexport type ParseArgsOptions = {\n /**\n * A list of arguments to parse.\n */\n argv?: string[];\n\n /**\n * When permissive set to `true`, arg will push any unknown arguments\n * onto the \"extra\" argument array (`ctx.args._`) instead of throwing\n * an error about an unknown flag.\n *\n * @default false\n */\n permissive?: boolean;\n\n /**\n * When stopAtPositional is set to true, context will stop parsing at\n * the first positional argument.\n *\n * @default false\n */\n stopAtPositional?: boolean;\n};\n\nexport const parseArgs = <Args extends ArgsDefinition>(args: Args, options?: arg.Options): ArgsDefinitionResult<Args> => {\n const spec: arg.Spec = {};\n const defaultValues: Record<string, unknown> = {};\n\n for (const [key, value] of Object.entries(args)) {\n if (!(\"type\" in value)) {\n spec[key] = value;\n continue;\n }\n\n spec[key] = value.type;\n defaultValues[key] = value.default;\n\n if (value.alias) {\n for (const alias of Array.isArray(value.alias) ? value.alias : [value.alias]) {\n spec[alias] = key;\n }\n }\n }\n\n try {\n const parsed = arg(spec, options);\n for (const [key, value] of Object.entries(defaultValues)) {\n if (isNil(parsed[key])) {\n parsed[key] = value as never;\n }\n }\n return parsed as ArgsDefinitionResult<Args>;\n } catch (error: unknown) {\n if (error instanceof arg.ArgError) {\n // convert arg.ArgError to GGTError\n // eslint-disable-next-line no-ex-assign\n error = new ArgError(error.message);\n }\n if (error instanceof GGTError) {\n throw error;\n }\n throw new UnexpectedError(error);\n }\n};\n\nexport class ArgError extends GGTError {\n isBug = IsBug.NO;\n\n protected override render(): string {\n return this.message;\n }\n}\n\n/**\n * Turns this:\n * ```ts\n * type Args = {\n * \"--string\": { type: String; alias: \"s\" };\n * \"--number\": { type: Number; default: 42 };\n * };\n * ```\n *\n * Into this:\n * ```ts\n * type Result = {\n * \"--string\": string | undefined;\n * \"--number\": number;\n * };\n * ```\n */\nexport type ArgsDefinitionResult<Args extends ArgsDefinition, Keys extends keyof Args = keyof Args> = Simplify<{\n [Key in Keys]: Args[Key] extends ArgDefinition<infer Handler>\n ? Args[Key] extends { default: unknown }\n ? NonNullable<ReturnType<Handler>>\n : ReturnType<Handler> | undefined\n : never;\n}> & { _: string[] };\n"],"names":["arg","GGTError","IsBug","UnexpectedError","isNil","parseArgs","args","options","spec","defaultValues","key","value","Object","entries","type","default","alias","Array","isArray","parsed","error","ArgError","message","render","isBug","NO"],"mappings":";AAAA,OAAOA,SAAS,MAAM;AAEtB,SAASC,QAAQ,EAAEC,KAAK,EAAEC,eAAe,QAAQ,sBAAsB;AACvE,SAASC,KAAK,QAAQ,gBAAgB;AAoCtC,OAAO,MAAMC,YAAY,CAA8BC,MAAYC;IACjE,MAAMC,OAAiB,CAAC;IACxB,MAAMC,gBAAyC,CAAC;IAEhD,KAAK,MAAM,CAACC,KAAKC,MAAM,IAAIC,OAAOC,OAAO,CAACP,MAAO;QAC/C,IAAI,CAAE,CAAA,UAAUK,KAAI,GAAI;YACtBH,IAAI,CAACE,IAAI,GAAGC;YACZ;QACF;QAEAH,IAAI,CAACE,IAAI,GAAGC,MAAMG,IAAI;QACtBL,aAAa,CAACC,IAAI,GAAGC,MAAMI,OAAO;QAElC,IAAIJ,MAAMK,KAAK,EAAE;YACf,KAAK,MAAMA,SAASC,MAAMC,OAAO,CAACP,MAAMK,KAAK,IAAIL,MAAMK,KAAK,GAAG;gBAACL,MAAMK,KAAK;aAAC,CAAE;gBAC5ER,IAAI,CAACQ,MAAM,GAAGN;YAChB;QACF;IACF;IAEA,IAAI;QACF,MAAMS,SAASnB,IAAIQ,MAAMD;QACzB,KAAK,MAAM,CAACG,KAAKC,MAAM,IAAIC,OAAOC,OAAO,CAACJ,eAAgB;YACxD,IAAIL,MAAMe,MAAM,CAACT,IAAI,GAAG;gBACtBS,MAAM,CAACT,IAAI,GAAGC;YAChB;QACF;QACA,OAAOQ;IACT,EAAE,OAAOC,OAAgB;QACvB,IAAIA,iBAAiBpB,IAAIqB,QAAQ,EAAE;YACjC,mCAAmC;YACnC,wCAAwC;YACxCD,QAAQ,IAAIC,SAASD,MAAME,OAAO;QACpC;QACA,IAAIF,iBAAiBnB,UAAU;YAC7B,MAAMmB;QACR;QACA,MAAM,IAAIjB,gBAAgBiB;IAC5B;AACF,EAAE;AAEF,OAAO,MAAMC,iBAAiBpB;IAGTsB,SAAiB;QAClC,OAAO,IAAI,CAACD,OAAO;IACrB;;;QAJAE,uBAAAA,SAAQtB,MAAMuB,EAAE;;AAKlB"}
1
+ {"version":3,"sources":["../../../src/services/command/arg.ts"],"sourcesContent":["import arg from \"arg\";\nimport chalk from \"chalk\";\nimport type { Simplify } from \"type-fest\";\nimport { GGTError, IsBug, UnexpectedError } from \"../output/report.js\";\nimport { symbol } from \"../output/symbols.js\";\nimport { isNil } from \"../util/is.js\";\n\nexport type ArgsDefinition = Record<string, ArgDefinition>;\n\ntype ArgDefinition<Handler extends arg.Handler = arg.Handler> =\n | Handler\n | {\n type: Handler;\n alias?: string | string[];\n default?: ReturnType<Handler>;\n };\n\nexport type ParseArgsOptions = {\n /**\n * A list of arguments to parse.\n */\n argv?: string[];\n\n /**\n * When permissive set to `true`, arg will push any unknown arguments\n * onto the \"extra\" argument array (`ctx.args._`) instead of throwing\n * an error about an unknown flag.\n *\n * @default false\n */\n permissive?: boolean;\n\n /**\n * When stopAtPositional is set to true, context will stop parsing at\n * the first positional argument.\n *\n * @default false\n */\n stopAtPositional?: boolean;\n};\n\nexport const parseArgs = <Args extends ArgsDefinition>(args: Args, options?: arg.Options): ArgsDefinitionResult<Args> => {\n const spec: arg.Spec = {};\n const defaultValues: Record<string, unknown> = {};\n\n for (const [key, value] of Object.entries(args)) {\n if (!(\"type\" in value)) {\n spec[key] = value;\n continue;\n }\n\n spec[key] = value.type;\n defaultValues[key] = value.default;\n\n if (value.alias) {\n for (const alias of Array.isArray(value.alias) ? value.alias : [value.alias]) {\n spec[alias] = key;\n }\n }\n }\n\n try {\n const parsed = arg(spec, options);\n for (const [key, value] of Object.entries(defaultValues)) {\n if (isNil(parsed[key])) {\n parsed[key] = value as never;\n }\n }\n return parsed as ArgsDefinitionResult<Args>;\n } catch (error: unknown) {\n if (error instanceof arg.ArgError) {\n // convert arg.ArgError to GGTError\n // eslint-disable-next-line no-ex-assign\n error = new ArgError(error.message);\n }\n if (error instanceof GGTError) {\n throw error;\n }\n throw new UnexpectedError(error);\n }\n};\n\nexport class ArgError extends GGTError {\n isBug = IsBug.NO;\n\n protected override render(): string {\n return `${chalk.redBright(symbol.cross)} ` + this.message;\n }\n}\n\n/**\n * Turns this:\n * ```ts\n * type Args = {\n * \"--string\": { type: String; alias: \"s\" };\n * \"--number\": { type: Number; default: 42 };\n * };\n * ```\n *\n * Into this:\n * ```ts\n * type Result = {\n * \"--string\": string | undefined;\n * \"--number\": number;\n * };\n * ```\n */\nexport type ArgsDefinitionResult<Args extends ArgsDefinition, Keys extends keyof Args = keyof Args> = Simplify<{\n [Key in Keys]: Args[Key] extends ArgDefinition<infer Handler>\n ? Args[Key] extends { default: unknown }\n ? NonNullable<ReturnType<Handler>>\n : ReturnType<Handler> | undefined\n : never;\n}> & { _: string[] };\n"],"names":["arg","chalk","GGTError","IsBug","UnexpectedError","symbol","isNil","parseArgs","args","options","spec","defaultValues","key","value","Object","entries","type","default","alias","Array","isArray","parsed","error","ArgError","message","render","redBright","cross","isBug","NO"],"rangeMappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;","mappings":";AAAA,OAAOA,SAAS,MAAM;AACtB,OAAOC,WAAW,QAAQ;AAE1B,SAASC,QAAQ,EAAEC,KAAK,EAAEC,eAAe,QAAQ,sBAAsB;AACvE,SAASC,MAAM,QAAQ,uBAAuB;AAC9C,SAASC,KAAK,QAAQ,gBAAgB;AAoCtC,OAAO,MAAMC,YAAY,CAA8BC,MAAYC;IACjE,MAAMC,OAAiB,CAAC;IACxB,MAAMC,gBAAyC,CAAC;IAEhD,KAAK,MAAM,CAACC,KAAKC,MAAM,IAAIC,OAAOC,OAAO,CAACP,MAAO;QAC/C,IAAI,CAAE,CAAA,UAAUK,KAAI,GAAI;YACtBH,IAAI,CAACE,IAAI,GAAGC;YACZ;QACF;QAEAH,IAAI,CAACE,IAAI,GAAGC,MAAMG,IAAI;QACtBL,aAAa,CAACC,IAAI,GAAGC,MAAMI,OAAO;QAElC,IAAIJ,MAAMK,KAAK,EAAE;YACf,KAAK,MAAMA,SAASC,MAAMC,OAAO,CAACP,MAAMK,KAAK,IAAIL,MAAMK,KAAK,GAAG;gBAACL,MAAMK,KAAK;aAAC,CAAE;gBAC5ER,IAAI,CAACQ,MAAM,GAAGN;YAChB;QACF;IACF;IAEA,IAAI;QACF,MAAMS,SAASrB,IAAIU,MAAMD;QACzB,KAAK,MAAM,CAACG,KAAKC,MAAM,IAAIC,OAAOC,OAAO,CAACJ,eAAgB;YACxD,IAAIL,MAAMe,MAAM,CAACT,IAAI,GAAG;gBACtBS,MAAM,CAACT,IAAI,GAAGC;YAChB;QACF;QACA,OAAOQ;IACT,EAAE,OAAOC,OAAgB;QACvB,IAAIA,iBAAiBtB,IAAIuB,QAAQ,EAAE;YACjC,mCAAmC;YACnC,wCAAwC;YACxCD,QAAQ,IAAIC,SAASD,MAAME,OAAO;QACpC;QACA,IAAIF,iBAAiBpB,UAAU;YAC7B,MAAMoB;QACR;QACA,MAAM,IAAIlB,gBAAgBkB;IAC5B;AACF,EAAE;AAEF,OAAO,MAAMC,iBAAiBrB;IAGTuB,SAAiB;QAClC,OAAO,CAAC,EAAExB,MAAMyB,SAAS,CAACrB,OAAOsB,KAAK,EAAE,CAAC,CAAC,GAAG,IAAI,CAACH,OAAO;IAC3D;;;QAJAI,uBAAAA,SAAQzB,MAAM0B,EAAE;;AAKlB"}
@@ -13,6 +13,7 @@ import { relativeToThisFile } from "../util/paths.js";
13
13
  "status",
14
14
  "push",
15
15
  "pull",
16
+ "add",
16
17
  "open",
17
18
  "list",
18
19
  "login",
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../src/services/command/command.ts"],"sourcesContent":["import assert from \"node:assert\";\nimport { pathToFileURL } from \"node:url\";\nimport type { EmptyObject, Promisable } from \"type-fest\";\nimport type { RootArgs } from \"../../commands/root.js\";\nimport { config } from \"../config/config.js\";\nimport { relativeToThisFile } from \"../util/paths.js\";\nimport type { ArgsDefinition } from \"./arg.js\";\nimport type { Context } from \"./context.js\";\n\n/**\n * The list of available commands.\n *\n * 1. Every command corresponds to a file inside of src/commands/\n * 2. The order determines the order of commands in the README\n */\nexport const Commands = [\"dev\", \"deploy\", \"status\", \"push\", \"pull\", \"open\", \"list\", \"login\", \"logout\", \"whoami\", \"version\"] as const;\n\n/**\n * One of the commands in {@link Commands}.\n */\nexport type AvailableCommand = (typeof Commands)[number];\n\n/**\n * Checks if a string is a valid command.\n *\n * @param command - The string to check\n * @returns Whether the string is a valid command\n */\nexport const isAvailableCommand = (command: string): command is AvailableCommand => {\n return Commands.includes(command as AvailableCommand);\n};\n\n/**\n * A command module is a file in the src/commands/ directory.\n */\nexport type CommandModule<Args extends ArgsDefinition = EmptyObject, ParentArgs extends ArgsDefinition = RootArgs> = {\n /**\n * The command's {@link ArgsDefinition args}.\n */\n args?: Args;\n\n /**\n * The command's {@link Usage usage}.\n */\n usage: Usage;\n\n /**\n * The command's {@link Command command}.\n *\n * TODO: rename this to `run`.\n */\n command: Command<Args, ParentArgs>;\n};\n\n/**\n * A {@linkcode Command command}'s usage is a function that returns a\n * string describing how to use the command. The function receives its\n * parent command's context.\n */\nexport type Usage = (ctx: Context) => string;\n\n/**\n * The function that is run when the command is called.\n *\n * @param ctx - A {@linkcode Context} with the command's {@linkcode Args} and {@linkcode ParentArgs}.\n */\nexport type Command<Args extends ArgsDefinition = EmptyObject, ParentArgs extends ArgsDefinition = RootArgs> = (\n ctx: Context<Args, ParentArgs>,\n) => Promisable<void>;\n\n/**\n * Imports a command module.\n *\n * @param cmd - The command to import\n * @see {@linkcode CommandModule}\n */\nexport const importCommand = async (cmd: AvailableCommand): Promise<CommandModule> => {\n assert(isAvailableCommand(cmd), `invalid command: ${cmd}`);\n let commandPath = relativeToThisFile(`../../commands/${cmd}.js`);\n if (config.windows) {\n // https://github.com/nodejs/node/issues/31710\n commandPath = pathToFileURL(commandPath).toString();\n }\n return (await import(commandPath)) as CommandModule;\n};\n"],"names":["assert","pathToFileURL","config","relativeToThisFile","Commands","isAvailableCommand","command","includes","importCommand","cmd","commandPath","windows","toString"],"mappings":"AAAA,OAAOA,YAAY,cAAc;AACjC,SAASC,aAAa,QAAQ,WAAW;AAGzC,SAASC,MAAM,QAAQ,sBAAsB;AAC7C,SAASC,kBAAkB,QAAQ,mBAAmB;AAItD;;;;;CAKC,GACD,OAAO,MAAMC,WAAW;IAAC;IAAO;IAAU;IAAU;IAAQ;IAAQ;IAAQ;IAAQ;IAAS;IAAU;IAAU;CAAU,CAAU;AAOrI;;;;;CAKC,GACD,OAAO,MAAMC,qBAAqB,CAACC;IACjC,OAAOF,SAASG,QAAQ,CAACD;AAC3B,EAAE;AAwCF;;;;;CAKC,GACD,OAAO,MAAME,gBAAgB,OAAOC;IAClCT,OAAOK,mBAAmBI,MAAM,CAAC,iBAAiB,EAAEA,IAAI,CAAC;IACzD,IAAIC,cAAcP,mBAAmB,CAAC,eAAe,EAAEM,IAAI,GAAG,CAAC;IAC/D,IAAIP,OAAOS,OAAO,EAAE;QAClB,8CAA8C;QAC9CD,cAAcT,cAAcS,aAAaE,QAAQ;IACnD;IACA,OAAQ,MAAM,MAAM,CAACF;AACvB,EAAE"}
1
+ {"version":3,"sources":["../../../src/services/command/command.ts"],"sourcesContent":["import assert from \"node:assert\";\nimport { pathToFileURL } from \"node:url\";\nimport type { EmptyObject, Promisable } from \"type-fest\";\nimport type { RootArgs } from \"../../commands/root.js\";\nimport { config } from \"../config/config.js\";\nimport { relativeToThisFile } from \"../util/paths.js\";\nimport type { ArgsDefinition } from \"./arg.js\";\nimport type { Context } from \"./context.js\";\n\n/**\n * The list of available commands.\n *\n * 1. Every command corresponds to a file inside of src/commands/\n * 2. The order determines the order of commands in the README\n */\nexport const Commands = [\"dev\", \"deploy\", \"status\", \"push\", \"pull\", \"add\", \"open\", \"list\", \"login\", \"logout\", \"whoami\", \"version\"] as const;\n\n/**\n * One of the commands in {@link Commands}.\n */\nexport type AvailableCommand = (typeof Commands)[number];\n\n/**\n * Checks if a string is a valid command.\n *\n * @param command - The string to check\n * @returns Whether the string is a valid command\n */\nexport const isAvailableCommand = (command: string): command is AvailableCommand => {\n return Commands.includes(command as AvailableCommand);\n};\n\n/**\n * A command module is a file in the src/commands/ directory.\n */\nexport type CommandModule<Args extends ArgsDefinition = EmptyObject, ParentArgs extends ArgsDefinition = RootArgs> = {\n /**\n * The command's {@link ArgsDefinition args}.\n */\n args?: Args;\n\n /**\n * The command's {@link Usage usage}.\n */\n usage: Usage;\n\n /**\n * The command's {@link Command command}.\n *\n * TODO: rename this to `run`.\n */\n command: Command<Args, ParentArgs>;\n};\n\n/**\n * A {@linkcode Command command}'s usage is a function that returns a\n * string describing how to use the command. The function receives its\n * parent command's context.\n */\nexport type Usage = (ctx: Context) => string;\n\n/**\n * The function that is run when the command is called.\n *\n * @param ctx - A {@linkcode Context} with the command's {@linkcode Args} and {@linkcode ParentArgs}.\n */\nexport type Command<Args extends ArgsDefinition = EmptyObject, ParentArgs extends ArgsDefinition = RootArgs> = (\n ctx: Context<Args, ParentArgs>,\n) => Promisable<void>;\n\n/**\n * Imports a command module.\n *\n * @param cmd - The command to import\n * @see {@linkcode CommandModule}\n */\nexport const importCommand = async (cmd: AvailableCommand): Promise<CommandModule> => {\n assert(isAvailableCommand(cmd), `invalid command: ${cmd}`);\n let commandPath = relativeToThisFile(`../../commands/${cmd}.js`);\n if (config.windows) {\n // https://github.com/nodejs/node/issues/31710\n commandPath = pathToFileURL(commandPath).toString();\n }\n return (await import(commandPath)) as CommandModule;\n};\n"],"names":["assert","pathToFileURL","config","relativeToThisFile","Commands","isAvailableCommand","command","includes","importCommand","cmd","commandPath","windows","toString"],"rangeMappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;","mappings":"AAAA,OAAOA,YAAY,cAAc;AACjC,SAASC,aAAa,QAAQ,WAAW;AAGzC,SAASC,MAAM,QAAQ,sBAAsB;AAC7C,SAASC,kBAAkB,QAAQ,mBAAmB;AAItD;;;;;CAKC,GACD,OAAO,MAAMC,WAAW;IAAC;IAAO;IAAU;IAAU;IAAQ;IAAQ;IAAO;IAAQ;IAAQ;IAAS;IAAU;IAAU;CAAU,CAAU;AAO5I;;;;;CAKC,GACD,OAAO,MAAMC,qBAAqB,CAACC;IACjC,OAAOF,SAASG,QAAQ,CAACD;AAC3B,EAAE;AAwCF;;;;;CAKC,GACD,OAAO,MAAME,gBAAgB,OAAOC;IAClCT,OAAOK,mBAAmBI,MAAM,CAAC,iBAAiB,EAAEA,IAAI,CAAC;IACzD,IAAIC,cAAcP,mBAAmB,CAAC,eAAe,EAAEM,IAAI,GAAG,CAAC;IAC/D,IAAIP,OAAOS,OAAO,EAAE;QAClB,8CAA8C;QAC9CD,cAAcT,cAAcS,aAAaE,QAAQ;IACnD;IACA,OAAQ,MAAM,MAAM,CAACF;AACvB,EAAE"}