atmn 0.0.7-beta.1 → 0.0.8

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 (3) hide show
  1. package/dist/cli.cjs +109 -16
  2. package/dist/cli.js +108 -16
  3. package/package.json +4 -3
package/dist/cli.cjs CHANGED
@@ -5,11 +5,13 @@ var commander = require('commander');
5
5
  var chalk6 = require('chalk');
6
6
  var axios = require('axios');
7
7
  var fs = require('fs');
8
+ var prompts = require('@inquirer/prompts');
8
9
  var path = require('path');
9
10
  var createJiti = require('jiti');
10
11
  var url = require('url');
12
+ var child_process = require('child_process');
11
13
  var open = require('open');
12
- var prompts = require('@inquirer/prompts');
14
+ var yoctoSpinner = require('yocto-spinner');
13
15
 
14
16
  function _interopDefault (e) { return e && e.__esModule ? e : { default: e }; }
15
17
 
@@ -19,6 +21,7 @@ var fs__default = /*#__PURE__*/_interopDefault(fs);
19
21
  var path__default = /*#__PURE__*/_interopDefault(path);
20
22
  var createJiti__default = /*#__PURE__*/_interopDefault(createJiti);
21
23
  var open__default = /*#__PURE__*/_interopDefault(open);
24
+ var yoctoSpinner__default = /*#__PURE__*/_interopDefault(yoctoSpinner);
22
25
 
23
26
  // ../node_modules/.pnpm/tsup@8.5.0_jiti@2.4.2_postcss@8.5.6_tsx@4.20.3_typescript@5.8.3_yaml@2.8.0/node_modules/tsup/assets/cjs_shims.js
24
27
  var getImportMetaUrl = () => typeof document === "undefined" ? new URL(`file:${__filename}`).href : document.currentScript && document.currentScript.src || new URL("main.js", document.baseURI).href;
