@supernovaio/cli-next 2.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (127) hide show
  1. package/README.md +201 -0
  2. package/bin/dev +7 -0
  3. package/bin/dev.cmd +3 -0
  4. package/bin/run +57 -0
  5. package/bin/run.cmd +3 -0
  6. package/dist/commands/describe-design-system.d.ts +45 -0
  7. package/dist/commands/describe-design-system.d.ts.map +1 -0
  8. package/dist/commands/describe-design-system.js +75 -0
  9. package/dist/commands/describe-design-system.js.map +1 -0
  10. package/dist/commands/describe-workspaces.d.ts +54 -0
  11. package/dist/commands/describe-workspaces.d.ts.map +1 -0
  12. package/dist/commands/describe-workspaces.js +111 -0
  13. package/dist/commands/describe-workspaces.js.map +1 -0
  14. package/dist/commands/import-components.d.ts +50 -0
  15. package/dist/commands/import-components.d.ts.map +1 -0
  16. package/dist/commands/import-components.js +93 -0
  17. package/dist/commands/import-components.js.map +1 -0
  18. package/dist/commands/import-storybook.d.ts +69 -0
  19. package/dist/commands/import-storybook.d.ts.map +1 -0
  20. package/dist/commands/import-storybook.js +348 -0
  21. package/dist/commands/import-storybook.js.map +1 -0
  22. package/dist/commands/login.d.ts +30 -0
  23. package/dist/commands/login.d.ts.map +1 -0
  24. package/dist/commands/login.js +78 -0
  25. package/dist/commands/login.js.map +1 -0
  26. package/dist/commands/logout.d.ts +28 -0
  27. package/dist/commands/logout.d.ts.map +1 -0
  28. package/dist/commands/logout.js +46 -0
  29. package/dist/commands/logout.js.map +1 -0
  30. package/dist/commands/publish-documentation.d.ts +63 -0
  31. package/dist/commands/publish-documentation.d.ts.map +1 -0
  32. package/dist/commands/publish-documentation.js +136 -0
  33. package/dist/commands/publish-documentation.js.map +1 -0
  34. package/dist/commands/sync-tokens.d.ts +70 -0
  35. package/dist/commands/sync-tokens.d.ts.map +1 -0
  36. package/dist/commands/sync-tokens.js +109 -0
  37. package/dist/commands/sync-tokens.js.map +1 -0
  38. package/dist/hooks/postrun/save-config.d.ts +4 -0
  39. package/dist/hooks/postrun/save-config.d.ts.map +1 -0
  40. package/dist/hooks/postrun/save-config.js +17 -0
  41. package/dist/hooks/postrun/save-config.js.map +1 -0
  42. package/dist/hooks/prerun/load-config.d.ts +4 -0
  43. package/dist/hooks/prerun/load-config.d.ts.map +1 -0
  44. package/dist/hooks/prerun/load-config.js +24 -0
  45. package/dist/hooks/prerun/load-config.js.map +1 -0
  46. package/dist/hooks/prerun/sentry.d.ts +4 -0
  47. package/dist/hooks/prerun/sentry.d.ts.map +1 -0
  48. package/dist/hooks/prerun/sentry.js +17 -0
  49. package/dist/hooks/prerun/sentry.js.map +1 -0
  50. package/dist/index.d.ts +2 -0
  51. package/dist/index.d.ts.map +1 -0
  52. package/dist/index.js +2 -0
  53. package/dist/index.js.map +1 -0
  54. package/dist/services/auth.service.d.ts +12 -0
  55. package/dist/services/auth.service.d.ts.map +1 -0
  56. package/dist/services/auth.service.js +104 -0
  57. package/dist/services/auth.service.js.map +1 -0
  58. package/dist/services/index.d.ts +3 -0
  59. package/dist/services/index.d.ts.map +1 -0
  60. package/dist/services/index.js +3 -0
  61. package/dist/services/index.js.map +1 -0
  62. package/dist/services/vault.service.d.ts +28 -0
  63. package/dist/services/vault.service.d.ts.map +1 -0
  64. package/dist/services/vault.service.js +181 -0
  65. package/dist/services/vault.service.js.map +1 -0
  66. package/dist/types/base-command.d.ts +23 -0
  67. package/dist/types/base-command.d.ts.map +1 -0
  68. package/dist/types/base-command.js +127 -0
  69. package/dist/types/base-command.js.map +1 -0
  70. package/dist/types/flags.d.ts +4 -0
  71. package/dist/types/flags.d.ts.map +1 -0
  72. package/dist/types/flags.js +11 -0
  73. package/dist/types/flags.js.map +1 -0
  74. package/dist/types/index.d.ts +7 -0
  75. package/dist/types/index.d.ts.map +1 -0
  76. package/dist/types/index.js +7 -0
  77. package/dist/types/index.js.map +1 -0
  78. package/dist/types/login.d.ts +189 -0
  79. package/dist/types/login.d.ts.map +1 -0
  80. package/dist/types/login.js +39 -0
  81. package/dist/types/login.js.map +1 -0
  82. package/dist/types/not-authorized.error.d.ts +6 -0
  83. package/dist/types/not-authorized.error.d.ts.map +1 -0
  84. package/dist/types/not-authorized.error.js +13 -0
  85. package/dist/types/not-authorized.error.js.map +1 -0
  86. package/dist/types/sentry-command.d.ts +15 -0
  87. package/dist/types/sentry-command.d.ts.map +1 -0
  88. package/dist/types/sentry-command.js +50 -0
  89. package/dist/types/sentry-command.js.map +1 -0
  90. package/dist/types/types.d.ts +29 -0
  91. package/dist/types/types.d.ts.map +1 -0
  92. package/dist/types/types.js +17 -0
  93. package/dist/types/types.js.map +1 -0
  94. package/dist/utils/api-client.d.ts +4 -0
  95. package/dist/utils/api-client.d.ts.map +1 -0
  96. package/dist/utils/api-client.js +11 -0
  97. package/dist/utils/api-client.js.map +1 -0
  98. package/dist/utils/common.d.ts +2 -0
  99. package/dist/utils/common.d.ts.map +1 -0
  100. package/dist/utils/common.js +6 -0
  101. package/dist/utils/common.js.map +1 -0
  102. package/dist/utils/config.service.d.ts +17 -0
  103. package/dist/utils/config.service.d.ts.map +1 -0
  104. package/dist/utils/config.service.js +70 -0
  105. package/dist/utils/config.service.js.map +1 -0
  106. package/dist/utils/figma-tokens-data-loader.d.ts +17 -0
  107. package/dist/utils/figma-tokens-data-loader.d.ts.map +1 -0
  108. package/dist/utils/figma-tokens-data-loader.js +193 -0
  109. package/dist/utils/figma-tokens-data-loader.js.map +1 -0
  110. package/dist/utils/index.d.ts +2 -0
  111. package/dist/utils/index.d.ts.map +1 -0
  112. package/dist/utils/index.js +2 -0
  113. package/dist/utils/index.js.map +1 -0
  114. package/dist/utils/network.d.ts +3 -0
  115. package/dist/utils/network.d.ts.map +1 -0
  116. package/dist/utils/network.js +13 -0
  117. package/dist/utils/network.js.map +1 -0
  118. package/dist/utils/run-exporter/exporter-utils.d.ts +14 -0
  119. package/dist/utils/run-exporter/exporter-utils.d.ts.map +1 -0
  120. package/dist/utils/run-exporter/exporter-utils.js +16 -0
  121. package/dist/utils/run-exporter/exporter-utils.js.map +1 -0
  122. package/dist/utils/sdk.d.ts +20 -0
  123. package/dist/utils/sdk.d.ts.map +1 -0
  124. package/dist/utils/sdk.js +52 -0
  125. package/dist/utils/sdk.js.map +1 -0
  126. package/oclif.manifest.json +534 -0
  127. package/package.json +143 -0
