@gadgetinc/ggt 0.4.9 → 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (142) hide show
  1. package/README.md +165 -93
  2. package/lib/__generated__/graphql.js +66 -1
  3. package/lib/__generated__/graphql.js.map +1 -1
  4. package/lib/commands/deploy.js +329 -184
  5. package/lib/commands/deploy.js.map +1 -1
  6. package/lib/commands/dev.js +445 -0
  7. package/lib/commands/dev.js.map +1 -0
  8. package/lib/commands/list.js +27 -19
  9. package/lib/commands/list.js.map +1 -1
  10. package/lib/commands/login.js +15 -11
  11. package/lib/commands/login.js.map +1 -1
  12. package/lib/commands/logout.js +5 -5
  13. package/lib/commands/logout.js.map +1 -1
  14. package/lib/commands/open.js +200 -0
  15. package/lib/commands/open.js.map +1 -0
  16. package/lib/commands/pull.js +128 -0
  17. package/lib/commands/pull.js.map +1 -0
  18. package/lib/commands/push.js +126 -0
  19. package/lib/commands/push.js.map +1 -0
  20. package/lib/commands/root.js +46 -28
  21. package/lib/commands/root.js.map +1 -1
  22. package/lib/commands/status.js +61 -0
  23. package/lib/commands/status.js.map +1 -0
  24. package/lib/commands/version.js +6 -6
  25. package/lib/commands/version.js.map +1 -1
  26. package/lib/commands/whoami.js +6 -6
  27. package/lib/commands/whoami.js.map +1 -1
  28. package/lib/ggt.js +33 -8
  29. package/lib/ggt.js.map +1 -1
  30. package/lib/main.js +5 -0
  31. package/lib/main.js.map +1 -0
  32. package/lib/services/app/api/api.js +191 -0
  33. package/lib/services/app/api/api.js.map +1 -0
  34. package/lib/services/app/api/operation.js +12 -0
  35. package/lib/services/app/api/operation.js.map +1 -0
  36. package/lib/services/app/app.js +44 -10
  37. package/lib/services/app/app.js.map +1 -1
  38. package/lib/services/app/{edit/client.js → client.js} +29 -19
  39. package/lib/services/app/client.js.map +1 -0
  40. package/lib/services/app/edit/edit.js +67 -31
  41. package/lib/services/app/edit/edit.js.map +1 -1
  42. package/lib/services/app/edit/operation.js +19 -3
  43. package/lib/services/app/edit/operation.js.map +1 -1
  44. package/lib/services/app/{edit/error.js → error.js} +6 -6
  45. package/lib/services/app/error.js.map +1 -0
  46. package/lib/services/command/arg.js +4 -4
  47. package/lib/services/command/arg.js.map +1 -1
  48. package/lib/services/command/command.js +9 -7
  49. package/lib/services/command/command.js.map +1 -1
  50. package/lib/services/command/context.js +82 -20
  51. package/lib/services/command/context.js.map +1 -1
  52. package/lib/services/config/config.js +4 -7
  53. package/lib/services/config/config.js.map +1 -1
  54. package/lib/services/config/env.js +1 -1
  55. package/lib/services/config/env.js.map +1 -1
  56. package/lib/services/filesync/changes.js +76 -37
  57. package/lib/services/filesync/changes.js.map +1 -1
  58. package/lib/services/filesync/conflicts.js +10 -9
  59. package/lib/services/filesync/conflicts.js.map +1 -1
  60. package/lib/services/filesync/directory.js +16 -1
  61. package/lib/services/filesync/directory.js.map +1 -1
  62. package/lib/services/filesync/error.js +96 -27
  63. package/lib/services/filesync/error.js.map +1 -1
  64. package/lib/services/filesync/filesync.js +448 -472
  65. package/lib/services/filesync/filesync.js.map +1 -1
  66. package/lib/services/filesync/hashes.js +8 -5
  67. package/lib/services/filesync/hashes.js.map +1 -1
  68. package/lib/services/filesync/strategy.js +59 -0
  69. package/lib/services/filesync/strategy.js.map +1 -0
  70. package/lib/services/filesync/sync-json.js +475 -0
  71. package/lib/services/filesync/sync-json.js.map +1 -0
  72. package/lib/services/http/auth.js +30 -1
  73. package/lib/services/http/auth.js.map +1 -1
  74. package/lib/services/http/http.js +5 -0
  75. package/lib/services/http/http.js.map +1 -1
  76. package/lib/services/output/confirm.js +149 -0
  77. package/lib/services/output/confirm.js.map +1 -0
  78. package/lib/services/output/footer.js +22 -0
  79. package/lib/services/output/footer.js.map +1 -0
  80. package/lib/services/output/log/format/pretty.js +2 -1
  81. package/lib/services/output/log/format/pretty.js.map +1 -1
  82. package/lib/services/output/log/logger.js +13 -5
  83. package/lib/services/output/log/logger.js.map +1 -1
  84. package/lib/services/output/log/structured.js +2 -2
  85. package/lib/services/output/log/structured.js.map +1 -1
  86. package/lib/services/output/output.js +197 -0
  87. package/lib/services/output/output.js.map +1 -0
  88. package/lib/services/output/print.js +31 -0
  89. package/lib/services/output/print.js.map +1 -0
  90. package/lib/services/output/problems.js +84 -0
  91. package/lib/services/output/problems.js.map +1 -0
  92. package/lib/services/output/prompt.js +173 -40
  93. package/lib/services/output/prompt.js.map +1 -1
  94. package/lib/services/output/report.js +63 -19
  95. package/lib/services/output/report.js.map +1 -1
  96. package/lib/services/output/select.js +198 -0
  97. package/lib/services/output/select.js.map +1 -0
  98. package/lib/services/output/spinner.js +141 -0
  99. package/lib/services/output/spinner.js.map +1 -0
  100. package/lib/services/output/sprint.js +38 -15
  101. package/lib/services/output/sprint.js.map +1 -1
  102. package/lib/services/output/symbols.js +23 -0
  103. package/lib/services/output/symbols.js.map +1 -0
  104. package/lib/services/output/table.js +98 -0
  105. package/lib/services/output/table.js.map +1 -0
  106. package/lib/services/output/timestamp.js +12 -0
  107. package/lib/services/output/timestamp.js.map +1 -0
  108. package/lib/services/output/update.js +29 -9
  109. package/lib/services/output/update.js.map +1 -1
  110. package/lib/services/user/session.js +4 -0
  111. package/lib/services/user/session.js.map +1 -1
  112. package/lib/services/user/user.js +15 -10
  113. package/lib/services/user/user.js.map +1 -1
  114. package/lib/services/util/assert.js +11 -0
  115. package/lib/services/util/assert.js.map +1 -0
  116. package/lib/services/util/boolean.js +2 -2
  117. package/lib/services/util/boolean.js.map +1 -1
  118. package/lib/services/util/function.js +45 -7
  119. package/lib/services/util/function.js.map +1 -1
  120. package/lib/services/util/is.js +23 -2
  121. package/lib/services/util/is.js.map +1 -1
  122. package/lib/services/util/json.js +16 -13
  123. package/lib/services/util/json.js.map +1 -1
  124. package/lib/services/util/object.js +2 -2
  125. package/lib/services/util/object.js.map +1 -1
  126. package/lib/services/util/promise.js +5 -2
  127. package/lib/services/util/promise.js.map +1 -1
  128. package/lib/services/util/types.js.map +1 -1
  129. package/npm-shrinkwrap.json +3436 -2833
  130. package/package.json +47 -40
  131. package/bin/dev.cmd +0 -3
  132. package/bin/dev.js +0 -14
  133. package/bin/run.cmd +0 -3
  134. package/bin/run.js +0 -5
  135. package/lib/commands/sync.js +0 -284
  136. package/lib/commands/sync.js.map +0 -1
  137. package/lib/services/app/edit/client.js.map +0 -1
  138. package/lib/services/app/edit/error.js.map +0 -1
  139. package/lib/services/output/log/printer.js +0 -120
  140. package/lib/services/output/log/printer.js.map +0 -1
  141. package/lib/services/output/stream.js +0 -54
  142. package/lib/services/output/stream.js.map +0 -1
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../src/services/command/arg.ts"],"sourcesContent":["import arg from \"arg\";\nimport type { Simplify } from \"type-fest\";\nimport { CLIError, 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 CLIError\n // eslint-disable-next-line no-ex-assign\n error = new ArgError(error.message);\n }\n if (error instanceof CLIError) {\n throw error;\n }\n throw new UnexpectedError(error);\n }\n};\n\nexport class ArgError extends CLIError {\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","CLIError","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 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"}
@@ -4,20 +4,22 @@ import { config } from "../config/config.js";
4
4
  import { relativeToThisFile } from "../util/paths.js";