@@ -86,27 +89,60 @@ function snakeCaseToCamelCase(value) {
86
89
  function idToVar(id) {
87
90
  return id.replace(/[-_](.)/g, (_, letter) => letter.toUpperCase()).replace(/^[^a-zA-Z_$]/, "_").replace(/[^a-zA-Z0-9_$]/g, "");
88
91
  }
92
+ async function upsertEnvVar(filePath, varName, newValue) {
93
+ const content = fs__default.default.readFileSync(filePath, "utf-8");
94
+ const lines = content.split("\n");
95
+ let found = false;
96
+ for (let i = 0; i < lines.length; i++) {
97
+ if (lines[i]?.startsWith(`${varName}=`)) {
98
+ const shouldOverwrite = await prompts.confirm({
99
+ message: `${varName} already exists in .env. Overwrite?`,
100
+ default: false
101
+ });
102
+ if (shouldOverwrite) {
103
+ lines[i] = `${varName}=${newValue}`;
104
+ found = true;
105
+ break;
106
+ }
107
+ }
108
+ }
109
+ if (!found) {
110
+ lines.push(`${varName}=${newValue}`);
111
+ }
112
+ fs__default.default.writeFileSync(filePath, lines.join("\n"));
113
+ }
89
114
  function storeToEnv(prodKey, sandboxKey) {
90
115
  const envPath = `${process.cwd()}/.env`;
91
- const envVars = `# AUTUMN_SECRET_KEY=${prodKey}
116
+ const envLocalPath = `${process.cwd()}/.env.local`;
117
+ const envVars = `AUTUMN_PROD_SECRET_KEY=${prodKey}
92
118
  AUTUMN_SECRET_KEY=${sandboxKey}
93
119
  `;
94
120
  if (fs__default.default.existsSync(envPath)) {
95
- fs__default.default.appendFileSync(envPath, envVars);
96
- console.log(chalk6__default.default.green(".env file found. Appended keys."));
121
+ upsertEnvVar(envPath, "AUTUMN_PROD_SECRET_KEY", prodKey);
122
+ upsertEnvVar(envPath, "AUTUMN_SECRET_KEY", sandboxKey);
123
+ console.log(chalk6__default.default.green(".env file found. Updated keys."));
124
+ } else if (fs__default.default.existsSync(envLocalPath)) {
125
+ fs__default.default.writeFileSync(envPath, envVars);
126
+ console.log(chalk6__default.default.green(".env.local found but .env not found. Created new .env file and wrote keys."));
97
127
  } else {
98
128
  fs__default.default.writeFileSync(envPath, envVars);
99
- console.log(chalk6__default.default.green(".env file not found. Created new .env file and wrote keys."));
129
+ console.log(chalk6__default.default.green("No .env or .env.local file found. Created new .env file and wrote keys."));
100
130
  }
101
131
  }
102
132
  function readFromEnv() {
103
133
  const envPath = `${process.cwd()}/.env`;
104
- if (!fs__default.default.existsSync(envPath)) {
105
- return void 0;
134
+ const envLocalPath = `${process.cwd()}/.env.local`;
135
+ if (fs__default.default.existsSync(envPath)) {
136
+ const envContent = fs__default.default.readFileSync(envPath, "utf-8");
137
+ const match = envContent.match(/^AUTUMN_SECRET_KEY=(.*)$/m);
138
+ if (match) return match[1];
106
139
  }
107
- const envContent = fs__default.default.readFileSync(envPath, "utf-8");
108
- const match = envContent.match(/^AUTUMN_SECRET_KEY=(.*)$/m);
109
- return match ? match[1] : void 0;
140
+ if (fs__default.default.existsSync(envLocalPath)) {
141
+ const envLocalContent = fs__default.default.readFileSync(envLocalPath, "utf-8");
142
+ const match = envLocalContent.match(/^AUTUMN_SECRET_KEY=(.*)$/m);
143
+ if (match) return match[1];
144
+ }
145
+ return void 0;
110
146
  }
111
147
 
112
148
  // source/core/api.ts
@@ -307,10 +343,58 @@ export const ${idToVar(feature.id)} = feature({
307
343
  })`;
308
344
  return snippet;
309
345
  }
346
+ function checkAtmnInstalled() {
347
+ try {
348
+ const packageJsonPath = path__default.default.join(process.cwd(), "package.json");
349
+ if (fs__default.default.existsSync(packageJsonPath)) {
350
+ const packageJson = JSON.parse(fs__default.default.readFileSync(packageJsonPath, "utf-8"));
351
+ return !!(packageJson.dependencies?.atmn || packageJson.devDependencies?.atmn);
352
+ }
353
+ child_process.execSync(`node -e "require.resolve('atmn')"`, { stdio: "ignore" });
354
+ return true;
355
+ } catch {
356
+ return false;
357
+ }
358
+ }
359
+ async function installAtmn() {
360
+ const shouldInstall = await prompts.confirm({
361
+ message: "The atmn package is not installed. Would you like to install it now?",
362
+ default: true
363
+ });
364
+ if (!shouldInstall) {
365
+ console.log(chalk6__default.default.yellow("Skipping installation. You can install atmn manually with your preferred package manager."));
366
+ return false;
367
+ }
368
+ const packageManager = await prompts.select({
369
+ message: "Which package manager would you like to use?",
370
+ choices: [
371
+ { name: "npm", value: "npm" },
372
+ { name: "pnpm", value: "pnpm" },
373
+ { name: "bun", value: "bun" }
374
+ ],
375
+ default: "npm"
376
+ });
377
+ try {
378
+ console.log(chalk6__default.default.blue(`Installing atmn with ${packageManager}...`));
379
+ const installCommand = packageManager === "npm" ? "npm install atmn" : packageManager === "pnpm" ? "pnpm add atmn" : "bun add atmn";
380
+ child_process.execSync(installCommand, { stdio: "inherit" });
381
+ console.log(chalk6__default.default.green("atmn installed successfully!"));
382
+ return true;
383
+ } catch (error) {
384
+ console.error(chalk6__default.default.red("Failed to install atmn:"), error);
385
+ return false;
386
+ }
387
+ }
310
388
  async function loadAutumnConfigFile() {
311
389
  const configPath = path__default.default.join(process.cwd(), "autumn.config.ts");
312
390
  const absolutePath = path.resolve(configPath);
313
391
  const fileUrl = url.pathToFileURL(absolutePath).href;
392
+ if (!checkAtmnInstalled()) {
393
+ const installed = await installAtmn();
394
+ if (!installed) {
395
+ throw new Error("atmn package is required but not installed. Please install it manually.");
396
+ }
397
+ }
314
398
  const jiti = createJiti__default.default(importMetaUrl);
315
399
  const mod = await jiti.import(fileUrl);
316
400
  const def = mod.default || mod;
@@ -521,6 +605,13 @@ async function upsertProduct(product) {
521
605
  }
522
606
 
523
607
  // source/commands/push.ts
608
+ var spinner = (message) => {
609
+ const spinner2 = yoctoSpinner__default.default({
610
+ text: message
611
+ });
612
+ spinner2.start();
613
+ return spinner2;
614
+ };
524
615
  async function Push({
525
616
  config,
526
617
  yes,
@@ -536,27 +627,29 @@ async function Push({
536
627
  message: `Delete product [${productId}]?`
537
628
  });
538
629
  if (shouldDelete) {
630
+ const s = spinner(`Deleting product [${productId}]`);
539
631
  await deleteProduct(productId);
540
- console.log(chalk6__default.default.green(`Product [${productId}] deleted successfully!`));
632
+ s.success(`Product [${productId}] deleted successfully!`);
541
633
  }
542
634
  }
543
635
  for (let feature of features) {
544
- console.log(chalk6__default.default.green(`Pushing feature [${feature.id}]`));
636
+ const s = spinner(`Pushing feature [${feature.id}]`);
545
637
  await upsertFeature(feature);
546
- console.log(chalk6__default.default.green(`Pushed feature [${feature.id}]`));
638
+ s.success(`Pushed feature [${feature.id}]`);
547
639
  }
548
640
  for (let product of products) {
549
- console.log(chalk6__default.default.green(`Pushing product [${product.id}]`));
641
+ const s = spinner(`Pushing product [${product.id}]`);
550
642
  await upsertProduct(product);
551
- console.log(chalk6__default.default.green(`Pushed product [${product.id}]`));
643
+ s.success(`Pushed product [${product.id}]`);
552
644
  }
553
645
  for (let featureId of featuresToDelete) {
554
646
  let shouldDelete = yes || await prompts.confirm({
555
647
  message: `Delete feature [${featureId}]?`
556
648
  });
557
649
  if (shouldDelete) {
650
+ const s = spinner(`Deleting feature [${featureId}]`);
558
651
  await deleteFeature(featureId);
559
- console.log(chalk6__default.default.green(`Feature [${featureId}] deleted successfully!`));
652
+ s.success(`Feature [${featureId}] deleted successfully!`);
560
653
  }
561
654
  }
562
655
  const env = prod ? "prod" : "sandbox";
package/dist/cli.js CHANGED
@@ -3,11 +3,13 @@ import { program } from 'commander';
3
3
  import chalk6 from 'chalk';
4
4
  import axios from 'axios';
5
5
  import fs from 'fs';
6
+ import { confirm, input, password, select } from '@inquirer/prompts';
6
7
  import path, { resolve } from 'path';
7
8
  import createJiti from 'jiti';
8
9
  import { pathToFileURL } from 'url';
10
+ import { execSync } from 'child_process';
9
11
  import open from 'open';
10
- import { confirm, input, password } from '@inquirer/prompts';
12
+ import yoctoSpinner from 'yocto-spinner';
11
13
 
12
14
  // source/constants.ts
13
15
  var FRONTEND_URL = "http://app.useautumn.com";
@@ -71,27 +73,60 @@ function snakeCaseToCamelCase(value) {
71
73
  function idToVar(id) {
72
74
  return id.replace(/[-_](.)/g, (_, letter) => letter.toUpperCase()).replace(/^[^a-zA-Z_$]/, "_").replace(/[^a-zA-Z0-9_$]/g, "");
73
75
  }
76
+ async function upsertEnvVar(filePath, varName, newValue) {
77
+ const content = fs.readFileSync(filePath, "utf-8");
78
+ const lines = content.split("\n");
79
+ let found = false;
80
+ for (let i = 0; i < lines.length; i++) {
81
+ if (lines[i]?.startsWith(`${varName}=`)) {
82
+ const shouldOverwrite = await confirm({
83
+ message: `${varName} already exists in .env. Overwrite?`,
84
+ default: false
85
+ });
86
+ if (shouldOverwrite) {
87
+ lines[i] = `${varName}=${newValue}`;
88
+ found = true;
89
+ break;
90
+ }
91
+ }
92
+ }
93
+ if (!found) {
94
+ lines.push(`${varName}=${newValue}`);
95
+ }
96
+ fs.writeFileSync(filePath, lines.join("\n"));
97
+ }
74
98
  function storeToEnv(prodKey, sandboxKey) {
75
99
  const envPath = `${process.cwd()}/.env`;
76
- const envVars = `# AUTUMN_SECRET_KEY=${prodKey}
100
+ const envLocalPath = `${process.cwd()}/.env.local`;
101
+ const envVars = `AUTUMN_PROD_SECRET_KEY=${prodKey}
77
102
  AUTUMN_SECRET_KEY=${sandboxKey}
78
103
  `;
79
104
  if (fs.existsSync(envPath)) {
80
- fs.appendFileSync(envPath, envVars);
81
- console.log(chalk6.green(".env file found. Appended keys."));
105
+ upsertEnvVar(envPath, "AUTUMN_PROD_SECRET_KEY", prodKey);
106
+ upsertEnvVar(envPath, "AUTUMN_SECRET_KEY", sandboxKey);
107
+ console.log(chalk6.green(".env file found. Updated keys."));
108
+ } else if (fs.existsSync(envLocalPath)) {
109
+ fs.writeFileSync(envPath, envVars);
110
+ console.log(chalk6.green(".env.local found but .env not found. Created new .env file and wrote keys."));
82
111
  } else {
83
112
  fs.writeFileSync(envPath, envVars);
84
- console.log(chalk6.green(".env file not found. Created new .env file and wrote keys."));
113
+ console.log(chalk6.green("No .env or .env.local file found. Created new .env file and wrote keys."));
85
114
  }
86
115
  }
87
116
  function readFromEnv() {
88
117
  const envPath = `${process.cwd()}/.env`;
89
- if (!fs.existsSync(envPath)) {
90
- return void 0;
118
+ const envLocalPath = `${process.cwd()}/.env.local`;
119
+ if (fs.existsSync(envPath)) {
120
+ const envContent = fs.readFileSync(envPath, "utf-8");
121
+ const match = envContent.match(/^AUTUMN_SECRET_KEY=(.*)$/m);
122
+ if (match) return match[1];
123
+ }
124
+ if (fs.existsSync(envLocalPath)) {
125
+ const envLocalContent = fs.readFileSync(envLocalPath, "utf-8");
126
+ const match = envLocalContent.match(/^AUTUMN_SECRET_KEY=(.*)$/m);
127
+ if (match) return match[1];
91
128
  }
92
- const envContent = fs.readFileSync(envPath, "utf-8");
93
- const match = envContent.match(/^AUTUMN_SECRET_KEY=(.*)$/m);
94
- return match ? match[1] : void 0;
129
+ return void 0;
95
130
  }
96
131
 
97
132
  // source/core/api.ts
@@ -292,10 +327,58 @@ export const ${idToVar(feature.id)} = feature({
292
327
  })`;
293
328
  return snippet;
294
329
  }
330
+ function checkAtmnInstalled() {
331
+ try {
332
+ const packageJsonPath = path.join(process.cwd(), "package.json");
333
+ if (fs.existsSync(packageJsonPath)) {
334
+ const packageJson = JSON.parse(fs.readFileSync(packageJsonPath, "utf-8"));
335
+ return !!(packageJson.dependencies?.atmn || packageJson.devDependencies?.atmn);
336
+ }
337
+ execSync(`node -e "require.resolve('atmn')"`, { stdio: "ignore" });
338
+ return true;
339
+ } catch {
340
+ return false;
341
+ }
342
+ }
343
+ async function installAtmn() {
344
+ const shouldInstall = await confirm({
345
+ message: "The atmn package is not installed. Would you like to install it now?",
346
+ default: true
347
+ });
348
+ if (!shouldInstall) {
349
+ console.log(chalk6.yellow("Skipping installation. You can install atmn manually with your preferred package manager."));
350
+ return false;
351
+ }
352
+ const packageManager = await select({
353
+ message: "Which package manager would you like to use?",
354
+ choices: [
355
+ { name: "npm", value: "npm" },
356
+ { name: "pnpm", value: "pnpm" },
357
+ { name: "bun", value: "bun" }
358
+ ],
359
+ default: "npm"
360
+ });
361
+ try {
362
+ console.log(chalk6.blue(`Installing atmn with ${packageManager}...`));
363
+ const installCommand = packageManager === "npm" ? "npm install atmn" : packageManager === "pnpm" ? "pnpm add atmn" : "bun add atmn";
364
+ execSync(installCommand, { stdio: "inherit" });
365
+ console.log(chalk6.green("atmn installed successfully!"));
366
+ return true;
367
+ } catch (error) {
368
+ console.error(chalk6.red("Failed to install atmn:"), error);
369
+ return false;
370
+ }
371
+ }
295
372
  async function loadAutumnConfigFile() {
296
373
  const configPath = path.join(process.cwd(), "autumn.config.ts");
297
374
  const absolutePath = resolve(configPath);
298
375
  const fileUrl = pathToFileURL(absolutePath).href;
376
+ if (!checkAtmnInstalled()) {
377
+ const installed = await installAtmn();
378
+ if (!installed) {
379
+ throw new Error("atmn package is required but not installed. Please install it manually.");
380
+ }
381
+ }
299
382
  const jiti = createJiti(import.meta.url);
300
383
  const mod = await jiti.import(fileUrl);
301
384
  const def = mod.default || mod;
@@ -506,6 +589,13 @@ async function upsertProduct(product) {
506
589
  }
507
590
 
508
591
  // source/commands/push.ts
592
+ var spinner = (message) => {
593
+ const spinner2 = yoctoSpinner({
594
+ text: message
595
+ });
596
+ spinner2.start();
597
+ return spinner2;
598
+ };
509
599
  async function Push({
510
600
  config,
511
601
  yes,
@@ -521,27 +611,29 @@ async function Push({
521
611
  message: `Delete product [${productId}]?`
522
612
  });
523
613
  if (shouldDelete) {
614
+ const s = spinner(`Deleting product [${productId}]`);
524
615
  await deleteProduct(productId);
525
- console.log(chalk6.green(`Product [${productId}] deleted successfully!`));
616
+ s.success(`Product [${productId}] deleted successfully!`);
526
617
  }
527
618
  }
528
619
  for (let feature of features) {
529
- console.log(chalk6.green(`Pushing feature [${feature.id}]`));
620
+ const s = spinner(`Pushing feature [${feature.id}]`);
530
621
  await upsertFeature(feature);
531
- console.log(chalk6.green(`Pushed feature [${feature.id}]`));
622
+ s.success(`Pushed feature [${feature.id}]`);
532
623
  }
533
624
  for (let product of products) {
534
- console.log(chalk6.green(`Pushing product [${product.id}]`));
625
+ const s = spinner(`Pushing product [${product.id}]`);
535
626
  await upsertProduct(product);
536
- console.log(chalk6.green(`Pushed product [${product.id}]`));
627
+ s.success(`Pushed product [${product.id}]`);
537
628
  }
538
629
  for (let featureId of featuresToDelete) {
539
630
  let shouldDelete = yes || await confirm({
540
631
  message: `Delete feature [${featureId}]?`
541
632
  });
542
633
  if (shouldDelete) {
634
+ const s = spinner(`Deleting feature [${featureId}]`);
543
635
  await deleteFeature(featureId);
544
- console.log(chalk6.green(`Feature [${featureId}] deleted successfully!`));
636
+ s.success(`Feature [${featureId}] deleted successfully!`);
545
637
  }
546
638
  }
547
639
  const env = prod ? "prod" : "sandbox";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "atmn",
3
- "version": "0.0.7-beta.1",
3
+ "version": "0.0.8",
4
4
  "license": "MIT",
5
5
  "bin": "dist/cli.js",
6
6
  "main": "dist/index.js",
@@ -28,7 +28,8 @@
28
28
  "dotenv": "^17.2.0",
29
29
  "inquirer": "^12.7.0",
30
30
  "jiti": "^2.4.2",
31
- "open": "^10.1.2"
31
+ "open": "^10.1.2",
32
+ "yocto-spinner": "^1.0.0"
32
33
  },
33
34
  "devDependencies": {
34
35
  "@sindresorhus/tsconfig": "^3.0.1",
@@ -42,7 +43,7 @@
42
43
  "ink-testing-library": "^3.0.0",
43
44
  "prettier": "^2.8.7",
44
45
  "ts-node": "^10.9.1",
45
- "tsup": "^8.4.0",
46
+ "tsup": "^8.5.0",
46
47
  "typescript": "^5.0.3",
47
48
  "xo": "^0.53.1",
48
49
  "zod": "^3.24.1"