@interactivethings/scripts 2.0.4 → 2.1.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.
package/dist/cli.js CHANGED
@@ -69,28 +69,37 @@ async function main() {
69
69
  const vercelParser = subparsers.add_parser("vercel", {
70
70
  help: "Vercel utilities",
71
71
  });
72
+ // Cloudflare subcommand
73
+ const cloudflareParser = subparsers.add_parser("cloudflare", {
74
+ help: "Cloudflare utilities",
75
+ });
72
76
  // Import and configure all subcommands
73
- const { configParser: configureInitParser, run: runInit } = await Promise.resolve().then(() => __importStar(require("./init/cli")));
74
- const { configParser: configureFigmaParser, run: runFigma } = await Promise.resolve().then(() => __importStar(require("./figma/cli")));
75
- const { configParser: configureTokensStudioParser, run: runTokensStudio } = await Promise.resolve().then(() => __importStar(require("./tokens-studio/cli")));
76
- const { configParser: configureVercelParser, run: runVercel } = await Promise.resolve().then(() => __importStar(require("./vercel/cli")));
77
- configureInitParser(initParser);
78
- configureFigmaParser(figmaParser);
79
- configureTokensStudioParser(tokensStudioParser);
80
- configureVercelParser(vercelParser);
77
+ const { default: initModule } = await Promise.resolve().then(() => __importStar(require("./init/cli")));
78
+ const { default: figmaModule } = await Promise.resolve().then(() => __importStar(require("./figma/cli")));
79
+ const { default: tokensStudioModule } = await Promise.resolve().then(() => __importStar(require("./tokens-studio/cli")));
80
+ const { default: vercelModule } = await Promise.resolve().then(() => __importStar(require("./vercel/cli")));
81
+ const { default: cloudflareModule } = await Promise.resolve().then(() => __importStar(require("./cloudflare/cli")));
82
+ initModule.configParser(initParser);
83
+ figmaModule.configParser(figmaParser);
84
+ tokensStudioModule.configParser(tokensStudioParser);
85
+ vercelModule.configParser(vercelParser);
86
+ cloudflareModule.configParser(cloudflareParser);
81
87
  const args = parser.parse_args();
82
88
  switch (args.command) {
83
89
  case "init":
84
- await runInit(args);
90
+ await initModule.run(args);
85
91
  break;
86
92
  case "figma":
87
- await runFigma(args);
93
+ await figmaModule.run(args);
88
94
  break;
89
95
  case "tokens-studio":
90
- await runTokensStudio(args);
96
+ await tokensStudioModule.run(args);
91
97
  break;
92
98
  case "vercel":
93
- await runVercel(args);
99
+ await vercelModule.run(args);
100
+ break;
101
+ case "cloudflare":
102
+ await cloudflareModule.run(args);
94
103
  break;
95
104
  default:
96
105
  parser.print_help();
@@ -0,0 +1,90 @@
1
+ #!/usr/bin/env node
2
+ "use strict";
3
+ Object.defineProperty(exports, "__esModule", { value: true });
4
+ const deployments_1 = require("./deployments");
5
+ const argparse_1 = require("argparse");
6
+ const config_1 = require("../config");
7
+ const cli_1 = require("../shared/cli");
8
+ const configParser = (parser) => {
9
+ const commands = parser.add_subparsers({
10
+ title: "Cloudflare commands",
11
+ dest: "subcommand",
12
+ help: "Use 'ixt cloudflare <command> --help' for more information",
13
+ });
14
+ // wait-deployment subcommand
15
+ const waitDeploymentParser = commands.add_parser("wait-deployment", {
16
+ help: "Wait for a Cloudflare deployment to complete",
17
+ });
18
+ waitDeploymentParser.add_argument("commit", {
19
+ help: "Commit that started the deployment",
20
+ });
21
+ waitDeploymentParser.add_argument("--interval", {
22
+ default: 5000,
23
+ type: Number,
24
+ });
25
+ waitDeploymentParser.add_argument("--project", {
26
+ help: "Cloudflare project name",
27
+ });
28
+ waitDeploymentParser.add_argument("--email", {
29
+ help: "Cloudflare account email",
30
+ });
31
+ waitDeploymentParser.add_argument("--account-id", {
32
+ help: "Cloudflare account ID",
33
+ });
34
+ waitDeploymentParser.add_argument("--timeout", {
35
+ default: 10 * 60 * 1000,
36
+ type: Number,
37
+ });
38
+ };
39
+ const run = async (args) => {
40
+ const config = await (0, config_1.loadConfig)(args.config);
41
+ const apiKey = process.env.CLOUDFLARE_API_KEY;
42
+ if (!apiKey) {
43
+ throw new Error("CLOUDFLARE_API_KEY environment variable is required");
44
+ }
45
+ switch (args.subcommand) {
46
+ case "wait-deployment":
47
+ // Merge config with CLI args
48
+ const mergedConfig = (0, config_1.mergeConfigWithArgs)(config, args, "cloudflare");
49
+ // Map CLI args to match the expected format
50
+ const finalConfig = {
51
+ ...mergedConfig,
52
+ accountId: mergedConfig.account_id || mergedConfig.accountId,
53
+ };
54
+ // Validate required fields
55
+ (0, config_1.validateRequiredConfig)(finalConfig, ["project", "email", "accountId"]);
56
+ const deployment = await (0, deployments_1.waitForDeploymentReady)({
57
+ accountId: finalConfig.accountId,
58
+ project: finalConfig.project,
59
+ email: finalConfig.email,
60
+ apiKey,
61
+ commitSha: args.commit,
62
+ interval: args.interval,
63
+ timeout: args.timeout,
64
+ });
65
+ if (!deployment) {
66
+ throw new Error("Could not retrieve deployment");
67
+ }
68
+ console.log(`DEPLOYMENT_URL=${deployment.url}`);
69
+ break;
70
+ }
71
+ };
72
+ exports.default = (0, cli_1.defineCLIModule)({
73
+ configParser,
74
+ run,
75
+ });
76
+ async function main() {
77
+ const parser = new argparse_1.ArgumentParser({
78
+ description: "Cloudflare deployment utilities",
79
+ });
80
+ const args = parser.parse_args();
81
+ configParser(parser);
82
+ await run(args);
83
+ }
84
+ // Only run main if this file is being executed directly
85
+ if (require.main === module) {
86
+ main().catch((e) => {
87
+ console.error(e);
88
+ process.exit(1);
89
+ });
90
+ }
@@ -0,0 +1,44 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.CloudflareDeploymentService = void 0;
7
+ const assert_1 = __importDefault(require("assert"));
8
+ const getDeploymentState = (deployment) => {
9
+ return deployment.latest_stage.name === "deploy" &&
10
+ deployment.latest_stage.status === "success"
11
+ ? "READY"
12
+ : "BUILDING";
13
+ };
14
+ const getDeploymentUrl = (deployment) => {
15
+ return deployment.url;
16
+ };
17
+ class CloudflareDeploymentService {
18
+ constructor(accountId, projectName, email, apiKey) {
19
+ this.accountId = accountId;
20
+ this.projectName = projectName;
21
+ this.email = email;
22
+ this.apiKey = apiKey;
23
+ }
24
+ async fetchForCommit(commitSha) {
25
+ const url = `https://api.cloudflare.com/client/v4/accounts/${this.accountId}/pages/projects/${this.projectName}/deployments`;
26
+ const headers = {
27
+ "X-Auth-Email": this.email,
28
+ "X-Auth-Key": this.apiKey,
29
+ };
30
+ const response = await fetch(url, { headers })
31
+ .then((x) => x.json())
32
+ .then((x) => x);
33
+ if (!response.success) {
34
+ throw new Error(`Cloudflare API request was not successful. Errors: ${JSON.stringify(response.errors)}`);
35
+ }
36
+ (0, assert_1.default)(response.success, "Cloudflare API request was not successful");
37
+ const deployments = response.result.filter((deployment) => deployment.deployment_trigger.metadata.commit_hash === commitSha);
38
+ return deployments.map((d) => ({
39
+ state: getDeploymentState(d),
40
+ url: getDeploymentUrl(d),
41
+ }));
42
+ }
43
+ }
44
+ exports.CloudflareDeploymentService = CloudflareDeploymentService;
@@ -0,0 +1,14 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.waitForDeploymentReady = waitForDeploymentReady;
4
+ const wait_deployment_1 = require("../shared/wait-deployment");
5
+ const cloudflare_1 = require("./cloudflare");
6
+ async function waitForDeploymentReady({ accountId, project, email, apiKey, commitSha, interval, timeout, }) {
7
+ const service = new cloudflare_1.CloudflareDeploymentService(accountId, project, email, apiKey);
8
+ return await (0, wait_deployment_1.waitForDeploymentReady)({
9
+ commitSha,
10
+ interval,
11
+ timeout,
12
+ deploymentService: service,
13
+ });
14
+ }
package/dist/config.js CHANGED
@@ -33,7 +33,7 @@ var __importStar = (this && this.__importStar) || (function () {
33
33
  };
34
34
  })();
35
35
  Object.defineProperty(exports, "__esModule", { value: true });
36
- exports.IxtConfigSchema = exports.VercelConfigSchema = exports.TokensStudioConfigSchema = exports.FigmaConfigSchema = exports.FigmaAssetConfigSchema = void 0;
36
+ exports.IxtConfigSchema = exports.CloudflareConfigSchema = exports.VercelConfigSchema = exports.TokensStudioConfigSchema = exports.FigmaConfigSchema = exports.FigmaAssetConfigSchema = void 0;
37
37
  exports.defineConfig = defineConfig;
38
38
  exports.loadConfig = loadConfig;
39
39
  exports.mergeConfigWithArgs = mergeConfigWithArgs;
@@ -73,11 +73,8 @@ exports.TokensStudioConfigSchema = zod_1.z.object({
73
73
  output: zod_1.z
74
74
  .string()
75
75
  .optional()
76
- .describe("Default output file path for transformations"),
77
- handler: zod_1.z
78
- .string()
79
- .optional()
80
- .describe("Default path to the transformer handler file"),
76
+ .describe("Output directory for transformed tokens"),
77
+ handler: zod_1.z.string().describe("Path to the transformer file"),
81
78
  });
82
79
  /**
83
80
  * Vercel configuration schema
@@ -86,6 +83,14 @@ exports.VercelConfigSchema = zod_1.z.object({
86
83
  team: zod_1.z.string().optional().describe("Vercel team name (organization)"),
87
84
  project: zod_1.z.string().optional().describe("Vercel project name"),
88
85
  });
86
+ /**
87
+ * Cloudflare configuration schema
88
+ */
89
+ exports.CloudflareConfigSchema = zod_1.z.object({
90
+ project: zod_1.z.string().optional().describe("Cloudflare project name"),
91
+ email: zod_1.z.string().optional().describe("Cloudflare account email"),
92
+ accountId: zod_1.z.string().optional().describe("Cloudflare account ID"),
93
+ });
89
94
  /**
90
95
  * Main IXT Scripts configuration schema
91
96
  */
@@ -93,6 +98,7 @@ exports.IxtConfigSchema = zod_1.z.object({
93
98
  figma: exports.FigmaConfigSchema.optional().describe("Figma-related configuration"),
94
99
  tokensStudio: exports.TokensStudioConfigSchema.optional().describe("Tokens Studio configuration"),
95
100
  vercel: exports.VercelConfigSchema.optional().describe("Vercel deployment configuration"),
101
+ cloudflare: exports.CloudflareConfigSchema.optional().describe("Cloudflare deployment configuration"),
96
102
  });
97
103
  /**
98
104
  * Helper function for type-safe configuration definition
@@ -141,7 +147,7 @@ async function loadConfig(configPath) {
141
147
  }
142
148
  }
143
149
  // No config file found, return default config
144
- return DEFAULT_CONFIG;
150
+ throw new Error(`No configuration file found. Please create an ixt.config.ts file in the current directory.`);
145
151
  }
146
152
  /**
147
153
  * Merge CLI arguments with configuration
package/dist/figma/cli.js CHANGED
@@ -53,7 +53,6 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
53
53
  return (mod && mod.__esModule) ? mod : { "default": mod };
54
54
  };
55
55
  Object.defineProperty(exports, "__esModule", { value: true });
56
- exports.run = exports.configParser = void 0;
57
56
  const fs = __importStar(require("fs/promises"));
58
57
  const path = __importStar(require("path"));
59
58
  const argparse_1 = require("argparse");
@@ -62,6 +61,7 @@ const api_1 = require("./api");
62
61
  const utils_1 = require("./utils");
63
62
  const config_1 = require("../config");
64
63
  const images_1 = require("./images");
64
+ const cli_1 = require("../shared/cli");
65
65
  const configParser = (parser) => {
66
66
  parser.add_argument("--token", {
67
67
  help: "Figma API token (can also use FIGMA_TOKEN env var)",
@@ -86,7 +86,6 @@ const configParser = (parser) => {
86
86
  help: "The Figma URL to fetch the node from",
87
87
  });
88
88
  };
89
- exports.configParser = configParser;
90
89
  const run = async (args) => {
91
90
  // Load configuration
92
91
  const config = await (0, config_1.loadConfig)(args.config);
@@ -145,14 +144,17 @@ const run = async (args) => {
145
144
  console.log(JSON.stringify(node, null, 2));
146
145
  }
147
146
  };
148
- exports.run = run;
147
+ exports.default = (0, cli_1.defineCLIModule)({
148
+ configParser,
149
+ run,
150
+ });
149
151
  const main = async () => {
150
152
  const parser = new argparse_1.ArgumentParser({
151
153
  description: "Download assets from Figma",
152
154
  });
153
- (0, exports.configParser)(parser);
155
+ configParser(parser);
154
156
  const args = parser.parse_args();
155
- await (0, exports.run)(args);
157
+ await run(args);
156
158
  };
157
159
  // Only run main if this file is being executed directly
158
160
  if (require.main === module) {
@@ -38,9 +38,10 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
38
38
  Object.defineProperty(exports, "__esModule", { value: true });
39
39
  const vitest_1 = require("vitest");
40
40
  const argparse_1 = require("argparse");
41
- const cli_1 = require("./cli");
41
+ const cli_1 = __importDefault(require("./cli"));
42
42
  const fs = __importStar(require("fs/promises"));
43
43
  const path_1 = __importDefault(require("path"));
44
+ const { run, configParser } = cli_1.default;
44
45
  // Mock the API and other dependencies
45
46
  vitest_1.vi.mock("../figma/api", () => ({
46
47
  createAPI: vitest_1.vi.fn(),
@@ -94,7 +95,7 @@ const config_1 = require("../config");
94
95
  (0, vitest_1.it)("should configure the argument parser correctly", () => {
95
96
  const parser = new argparse_1.ArgumentParser();
96
97
  const addSubparsersSpy = vitest_1.vi.spyOn(parser, "add_subparsers");
97
- (0, cli_1.configParser)(parser);
98
+ configParser(parser);
98
99
  (0, vitest_1.expect)(addSubparsersSpy).toHaveBeenCalledWith({
99
100
  title: "commands",
100
101
  dest: "subcommand",
@@ -127,7 +128,7 @@ const config_1 = require("../config");
127
128
  config: undefined,
128
129
  token: undefined,
129
130
  };
130
- await (0, cli_1.run)(args);
131
+ await run(args);
131
132
  (0, vitest_1.expect)(config_1.loadConfig).toHaveBeenCalledWith(undefined);
132
133
  (0, vitest_1.expect)(api_1.createAPI).toHaveBeenCalledWith("test-token");
133
134
  (0, vitest_1.expect)(mockAPI.images.fetch).toHaveBeenCalled();
@@ -146,7 +147,7 @@ const config_1 = require("../config");
146
147
  config: undefined,
147
148
  token: undefined,
148
149
  };
149
- await (0, vitest_1.expect)((0, cli_1.run)(args)).rejects.toThrow("No figma assets configured");
150
+ await (0, vitest_1.expect)(run(args)).rejects.toThrow("No figma assets configured");
150
151
  });
151
152
  (0, vitest_1.it)("should throw error when asset is not found", async () => {
152
153
  vitest_1.vi.mocked(config_1.mergeConfigWithArgs).mockReturnValue({
@@ -165,7 +166,7 @@ const config_1 = require("../config");
165
166
  config: undefined,
166
167
  token: undefined,
167
168
  };
168
- await (0, vitest_1.expect)((0, cli_1.run)(args)).rejects.toThrow('No asset configuration found for name "test-assets"');
169
+ await (0, vitest_1.expect)(run(args)).rejects.toThrow('No asset configuration found for name "test-assets"');
169
170
  });
170
171
  });
171
172
  (0, vitest_1.describe)("get subcommand", () => {
@@ -178,7 +179,7 @@ const config_1 = require("../config");
178
179
  config: undefined,
179
180
  token: undefined,
180
181
  };
181
- await (0, cli_1.run)(args);
182
+ await run(args);
182
183
  (0, vitest_1.expect)(mockAPI.nodes.fetch).toHaveBeenCalled();
183
184
  (0, vitest_1.expect)(vitest_1.vi.mocked(console.log)).toHaveBeenCalledWith(JSON.stringify(mockNodeData, null, 2));
184
185
  });
@@ -190,7 +191,7 @@ const config_1 = require("../config");
190
191
  config: undefined,
191
192
  token: undefined,
192
193
  };
193
- await (0, cli_1.run)(args);
194
+ await run(args);
194
195
  (0, vitest_1.expect)(config_1.validateRequiredConfig).toHaveBeenCalledWith(vitest_1.expect.objectContaining({ token: "test-token" }), ["token"]);
195
196
  });
196
197
  });
package/dist/init/cli.js CHANGED
@@ -36,19 +36,18 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
36
36
  return (mod && mod.__esModule) ? mod : { "default": mod };
37
37
  };
38
38
  Object.defineProperty(exports, "__esModule", { value: true });
39
- exports.configParser = configParser;
40
- exports.run = run;
41
39
  const fs = __importStar(require("fs/promises"));
42
40
  const path = __importStar(require("path"));
43
41
  const prompts_1 = __importDefault(require("prompts"));
44
42
  const ora_1 = __importDefault(require("ora"));
45
- function configParser(parser) {
43
+ const cli_1 = require("../shared/cli");
44
+ const configParser = (parser) => {
46
45
  parser.add_argument("--force", {
47
46
  action: "store_true",
48
47
  help: "Overwrite existing configuration files",
49
48
  });
50
- }
51
- async function run(args) {
49
+ };
50
+ const run = async (args) => {
52
51
  console.log("🚀 Welcome to Interactive Things Scripts setup!\n");
53
52
  console.log("This wizard will help you configure your project for optimal development workflow.\n");
54
53
  // Check if config already exists
@@ -103,7 +102,11 @@ async function run(args) {
103
102
  spinner.fail("Setup failed");
104
103
  throw error;
105
104
  }
106
- }
105
+ };
106
+ exports.default = (0, cli_1.defineCLIModule)({
107
+ configParser,
108
+ run,
109
+ });
107
110
  async function collectUserPreferences() {
108
111
  const questions = [
109
112
  {
@@ -247,11 +250,8 @@ function generateConfig(answers) {
247
250
  config.tokensStudio = {
248
251
  input: answers.tokensInputDir,
249
252
  output: answers.tokensOutputFile,
253
+ handler: `./ixt/transforms/${answers.stylingFramework}-transform.ts`,
250
254
  };
251
- // Add handler path based on styling framework choice
252
- if (answers.stylingFramework && answers.stylingFramework !== "custom") {
253
- config.tokensStudio.handler = `./ixt/transforms/${answers.stylingFramework}-transform.ts`;
254
- }
255
255
  }
256
256
  if (answers.useVercel && (answers.vercelTeam || answers.vercelProject)) {
257
257
  config.vercel = {};
@@ -0,0 +1,13 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.defineCLIModule = defineCLIModule;
4
+ /**
5
+ * Type-safe factory function for creating CLI modules
6
+ * Provides consistent interface and utilities for all CLI modules
7
+ */
8
+ function defineCLIModule(config) {
9
+ return {
10
+ configParser: config.configParser,
11
+ run: config.run,
12
+ };
13
+ }
@@ -0,0 +1,2 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
@@ -0,0 +1,29 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.waitForDeploymentReady = waitForDeploymentReady;
4
+ const sleep = (duration) => new Promise((resolve) => setTimeout(resolve, duration));
5
+ async function waitForDeploymentReady({ commitSha, interval, timeout, deploymentService, }) {
6
+ const start = Date.now();
7
+ const end = start + timeout;
8
+ while (Date.now() < end) {
9
+ const deployments = await deploymentService.fetchForCommit(commitSha);
10
+ if (deployments.length === 0) {
11
+ throw new Error(`No available deployments for commit ${commitSha}`);
12
+ }
13
+ if (deployments[0].state !== "READY") {
14
+ const state = deployments[0].state;
15
+ if (state === "ERROR") {
16
+ throw new Error("Deployment errored");
17
+ }
18
+ console.log(`Deployment not yet ready (state: ${state}), waiting ${interval}ms for deployment with commit ${commitSha}`);
19
+ await sleep(Math.min(end - Date.now(), interval));
20
+ }
21
+ else {
22
+ console.log(`Deployment for commit ${commitSha} is READY`);
23
+ return deployments[0];
24
+ }
25
+ }
26
+ if (Date.now() > end) {
27
+ throw new Error("Timeout for waitForDeploymentReady");
28
+ }
29
+ }
@@ -38,12 +38,12 @@ var __importStar = (this && this.__importStar) || (function () {
38
38
  };
39
39
  })();