5
5
  /**
6
6
  * The list of available commands.
7
- * - Each command is a separate file in src/commands.
8
- * - The order determines the order of commands in the README.
7
+ *
8
+ * 1. Every command corresponds to a file inside of src/commands/
9
+ * 2. The order determines the order of commands in the README
9
10
  */ export const Commands = [
10
- "sync",
11
+ "dev",
12
+ "deploy",
13
+ "status",
14
+ "push",
15
+ "pull",
16
+ "open",
11
17
  "list",
12
18
  "login",
13
19
  "logout",
14
20
  "whoami",
15
21
  "version"
16
22
  ];
17
- // deploy is still in preview
18
- if (process.env["GGT_DEPLOY_PREVIEW"]) {
19
- Commands.push("deploy");
20
- }
21
23
  /**
22
24
  * Checks if a string is a valid command.
23
25
  *
@@ -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 * - Each command is a separate file in src/commands.\n * - The order determines the order of commands in the README.\n */\nexport const Commands = [\"sync\", \"list\", \"login\", \"logout\", \"whoami\", \"version\"] as const;\n\n// deploy is still in preview\nif (process.env[\"GGT_DEPLOY_PREVIEW\"]) {\n (Commands as unknown as string[]).push(\"deploy\");\n}\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}.\n */\n args?: Args;\n\n /**\n * The command's {@link Usage}.\n */\n usage: Usage;\n\n /**\n * The command's {@link Command}.\n */\n command: Command<Args, ParentArgs>;\n};\n\n/**\n * A command's usage is a string that describes how to use the command.\n */\nexport type Usage = () => string;\n\n/**\n * The function that is run when the command is invoked.\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","process","env","push","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;;;;CAIC,GACD,OAAO,MAAMC,WAAW;IAAC;IAAQ;IAAQ;IAAS;IAAU;IAAU;CAAU,CAAU;AAE1F,6BAA6B;AAC7B,IAAIC,QAAQC,GAAG,CAAC,qBAAqB,EAAE;IACpCF,SAAiCG,IAAI,CAAC;AACzC;AAOA;;;;;CAKC,GACD,OAAO,MAAMC,qBAAqB,CAACC;IACjC,OAAOL,SAASM,QAAQ,CAACD;AAC3B,EAAE;AAoCF;;;;;CAKC,GACD,OAAO,MAAME,gBAAgB,OAAOC;IAClCZ,OAAOQ,mBAAmBI,MAAM,CAAC,iBAAiB,EAAEA,IAAI,CAAC;IACzD,IAAIC,cAAcV,mBAAmB,CAAC,eAAe,EAAES,IAAI,GAAG,CAAC;IAC/D,IAAIV,OAAOY,OAAO,EAAE;QAClB,8CAA8C;QAC9CD,cAAcZ,cAAcY,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\", \"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"}
@@ -2,11 +2,25 @@ import { _ as _class_private_field_get } from "@swc/helpers/_/_class_private_fie
2
2
  import { _ as _class_private_field_init } from "@swc/helpers/_/_class_private_field_init";
3
3
  import { _ as _class_private_field_set } from "@swc/helpers/_/_class_private_field_set";
4
4
  import { _ as _define_property } from "@swc/helpers/_/_define_property";
5
- import assert from "node:assert";
6
5
  import { createLogger } from "../output/log/logger.js";
7
6
  import { defaults, pick } from "../util/object.js";
7
+ import { PromiseSignal } from "../util/promise.js";
8
8
  import { parseArgs } from "./arg.js";
9
- var _log = /*#__PURE__*/ new WeakMap(), _parent = /*#__PURE__*/ new WeakMap(), _user = /*#__PURE__*/ new WeakMap(), _app = /*#__PURE__*/ new WeakMap();
9
+ var /**
10
+ * The logger for the current context.
11
+ */ _log = /*#__PURE__*/ new WeakMap(), /**
12
+ * The callbacks that will be called when this context is aborted.
13
+ */ _onAborts = /*#__PURE__*/ new WeakMap(), /**
14
+ * The parent context, if any.
15
+ */ _parent = /*#__PURE__*/ new WeakMap(), /**
16
+ * The command that this context is running.
17
+ */ _command = /*#__PURE__*/ new WeakMap(), /**
18
+ * The user who is running this command, if any.
19
+ */ _user = /*#__PURE__*/ new WeakMap(), /**
20
+ * The app this command is running against, if any.
21
+ */ _app = /*#__PURE__*/ new WeakMap(), /**
22
+ * The environment this command is running against, if any.
23
+ */ _env = /*#__PURE__*/ new WeakMap();
10
24
  /**
11
25
  * Represents the context of a command-line operation.
12
26
  */ export class Context extends AbortController {
@@ -16,6 +30,9 @@ var _log = /*#__PURE__*/ new WeakMap(), _parent = /*#__PURE__*/ new WeakMap(), _
16
30
  */ get log() {
17
31
  return _class_private_field_get(this, _log);
18
32
  }
33
+ get command() {
34
+ return _class_private_field_get(this, _command) ?? _class_private_field_get(this, _parent)?.command ?? "root";
35
+ }
19
36
  get user() {
20
37
  return _class_private_field_get(this, _user) ?? _class_private_field_get(this, _parent)?.user;
21
38
  }
@@ -26,11 +43,12 @@ var _log = /*#__PURE__*/ new WeakMap(), _parent = /*#__PURE__*/ new WeakMap(), _
26
43
  }
27
44
  _class_private_field_set(this, _log, _class_private_field_get(this, _log).child({
28
45
  fields: {
29
- user: pick(user, [
30
- "id",
31
- "name",
32
- "email"
33
- ])
46
+ user: {
47
+ id: user.id
48
+ }
49
+ },
50
+ devFields: {
51
+ user
34
52
  }
35
53
  }));
36
54
  }
@@ -49,6 +67,21 @@ var _log = /*#__PURE__*/ new WeakMap(), _parent = /*#__PURE__*/ new WeakMap(), _
49
67
  }
50
68
  }));
51
69
  }
70
+ // eslint-disable-next-line @typescript-eslint/member-ordering
71
+ get env() {
72
+ return _class_private_field_get(this, _env) ?? _class_private_field_get(this, _parent)?.env;
73
+ }
74
+ set env(env) {
75
+ _class_private_field_set(this, _env, env);
76
+ if (_class_private_field_get(this, _parent)) {
77
+ _class_private_field_get(this, _parent).env = env;
78
+ }
79
+ _class_private_field_set(this, _log, _class_private_field_get(this, _log).child({
80
+ fields: {
81
+ env
82
+ }
83
+ }));
84
+ }
52
85
  /**
53
86
  * Initializes a new context.
54
87
  *
@@ -71,9 +104,10 @@ var _log = /*#__PURE__*/ new WeakMap(), _parent = /*#__PURE__*/ new WeakMap(), _
71
104
  * Returns a new context that is a child of the current context.
72
105
  *
73
106
  * @see {@linkcode ChildContextInit}