@@ -0,0 +1 @@
1
+ {"version":3,"file":"save-config.js","sourceRoot":"","sources":["../../../src/hooks/postrun/save-config.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,OAAO,MAAM,cAAc,CAAA;AAEvC,OAAO,EAAE,WAAW,EAAE,MAAM,sBAAsB,CAAA;AAElD,MAAM,IAAI,GAAoB,KAAK,WAAW,EAAE,IAAI,EAAE,OAAO,EAAE,MAAM,EAAE;IACrE,IAAI,OAAO,IAAI,OAAO,CAAC,SAAS,YAAY,WAAW,EAAE,CAAC;QACxD,IAAI,CAAC;YAEH,MAAM,GAAG,GAAG,IAAK,OAAiB,CAAC,IAAI,EAAE,MAAM,CAAC,CAAA;YAChD,MAAM,EAAE,KAAK,EAAE,GAAG,MAAM,GAAG,CAAC,KAAK,CAAC,OAAO,CAAC,CAAA;YAC1C,GAAG,CAAC,UAAU,CAAC,KAAK,CAAC,CAAA;YACrB,IAAI,CAAC,GAAG,CAAC,uDAAuD,CAAC,CAAA;QACnE,CAAC;QAAC,MAAM,CAAC;YACP,OAAO,CAAC,GAAG,CAAC,iDAAiD,CAAC,CAAA;QAChE,CAAC;IACH,CAAC;AACH,CAAC,CAAA;AAED,eAAe,IAAI,CAAA","sourcesContent":["import { Hook } from \"@oclif/core\"\nimport * as console from \"node:console\"\n\nimport { BaseCommand } from \"../../types/index.js\"\n\nconst hook: Hook<\"postrun\"> = async function ({ argv, Command, config }) {\n if (Command && Command.prototype instanceof BaseCommand) {\n try {\n // @ts-expect-error TS-2351\n const cmd = new (Command as never)(argv, config)\n const { flags } = await cmd.parse(Command)\n cmd.saveConfig(flags)\n this.log(\"Configuration saved for future use in .supernova.json\")\n } catch {\n console.log(\"Cannot apply configuration from .supernova.json\")\n }\n }\n}\n\nexport default hook\n"]}
@@ -0,0 +1,4 @@
1
+ import { Hook } from "@oclif/core";
2
+ declare const hook: Hook<"prerun">;
3
+ export default hook;
4
+ //# sourceMappingURL=load-config.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"load-config.d.ts","sourceRoot":"","sources":["../../../src/hooks/prerun/load-config.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,aAAa,CAAA;AAMlC,QAAA,MAAM,IAAI,EAAE,IAAI,CAAC,QAAQ,CAsBxB,CAAA;AAED,eAAe,IAAI,CAAA"}
@@ -0,0 +1,24 @@
1
+ import * as console from "node:console";
2
+ import { BaseCommand } from "../../types/index.js";
3
+ import { ConfigService } from "../../utils/config.service.js";
4
+ const hook = async function ({ Command }) {
5
+ if (Command && Command.prototype instanceof BaseCommand) {
6
+ const { commandId, configSchema } = new Command();
7
+ try {
8
+ const configService = ConfigService.getInstance();
9
+ const fileConfig = configService.getCommandConfig(commandId, configSchema);
10
+ if (Command.flags) {
11
+ for (const [flagName, flagDef] of Object.entries(Command.flags)) {
12
+ if (flagDef.required && fileConfig && flagName in fileConfig && fileConfig[flagName] !== undefined) {
13
+ flagDef.required = false;
14
+ }
15
+ }
16
+ }
17
+ }
18
+ catch {
19
+ console.log("Cannot apply configuration from .supernova.json");
20
+ }
21
+ }
22
+ };
23
+ export default hook;
24
+ //# sourceMappingURL=load-config.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"load-config.js","sourceRoot":"","sources":["../../../src/hooks/prerun/load-config.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,OAAO,MAAM,cAAc,CAAA;AAEvC,OAAO,EAAE,WAAW,EAAE,MAAM,sBAAsB,CAAA;AAClD,OAAO,EAAE,aAAa,EAAE,MAAM,+BAA+B,CAAA;AAE7D,MAAM,IAAI,GAAmB,KAAK,WAAW,EAAE,OAAO,EAAE;IACtD,IAAI,OAAO,IAAI,OAAO,CAAC,SAAS,YAAY,WAAW,EAAE,CAAC;QAExD,MAAM,EAAE,SAAS,EAAE,YAAY,EAAE,GAAG,IAAK,OAAiB,EAAE,CAAA;QAC5D,IAAI,CAAC;YACH,MAAM,aAAa,GAAG,aAAa,CAAC,WAAW,EAAE,CAAA;YACjD,MAAM,UAAU,GAAG,aAAa,CAAC,gBAAgB,CAAC,SAAS,EAAE,YAAY,CAExE,CAAA;YACD,IAAI,OAAO,CAAC,KAAK,EAAE,CAAC;gBAClB,KAAK,MAAM,CAAC,QAAQ,EAAE,OAAO,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,OAAO,CAAC,KAAK,CAAC,EAAE,CAAC;oBAEhE,IAAI,OAAO,CAAC,QAAQ,IAAI,UAAU,IAAI,QAAQ,IAAI,UAAU,IAAI,UAAU,CAAC,QAAQ,CAAC,KAAK,SAAS,EAAE,CAAC;wBAEnG,OAAO,CAAC,QAAQ,GAAG,KAAK,CAAA;oBAC1B,CAAC;gBACH,CAAC;YACH,CAAC;QACH,CAAC;QAAC,MAAM,CAAC;YACP,OAAO,CAAC,GAAG,CAAC,iDAAiD,CAAC,CAAA;QAChE,CAAC;IACH,CAAC;AACH,CAAC,CAAA;AAED,eAAe,IAAI,CAAA","sourcesContent":["import { Hook } from \"@oclif/core\"\nimport * as console from \"node:console\"\n\nimport { BaseCommand } from \"../../types/index.js\"\nimport { ConfigService } from \"../../utils/config.service.js\"\n\nconst hook: Hook<\"prerun\"> = async function ({ Command }) {\n if (Command && Command.prototype instanceof BaseCommand) {\n // @ts-expect-error TS-2351\n const { commandId, configSchema } = new (Command as never)()\n try {\n const configService = ConfigService.getInstance()\n const fileConfig = configService.getCommandConfig(commandId, configSchema) as {\n [key: string]: boolean | number | string | undefined\n }\n if (Command.flags) {\n for (const [flagName, flagDef] of Object.entries(Command.flags)) {\n // If the flag is marked as required but exists in config\n if (flagDef.required && fileConfig && flagName in fileConfig && fileConfig[flagName] !== undefined) {\n // Make it not required since we'll use the config value\n flagDef.required = false\n }\n }\n }\n } catch {\n console.log(\"Cannot apply configuration from .supernova.json\")\n }\n }\n}\n\nexport default hook\n"]}
@@ -0,0 +1,4 @@
1
+ import { Hook } from '@oclif/core';
2
+ declare const hook: Hook<'prerun'>;
3
+ export default hook;
4
+ //# sourceMappingURL=sentry.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sentry.d.ts","sourceRoot":"","sources":["../../../src/hooks/prerun/sentry.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,IAAI,EAAC,MAAM,aAAa,CAAA;AAMhC,QAAA,MAAM,IAAI,EAAE,IAAI,CAAC,QAAQ,CAYxB,CAAA;AAED,eAAe,IAAI,CAAA"}
@@ -0,0 +1,17 @@
1
+ import * as Sentry from '@sentry/node';
2
+ import { VaultService } from '../../services/index.js';
3
+ const hook = async function (opts) {
4
+ const span = Sentry.getActiveSpan();
5
+ if (span) {
6
+ span.setAttribute('command', opts.Command.id);
7
+ span.updateName(opts.Command.id);
8
+ const vaultService = new VaultService();
9
+ const user = await vaultService.getLoggedInUser(process.env.SUPERNOVA_ENV);
10
+ if (user) {
11
+ Sentry.setUser({ id: user });
12
+ span.setAttribute('user', user);
13
+ }
14
+ }
15
+ };
16
+ export default hook;
17
+ //# sourceMappingURL=sentry.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sentry.js","sourceRoot":"","sources":["../../../src/hooks/prerun/sentry.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,MAAM,MAAM,cAAc,CAAA;AAEtC,OAAO,EAAC,YAAY,EAAC,MAAM,yBAAyB,CAAA;AAGpD,MAAM,IAAI,GAAmB,KAAK,WAAW,IAAI;IAC/C,MAAM,IAAI,GAAG,MAAM,CAAC,aAAa,EAAE,CAAA;IACnC,IAAI,IAAI,EAAE,CAAC;QACT,IAAI,CAAC,YAAY,CAAC,SAAS,EAAE,IAAI,CAAC,OAAO,CAAC,EAAE,CAAC,CAAA;QAC7C,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC,OAAO,CAAC,EAAE,CAAC,CAAA;QAChC,MAAM,YAAY,GAAG,IAAI,YAAY,EAAE,CAAA;QACvC,MAAM,IAAI,GAAG,MAAM,YAAY,CAAC,eAAe,CAAC,OAAO,CAAC,GAAG,CAAC,aAA0B,CAAC,CAAA;QACvF,IAAI,IAAI,EAAE,CAAC;YACT,MAAM,CAAC,OAAO,CAAC,EAAC,EAAE,EAAE,IAAI,EAAC,CAAC,CAAA;YAC1B,IAAI,CAAC,YAAY,CAAC,MAAM,EAAE,IAAI,CAAC,CAAA;QACjC,CAAC;IACH,CAAC;AACH,CAAC,CAAA;AAED,eAAe,IAAI,CAAA","sourcesContent":["import {Hook} from '@oclif/core'\nimport * as Sentry from '@sentry/node'\n\nimport {VaultService} from '../../services/index.js'\nimport {TargetEnv} from '../../types/index.js'\n\nconst hook: Hook<'prerun'> = async function (opts) {\n const span = Sentry.getActiveSpan()\n if (span) {\n span.setAttribute('command', opts.Command.id)\n span.updateName(opts.Command.id)\n const vaultService = new VaultService()\n const user = await vaultService.getLoggedInUser(process.env.SUPERNOVA_ENV as TargetEnv)\n if (user) {\n Sentry.setUser({id: user})\n span.setAttribute('user', user)\n }\n }\n}\n\nexport default hook\n"]}
@@ -0,0 +1,2 @@
1
+ export { run } from "@oclif/core";
2
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,GAAG,EAAE,MAAM,aAAa,CAAA"}
package/dist/index.js ADDED
@@ -0,0 +1,2 @@
1
+ export { run } from "@oclif/core";
2
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,GAAG,EAAE,MAAM,aAAa,CAAA","sourcesContent":["export { run } from \"@oclif/core\"\n"]}
@@ -0,0 +1,12 @@
1
+ import { TargetEnv, Tokens } from "../types/index.js";
2
+ export declare class AuthService {
3
+ getAuthUrlFromServer(env: TargetEnv, codeChallenge: string): Promise<{
4
+ authorizeUrl: string;
5
+ readKey: string;
6
+ }>;
7
+ getTokensFromServer(env: TargetEnv, verifier: string, readKey: string): Promise<Tokens | undefined>;
8
+ refreshToken(env: TargetEnv, refreshToken?: string): Promise<Tokens | undefined>;
9
+ sleep(ms?: number): Promise<unknown>;
10
+ private getOAuthUrl;
11
+ }
12
+ //# sourceMappingURL=auth.service.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"auth.service.d.ts","sourceRoot":"","sources":["../../src/services/auth.service.ts"],"names":[],"mappings":"AAEA,OAAO,EAGL,SAAS,EACT,MAAM,EAGP,MAAM,mBAAmB,CAAA;AAE1B,qBAAa,WAAW;IAET,oBAAoB,CAAC,GAAG,EAAE,SAAS,EAAE,aAAa,EAAE,MAAM;;;;IAkB1D,mBAAmB,CAAC,GAAG,EAAE,SAAS,EAAE,QAAQ,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,GAAG,SAAS,CAAC;IA+BnG,YAAY,CAAC,GAAG,EAAE,SAAS,EAAE,YAAY,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,GAAG,SAAS,CAAC;IA4BtF,KAAK,CAAC,EAAE,GAAE,MAAa;IAM9B,OAAO,CAAC,WAAW;CAGpB"}
@@ -0,0 +1,104 @@
1
+ var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
2
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
3
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
4
+ else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
5
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
6
+ };
7
+ var __metadata = (this && this.__metadata) || function (k, v) {
8
+ if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
9
+ };
10
+ import { SentryTraced } from "@sentry/nestjs";
11
+ import { AuthResponseSchema, RefreshTokenResponseSchema, TokensResponseSchema, urlMap, } from "../types/index.js";
12
+ export class AuthService {
13
+ async getAuthUrlFromServer(env, codeChallenge) {
14
+ const { result: { authorizeUrl, readKey }, } = await fetch(this.getOAuthUrl(env), {
15
+ body: JSON.stringify({
16
+ codeChallenge,
17
+ }),
18
+ headers: {
19
+ "Content-Type": "application/json",
20
+ },
21
+ method: "POST",
22
+ })
23
+ .then(res => res.json())
24
+ .then(async (data) => AuthResponseSchema.parse(data));
25
+ return { authorizeUrl, readKey };
26
+ }
27
+ async getTokensFromServer(env, verifier, readKey) {
28
+ let success = false;
29
+ let tokens;
30
+ let repeatCounts = 300;
31
+ while (!success && repeatCounts-- > 0) {
32
+ success = await fetch(`${this.getOAuthUrl(env)}?read_key=${readKey}&code_verifier=${verifier}`)
33
+ .then(response => {
34
+ if (!response.ok) {
35
+ throw new Error("Network response was not ok");
36
+ }
37
+ return response.json();
38
+ })
39
+ .then(async (data) => {
40
+ const body = TokensResponseSchema.parse(data);
41
+ if (body.result.status === "Success") {
42
+ tokens = body.result.tokens;
43
+ return true;
44
+ }
45
+ await this.sleep();
46
+ return false;
47
+ });
48
+ }
49
+ return tokens;
50
+ }
51
+ async refreshToken(env, refreshToken) {
52
+ if (!refreshToken)
53
+ return undefined;
54
+ const authUrl = `${this.getOAuthUrl(env)}/token`;
55
+ const response = await fetch(authUrl, {
56
+ body: JSON.stringify({
57
+ grant_type: "refresh_token",
58
+ refresh_token: refreshToken,
59
+ }),
60
+ headers: {
61
+ "Content-Type": "application/json",
62
+ },
63
+ method: "POST",
64
+ });
65
+ if (!response.ok) {
66
+ return undefined;
67
+ }
68
+ const { result: { tokens }, } = RefreshTokenResponseSchema.parse(await response.json());
69
+ return { ...tokens, refreshToken };
70
+ }
71
+ sleep(ms = 5000) {
72
+ return new Promise(resolve => {
73
+ setTimeout(resolve, ms);
74
+ });
75
+ }
76
+ getOAuthUrl(target) {
77
+ return urlMap[target];
78
+ }
79
+ }
80
+ __decorate([
81
+ SentryTraced(),
82
+ __metadata("design:type", Function),
83
+ __metadata("design:paramtypes", [String, String]),
84
+ __metadata("design:returntype", Promise)
85
+ ], AuthService.prototype, "getAuthUrlFromServer", null);
86
+ __decorate([
87
+ SentryTraced(),
88
+ __metadata("design:type", Function),
89
+ __metadata("design:paramtypes", [String, String, String]),
90
+ __metadata("design:returntype", Promise)
91
+ ], AuthService.prototype, "getTokensFromServer", null);
92
+ __decorate([
93
+ SentryTraced(),
94
+ __metadata("design:type", Function),
95
+ __metadata("design:paramtypes", [String, String]),
96
+ __metadata("design:returntype", Promise)
97
+ ], AuthService.prototype, "refreshToken", null);
98
+ __decorate([
99
+ SentryTraced(),
100
+ __metadata("design:type", Function),
101
+ __metadata("design:paramtypes", [Number]),
102
+ __metadata("design:returntype", void 0)
103
+ ], AuthService.prototype, "sleep", null);
104
+ //# sourceMappingURL=auth.service.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"auth.service.js","sourceRoot":"","sources":["../../src/services/auth.service.ts"],"names":[],"mappings":"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","sourcesContent":["import { SentryTraced } from \"@sentry/nestjs\"\n\nimport {\n AuthResponseSchema,\n RefreshTokenResponseSchema,\n TargetEnv,\n Tokens,\n TokensResponseSchema,\n urlMap,\n} from \"../types/index.js\"\n\nexport class AuthService {\n @SentryTraced()\n public async getAuthUrlFromServer(env: TargetEnv, codeChallenge: string) {\n const {\n result: { authorizeUrl, readKey },\n } = await fetch(this.getOAuthUrl(env), {\n body: JSON.stringify({\n codeChallenge,\n }),\n headers: {\n \"Content-Type\": \"application/json\",\n },\n method: \"POST\",\n })\n .then(res => res.json())\n .then(async data => AuthResponseSchema.parse(data))\n return { authorizeUrl, readKey }\n }\n\n @SentryTraced()\n public async getTokensFromServer(env: TargetEnv, verifier: string, readKey: string): Promise<Tokens | undefined> {\n let success = false\n let tokens: Tokens | undefined\n let repeatCounts = 300 // five minutes\n while (!success && repeatCounts-- > 0) {\n // eslint-disable-next-line no-await-in-loop\n success = await fetch(`${this.getOAuthUrl(env)}?read_key=${readKey}&code_verifier=${verifier}`)\n .then(response => {\n if (!response.ok) {\n throw new Error(\"Network response was not ok\")\n }\n\n return response.json()\n })\n .then(async data => {\n const body = TokensResponseSchema.parse(data)\n if (body.result.status === \"Success\") {\n tokens = body.result.tokens\n return true\n }\n\n await this.sleep()\n\n return false\n })\n }\n\n return tokens\n }\n\n @SentryTraced()\n public async refreshToken(env: TargetEnv, refreshToken?: string): Promise<Tokens | undefined> {\n if (!refreshToken) return undefined\n\n const authUrl = `${this.getOAuthUrl(env)}/token`\n const response = await fetch(authUrl, {\n body: JSON.stringify({\n // eslint-disable-next-line camelcase\n grant_type: \"refresh_token\",\n // eslint-disable-next-line camelcase\n refresh_token: refreshToken,\n }),\n headers: {\n \"Content-Type\": \"application/json\",\n },\n method: \"POST\",\n })\n\n if (!response.ok) {\n return undefined\n }\n\n const {\n result: { tokens },\n } = RefreshTokenResponseSchema.parse(await response.json())\n return { ...tokens, refreshToken }\n }\n\n @SentryTraced()\n public sleep(ms: number = 5000) {\n return new Promise(resolve => {\n setTimeout(resolve, ms)\n })\n }\n\n private getOAuthUrl(target: TargetEnv): string {\n return urlMap[target]\n }\n}\n"]}
@@ -0,0 +1,3 @@
1
+ export * from './auth.service.js';
2
+ export * from './vault.service.js';
3
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/services/index.ts"],"names":[],"mappings":"AAAA,cAAc,mBAAmB,CAAA;AACjC,cAAc,oBAAoB,CAAA"}
@@ -0,0 +1,3 @@
1
+ export * from './auth.service.js';
2
+ export * from './vault.service.js';
3
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/services/index.ts"],"names":[],"mappings":"AAAA,cAAc,mBAAmB,CAAA;AACjC,cAAc,oBAAoB,CAAA","sourcesContent":["export * from './auth.service.js'\nexport * from './vault.service.js'\n"]}
@@ -0,0 +1,28 @@
1
+ import { TargetEnv, Tokens } from "../types/index.js";
2
+ import { AuthService } from "./auth.service.js";
3
+ export interface IVault {
4
+ deletePassword: (serviceName: string, account: string) => Promise<void>;
5
+ getPassword: (serviceName: string, account: string) => Promise<null | string>;
6
+ setPassword: (serviceName: string, account: string, password: string) => Promise<void>;
7
+ }
8
+ export declare class KeytarVault implements IVault {
9
+ deletePassword(serviceName: string, account: string): Promise<void>;
10
+ getPassword(serviceName: string, account: string): Promise<null | string>;
11
+ setPassword(serviceName: string, account: string, password: string): Promise<void>;
12
+ }
13
+ export declare class VaultService {
14
+ private readonly authService;
15
+ private readonly vault;
16
+ private readonly serviceName;
17
+ constructor(authService?: AuthService, vault?: IVault);
18
+ deleteTokensFromVault(env?: TargetEnv): Promise<void>;
19
+ getLoggedInUser(env?: TargetEnv): Promise<string | undefined>;
20
+ getTokensFromFile(env: TargetEnv): Tokens | undefined;
21
+ getTokensFromVault(env?: TargetEnv): Promise<Tokens>;
22
+ refreshTokens(env: TargetEnv, accessToken: string, refreshToken: string): Promise<Tokens | undefined>;
23
+ storeTokensInFile(env: TargetEnv, tokens?: Tokens): void;
24
+ storeTokensToVault({ accessToken, refreshToken }: Tokens, env?: TargetEnv): Promise<void>;
25
+ supernovaDir(): string;
26
+ tokensFilePath(): string;
27
+ }
28
+ //# sourceMappingURL=vault.service.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"vault.service.d.ts","sourceRoot":"","sources":["../../src/services/vault.service.ts"],"names":[],"mappings":"AAOA,OAAO,EAAoE,SAAS,EAAE,MAAM,EAAE,MAAM,mBAAmB,CAAA;AACvH,OAAO,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAA;AAE/C,MAAM,WAAW,MAAM;IACrB,cAAc,EAAE,CAAC,WAAW,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,CAAA;IACvE,WAAW,EAAE,CAAC,WAAW,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,GAAG,MAAM,CAAC,CAAA;IAC7E,WAAW,EAAE,CAAC,WAAW,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,CAAA;CACvF;AAED,qBAAa,WAAY,YAAW,MAAM;IAClC,cAAc,CAAC,WAAW,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAInE,WAAW,CAAC,WAAW,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,GAAG,MAAM,CAAC;IAIzE,WAAW,CAAC,WAAW,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;CAGzF;AAED,qBAAa,YAAY;IAIrB,OAAO,CAAC,QAAQ,CAAC,WAAW;IAC5B,OAAO,CAAC,QAAQ,CAAC,KAAK;IAJxB,OAAO,CAAC,QAAQ,CAAC,WAAW,CAAc;gBAGvB,WAAW,GAAE,WAA+B,EAC5C,KAAK,GAAE,MAA0B;IAIvC,qBAAqB,CAAC,GAAG,GAAE,SAA4B;IAUvD,eAAe,CAAC,GAAG,GAAE,SAA4B,GAAG,OAAO,CAAC,MAAM,GAAG,SAAS,CAAC;IAWrF,iBAAiB,CAAC,GAAG,EAAE,SAAS,GAAG,MAAM,GAAG,SAAS;IAa/C,kBAAkB,CAAC,GAAG,GAAE,SAA4B,GAAG,OAAO,CAAC,MAAM,CAAC;IA+BtE,aAAa,CAAC,GAAG,EAAE,SAAS,EAAE,WAAW,EAAE,MAAM,EAAE,YAAY,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,GAAG,SAAS,CAAC;IAkB3G,iBAAiB,CAAC,GAAG,EAAE,SAAS,EAAE,MAAM,CAAC,EAAE,MAAM;IAoB3C,kBAAkB,CAAC,EAAE,WAAW,EAAE,YAAY,EAAE,EAAE,MAAM,EAAE,GAAG,GAAE,SAA4B;IAWjG,YAAY,IAAI,MAAM;IAKtB,cAAc,IAAI,MAAM;CAIhC"}
@@ -0,0 +1,181 @@
1
+ var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
2
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
3
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
4
+ else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
5
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
6
+ };
7
+ var __metadata = (this && this.__metadata) || function (k, v) {
8
+ if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
9
+ };
10
+ import { SentryTraced } from "@sentry/nestjs";
11
+ import { jwtDecode } from "jwt-decode";
12
+ import * as keytar from "keytar";
13
+ import * as fs from "node:fs";
14
+ import * as os from "node:os";
15
+ import path from "node:path";
16
+ import { defaultTargetEnv, EnvTokensSchema, NotAuthorizedError } from "../types/index.js";
17
+ import { AuthService } from "./auth.service.js";
18
+ export class KeytarVault {
19
+ async deletePassword(serviceName, account) {
20
+ await keytar.deletePassword(serviceName, account);
21
+ }
22
+ async getPassword(serviceName, account) {
23
+ return keytar.getPassword(serviceName, account);
24
+ }
25
+ async setPassword(serviceName, account, password) {
26
+ await keytar.setPassword(serviceName, account, password);
27
+ }
28
+ }
29
+ export class VaultService {
30
+ authService;
31
+ vault;
32
+ serviceName = "Supernova";
33
+ constructor(authService = new AuthService(), vault = new KeytarVault()) {
34
+ this.authService = authService;
35
+ this.vault = vault;
36
+ }
37
+ async deleteTokensFromVault(env = defaultTargetEnv) {
38
+ try {
39
+ await this.vault.deletePassword(this.serviceName, `${env}_access_token`);
40
+ await this.vault.deletePassword(this.serviceName, `${env}_refresh_token`);
41
+ }
42
+ catch {
43
+ this.storeTokensInFile(env);
44
+ }
45
+ }
46
+ async getLoggedInUser(env = defaultTargetEnv) {
47
+ try {
48
+ const tokens = await this.getTokensFromVault(env);
49
+ const decoded = jwtDecode(tokens.accessToken);
50
+ return decoded.sub;
51
+ }
52
+ catch {
53
+ return undefined;
54
+ }
55
+ }
56
+ getTokensFromFile(env) {
57
+ const filePath = this.tokensFilePath();
58
+ if (!fs.existsSync(filePath)) {
59
+ return undefined;
60
+ }
61
+ const fileContent = fs.readFileSync(filePath, "utf8");
62
+ const data = JSON.parse(fileContent);
63
+ return data[env] ?? {};
64
+ }
65
+ async getTokensFromVault(env = defaultTargetEnv) {
66
+ if (process.env.SUPERNOVA_TOKEN) {
67
+ return { accessToken: process.env.SUPERNOVA_TOKEN };
68
+ }
69
+ let accessToken;
70
+ let refreshToken;
71
+ try {
72
+ accessToken = (await this.vault.getPassword(this.serviceName, `${env}_access_token`)) ?? undefined;
73
+ refreshToken = (await this.vault.getPassword(this.serviceName, `${env}_refresh_token`)) ?? undefined;
74
+ }
75
+ catch {
76
+ const tokens = this.getTokensFromFile(env);
77
+ if (tokens) {
78
+ accessToken = tokens.accessToken;
79
+ refreshToken = tokens.refreshToken;
80
+ }
81
+ }
82
+ if (!accessToken) {
83
+ throw new NotAuthorizedError();
84
+ }
85
+ const freshTokens = refreshToken ? await this.refreshTokens(env, accessToken, refreshToken) : undefined;
86
+ if (freshTokens) {
87
+ return freshTokens;
88
+ }
89
+ return { accessToken, refreshToken };
90
+ }
91
+ async refreshTokens(env, accessToken, refreshToken) {
92
+ const decoded = jwtDecode(accessToken);
93
+ const currentTime = Math.floor(Date.now() / 1000);
94
+ if (decoded.exp && decoded.exp < currentTime + 300) {
95
+ const freshTokens = await this.authService.refreshToken(env, refreshToken);
96
+ if (!freshTokens) {
97
+ await this.deleteTokensFromVault(env);
98
+ throw new NotAuthorizedError();
99
+ }
100
+ await this.storeTokensToVault(freshTokens, env);
101
+ return freshTokens;
102
+ }
103
+ return undefined;
104
+ }
105
+ storeTokensInFile(env, tokens) {
106
+ const supernovaDir = this.supernovaDir();
107
+ const filePath = path.join(supernovaDir, "tokens.json");
108
+ if (!fs.existsSync(supernovaDir)) {
109
+ fs.mkdirSync(supernovaDir, { recursive: true });
110
+ }
111
+ let data = {};
112
+ if (fs.existsSync(filePath)) {
113
+ const fileContent = fs.readFileSync(filePath, "utf8");
114
+ data = EnvTokensSchema.parse(JSON.parse(fileContent));
115
+ }
116
+ data[env] = tokens;
117
+ fs.writeFileSync(filePath, JSON.stringify(data, null, 2), "utf8");
118
+ }
119
+ async storeTokensToVault({ accessToken, refreshToken }, env = defaultTargetEnv) {
120
+ try {
121
+ await this.vault.setPassword(this.serviceName, `${env}_access_token`, accessToken);
122
+ if (refreshToken) {
123
+ await this.vault.setPassword(this.serviceName, `${env}_refresh_token`, refreshToken);
124
+ }
125
+ }
126
+ catch {
127
+ this.storeTokensInFile(env, { accessToken, refreshToken });
128
+ }
129
+ }
130
+ supernovaDir() {
131
+ const homeDir = os.homedir();
132
+ return path.join(homeDir, ".supernova");
133
+ }
134
+ tokensFilePath() {
135
+ const homeDir = this.supernovaDir();
136
+ return path.join(homeDir, "tokens.json");
137
+ }
138
+ }
139
+ __decorate([
140
+ SentryTraced(),
141
+ __metadata("design:type", Function),
142
+ __metadata("design:paramtypes", [String]),
143
+ __metadata("design:returntype", Promise)
144
+ ], VaultService.prototype, "deleteTokensFromVault", null);
145
+ __decorate([
146
+ SentryTraced(),
147
+ __metadata("design:type", Function),
148
+ __metadata("design:paramtypes", [String]),
149
+ __metadata("design:returntype", Promise)
150
+ ], VaultService.prototype, "getLoggedInUser", null);
151
+ __decorate([
152
+ SentryTraced(),
153
+ __metadata("design:type", Function),
154
+ __metadata("design:paramtypes", [String]),
155
+ __metadata("design:returntype", Object)
156
+ ], VaultService.prototype, "getTokensFromFile", null);
157
+ __decorate([
158
+ SentryTraced(),
159
+ __metadata("design:type", Function),
160
+ __metadata("design:paramtypes", [String]),
161
+ __metadata("design:returntype", Promise)
162
+ ], VaultService.prototype, "getTokensFromVault", null);
163
+ __decorate([
164
+ SentryTraced(),
165
+ __metadata("design:type", Function),
166
+ __metadata("design:paramtypes", [String, String, String]),
167
+ __metadata("design:returntype", Promise)
168
+ ], VaultService.prototype, "refreshTokens", null);
169
+ __decorate([
170
+ SentryTraced(),
171
+ __metadata("design:type", Function),
172
+ __metadata("design:paramtypes", [String, Object]),
173
+ __metadata("design:returntype", void 0)
174
+ ], VaultService.prototype, "storeTokensInFile", null);
175
+ __decorate([
176
+ SentryTraced(),
177
+ __metadata("design:type", Function),
178
+ __metadata("design:paramtypes", [Object, String]),
179
+ __metadata("design:returntype", Promise)
180
+ ], VaultService.prototype, "storeTokensToVault", null);
181
+ //# sourceMappingURL=vault.service.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"vault.service.js","sourceRoot":"","sources":["../../src/services/vault.service.ts"],"names":[],"mappings":"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","sourcesContent":["import { SentryTraced } from \"@sentry/nestjs\"\nimport { jwtDecode } from \"jwt-decode\"\nimport * as keytar from \"keytar\"\nimport * as fs from \"node:fs\"\nimport * as os from \"node:os\"\nimport path from \"node:path\"\n\nimport { defaultTargetEnv, EnvTokens, EnvTokensSchema, NotAuthorizedError, TargetEnv, Tokens } from \"../types/index.js\"\nimport { AuthService } from \"./auth.service.js\"\n\nexport interface IVault {\n deletePassword: (serviceName: string, account: string) => Promise<void>\n getPassword: (serviceName: string, account: string) => Promise<null | string>\n setPassword: (serviceName: string, account: string, password: string) => Promise<void>\n}\n\nexport class KeytarVault implements IVault {\n async deletePassword(serviceName: string, account: string): Promise<void> {\n await keytar.deletePassword(serviceName, account)\n }\n\n async getPassword(serviceName: string, account: string): Promise<null | string> {\n return keytar.getPassword(serviceName, account)\n }\n\n async setPassword(serviceName: string, account: string, password: string): Promise<void> {\n await keytar.setPassword(serviceName, account, password)\n }\n}\n\nexport class VaultService {\n private readonly serviceName = \"Supernova\"\n\n constructor(\n private readonly authService: AuthService = new AuthService(),\n private readonly vault: IVault = new KeytarVault(),\n ) {}\n\n @SentryTraced()\n public async deleteTokensFromVault(env: TargetEnv = defaultTargetEnv) {\n try {\n await this.vault.deletePassword(this.serviceName, `${env}_access_token`)\n await this.vault.deletePassword(this.serviceName, `${env}_refresh_token`)\n } catch {\n this.storeTokensInFile(env)\n }\n }\n\n @SentryTraced()\n public async getLoggedInUser(env: TargetEnv = defaultTargetEnv): Promise<string | undefined> {\n try {\n const tokens = await this.getTokensFromVault(env)\n const decoded = jwtDecode<{ sub?: string }>(tokens.accessToken)\n return decoded.sub\n } catch {\n return undefined\n }\n }\n\n @SentryTraced()\n public getTokensFromFile(env: TargetEnv): Tokens | undefined {\n const filePath = this.tokensFilePath()\n\n if (!fs.existsSync(filePath)) {\n return undefined\n }\n\n const fileContent = fs.readFileSync(filePath, \"utf8\")\n const data = JSON.parse(fileContent)\n return data[env] ?? {}\n }\n\n @SentryTraced()\n public async getTokensFromVault(env: TargetEnv = defaultTargetEnv): Promise<Tokens> {\n if (process.env.SUPERNOVA_TOKEN) {\n return { accessToken: process.env.SUPERNOVA_TOKEN }\n }\n\n let accessToken: string | undefined\n let refreshToken: string | undefined\n try {\n accessToken = (await this.vault.getPassword(this.serviceName, `${env}_access_token`)) ?? undefined\n refreshToken = (await this.vault.getPassword(this.serviceName, `${env}_refresh_token`)) ?? undefined\n } catch {\n const tokens = this.getTokensFromFile(env)\n if (tokens) {\n accessToken = tokens.accessToken\n refreshToken = tokens.refreshToken\n }\n }\n\n if (!accessToken) {\n throw new NotAuthorizedError()\n }\n\n const freshTokens = refreshToken ? await this.refreshTokens(env, accessToken, refreshToken) : undefined\n if (freshTokens) {\n return freshTokens\n }\n\n return { accessToken, refreshToken }\n }\n\n @SentryTraced()\n public async refreshTokens(env: TargetEnv, accessToken: string, refreshToken: string): Promise<Tokens | undefined> {\n const decoded = jwtDecode<{ exp?: number }>(accessToken)\n const currentTime = Math.floor(Date.now() / 1000)\n if (decoded.exp && decoded.exp < currentTime + 300) {\n const freshTokens = await this.authService.refreshToken(env, refreshToken)\n if (!freshTokens) {\n await this.deleteTokensFromVault(env)\n throw new NotAuthorizedError()\n }\n\n await this.storeTokensToVault(freshTokens, env)\n return freshTokens\n }\n\n return undefined\n }\n\n @SentryTraced()\n public storeTokensInFile(env: TargetEnv, tokens?: Tokens) {\n const supernovaDir = this.supernovaDir()\n const filePath = path.join(supernovaDir, \"tokens.json\")\n\n if (!fs.existsSync(supernovaDir)) {\n fs.mkdirSync(supernovaDir, { recursive: true })\n }\n\n let data: EnvTokens = {} as EnvTokens\n if (fs.existsSync(filePath)) {\n const fileContent = fs.readFileSync(filePath, \"utf8\")\n data = EnvTokensSchema.parse(JSON.parse(fileContent))\n }\n\n data[env] = tokens\n\n fs.writeFileSync(filePath, JSON.stringify(data, null, 2), \"utf8\")\n }\n\n @SentryTraced()\n public async storeTokensToVault({ accessToken, refreshToken }: Tokens, env: TargetEnv = defaultTargetEnv) {\n try {\n await this.vault.setPassword(this.serviceName, `${env}_access_token`, accessToken)\n if (refreshToken) {\n await this.vault.setPassword(this.serviceName, `${env}_refresh_token`, refreshToken)\n }\n } catch {\n this.storeTokensInFile(env, { accessToken, refreshToken })\n }\n }\n\n public supernovaDir(): string {\n const homeDir = os.homedir()\n return path.join(homeDir, \".supernova\")\n }\n\n public tokensFilePath(): string {\n const homeDir = this.supernovaDir()\n return path.join(homeDir, \"tokens.json\")\n }\n}\n"]}
@@ -0,0 +1,23 @@
1
+ import { Command } from "@oclif/core";
2
+ import { Input, ParserOutput } from "@oclif/core/interfaces";
3
+ import { ArgOutput, FlagOutput } from "@oclif/core/lib/interfaces/parser.js";
4
+ import { SupernovaApiClient } from "@supernova-studio/client";
5
+ import { z } from "zod";
6
+ import { ConfigService } from "../utils/config.service.js";
7
+ import { TargetEnv } from "./login.js";
8
+ export declare abstract class BaseCommand<T extends object> extends Command {
9
+ protected configService: ConfigService;
10
+ private apiClientForEnv;
11
+ abstract get commandId(): string;
12
+ abstract get configSchema(): z.ZodType<T>;
13
+ protected apiClient(env: TargetEnv): Promise<SupernovaApiClient>;
14
+ protected getBrandId(env: TargetEnv, designSystemId: string, versionId: string, brandId?: string): Promise<string>;
15
+ protected getDesignSystemId(env: TargetEnv, designSystemId?: string): Promise<string>;
16
+ protected getVersionId(env: TargetEnv, designSystemId: string, versionId?: string): Promise<string>;
17
+ protected getWorkspaceId(env: TargetEnv, workspaceId?: string): Promise<string>;
18
+ parse<F extends FlagOutput, B extends FlagOutput, A extends ArgOutput>(options?: Input<F, B, A>, argv?: string[]): Promise<ParserOutput<F, B, A>>;
19
+ protected saveConfig(config: Record<string, unknown>): void;
20
+ private promptWithExit;
21
+ private removeUndefinedValues;
22
+ }
23
+ //# sourceMappingURL=base-command.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"base-command.d.ts","sourceRoot":"","sources":["../../src/types/base-command.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,aAAa,CAAA;AACrC,OAAO,EAAE,KAAK,EAAE,YAAY,EAAE,MAAM,wBAAwB,CAAA;AAG5D,OAAO,EAAE,SAAS,EAAE,UAAU,EAAE,MAAM,sCAAsC,CAAA;AAC5E,OAAO,EAAmB,kBAAkB,EAAE,MAAM,0BAA0B,CAAA;AAE9E,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAA;AAEvB,OAAO,EAAE,aAAa,EAAE,MAAM,4BAA4B,CAAA;AAE1D,OAAO,EAAE,SAAS,EAAE,MAAM,YAAY,CAAA;AAKtC,8BAAsB,WAAW,CAAC,CAAC,SAAS,MAAM,CAAE,SAAQ,OAAO;IACjE,SAAS,CAAC,aAAa,gBAA8B;IACrD,OAAO,CAAC,eAAe,CAAgD;IAEvE,QAAQ,KAAK,SAAS,IAAI,MAAM,CAAA;IAChC,QAAQ,KAAK,YAAY,IAAI,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,CAAA;cAEzB,SAAS,CAAC,GAAG,EAAE,SAAS,GAAG,OAAO,CAAC,kBAAkB,CAAC;cAUtD,UAAU,CACxB,GAAG,EAAE,SAAS,EACd,cAAc,EAAE,MAAM,EACtB,SAAS,EAAE,MAAM,EACjB,OAAO,CAAC,EAAE,MAAM,GACf,OAAO,CAAC,MAAM,CAAC;cA2BF,iBAAiB,CAAC,GAAG,EAAE,SAAS,EAAE,cAAc,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;cAyC3E,YAAY,CAAC,GAAG,EAAE,SAAS,EAAE,cAAc,EAAE,MAAM,EAAE,SAAS,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;cAqBzF,cAAc,CAAC,GAAG,EAAE,SAAS,EAAE,WAAW,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;IAyBxE,KAAK,CAAC,CAAC,SAAS,UAAU,EAAE,CAAC,SAAS,UAAU,EAAE,CAAC,SAAS,SAAS,EAChF,OAAO,CAAC,EAAE,KAAK,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,EACxB,IAAI,CAAC,EAAE,MAAM,EAAE,GACd,OAAO,CAAC,YAAY,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC;IAOjC,SAAS,CAAC,UAAU,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI;YAI7C,cAAc;IAiB5B,OAAO,CAAC,qBAAqB;CAS9B"}