40
40
  Object.defineProperty(exports, "__esModule", { value: true });
41
- exports.run = exports.configParser = void 0;
42
41
  const fs = __importStar(require("fs"));
43
42
  const path = __importStar(require("path"));
44
43
  const config_1 = require("../config");
45
44
  const utils_1 = require("./utils");
46
45
  const require_1 = require("./require");
46
+ const cli_1 = require("../shared/cli");
47
47
  const readJsonFile = (filePath) => {
48
48
  return JSON.parse(fs.readFileSync(filePath, "utf-8"));
49
49
  };
@@ -83,7 +83,6 @@ const configParser = (parser) => {
83
83
  help: "Output file path (e.g., theme.json)",
84
84
  });
85
85
  };
86
- exports.configParser = configParser;
87
86
  const run = async (args) => {
88
87
  switch (args.subcommand) {
89
88
  case "transform":
@@ -127,7 +126,10 @@ const run = async (args) => {
127
126
  throw new Error(`Unknown subcommand: ${args.subcommand}`);
128
127
  }
129
128
  };
130
- exports.run = run;
129
+ exports.default = (0, cli_1.defineCLIModule)({
130
+ configParser,
131
+ run,
132
+ });
131
133
  const sortKeysRecursively = (obj) => {
132
134
  if (Array.isArray(obj)) {
133
135
  return obj.map(sortKeysRecursively);
@@ -32,15 +32,19 @@ var __importStar = (this && this.__importStar) || (function () {
32
32
  return result;
33
33
  };
34
34
  })();
35
+ var __importDefault = (this && this.__importDefault) || function (mod) {
36
+ return (mod && mod.__esModule) ? mod : { "default": mod };
37
+ };
35
38
  Object.defineProperty(exports, "__esModule", { value: true });
36
39
  const vitest_1 = require("vitest");
37
40
  const fs = __importStar(require("fs"));
38
41
  const path = __importStar(require("path"));
39
42
  const argparse_1 = require("argparse");
40
- const cli_1 = require("./cli");
43
+ const cli_1 = __importDefault(require("./cli"));
41
44
  const config = __importStar(require("../config"));
42
45
  const require_1 = require("./require");
43
46
  const testTransformer = __importStar(require("./__tests__/fixtures/test-transformer"));
47
+ const { run, configParser } = cli_1.default;
44
48
  // Mock dependencies
45
49
  vitest_1.vi.mock("fs");
46
50
  vitest_1.vi.mock("../config");
@@ -75,6 +79,8 @@ vitest_1.vi.mock("./require", () => ({
75
79
  mockedConfig.loadConfig.mockResolvedValue({
76
80
  tokensStudio: {
77
81
  input: "./tokens",
82
+ output: "./output.json",
83
+ handler: "./transformer.ts",
78
84
  },
79
85
  });
80
86
  mockedConfig.mergeConfigWithArgs.mockReturnValue({
@@ -96,7 +102,7 @@ vitest_1.vi.mock("./require", () => ({
96
102
  const parser = new argparse_1.ArgumentParser({ description: "Test parser" });
97
103
  const addArgumentSpy = vitest_1.vi.spyOn(parser, "add_argument");
98
104
  const addSubparsersSpy = vitest_1.vi.spyOn(parser, "add_subparsers");
99
- (0, cli_1.configParser)(parser);
105
+ configParser(parser);
100
106
  // Check that config argument is added
101
107
  (0, vitest_1.expect)(addArgumentSpy).toHaveBeenCalledWith("--config", {
102
108
  help: "Path to TypeScript config file (default: looks for ixt.config.ts in current directory)",
@@ -127,7 +133,7 @@ vitest_1.vi.mock("./require", () => ({
127
133
  input: tokensDir,
128
134
  output: "./output.json",
129
135
  };
130
- await (0, cli_1.run)(args);
136
+ await run(args);
131
137
  // Verify transformer was called with correct structure
132
138
  (0, vitest_1.expect)(mockTransform).toHaveBeenCalledWith({
133
139
  metadata: { tokenSetOrder: ["base", "semantic"] },
@@ -153,7 +159,7 @@ vitest_1.vi.mock("./require", () => ({
153
159
  input: tokensDir,
154
160
  output: "./output.json",
155
161
  };
156
- await (0, vitest_1.expect)((0, cli_1.run)(args)).rejects.toThrow("Missing required configuration: handler");
162
+ await (0, vitest_1.expect)(run(args)).rejects.toThrow("Missing required configuration: handler");
157
163
  });
158
164
  });
159
165
  });
@@ -1,9 +1,9 @@
1
1
  #!/usr/bin/env node
2
2
  "use strict";
3
3
  Object.defineProperty(exports, "__esModule", { value: true });
4
- exports.run = exports.configParser = void 0;
5
4
  const deployments_1 = require("./deployments");
6
5
  const argparse_1 = require("argparse");
6
+ const cli_1 = require("../shared/cli");
7
7
  const configParser = (parser) => {
8
8
  const commands = parser.add_subparsers({
9
9
  title: "Vercel commands",
@@ -32,7 +32,6 @@ const configParser = (parser) => {
32
32
  type: Number,
33
33
  });
34
34
  };
35
- exports.configParser = configParser;
36
35
  const run = async (args) => {
37
36
  const accessToken = process.env.VERCEL_TOKEN;
38
37
  switch (args.subcommand) {
@@ -52,14 +51,17 @@ const run = async (args) => {
52
51
  break;
53
52
  }
54
53
  };
55
- exports.run = run;
54
+ exports.default = (0, cli_1.defineCLIModule)({
55
+ configParser,
56
+ run,
57
+ });
56
58
  async function main() {
57
59
  const parser = new argparse_1.ArgumentParser({
58
60
  description: "Vercel deployment utilities",
59
61
  });
60
62
  const args = parser.parse_args();
61
- (0, exports.configParser)(parser);
62
- await (0, exports.run)(args);
63
+ configParser(parser);
64
+ await run(args);
63
65
  }
64
66
  // Only run main if this file is being executed directly
65
67
  if (require.main === module) {
@@ -1,8 +1,12 @@
1
1
  "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
2
5
  Object.defineProperty(exports, "__esModule", { value: true });
3
6
  const vitest_1 = require("vitest");
4
7
  const argparse_1 = require("argparse");
5
- const cli_1 = require("./cli");
8
+ const cli_1 = __importDefault(require("./cli"));
9
+ const { run, configParser } = cli_1.default;
6
10
  // Mock the waitForDeploymentReady function
7
11
  vitest_1.vi.mock("@interactivethings/scripts/vercel/deployments", () => ({
8
12
  waitForDeploymentReady: vitest_1.vi.fn(),
@@ -18,7 +22,7 @@ const deployments_1 = require("@interactivethings/scripts/vercel/deployments");
18
22
  (0, vitest_1.it)("should configure the argument parser correctly", () => {
19
23
  const parser = new argparse_1.ArgumentParser();
20
24
  const addSubparsersSpy = vitest_1.vi.spyOn(parser, "add_subparsers");
21
- (0, cli_1.configParser)(parser);
25
+ configParser(parser);
22
26
  (0, vitest_1.expect)(addSubparsersSpy).toHaveBeenCalledWith({
23
27
  title: "Vercel commands",
24
28
  dest: "subcommand",
@@ -45,7 +49,7 @@ const deployments_1 = require("@interactivethings/scripts/vercel/deployments");
45
49
  team: "test-team",
46
50
  project: "test-project",
47
51
  };
48
- await (0, cli_1.run)(args);
52
+ await run(args);
49
53
  (0, vitest_1.expect)(deployments_1.waitForDeploymentReady).toHaveBeenCalledWith({
50
54
  commitSha: "test-commit-sha",
51
55
  interval: 5000,
@@ -67,7 +71,7 @@ const deployments_1 = require("@interactivethings/scripts/vercel/deployments");
67
71
  team: "test-team",
68
72
  project: "test-project",
69
73
  };
70
- await (0, vitest_1.expect)((0, cli_1.run)(args)).rejects.toThrow("Could not retrieve deployment");
74
+ await (0, vitest_1.expect)(run(args)).rejects.toThrow("Could not retrieve deployment");
71
75
  });
72
76
  (0, vitest_1.it)("should throw error when waitForDeploymentReady fails", async () => {
73
77
  const error = new Error("Network error");
@@ -80,7 +84,7 @@ const deployments_1 = require("@interactivethings/scripts/vercel/deployments");
80
84
  team: "test-team",
81
85
  project: "test-project",
82
86
  };
83
- await (0, vitest_1.expect)((0, cli_1.run)(args)).rejects.toThrow("Network error");
87
+ await (0, vitest_1.expect)(run(args)).rejects.toThrow("Network error");
84
88
  });
85
89
  });
86
90
  });
@@ -1,41 +1,14 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.waitForDeploymentReady = waitForDeploymentReady;
4
- async function fetchDeploymentForCommit(commitSha, teamId, projectId, accessToken) {
5
- try {
6
- const response = await fetch(`https://vercel.com/api/v6/deployments?limit=20&projectId=${projectId}&state=READY,ERROR,BUILDING,QUEUED&teamId=${teamId}`, {
7
- headers: {
8
- Authorization: `Bearer ${accessToken}`,
9
- },
10
- }).then((x) => x.json());
11
- const deployments = response.deployments.filter((deployment) => deployment.meta.githubCommitSha === commitSha);
12
- return deployments;
13
- }
14
- catch (error) {
15
- console.error("Error:", error);
16
- return [];
17
- }
18
- }
19
- const sleep = (duration) => new Promise((resolve) => setTimeout(resolve, duration));
4
+ const wait_deployment_1 = require("../shared/wait-deployment");
5
+ const vercel_1 = require("./vercel");
20
6
  async function waitForDeploymentReady({ team, project, commitSha, interval, timeout, accessToken, }) {
21
- const start = Date.now();
22
- const end = start + timeout;
23
- while (Date.now() < end) {
24
- const deployments = await fetchDeploymentForCommit(commitSha, team, project, accessToken);
25
- if (deployments.length === 0 || deployments[0].state !== "READY") {
26
- const state = deployments[0].state;
27
- if (state === "ERROR") {
28
- throw new Error("Deployment errored");
29
- }
30
- console.log(`Deployment not yet ready (state: ${deployments[0].state}), waiting ${interval}ms for deployment with commit ${commitSha}`);
31
- await sleep(Math.min(end - Date.now(), interval));
32
- }
33
- else {
34
- console.log(`Deployment for commit ${commitSha} is READY`);
35
- return deployments[0];
36
- }
37
- }
38
- if (Date.now() > end) {
39
- throw new Error("Timeout for waitForDeploymentReady");
40
- }
7
+ const service = new vercel_1.VercelDeploymentService(team, project, accessToken);
8
+ return await (0, wait_deployment_1.waitForDeploymentReady)({
9
+ commitSha,
10
+ interval,
11
+ timeout,
12
+ deploymentService: service,
13
+ });
41
14
  }
@@ -0,0 +1,31 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.VercelDeploymentService = void 0;
4
+ const getDeploymentState = (deployment) => {
5
+ return deployment.state;
6
+ };
7
+ const getDeploymentUrl = (deployment) => {
8
+ return `https://${deployment.url}`;
9
+ };
10
+ class VercelDeploymentService {
11
+ constructor(teamId, projectId, accessToken) {
12
+ this.teamId = teamId;
13
+ this.projectId = projectId;
14
+ this.accessToken = accessToken;
15
+ }
16
+ async fetchForCommit(commitSha) {
17
+ const response = await fetch(`https://vercel.com/api/v6/deployments?limit=20&projectId=${this.projectId}&state=READY,ERROR,BUILDING,QUEUED&teamId=${this.teamId}`, {
18
+ headers: {
19
+ Authorization: `Bearer ${this.accessToken}`,
20
+ },
21
+ })
22
+ .then((x) => x.json())
23
+ .then((x) => x);
24
+ const deployments = response.deployments.filter((deployment) => deployment.meta.githubCommitSha === commitSha);
25
+ return deployments.map((d) => ({
26
+ state: getDeploymentState(d),
27
+ url: getDeploymentUrl(d),
28
+ }));
29
+ }
30
+ }
31
+ exports.VercelDeploymentService = VercelDeploymentService;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@interactivethings/scripts",
3
- "version": "2.0.4",
3
+ "version": "2.1.1",
4
4
  "main": "dist/index.js",
5
5
  "exports": {
6
6
  ".": "./dist/index.js",
@@ -28,9 +28,7 @@
28
28
  "start": "bun ./dist/cli.js"
29
29
  },
30
30
  "bin": {
31
- "ixt": "dist/cli.js",
32
- "wait-for-vercel-deploy": "dist/wait-for-vercel-deploy.js",
33
- "mui-tokens-studio": "dist/mui-tokens-studio.js"
31
+ "ixt": "dist/cli.js"
34
32
  },
35
33
  "files": [
36
34
  "dist",
@@ -42,13 +40,13 @@
42
40
  "@semantic-release/changelog": "^6.0.3",
43
41
  "@semantic-release/git": "^10.0.1",
44
42
  "@semantic-release/github": "^11.0.6",
45
- "@types/argparse": "^2.0.12",
43
+ "@types/argparse": "^2.0.17",
46
44
  "@types/jscodeshift": "^0.11.10",
47
45
  "argparse": "^2.0.1",
48
46
  "jiti": "^2.6.1",
49
47
  "ora": "^9.0.0",
50
48
  "prompts": "^2.4.2",
51
- "remeda": "^1.19.0",
49
+ "remeda": "^2.32.0",
52
50
  "zod": "^4.1.11"
53
51
  },
54
52
  "devDependencies": {
@@ -57,7 +55,7 @@
57
55
  "jscodeshift": "^0.15.1",
58
56
  "oxlint": "^1.19.0",
59
57
  "typescript": "^5.9.3",
60
- "vitest": "^0.34.6"
58
+ "vitest": "^3.2.4"
61
59
  },
62
60
  "peerDependencies": {
63
61
  "@next/env": "^15.5.4"