74
- */ child({ parse: spec, ...options }) {
107
+ */ child({ parse: spec, command = _class_private_field_get(this, _command), ...options }) {
75
108
  const ctx = new Context({
76
109
  parent: this,
110
+ command,
77
111
  args: {
78
112
  ...this.args,
79
113
  ...options.overwrite,
@@ -100,32 +134,34 @@ var _log = /*#__PURE__*/ new WeakMap(), _parent = /*#__PURE__*/ new WeakMap(), _
100
134
  *
101
135
  * @param callback - The callback to call when the context is aborted.
102
136
  */ onAbort(callback) {
103
- this.signal.addEventListener("abort", // eslint-disable-next-line @typescript-eslint/no-misused-promises
104
- async ()=>{
105
- try {
106
- assert(callback, "callback must have been provided");
107
- await callback(this.signal.reason);
108
- } catch (error) {
109
- this.log.error("error during abort", {
110
- error
111
- });
112
- }
113
- });
137
+ _class_private_field_get(this, _onAborts).push(callback);
114
138
  }
115
- constructor({ args, log, parent }){
139
+ constructor({ parent, command, args, log }){
116
140
  super();
117
141
  /**
118
142
  * The parsed command-line arguments for the current context and any
119
143
  * parent contexts.
120
144
  */ _define_property(this, "args", void 0);
145
+ /**
146
+ * A promise that resolves when the context is aborted and all the
147
+ * registered onAbort callbacks have finished.
148
+ */ _define_property(this, "done", new PromiseSignal());
121
149
  _class_private_field_init(this, _log, {
122
150
  writable: true,
123
151
  value: void 0
124
152
  });
153
+ _class_private_field_init(this, _onAborts, {
154
+ writable: true,
155
+ value: []
156
+ });
125
157
  _class_private_field_init(this, _parent, {
126
158
  writable: true,
127
159
  value: void 0
128
160
  });
161
+ _class_private_field_init(this, _command, {
162
+ writable: true,
163
+ value: void 0
164
+ });
129
165
  _class_private_field_init(this, _user, {
130
166
  writable: true,
131
167
  value: void 0
@@ -134,13 +170,39 @@ var _log = /*#__PURE__*/ new WeakMap(), _parent = /*#__PURE__*/ new WeakMap(), _
134
170
  writable: true,
135
171
  value: void 0
136
172
  });
173
+ _class_private_field_init(this, _env, {
174
+ writable: true,
175
+ value: void 0
176
+ });
137
177
  this.args = args;
138
178
  _class_private_field_set(this, _log, log);
139
179
  _class_private_field_set(this, _parent, parent);
180
+ _class_private_field_set(this, _command, command);
140
181
  // in case this context is ...spread into another object
141
182
  this.abort = this.abort.bind(this);
142
183
  this.child = this.child.bind(this);
143
184
  this.onAbort = this.onAbort.bind(this);
185
+ // when the context is aborted, call all the registered callbacks
186
+ this.signal.addEventListener("abort", // eslint-disable-next-line @typescript-eslint/no-misused-promises
187
+ async ()=>{
188
+ let error;
189
+ // call the callbacks in reverse order, like go's defer
190
+ for (const callback of _class_private_field_get(this, _onAborts).reverse()){
191
+ try {
192
+ await callback(this.signal.reason);
193
+ } catch (e) {
194
+ error = e;
195
+ this.log.error("error during abort", {
196
+ error
197
+ });
198
+ }
199
+ }
200
+ if (error) {
201
+ this.done.reject(error);
202
+ } else {
203
+ this.done.resolve();
204
+ }
205
+ });
144
206
  }
145
207
  }
146
208
 
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../src/services/command/context.ts"],"sourcesContent":["import assert from \"node:assert\";\nimport type { EmptyObject } from \"type-fest\";\nimport type { RootArgs } from \"../../commands/root.js\";\nimport type { App } from \"../app/app.js\";\nimport { createLogger, type Logger } from \"../output/log/logger.js\";\nimport type { StructuredLoggerOptions } from \"../output/log/structured.js\";\nimport type { User } from \"../user/user.js\";\nimport { defaults, pick } from \"../util/object.js\";\nimport type { AnyVoid } from \"../util/types.js\";\nimport { parseArgs, type ArgsDefinition, type ArgsDefinitionResult, type ParseArgsOptions } from \"./arg.js\";\n\n/**\n * Represents the options that can be passed to {@linkcode Context.init}.\n */\nexport type ContextInit<Args extends ArgsDefinition> = ParseArgsOptions &\n StructuredLoggerOptions & {\n /**\n * The {@linkcode ArgsDefinition} to use to parse the arguments (`argv`).\n */\n parse?: Args;\n };\n\n/**\n * Represents the options that can be passed to {@linkcode Context.child}.\n *\n * @see {@linkcode Context.child}\n * @see {@linkcode ContextInit}\n */\nexport type ChildContextInit<Args extends ArgsDefinition, Parsed extends ArgsDefinitionResult<ArgsDefinition>> = Partial<\n ContextInit<Args>\n> & {\n /**\n * Replaces the parsed arguments of the parent context.\n */\n overwrite?: Partial<Omit<Parsed, \"_\">>;\n};\n\n/**\n * Represents the context of a command-line operation.\n */\nexport class Context<\n Args extends ArgsDefinition = EmptyObject,\n ParentArgs extends ArgsDefinition = RootArgs,\n ThisArgs extends ArgsDefinition = ParentArgs & Args,\n> extends AbortController {\n /**\n * The parsed command-line arguments for the current context and any\n * parent contexts.\n */\n readonly args: ArgsDefinitionResult<ThisArgs>;\n\n #log: Logger;\n #parent?: Context<ArgsDefinition, ParentArgs>;\n #user?: User;\n #app?: App;\n\n private constructor({\n args,\n log,\n parent,\n }: {\n parent?: Context<ArgsDefinition, ParentArgs>;\n args: ArgsDefinitionResult<ThisArgs>;\n log: Logger;\n }) {\n super();\n this.args = args;\n this.#log = log;\n this.#parent = parent;\n\n // in case this context is ...spread into another object\n this.abort = this.abort.bind(this);\n this.child = this.child.bind(this);\n this.onAbort = this.onAbort.bind(this);\n }\n\n /**\n * A {@linkcode Logger} that can print to stdout and log structured\n * messages to stderr.\n */\n get log(): Logger {\n return this.#log;\n }\n\n get user(): User | undefined {\n return this.#user ?? this.#parent?.user;\n }\n\n set user(user: User) {\n this.#user = user;\n if (this.#parent) {\n this.#parent.user = user;\n }\n\n this.#log = this.#log.child({ fields: { user: pick(user, [\"id\", \"name\", \"email\"]) } });\n }\n\n // eslint-disable-next-line @typescript-eslint/member-ordering\n get app(): App | undefined {\n return this.#app ?? this.#parent?.app;\n }\n\n set app(app: App) {\n this.#app = app;\n if (this.#parent) {\n this.#parent.app = app;\n }\n\n this.#log = this.#log.child({ fields: { app } });\n }\n\n /**\n * Initializes a new context.\n *\n * @see {@linkcode ContextInit}\n */\n static init<Args extends ArgsDefinition = EmptyObject>({ parse: spec, ...options }: ContextInit<Args>): Context<Args> {\n return new Context({\n args: spec ? parseArgs(spec, pick(options, [\"argv\", \"permissive\", \"stopAtPositional\"])) : ({} as ArgsDefinitionResult<Args>),\n log: createLogger(pick(options, [\"name\", \"fields\", \"devFields\"])),\n });\n }\n\n /**\n * Returns a new context that is a child of the current context.\n *\n * @see {@linkcode ChildContextInit}\n */\n child<ChildArgs extends ArgsDefinition = EmptyObject>({\n parse: spec,\n ...options\n }: ChildContextInit<ChildArgs, ArgsDefinitionResult<ThisArgs>>): Context<ChildArgs, ThisArgs> {\n const ctx = new Context<ChildArgs, ThisArgs>({\n parent: this,\n args: {\n ...this.args,\n ...options.overwrite,\n ...(spec\n ? parseArgs(spec, defaults(pick(options, [\"argv\", \"permissive\", \"stopAtPositional\"]), { argv: this.args._ }))\n : ({} as ArgsDefinitionResult<ChildArgs>)),\n },\n log: this.log.child(pick(options, [\"name\", \"fields\", \"devFields\"])),\n });\n\n this.onAbort(() => ctx.abort());\n\n return ctx;\n }\n\n /**\n * Registers a callback that will be called when the context is\n * aborted (e.g. when the user presses Ctrl+C).\n *\n * @param callback - The callback to call when the context is aborted.\n */\n onAbort(callback: OnAbort): void {\n this.signal.addEventListener(\n \"abort\",\n // eslint-disable-next-line @typescript-eslint/no-misused-promises\n async () => {\n try {\n assert(callback, \"callback must have been provided\");\n await callback(this.signal.reason);\n } catch (error: unknown) {\n this.log.error(\"error during abort\", { error });\n }\n },\n );\n }\n}\n\n/**\n * A callback that will be called when the context is aborted.\n */\nexport type OnAbort = (reason: unknown) => AnyVoid;\n"],"names":["assert","createLogger","defaults","pick","parseArgs","Context","AbortController","log","user","parent","child","fields","app","init","parse","spec","options","args","ctx","overwrite","argv","_","onAbort","abort","callback","signal","addEventListener","reason","error","bind"],"mappings":"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"}
1
+ {"version":3,"sources":["../../../src/services/command/context.ts"],"sourcesContent":["import type { EmptyObject } from \"type-fest\";\nimport type { RootArgs } from \"../../commands/root.js\";\nimport type { Application, Environment } from \"../app/app.js\";\nimport { createLogger, type Logger } from \"../output/log/logger.js\";\nimport type { StructuredLoggerOptions } from \"../output/log/structured.js\";\nimport type { User } from \"../user/user.js\";\nimport { defaults, pick } from \"../util/object.js\";\nimport { PromiseSignal } from \"../util/promise.js\";\nimport type { AnyVoid } from \"../util/types.js\";\nimport { parseArgs, type ArgsDefinition, type ArgsDefinitionResult, type ParseArgsOptions } from \"./arg.js\";\nimport type { AvailableCommand } from \"./command.js\";\n\n/**\n * Represents the options that can be passed to {@linkcode Context.init}.\n */\nexport type ContextInit<Args extends ArgsDefinition> = ParseArgsOptions &\n StructuredLoggerOptions & {\n /**\n * The command that this context is running.\n */\n command?: AvailableCommand;\n\n /**\n * The {@linkcode ArgsDefinition} to use to parse the arguments (`argv`).\n */\n parse?: Args;\n };\n\n/**\n * Represents the options that can be passed to {@linkcode Context.child}.\n *\n * @see {@linkcode Context.child}\n * @see {@linkcode ContextInit}\n */\nexport type ChildContextInit<Args extends ArgsDefinition, Parsed extends ArgsDefinitionResult<ArgsDefinition>> = Partial<\n ContextInit<Args>\n> & {\n /**\n * Replaces the parsed arguments of the parent context.\n */\n overwrite?: Partial<Omit<Parsed, \"_\">>;\n};\n\n/**\n * Represents the context of a command-line operation.\n */\nexport class Context<\n Args extends ArgsDefinition = EmptyObject,\n ParentArgs extends ArgsDefinition = RootArgs,\n ThisArgs extends ArgsDefinition = ParentArgs & Args,\n> extends AbortController {\n /**\n * The parsed command-line arguments for the current context and any\n * parent contexts.\n */\n readonly args: ArgsDefinitionResult<ThisArgs>;\n\n /**\n * A promise that resolves when the context is aborted and all the\n * registered onAbort callbacks have finished.\n */\n readonly done = new PromiseSignal<void>();\n\n /**\n * The logger for the current context.\n */\n #log: Logger;\n\n /**\n * The callbacks that will be called when this context is aborted.\n */\n #onAborts: OnAbort[] = [];\n\n /**\n * The parent context, if any.\n */\n #parent?: Context<ArgsDefinition, ParentArgs>;\n\n /**\n * The command that this context is running.\n */\n #command?: AvailableCommand;\n\n /**\n * The user who is running this command, if any.\n */\n #user?: User;\n\n /**\n * The app this command is running against, if any.\n */\n #app?: Application;\n\n /**\n * The environment this command is running against, if any.\n */\n #env?: Environment;\n\n private constructor({\n parent,\n command,\n args,\n log,\n }: {\n parent?: Context<ArgsDefinition, ParentArgs>;\n command?: AvailableCommand;\n args: ArgsDefinitionResult<ThisArgs>;\n log: Logger;\n }) {\n super();\n this.args = args;\n this.#log = log;\n this.#parent = parent;\n this.#command = command;\n\n // in case this context is ...spread into another object\n this.abort = this.abort.bind(this);\n this.child = this.child.bind(this);\n this.onAbort = this.onAbort.bind(this);\n\n // when the context is aborted, call all the registered callbacks\n this.signal.addEventListener(\n \"abort\",\n // eslint-disable-next-line @typescript-eslint/no-misused-promises\n async () => {\n let error: unknown;\n\n // call the callbacks in reverse order, like go's defer\n for (const callback of this.#onAborts.reverse()) {\n try {\n await callback(this.signal.reason);\n } catch (e: unknown) {\n error = e;\n this.log.error(\"error during abort\", { error });\n }\n }\n\n if (error) {\n this.done.reject(error);\n } else {\n this.done.resolve();\n }\n },\n );\n }\n\n /**\n * A {@linkcode Logger} that can print to stdout and log structured\n * messages to stderr.\n */\n get log(): Logger {\n return this.#log;\n }\n\n get command(): AvailableCommand | \"root\" {\n return this.#command ?? this.#parent?.command ?? \"root\";\n }\n\n get user(): User | undefined {\n return this.#user ?? this.#parent?.user;\n }\n\n set user(user: User) {\n this.#user = user;\n if (this.#parent) {\n this.#parent.user = user;\n }\n\n this.#log = this.#log.child({\n fields: { user: { id: user.id } },\n devFields: { user },\n });\n }\n\n // eslint-disable-next-line @typescript-eslint/member-ordering\n get app(): Application | undefined {\n return this.#app ?? this.#parent?.app;\n }\n\n set app(app: Application) {\n this.#app = app;\n if (this.#parent) {\n this.#parent.app = app;\n }\n\n this.#log = this.#log.child({ fields: { app } });\n }\n\n // eslint-disable-next-line @typescript-eslint/member-ordering\n get env(): Environment | undefined {\n return this.#env ?? this.#parent?.env;\n }\n\n set env(env: Environment) {\n this.#env = env;\n if (this.#parent) {\n this.#parent.env = env;\n }\n\n this.#log = this.#log.child({ fields: { env } });\n }\n\n /**\n * Initializes a new context.\n *\n * @see {@linkcode ContextInit}\n */\n static init<Args extends ArgsDefinition = EmptyObject>({ parse: spec, ...options }: ContextInit<Args>): Context<Args> {\n return new Context({\n args: spec ? parseArgs(spec, pick(options, [\"argv\", \"permissive\", \"stopAtPositional\"])) : ({} as ArgsDefinitionResult<Args>),\n log: createLogger(pick(options, [\"name\", \"fields\", \"devFields\"])),\n });\n }\n\n /**\n * Returns a new context that is a child of the current context.\n *\n * @see {@linkcode ChildContextInit}\n */\n child<ChildArgs extends ArgsDefinition = EmptyObject>({\n parse: spec,\n command = this.#command,\n ...options\n }: ChildContextInit<ChildArgs, ArgsDefinitionResult<ThisArgs>>): Context<ChildArgs, ThisArgs> {\n const ctx = new Context<ChildArgs, ThisArgs>({\n parent: this,\n command,\n args: {\n ...this.args,\n ...options.overwrite,\n ...(spec\n ? parseArgs(spec, defaults(pick(options, [\"argv\", \"permissive\", \"stopAtPositional\"]), { argv: this.args._ }))\n : ({} as ArgsDefinitionResult<ChildArgs>)),\n },\n log: this.log.child(pick(options, [\"name\", \"fields\", \"devFields\"])),\n });\n\n this.onAbort(() => ctx.abort());\n\n return ctx;\n }\n\n /**\n * Registers a callback that will be called when the context is\n * aborted (e.g. when the user presses Ctrl+C).\n *\n * @param callback - The callback to call when the context is aborted.\n */\n onAbort(callback: OnAbort): void {\n this.#onAborts.push(callback);\n }\n}\n\n/**\n * A callback that will be called when the context is aborted.\n */\nexport type OnAbort = (reason: unknown) => AnyVoid;\n"],"names":["createLogger","defaults","pick","PromiseSignal","parseArgs","Context","AbortController","log","command","parent","user","child","fields","id","devFields","app","env","init","parse","spec","options","args","ctx","overwrite","argv","_","onAbort","abort","callback","onAborts","push","done","bind","signal","addEventListener","error","reverse","reason","e","reject","resolve"],"mappings":"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"}
@@ -6,12 +6,6 @@ import { Level, parseLevel } from "../output/log/level.js";
6
6
  import { env } from "./env.js";
7
7
  import { packageJson } from "./package-json.js";
8
8
  export const config = {
9
- get name () {
10
- return packageJson.name;
11
- },
12
- get version () {
13
- return packageJson.version;
14
- },
15
9
  get logLevel () {
16
10
  return parseLevel(process.env["GGT_LOG_LEVEL"], Level.PRINT);
17
11
  },
@@ -25,7 +19,7 @@ export const config = {
25
19
  *
26
20
  * @example "ggt/1.2.3 darwin-arm64 node-v16.0.0"
27
21
  */ get versionFull () {
28
- return `${this.name}/${this.version} ${this.platform}-${this.arch} node-${process.version}`;
22
+ return `${packageJson.name}/${packageJson.version} ${this.platform}-${this.arch} node-${process.version}`;
29
23
  },
30
24
  get arch () {
31
25
  return os.arch() === "ia32" ? "x86" : os.arch();
@@ -36,6 +30,9 @@ export const config = {
36
30
  get windows () {
37
31
  return process.platform === "win32";
38
32
  },
33
+ get windowsOrWsl () {
34
+ return this.windows || isWsl;
35
+ },
39
36
  get macos () {
40
37
  return process.platform === "darwin";
41
38
  },
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../src/services/config/config.ts"],"sourcesContent":["import isWsl from \"is-wsl\";\nimport os from \"node:os\";\nimport path from \"node:path\";\nimport process from \"node:process\";\nimport { Level, parseLevel } from \"../output/log/level.js\";\nimport { env } from \"./env.js\";\nimport { packageJson } from \"./package-json.js\";\n\nexport const config = {\n get name(): string {\n return packageJson.name;\n },\n\n get version(): string {\n return packageJson.version;\n },\n\n get logLevel() {\n return parseLevel(process.env[\"GGT_LOG_LEVEL\"], Level.PRINT);\n },\n\n get logFormat() {\n return process.env[\"GGT_LOG_FORMAT\"] === \"json\" ? \"json\" : \"pretty\";\n },\n\n /**\n * Returns the full version string including name, version, platform,\n * arch, and Node.js version. This is passed as the user agent for all\n * outgoing http requests.\n *\n * @example \"ggt/1.2.3 darwin-arm64 node-v16.0.0\"\n */\n get versionFull(): string {\n return `${this.name}/${this.version} ${this.platform}-${this.arch} node-${process.version}`;\n },\n\n get arch(): string {\n return os.arch() === \"ia32\" ? \"x86\" : os.arch();\n },\n\n get platform(): string {\n return isWsl ? \"wsl\" : os.platform();\n },\n\n get windows(): boolean {\n return process.platform === \"win32\";\n },\n\n get macos(): boolean {\n return process.platform === \"darwin\";\n },\n\n get shell(): string | undefined {\n const SHELL = process.env[\"SHELL\"] ?? os.userInfo().shell?.split(path.sep).pop();\n if (SHELL) {\n return SHELL.split(\"/\").at(-1);\n }\n if (this.windows && process.env[\"COMSPEC\"]) {\n return process.env[\"COMSPEC\"].split(/\\\\|\\//).at(-1);\n }\n return \"unknown\";\n },\n\n get homeDir(): string {\n if (process.env[\"HOME\"]) {\n return process.env[\"HOME\"];\n }\n\n if (this.windows) {\n if (process.env[\"HOMEDRIVE\"] && process.env[\"HOMEPATH\"]) {\n return path.join(process.env[\"HOMEDRIVE\"], process.env[\"HOMEPATH\"]);\n }\n if (process.env[\"USERPROFILE\"]) {\n return process.env[\"USERPROFILE\"];\n }\n }\n\n return os.homedir() || os.tmpdir();\n },\n\n /**\n * - Unix: `~/.config/ggt`\n * - Windows: `%LOCALAPPDATA%\\ggt`\n *\n * Can be overridden by `GGT_CONFIG_DIR`\n */\n get configDir(): string {\n if (process.env[\"GGT_CONFIG_DIR\"]) {\n return process.env[\"GGT_CONFIG_DIR\"];\n }\n\n const base = process.env[\"XDG_CONFIG_HOME\"] || (this.windows && process.env[\"LOCALAPPDATA\"]) || path.join(this.homeDir, \".config\");\n return path.join(base, \"ggt\");\n },\n\n /**\n * - Linux: `~/.cache/ggt`\n * - macOS: `~/Library/Caches/ggt`\n * - Windows: `%LOCALAPPDATA%\\ggt`\n *\n * Can be overridden with `GGT_CACHE_DIR`\n */\n get cacheDir(): string {\n if (process.env[\"GGT_CACHE_DIR\"]) {\n return process.env[\"GGT_CACHE_DIR\"];\n }\n\n if (this.macos) {\n return path.join(this.homeDir, \"Library/Caches/ggt\");\n }\n\n const base = process.env[\"XDG_CACHE_HOME\"] || (this.windows && process.env[\"LOCALAPPDATA\"]) || path.join(this.homeDir, \".cache\");\n return path.join(base, \"ggt\");\n },\n\n /**\n * - Unix: `~/.local/share/ggt`\n * - Windows: `%LOCALAPPDATA%\\ggt`\n *\n * Can be overridden with `GGT_DATA_DIR`\n */\n get dataDir(): string {\n if (process.env[\"GGT_DATA_DIR\"]) {\n return process.env[\"GGT_DATA_DIR\"];\n }\n\n const base = process.env[\"XDG_DATA_HOME\"] || (this.windows && process.env[\"LOCALAPPDATA\"]) || path.join(this.homeDir, \".local/share\");\n return path.join(base, \"ggt\");\n },\n\n /**\n * Domains for various Gadget services.\n */\n domains: {\n /**\n * The domain for the Gadget applications. This is where the user's application is hosted.\n */\n get app() {\n return process.env[\"GGT_GADGET_APP_DOMAIN\"] || (env.productionLike ? \"gadget.app\" : \"ggt.pub\");\n },\n\n /**\n * The domain for the Gadget services. This is where Gadget's API is hosted.\n */\n get services() {\n return process.env[\"GGT_GADGET_SERVICES_DOMAIN\"] || (env.productionLike ? \"app.gadget.dev\" : \"app.ggt.dev\");\n },\n },\n};\n\n/**\n * Returns an absolute path within the {@linkcode config.configDir}\n * directory.\n *\n * @param segments - The segments of the path to join.\n * @returns The absolute path to the file or directory.\n */\nexport const configPath = (...segments: string[]): string => path.join(config.configDir, ...segments);\n\n/**\n * Returns an absolute path within the {@linkcode config.homeDir}\n * directory.\n *\n * @param segments - The segments of the path to join.\n * @returns The absolute path to the file or directory.\n */\nexport const homePath = (...segments: string[]): string => path.join(config.homeDir, ...segments);\n"],"names":["isWsl","os","path","process","Level","parseLevel","env","packageJson","config","name","version","logLevel","PRINT","logFormat","versionFull","platform","arch","windows","macos","shell","SHELL","userInfo","split","sep","pop","at","homeDir","join","homedir","tmpdir","configDir","base","cacheDir","dataDir","domains","app","productionLike","services","configPath","segments","homePath"],"mappings":"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"}
1
+ {"version":3,"sources":["../../../src/services/config/config.ts"],"sourcesContent":["import isWsl from \"is-wsl\";\nimport os from \"node:os\";\nimport path from \"node:path\";\nimport process from \"node:process\";\nimport { Level, parseLevel } from \"../output/log/level.js\";\nimport { env } from \"./env.js\";\nimport { packageJson } from \"./package-json.js\";\n\nexport const config = {\n get logLevel() {\n return parseLevel(process.env[\"GGT_LOG_LEVEL\"], Level.PRINT);\n },\n\n get logFormat() {\n return process.env[\"GGT_LOG_FORMAT\"] === \"json\" ? \"json\" : \"pretty\";\n },\n\n /**\n * Returns the full version string including name, version, platform,\n * arch, and Node.js version. This is passed as the user agent for all\n * outgoing http requests.\n *\n * @example \"ggt/1.2.3 darwin-arm64 node-v16.0.0\"\n */\n get versionFull(): string {\n return `${packageJson.name}/${packageJson.version} ${this.platform}-${this.arch} node-${process.version}`;\n },\n\n get arch(): string {\n return os.arch() === \"ia32\" ? \"x86\" : os.arch();\n },\n\n get platform(): NodeJS.Platform | \"wsl\" {\n return isWsl ? \"wsl\" : os.platform();\n },\n\n get windows(): boolean {\n return process.platform === \"win32\";\n },\n\n get windowsOrWsl(): boolean {\n return this.windows || isWsl;\n },\n\n get macos(): boolean {\n return process.platform === \"darwin\";\n },\n\n get shell(): string | undefined {\n const SHELL = process.env[\"SHELL\"] ?? os.userInfo().shell?.split(path.sep).pop();\n if (SHELL) {\n return SHELL.split(\"/\").at(-1);\n }\n if (this.windows && process.env[\"COMSPEC\"]) {\n return process.env[\"COMSPEC\"].split(/\\\\|\\//).at(-1);\n }\n return \"unknown\";\n },\n\n get homeDir(): string {\n if (process.env[\"HOME\"]) {\n return process.env[\"HOME\"];\n }\n\n if (this.windows) {\n if (process.env[\"HOMEDRIVE\"] && process.env[\"HOMEPATH\"]) {\n return path.join(process.env[\"HOMEDRIVE\"], process.env[\"HOMEPATH\"]);\n }\n if (process.env[\"USERPROFILE\"]) {\n return process.env[\"USERPROFILE\"];\n }\n }\n\n return os.homedir() || os.tmpdir();\n },\n\n /**\n * - Unix: `~/.config/ggt`\n * - Windows: `%LOCALAPPDATA%\\ggt`\n *\n * Can be overridden by `GGT_CONFIG_DIR`\n */\n get configDir(): string {\n if (process.env[\"GGT_CONFIG_DIR\"]) {\n return process.env[\"GGT_CONFIG_DIR\"];\n }\n\n const base = process.env[\"XDG_CONFIG_HOME\"] || (this.windows && process.env[\"LOCALAPPDATA\"]) || path.join(this.homeDir, \".config\");\n return path.join(base, \"ggt\");\n },\n\n /**\n * - Linux: `~/.cache/ggt`\n * - macOS: `~/Library/Caches/ggt`\n * - Windows: `%LOCALAPPDATA%\\ggt`\n *\n * Can be overridden with `GGT_CACHE_DIR`\n */\n get cacheDir(): string {\n if (process.env[\"GGT_CACHE_DIR\"]) {\n return process.env[\"GGT_CACHE_DIR\"];\n }\n\n if (this.macos) {\n return path.join(this.homeDir, \"Library/Caches/ggt\");\n }\n\n const base = process.env[\"XDG_CACHE_HOME\"] || (this.windows && process.env[\"LOCALAPPDATA\"]) || path.join(this.homeDir, \".cache\");\n return path.join(base, \"ggt\");\n },\n\n /**\n * - Unix: `~/.local/share/ggt`\n * - Windows: `%LOCALAPPDATA%\\ggt`\n *\n * Can be overridden with `GGT_DATA_DIR`\n */\n get dataDir(): string {\n if (process.env[\"GGT_DATA_DIR\"]) {\n return process.env[\"GGT_DATA_DIR\"];\n }\n\n const base = process.env[\"XDG_DATA_HOME\"] || (this.windows && process.env[\"LOCALAPPDATA\"]) || path.join(this.homeDir, \".local/share\");\n return path.join(base, \"ggt\");\n },\n\n /**\n * Domains for various Gadget services.\n */\n domains: {\n /**\n * The domain for the Gadget applications. This is where the user's application is hosted.\n */\n get app() {\n return process.env[\"GGT_GADGET_APP_DOMAIN\"] || (env.productionLike ? \"gadget.app\" : \"ggt.pub\");\n },\n\n /**\n * The domain for the Gadget services. This is where Gadget's API is hosted.\n */\n get services() {\n return process.env[\"GGT_GADGET_SERVICES_DOMAIN\"] || (env.productionLike ? \"app.gadget.dev\" : \"app.ggt.dev\");\n },\n },\n};\n\n/**\n * Returns an absolute path within the {@linkcode config.configDir}\n * directory.\n *\n * @param segments - The segments of the path to join.\n * @returns The absolute path to the file or directory.\n */\nexport const configPath = (...segments: string[]): string => path.join(config.configDir, ...segments);\n\n/**\n * Returns an absolute path within the {@linkcode config.homeDir}\n * directory.\n *\n * @param segments - The segments of the path to join.\n * @returns The absolute path to the file or directory.\n */\nexport const homePath = (...segments: string[]): string => path.join(config.homeDir, ...segments);\n"],"names":["isWsl","os","path","process","Level","parseLevel","env","packageJson","config","logLevel","PRINT","logFormat","versionFull","name","version","platform","arch","windows","windowsOrWsl","macos","shell","SHELL","userInfo","split","sep","pop","at","homeDir","join","homedir","tmpdir","configDir","base","cacheDir","dataDir","domains","app","productionLike","services","configPath","segments","homePath"],"mappings":"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"}
@@ -1,6 +1,6 @@
1
1
  import process from "node:process";
2
2
  /**
3
- * Captures the name and nature of the environment
3
+ * Captures the current environment ggt is running in.
4
4
  */ export const env = {
5
5
  get value () {
6
6
  return process.env["GGT_ENV"] || "production";
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../src/services/config/env.ts"],"sourcesContent":["import process from \"node:process\";\n\n/**\n * Captures the name and nature of the environment\n */\nexport const env = {\n get value(): string {\n return process.env[\"GGT_ENV\"] || \"production\";\n },\n\n get productionLike(): boolean {\n return !this.developmentOrTestLike;\n },\n\n get developmentLike(): boolean {\n return this.value.startsWith(\"development\");\n },\n\n get testLike(): boolean {\n return this.value.startsWith(\"test\");\n },\n\n get developmentOrTestLike(): boolean {\n return this.developmentLike || this.testLike;\n },\n};\n"],"names":["process","env","value","productionLike","developmentOrTestLike","developmentLike","startsWith","testLike"],"mappings":"AAAA,OAAOA,aAAa,eAAe;AAEnC;;CAEC,GACD,OAAO,MAAMC,MAAM;IACjB,IAAIC,SAAgB;QAClB,OAAOF,QAAQC,GAAG,CAAC,UAAU,IAAI;IACnC;IAEA,IAAIE,kBAA0B;QAC5B,OAAO,CAAC,IAAI,CAACC,qBAAqB;IACpC;IAEA,IAAIC,mBAA2B;QAC7B,OAAO,IAAI,CAACH,KAAK,CAACI,UAAU,CAAC;IAC/B;IAEA,IAAIC,YAAoB;QACtB,OAAO,IAAI,CAACL,KAAK,CAACI,UAAU,CAAC;IAC/B;IAEA,IAAIF,yBAAiC;QACnC,OAAO,IAAI,CAACC,eAAe,IAAI,IAAI,CAACE,QAAQ;IAC9C;AACF,EAAE"}
1
+ {"version":3,"sources":["../../../src/services/config/env.ts"],"sourcesContent":["import process from \"node:process\";\n\n/**\n * Captures the current environment ggt is running in.\n */\nexport const env = {\n get value(): string {\n return process.env[\"GGT_ENV\"] || \"production\";\n },\n\n get productionLike(): boolean {\n return !this.developmentOrTestLike;\n },\n\n get developmentLike(): boolean {\n return this.value.startsWith(\"development\");\n },\n\n get testLike(): boolean {\n return this.value.startsWith(\"test\");\n },\n\n get developmentOrTestLike(): boolean {\n return this.developmentLike || this.testLike;\n },\n};\n"],"names":["process","env","value","productionLike","developmentOrTestLike","developmentLike","startsWith","testLike"],"mappings":"AAAA,OAAOA,aAAa,eAAe;AAEnC;;CAEC,GACD,OAAO,MAAMC,MAAM;IACjB,IAAIC,SAAgB;QAClB,OAAOF,QAAQC,GAAG,CAAC,UAAU,IAAI;IACnC;IAEA,IAAIE,kBAA0B;QAC5B,OAAO,CAAC,IAAI,CAACC,qBAAqB;IACpC;IAEA,IAAIC,mBAA2B;QAC7B,OAAO,IAAI,CAACH,KAAK,CAACI,UAAU,CAAC;IAC/B;IAEA,IAAIC,YAAoB;QACtB,OAAO,IAAI,CAACL,KAAK,CAACI,UAAU,CAAC;IAC/B;IAEA,IAAIF,yBAAiC;QACnC,OAAO,IAAI,CAACC,eAAe,IAAI,IAAI,CAACE,QAAQ;IAC9C;AACF,EAAE"}
@@ -1,57 +1,81 @@
1
+ import { _ as _define_property } from "@swc/helpers/_/_define_property";
1
2
  import chalk from "chalk";
2
3
  import pluralize from "pluralize";
3
4
  import { config } from "../config/config.js";
4
5
  import { Level } from "../output/log/level.js";
5
- import { sprint } from "../output/sprint.js";
6
+ import { println } from "../output/print.js";
7
+ import { sprint, sprintln } from "../output/sprint.js";
8
+ import { symbol } from "../output/symbols.js";
9
+ import { sprintTable } from "../output/table.js";
10
+ import { memo } from "../util/function.js";
6
11
  import { isNever, isString } from "../util/is.js";
7
12
  export class Changes extends Map {
8
- created() {
9
- return Array.from(this.entries()).filter(([, change])=>change.type === "create").map(([path])=>path);
10
- }
11
- updated() {
12
- return Array.from(this.entries()).filter(([, change])=>change.type === "update").map(([path])=>path);
13
- }
14
- deleted() {
15
- return Array.from(this.entries()).filter(([, change])=>change.type === "delete").map(([path])=>path);
13
+ constructor(...args){
14
+ super(...args);
15
+ _define_property(this, "created", memo(()=>{
16
+ return Array.from(this.entries()).filter(([, change])=>change.type === "create").map(([path])=>path);
17
+ }));
18
+ _define_property(this, "updated", memo(()=>{
19
+ return Array.from(this.entries()).filter(([, change])=>change.type === "update").map(([path])=>path);
20
+ }));
21
+ _define_property(this, "deleted", memo(()=>{
22
+ return Array.from(this.entries()).filter(([, change])=>change.type === "delete").map(([path])=>path);
23
+ }));
16
24
  }
17
25
  }
26
+ const createdSymbol = chalk.greenBright("+");
27
+ const updatedSymbol = chalk.blueBright("±");
28
+ const deletedSymbol = chalk.redBright("-");
29
+ const renameSymbol = chalk.yellowBright("→");
18
30
  /**
19
31
  * Prints the changes to the console.
20
32
  *
21
- * @param ctx - The current context.
22
- * @param options - The options to use.
23
- * @param options.changes - The changes to print.
24
- * @param options.tense - The tense to use for the change type.
25
- * @param options.limit - The maximum number of changes to print.
26
- */ export const printChanges = (ctx, { changes, tense, limit = Infinity, ...tableOptions })=>{
33
+ * @param _ctx - The current context.
34
+ * @see {@linkcode SprintChangesOptions}
35
+ */ export const sprintChanges = (_ctx, { changes, tense, includeDotGadget, limit = Infinity, ...tableOptions })=>{
27
36
  if (config.logLevel <= Level.TRACE) {
28
37
  // print all changes when tracing
29
38
  limit = Infinity;
30
39
  }
31
- const renamed = chalk.yellowBright((tense === "past" ? "renamed" : "rename") + " →");
32
- const created = chalk.greenBright((tense === "past" ? "created" : "create") + " +");
33
- const updated = chalk.blueBright((tense === "past" ? "updated" : "update") + " ±");
34
- const deleted = chalk.redBright((tense === "past" ? "deleted" : "delete") + " -");
35
- const rows = Array.from(changes.entries()).sort((a, b)=>a[0].localeCompare(b[0])).slice(0, limit).map(([path, change])=>{
40
+ let changesToPrint = Array.from(changes.entries());
41
+ if (includeDotGadget === undefined && changesToPrint.every(([filepath])=>filepath.startsWith(".gadget/"))) {
42
+ // we weren't explicitly told to exclude `.gadget/` files, and all
43
+ // the changes are to files within `.gadget/`, so include them since
44
+ // there's nothing else to show
45
+ includeDotGadget = true;
46
+ }
47
+ if (!includeDotGadget) {
48
+ changesToPrint = changesToPrint.filter(([filepath])=>!filepath.startsWith(".gadget/"));
49
+ }
50
+ const renamed = chalk.yellowBright(tense === "past" ? "renamed" : "rename");
51
+ const created = chalk.greenBright(tense === "past" ? "created" : "create");
52
+ const updated = chalk.blueBright(tense === "past" ? "updated" : "update");
53
+ const deleted = chalk.redBright(tense === "past" ? "deleted" : "delete");
54
+ const rows = changesToPrint.sort((a, b)=>a[0].localeCompare(b[0])).slice(0, limit).map(([path, change])=>{
36
55
  switch(true){
37
56
  case change.type === "create" && isString(change.oldPath):
38
57
  return [
58
+ renameSymbol,
39
59
  chalk.yellowBright(change.oldPath),
40
60
  renamed,
61
+ renameSymbol,
41
62
  chalk.yellowBright(path)
42
63
  ];
43
64
  case change.type === "create":
44
65
  return [
66
+ createdSymbol,
45
67
  chalk.greenBright(path),
46
68
  created
47
69
  ];
48
70
  case change.type === "update":
49
71
  return [
72
+ updatedSymbol,
50
73
  chalk.blueBright(path),
51
74
  updated
52
75
  ];
53
76
  case change.type === "delete":
54
77
  return [
78
+ deletedSymbol,
55
79
  chalk.redBright(path),
56
80
  deleted
57
81
  ];
@@ -59,37 +83,52 @@ export class Changes extends Map {
59
83
  return isNever(change);
60
84
  }
61
85
  });
62
- if (changes.size > limit) {
86
+ if (changesToPrint.length > limit) {
63
87
  rows.push([
64
- sprint`{gray … ${changes.size - limit} more}`,
88
+ chalk.gray(symbol.ellipsis),
89
+ sprint`{gray ${changesToPrint.length - limit} more}`,
65
90
  ""
66
91
  ]);
67
92
  }
68
93
  let footer;
69
- if (changes.size >= 10) {
70
- tableOptions.spaceY = 1;
71
- footer = sprint`${pluralize("change", changes.size, true)} in total. `;
94
+ if (changesToPrint.length >= 5) {
72
95
  const breakdown = [];
73
- const created = changes.created();
74
- if (created.length > 0) {
75
- breakdown.push(sprint`{greenBright ${pluralize("create", created.length, true)}}`);
96
+ const createdCount = changesToPrint.filter(([, change])=>change.type === "create").length;
97
+ if (createdCount > 0) {
98
+ const created = tense === "past" ? `${createdCount} created` : pluralize("create", createdCount, true);
99
+ breakdown.push(sprint`{greenBright ${created}}`);
76
100
  }
77
- const updated = changes.updated();
78
- if (updated.length > 0) {
79
- breakdown.push(sprint`{blueBright ${pluralize("update", updated.length, true)}}`);
101
+ const updatedCount = changesToPrint.filter(([, change])=>change.type === "update").length;
102
+ if (updatedCount > 0) {
103
+ const updated = tense === "past" ? `${updatedCount} updated` : pluralize("update", updatedCount, true);
104
+ breakdown.push(sprint`{blueBright ${updated}}`);
80
105
  }
81
- const deleted = changes.deleted();
82
- if (deleted.length > 0) {
83
- breakdown.push(sprint`{redBright ${pluralize("delete", deleted.length, true)}}`);
106
+ const deletedCount = changesToPrint.filter(([, change])=>change.type === "delete").length;
107
+ if (deletedCount > 0) {
108
+ const deleted = tense === "past" ? `${deletedCount} deleted` : pluralize("delete", deletedCount, true);
109
+ breakdown.push(sprint`{redBright ${deleted}}`);
84
110
  }
85
- footer += breakdown.join(", ");
86
- footer += ".";
111
+ footer = sprintln`
112
+ ${pluralize("change", changesToPrint.length, true)} in total. ${breakdown.join(", ")}.
113
+ `;
87
114
  }
88
- ctx.log.printTable({
115
+ return sprintTable({
89
116
  rows,
90
117
  footer,
118
+ ensureEmptyLineAbove: true,
119
+ ensureEmptyLineAboveBody: false,
120
+ ensureEmptyLineAboveFooter: true,
121
+ indent: 0,
91
122
  ...tableOptions
92
123
  });
93
124
  };
125
+ /**
126
+ * Prints the changes to the console.
127
+ *
128
+ * @param _ctx - The current context.
129
+ * @see {@linkcode SprintChangesOptions}
130
+ */ export const printChanges = (_ctx, options)=>{
131
+ println(sprintChanges(_ctx, options));
132
+ };
94
133
 
95
134
  //# sourceMappingURL=changes.js.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../src/services/filesync/changes.ts"],"sourcesContent":["import chalk from \"chalk\";\nimport pluralize from \"pluralize\";\nimport type { Context } from \"../command/context.js\";\nimport { config } from \"../config/config.js\";\nimport { Level } from \"../output/log/level.js\";\nimport type { PrintTableOptions } from \"../output/log/printer.js\";\nimport { sprint } from \"../output/sprint.js\";\nimport { isNever, isString } from \"../util/is.js\";\n\nexport type Create = { type: \"create\"; oldPath?: string };\nexport type Update = { type: \"update\" };\nexport type Delete = { type: \"delete\" };\nexport type Change = Create | Update | Delete;\n\nexport class Changes extends Map<string, Change> {\n created(): string[] {\n return Array.from(this.entries())\n .filter(([, change]) => change.type === \"create\")\n .map(([path]) => path);\n }\n\n updated(): string[] {\n return Array.from(this.entries())\n .filter(([, change]) => change.type === \"update\")\n .map(([path]) => path);\n }\n\n deleted(): string[] {\n return Array.from(this.entries())\n .filter(([, change]) => change.type === \"delete\")\n .map(([path]) => path);\n }\n}\n\n/**\n * Prints the changes to the console.\n *\n * @param ctx - The current context.\n * @param options - The options to use.\n * @param options.changes - The changes to print.\n * @param options.tense - The tense to use for the change type.\n * @param options.limit - The maximum number of changes to print.\n */\nexport const printChanges = (\n ctx: Context,\n {\n changes,\n tense,\n limit = Infinity,\n ...tableOptions\n }: {\n changes: Changes;\n tense: \"past\" | \"present\";\n limit?: number;\n } & Partial<PrintTableOptions>,\n): void => {\n if (config.logLevel <= Level.TRACE) {\n // print all changes when tracing\n limit = Infinity;\n }\n\n const renamed = chalk.yellowBright((tense === \"past\" ? \"renamed\" : \"rename\") + \" →\");\n const created = chalk.greenBright((tense === \"past\" ? \"created\" : \"create\") + \" +\");\n const updated = chalk.blueBright((tense === \"past\" ? \"updated\" : \"update\") + \" ±\");\n const deleted = chalk.redBright((tense === \"past\" ? \"deleted\" : \"delete\") + \" -\");\n\n const rows = Array.from(changes.entries())\n .sort((a, b) => a[0].localeCompare(b[0]))\n .slice(0, limit)\n .map(([path, change]) => {\n switch (true) {\n case change.type === \"create\" && isString(change.oldPath):\n return [chalk.yellowBright(change.oldPath), renamed, chalk.yellowBright(path)];\n case change.type === \"create\":\n return [chalk.greenBright(path), created];\n case change.type === \"update\":\n return [chalk.blueBright(path), updated];\n case change.type === \"delete\":\n return [chalk.redBright(path), deleted];\n default:\n return isNever(change);\n }\n });\n\n if (changes.size > limit) {\n rows.push([sprint`{gray … ${changes.size - limit} more}`, \"\"]);\n }\n\n let footer: string | undefined;\n if (changes.size >= 10) {\n tableOptions.spaceY = 1;\n\n footer = sprint`${pluralize(\"change\", changes.size, true)} in total. `;\n\n const breakdown = [];\n\n const created = changes.created();\n if (created.length > 0) {\n breakdown.push(sprint`{greenBright ${pluralize(\"create\", created.length, true)}}`);\n }\n\n const updated = changes.updated();\n if (updated.length > 0) {\n breakdown.push(sprint`{blueBright ${pluralize(\"update\", updated.length, true)}}`);\n }\n\n const deleted = changes.deleted();\n if (deleted.length > 0) {\n breakdown.push(sprint`{redBright ${pluralize(\"delete\", deleted.length, true)}}`);\n }\n\n footer += breakdown.join(\", \");\n footer += \".\";\n }\n\n ctx.log.printTable({ rows, footer, ...tableOptions });\n};\n"],"names":["chalk","pluralize","config","Level","sprint","isNever","isString","Changes","Map","created","Array","from","entries","filter","change","type","map","path","updated","deleted","printChanges","ctx","changes","tense","limit","Infinity","tableOptions","logLevel","TRACE","renamed","yellowBright","greenBright","blueBright","redBright","rows","sort","a","b","localeCompare","slice","oldPath","size","push","footer","spaceY","breakdown","length","join","log","printTable"],"mappings":"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"}
1
+ {"version":3,"sources":["../../../src/services/filesync/changes.ts"],"sourcesContent":["import chalk from \"chalk\";\nimport pluralize from \"pluralize\";\nimport type { Context } from \"../command/context.js\";\nimport { config } from \"../config/config.js\";\nimport { Level } from \"../output/log/level.js\";\nimport { println } from \"../output/print.js\";\nimport { sprint, sprintln } from \"../output/sprint.js\";\nimport { symbol } from \"../output/symbols.js\";\nimport { sprintTable, type SprintTableOptions } from \"../output/table.js\";\nimport { memo } from \"../util/function.js\";\nimport { isNever, isString } from \"../util/is.js\";\nimport type { ChangesWithHash } from \"./hashes.js\";\n\nexport type Create = { type: \"create\"; oldPath?: string };\nexport type Update = { type: \"update\" };\nexport type Delete = { type: \"delete\" };\nexport type Change = Create | Update | Delete;\n\nexport class Changes extends Map<string, Change> {\n created = memo((): string[] => {\n return Array.from(this.entries())\n .filter(([, change]) => change.type === \"create\")\n .map(([path]) => path);\n });\n\n updated = memo((): string[] => {\n return Array.from(this.entries())\n .filter(([, change]) => change.type === \"update\")\n .map(([path]) => path);\n });\n\n deleted = memo((): string[] => {\n return Array.from(this.entries())\n .filter(([, change]) => change.type === \"delete\")\n .map(([path]) => path);\n });\n}\n\nexport type PrintChangesOptions = Partial<SprintTableOptions> & {\n /**\n * The tense to use for the change type.\n */\n tense: \"past\" | \"present\";\n\n /**\n * Whether to include `.gadget/` files in the output.\n *\n * @default undefined (true if there are no other changes, false otherwise)\n */\n includeDotGadget?: boolean;\n\n /**\n * The maximum number of changes to print.\n *\n * @default Infinity\n */\n limit?: number;\n};\n\nconst createdSymbol = chalk.greenBright(\"+\");\nconst updatedSymbol = chalk.blueBright(\"±\");\nconst deletedSymbol = chalk.redBright(\"-\");\nconst renameSymbol = chalk.yellowBright(\"→\");\n\n/**\n * Prints the changes to the console.\n *\n * @param _ctx - The current context.\n * @see {@linkcode SprintChangesOptions}\n */\nexport const sprintChanges = (\n _ctx: Context,\n { changes, tense, includeDotGadget, limit = Infinity, ...tableOptions }: { changes: Changes | ChangesWithHash } & PrintChangesOptions,\n): string => {\n if (config.logLevel <= Level.TRACE) {\n // print all changes when tracing\n limit = Infinity;\n }\n\n let changesToPrint = Array.from(changes.entries());\n\n if (includeDotGadget === undefined && changesToPrint.every(([filepath]) => filepath.startsWith(\".gadget/\"))) {\n // we weren't explicitly told to exclude `.gadget/` files, and all\n // the changes are to files within `.gadget/`, so include them since\n // there's nothing else to show\n includeDotGadget = true;\n }\n\n if (!includeDotGadget) {\n changesToPrint = changesToPrint.filter(([filepath]) => !filepath.startsWith(\".gadget/\"));\n }\n\n const renamed = chalk.yellowBright(tense === \"past\" ? \"renamed\" : \"rename\");\n const created = chalk.greenBright(tense === \"past\" ? \"created\" : \"create\");\n const updated = chalk.blueBright(tense === \"past\" ? \"updated\" : \"update\");\n const deleted = chalk.redBright(tense === \"past\" ? \"deleted\" : \"delete\");\n\n const rows = changesToPrint\n .sort((a, b) => a[0].localeCompare(b[0]))\n .slice(0, limit)\n .map(([path, change]) => {\n switch (true) {\n case change.type === \"create\" && isString(change.oldPath):\n return [renameSymbol, chalk.yellowBright(change.oldPath), renamed, renameSymbol, chalk.yellowBright(path)];\n case change.type === \"create\":\n return [createdSymbol, chalk.greenBright(path), created];\n case change.type === \"update\":\n return [updatedSymbol, chalk.blueBright(path), updated];\n case change.type === \"delete\":\n return [deletedSymbol, chalk.redBright(path), deleted];\n default:\n return isNever(change);\n }\n });\n\n if (changesToPrint.length > limit) {\n rows.push([chalk.gray(symbol.ellipsis), sprint`{gray ${changesToPrint.length - limit} more}`, \"\"]);\n }\n\n let footer: string | undefined;\n if (changesToPrint.length >= 5) {\n const breakdown = [];\n\n const createdCount = changesToPrint.filter(([, change]) => change.type === \"create\").length;\n if (createdCount > 0) {\n const created = tense === \"past\" ? `${createdCount} created` : pluralize(\"create\", createdCount, true);\n breakdown.push(sprint`{greenBright ${created}}`);\n }\n\n const updatedCount = changesToPrint.filter(([, change]) => change.type === \"update\").length;\n if (updatedCount > 0) {\n const updated = tense === \"past\" ? `${updatedCount} updated` : pluralize(\"update\", updatedCount, true);\n breakdown.push(sprint`{blueBright ${updated}}`);\n }\n\n const deletedCount = changesToPrint.filter(([, change]) => change.type === \"delete\").length;\n if (deletedCount > 0) {\n const deleted = tense === \"past\" ? `${deletedCount} deleted` : pluralize(\"delete\", deletedCount, true);\n breakdown.push(sprint`{redBright ${deleted}}`);\n }\n\n footer = sprintln`\n ${pluralize(\"change\", changesToPrint.length, true)} in total. ${breakdown.join(\", \")}.\n `;\n }\n\n return sprintTable({\n rows,\n footer,\n ensureEmptyLineAbove: true,\n ensureEmptyLineAboveBody: false,\n ensureEmptyLineAboveFooter: true,\n indent: 0,\n ...tableOptions,\n });\n};\n\n/**\n * Prints the changes to the console.\n *\n * @param _ctx - The current context.\n * @see {@linkcode SprintChangesOptions}\n */\nexport const printChanges = (_ctx: Context, options: { changes: Changes | ChangesWithHash } & PrintChangesOptions): void => {\n println(sprintChanges(_ctx, options));\n};\n"],"names":["chalk","pluralize","config","Level","println","sprint","sprintln","symbol","sprintTable","memo","isNever","isString","Changes","Map","created","Array","from","entries","filter","change","type","map","path","updated","deleted","createdSymbol","greenBright","updatedSymbol","blueBright","deletedSymbol","redBright","renameSymbol","yellowBright","sprintChanges","_ctx","changes","tense","includeDotGadget","limit","Infinity","tableOptions","logLevel","TRACE","changesToPrint","undefined","every","filepath","startsWith","renamed","rows","sort","a","b","localeCompare","slice","oldPath","length","push","gray","ellipsis","footer","breakdown","createdCount","updatedCount","deletedCount","join","ensureEmptyLineAbove","ensureEmptyLineAboveBody","ensureEmptyLineAboveFooter","indent","printChanges","options"],"mappings":"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"}