@superblocksteam/util 1.99.99-next.3 → 2.0.0-SNAPSHOT.fefa63e659e53195

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (100) hide show
  1. package/dist/index.js +1 -0
  2. package/{eslint.config.js → eslint.config.mjs} +26 -42
  3. package/lint-staged.config.mjs +6 -0
  4. package/package.json +22 -22
  5. package/src/api-files/api.mts +4 -2
  6. package/src/api-files/index.ts +7 -0
  7. package/src/api-files/types.ts +11 -14
  8. package/src/component-configs.ts +5 -3
  9. package/src/constants.ts +1 -15
  10. package/src/data-types.ts +1 -15
  11. package/src/file-uploader.test.ts +69 -0
  12. package/src/file-uploader.ts +26 -12
  13. package/src/index.ts +1 -0
  14. package/src/login.ts +24 -8
  15. package/src/mask-unix-signals.ts +1 -1
  16. package/src/resource-configs.ts +68 -5
  17. package/src/token-manager.ts +26 -0
  18. package/src/types.ts +5 -4
  19. package/src/validation.ts +4 -4
  20. package/tsconfig.json +3 -2
  21. package/turbo.json +9 -0
  22. package/vitest.config.ts +7 -0
  23. package/.prettierrc +0 -18
  24. package/dist/api-files/api.d.mts +0 -7
  25. package/dist/api-files/api.d.mts.map +0 -1
  26. package/dist/api-files/api.mjs +0 -262
  27. package/dist/api-files/api.mjs.map +0 -1
  28. package/dist/api-files/constants.d.ts +0 -6
  29. package/dist/api-files/constants.d.ts.map +0 -1
  30. package/dist/api-files/constants.js +0 -9
  31. package/dist/api-files/constants.js.map +0 -1
  32. package/dist/api-files/index.d.ts +0 -7
  33. package/dist/api-files/index.d.ts.map +0 -1
  34. package/dist/api-files/index.js +0 -13
  35. package/dist/api-files/index.js.map +0 -1
  36. package/dist/api-files/types.d.ts +0 -117
  37. package/dist/api-files/types.d.ts.map +0 -1
  38. package/dist/api-files/types.js +0 -17
  39. package/dist/api-files/types.js.map +0 -1
  40. package/dist/component-configs.d.ts +0 -6
  41. package/dist/component-configs.d.ts.map +0 -1
  42. package/dist/component-configs.js +0 -178
  43. package/dist/component-configs.js.map +0 -1
  44. package/dist/constants.d.ts +0 -18
  45. package/dist/constants.d.ts.map +0 -1
  46. package/dist/constants.js +0 -50
  47. package/dist/constants.js.map +0 -1
  48. package/dist/data-types.d.ts +0 -10
  49. package/dist/data-types.d.ts.map +0 -1
  50. package/dist/data-types.js +0 -32
  51. package/dist/data-types.js.map +0 -1
  52. package/dist/events.d.ts +0 -13
  53. package/dist/events.d.ts.map +0 -1
  54. package/dist/events.js +0 -17
  55. package/dist/events.js.map +0 -1
  56. package/dist/file-uploader.d.ts +0 -3
  57. package/dist/file-uploader.d.ts.map +0 -1
  58. package/dist/file-uploader.js +0 -28
  59. package/dist/file-uploader.js.map +0 -1
  60. package/dist/generate-component-types.d.ts +0 -3
  61. package/dist/generate-component-types.d.ts.map +0 -1
  62. package/dist/generate-component-types.js +0 -45
  63. package/dist/generate-component-types.js.map +0 -1
  64. package/dist/identifiers.d.ts +0 -9
  65. package/dist/identifiers.d.ts.map +0 -1
  66. package/dist/identifiers.js +0 -68
  67. package/dist/identifiers.js.map +0 -1
  68. package/dist/index.d.ts +0 -16
  69. package/dist/index.d.ts.map +0 -1
  70. package/dist/index.js.map +0 -1
  71. package/dist/localGitRepoState.d.ts +0 -20
  72. package/dist/localGitRepoState.d.ts.map +0 -1
  73. package/dist/localGitRepoState.js +0 -3
  74. package/dist/localGitRepoState.js.map +0 -1
  75. package/dist/login.d.ts +0 -11
  76. package/dist/login.d.ts.map +0 -1
  77. package/dist/login.js +0 -93
  78. package/dist/login.js.map +0 -1
  79. package/dist/mask-unix-signals.d.ts +0 -27
  80. package/dist/mask-unix-signals.d.ts.map +0 -1
  81. package/dist/mask-unix-signals.js +0 -81
  82. package/dist/mask-unix-signals.js.map +0 -1
  83. package/dist/resource-configs.d.ts +0 -61
  84. package/dist/resource-configs.d.ts.map +0 -1
  85. package/dist/resource-configs.js +0 -217
  86. package/dist/resource-configs.js.map +0 -1
  87. package/dist/types.d.ts +0 -105
  88. package/dist/types.d.ts.map +0 -1
  89. package/dist/types.js +0 -3
  90. package/dist/types.js.map +0 -1
  91. package/dist/unreachable.d.ts +0 -2
  92. package/dist/unreachable.d.ts.map +0 -1
  93. package/dist/unreachable.js +0 -7
  94. package/dist/unreachable.js.map +0 -1
  95. package/dist/validation.d.ts +0 -5
  96. package/dist/validation.d.ts.map +0 -1
  97. package/dist/validation.js +0 -152
  98. package/dist/validation.js.map +0 -1
  99. package/tsconfig.tsbuildinfo +0 -1
  100. package/tsup.config.ts +0 -8
package/dist/index.js CHANGED
@@ -29,4 +29,5 @@ __exportStar(require("./api-files/types.js"), exports);
29
29
  __exportStar(require("./api-files/index.js"), exports);
30
30
  __exportStar(require("./api-files/constants.js"), exports);
31
31
  __exportStar(require("./mask-unix-signals.js"), exports);
32
+ __exportStar(require("./token-manager.js"), exports);
32
33
  //# sourceMappingURL=index.js.map
@@ -1,38 +1,38 @@
1
- const js = require("@eslint/js");
2
- const importPlugin = require("eslint-plugin-import");
3
- const prettier = require("eslint-plugin-prettier");
4
- const eslintPluginPrettierRecommended = require("eslint-plugin-prettier/recommended");
5
- const unicorn = require("eslint-plugin-unicorn");
6
- const globals = require("globals");
7
- const tseslint = require("typescript-eslint");
1
+ import js from "@eslint/js";
2
+ import prettier from "eslint-config-prettier";
3
+ import turbo from "eslint-config-turbo/flat";
4
+ import importPlugin from "eslint-plugin-import";
5
+ import unicorn from "eslint-plugin-unicorn";
6
+ import { defineConfig } from "eslint/config";
7
+ import globals from "globals";
8
+ import tseslint from "typescript-eslint";
8
9
 
9
- const config = [
10
+ export default defineConfig(
10
11
  {
11
- ignores: [
12
- "**/public/*",
13
- "**/build/*",
14
- "**/node_modules/*",
15
- "**/dist/*",
16
- "**/assets/",
17
- "**/.*",
18
- "eslint.config.js",
19
- "tsup.config.ts",
20
- ],
12
+ ignores: ["dist/**/*", ".turbo/**/*"],
21
13
  },
22
14
  js.configs.recommended,
23
- ...tseslint.configs.recommended,
24
- { files: ["./*", "src/**"], ...eslintPluginPrettierRecommended },
15
+ tseslint.configs.recommended,
16
+ turbo,
25
17
  {
26
18
  plugins: {
27
- "@typescript-eslint": tseslint.plugin,
28
- prettier,
29
19
  import: importPlugin,
30
20
  unicorn,
31
21
  },
32
22
  languageOptions: {
33
- ecmaVersion: 2020,
23
+ ecmaVersion: 2024,
34
24
  sourceType: "commonjs",
35
25
  globals: globals.node,
26
+ parserOptions: {
27
+ projectService: {
28
+ allowDefaultProject: [
29
+ "eslint.config.mjs",
30
+ "lint-staged.config.mjs",
31
+ "vitest.config.ts",
32
+ ],
33
+ },
34
+ tsconfigRootDir: import.meta.dirname,
35
+ },
36
36
  },
37
37
  rules: {
38
38
  "@typescript-eslint/explicit-module-boundary-types": "off",
@@ -42,22 +42,7 @@ const config = [
42
42
  "@typescript-eslint/no-import-type-side-effects": "error",
43
43
  "@typescript-eslint/consistent-type-imports": "error",
44
44
  "unicorn/no-nested-ternary": "off",
45
- "import/order": [
46
- "error",
47
- {
48
- alphabetize: { order: "asc" },
49
- groups: [
50
- "builtin",
51
- "external",
52
- "internal",
53
- "parent",
54
- "sibling",
55
- "index",
56
- "object",
57
- "type",
58
- ],
59
- },
60
- ],
45
+ "import/order": "off",
61
46
  "import/no-cycle": "error",
62
47
  "import/extensions": [
63
48
  "error",
@@ -78,6 +63,5 @@ const config = [
78
63
  "@typescript-eslint/no-unused-expressions": "off",
79
64
  },
80
65
  },
81
- ];
82
-
83
- module.exports = config;
66
+ prettier,
67
+ );
@@ -0,0 +1,6 @@
1
+ export default {
2
+ "*.{js,jsx,ts,tsx,mjs,mts}":
3
+ "eslint --fix --max-warnings 0 --no-warn-ignored --concurrency=auto",
4
+ "*": "oxfmt --no-error-on-unmatched-pattern",
5
+ "**/*.{ts,tsx,mts}": () => "pnpm typecheck",
6
+ };
package/package.json CHANGED
@@ -1,38 +1,35 @@
1
1
  {
2
2
  "name": "@superblocksteam/util",
3
+ "version": "2.0.0-SNAPSHOT.fefa63e659e53195",
3
4
  "description": "",
4
- "version": "1.99.99-next.3",
5
5
  "homepage": "https://www.superblocks.com",
6
6
  "license": "Superblocks Community Software License",
7
+ "sideEffects": false,
7
8
  "main": "dist/index.js",
8
9
  "dependencies": {
9
- "ajv": "^8.12.0",
10
+ "ajv": "^8.20.0",
10
11
  "better-ajv-errors": "1.2.0",
11
12
  "fs-extra": "^11.1.1",
12
- "lodash": "^4.17.21",
13
- "lodash-es": "^4.17.21",
13
+ "lodash-es": "^4.18.1",
14
14
  "mime-types": "^2.1.35",
15
15
  "slugify": "^1.6.6",
16
- "typescript": "^5.1.3",
16
+ "typescript": "^6.0.3",
17
17
  "yaml": "^2.4.2"
18
18
  },
19
19
  "devDependencies": {
20
- "@eslint/js": "^9.16.0",
20
+ "@eslint/js": "^9.39.2",
21
21
  "@types/fs-extra": "^11.0.1",
22
- "@types/lodash": "^4.17.7",
23
22
  "@types/lodash-es": "^4.17.12",
24
23
  "@types/mime-types": "^2.1.1",
25
- "@types/node": "^20.11.18",
26
- "@typescript-eslint/eslint-plugin": "^8.25.0",
27
- "@typescript-eslint/parser": "^8.25.0",
28
- "eslint": "^9.21.0",
29
- "eslint-plugin-import": "2.31.0",
30
- "eslint-plugin-mocha": "^10.5.0",
31
- "eslint-plugin-prettier": "^5.2.5",
32
- "eslint-plugin-unicorn": "^47.0.0",
33
- "prettier": "^3.5.2",
34
- "tslib": "^2.5.0",
35
- "typescript-eslint": "^8.18.0"
24
+ "@types/node": "^24",
25
+ "eslint": "^9.39.2",
26
+ "eslint-config-prettier": "^10.1.8",
27
+ "eslint-config-turbo": "^2.9.16",
28
+ "eslint-plugin-import": "^2.32.0",
29
+ "eslint-plugin-unicorn": "^62.0.0",
30
+ "globals": "^17.3.0",
31
+ "typescript-eslint": "^8.59.2",
32
+ "vitest": "^4.0.17"
36
33
  },
37
34
  "publishConfig": {
38
35
  "registry": "https://registry.npmjs.org"
@@ -40,10 +37,13 @@
40
37
  "scripts": {
41
38
  "build": "tsc --build",
42
39
  "check": "pnpm run lint && pnpm run typecheck",
43
- "clean": "rm -rf dist tsconfig.tsbuildinfo",
44
- "dev": "tsc --build --watch",
45
- "lint": "eslint .",
46
- "lint:fix": "eslint . --fix",
40
+ "clean": "premove dist/ tsconfig.tsbuildinfo",
41
+ "dev": "tsc --build --watch --preserveWatchOutput",
42
+ "lint": "eslint --concurrency=auto",
43
+ "lint:fix": "eslint --fix --concurrency=auto",
44
+ "publish-package": "pnpm publish",
45
+ "test": "vitest run",
46
+ "test:watch": "vitest",
47
47
  "typecheck": "tsc --noEmit"
48
48
  }
49
49
  }
@@ -2,6 +2,7 @@ import fs from "fs-extra";
2
2
  import { cloneDeep } from "lodash-es";
3
3
  import slugify from "slugify";
4
4
  import { parse, stringify as ymlstringify } from "yaml";
5
+
5
6
  import {
6
7
  DEFAULT_LINES_FOR_LARGE_STEPS,
7
8
  LANGUAGE_STEP_EXTENSIONS,
@@ -257,7 +258,7 @@ async function readYamlFile(path: string): Promise<any> {
257
258
  return parse(await fs.readFile(path, "utf8"));
258
259
  }
259
260
 
260
- async function resolveLanguageSpecificStepContentFromBlocks(
261
+ export async function resolveLanguageSpecificStepContentFromBlocks(
261
262
  parentPath: string,
262
263
  blocks: Block[],
263
264
  stepPathMap: Record<string, string>,
@@ -464,12 +465,13 @@ export async function writeApiFiles(
464
465
  export async function readAppApiYamlFile(
465
466
  parentDirectory: string,
466
467
  apiName?: string,
468
+ slugifyDirectoryName: boolean = true,
467
469
  ): Promise<{ api: Api; stepPathMap: Record<string, string> }> {
468
470
  // The API is either stored in its entirety in a single YAML file, or
469
471
  // or in a subdirectory containing the YAML file and zero or more language-specific files.
470
472
  const apiNameSlug = slugifyName(apiName ?? "api");
471
473
  const singularApiYamlPath = `${parentDirectory}/${apiNameSlug}.yaml`;
472
- const apiDirPath = `${parentDirectory}/${apiNameSlug}`;
474
+ const apiDirPath = `${parentDirectory}/${slugifyDirectoryName ? apiNameSlug : apiName}`;
473
475
  const nestedApiYamlPath = `${apiDirPath}/api.yaml`;
474
476
 
475
477
  // Read the YAML file
@@ -13,3 +13,10 @@ export async function readAppApiYamlFile(
13
13
  const esmFunction = await import("./api.mjs");
14
14
  return esmFunction.readAppApiYamlFile(...args);
15
15
  }
16
+
17
+ export async function resolveLanguageSpecificStepContentFromBlocks(
18
+ ...args: Parameters<typeof Api.resolveLanguageSpecificStepContentFromBlocks>
19
+ ) {
20
+ const esmFunction = await import("./api.mjs");
21
+ return esmFunction.resolveLanguageSpecificStepContentFromBlocks(...args);
22
+ }
@@ -60,7 +60,7 @@ export type Step = {
60
60
  python?: LanguageContent;
61
61
  };
62
62
 
63
- export type Loop = {
63
+ type Loop = {
64
64
  blocks: Block[];
65
65
  range: string;
66
66
  type: LoopType;
@@ -68,34 +68,31 @@ export type Loop = {
68
68
  };
69
69
 
70
70
  export enum LoopType {
71
- FOR = "TYPE_FOR",
72
71
  FOR_EACH = "TYPE_FOREACH",
73
- WHILE = "TYPE_WHILE",
74
- UNSPECIFIED = "TYPE_UNSPECIFIED",
75
72
  }
76
73
 
77
- export type TryCatch = {
74
+ type TryCatch = {
78
75
  try?: Blocks;
79
76
  catch?: Blocks;
80
77
  finally?: Blocks;
81
78
  variables?: Variables;
82
79
  };
83
80
 
84
- export type Conditional = {
81
+ type Conditional = {
85
82
  if?: ConditionalBlockWithCondition;
86
83
  elseIf: ConditionalBlockWithCondition[];
87
84
  else?: Blocks;
88
85
  };
89
86
 
90
- export type Blocks = {
87
+ type Blocks = {
91
88
  blocks: Block[];
92
89
  };
93
90
 
94
- export type ConditionalBlockWithCondition = Blocks & {
91
+ type ConditionalBlockWithCondition = Blocks & {
95
92
  condition?: string;
96
93
  };
97
94
 
98
- export type Parallel = {
95
+ type Parallel = {
99
96
  static?: {
100
97
  paths: Record<string, Blocks>;
101
98
  };
@@ -108,27 +105,27 @@ export type Parallel = {
108
105
  wait?: WAIT_TYPE;
109
106
  };
110
107
 
111
- export type Stream = {
108
+ type Stream = {
112
109
  trigger?: StreamTrigger;
113
110
  process?: Blocks;
114
111
  variables?: Variables;
115
112
  };
116
113
 
117
- export type StreamTrigger = {
114
+ type StreamTrigger = {
118
115
  name: string;
119
116
  step?: Step;
120
117
  };
121
118
 
122
- export enum WAIT_TYPE {
119
+ enum WAIT_TYPE {
123
120
  ALL = "WAIT_ALL",
124
121
  ANY = "WAIT_NONE",
125
122
  UNSPECIFIED = "WAIT_UNSPECIFIED",
126
123
  }
127
124
 
128
- export type Variables = Record<string, string>;
125
+ type Variables = Record<string, string>;
129
126
 
130
127
  export type LanguageContent = {
131
128
  body: Body;
132
129
  };
133
130
 
134
- export type Body = string | { path: string };
131
+ type Body = string | { path: string };
@@ -2,8 +2,10 @@ import { execFile } from "node:child_process";
2
2
  import os from "node:os";
3
3
  import path from "node:path";
4
4
  import * as util from "node:util";
5
- import * as fs from "fs-extra";
6
- import * as mimeTypes from "mime-types";
5
+
6
+ import fs from "fs-extra";
7
+ import mimeTypes from "mime-types";
8
+
7
9
  import { CUSTOM_COMPONENTS_PATH } from "./constants.js";
8
10
  import { generateComponentTypesFile } from "./generate-component-types.js";
9
11
  import { validateCustomComponents } from "./validation.js";
@@ -31,7 +33,7 @@ async function compileTypeScript(
31
33
  "--moduleResolution",
32
34
  "node",
33
35
  "--module",
34
- "commonjs",
36
+ "es2022",
35
37
  "--strict",
36
38
  "true",
37
39
  "--skipLibCheck",
package/src/constants.ts CHANGED
@@ -1,21 +1,7 @@
1
1
  export const SUPERBLOCKS_HOME_FOLDER_NAME = ".superblocks";
2
2
  export const TOKEN_CONFIG_PATH = ".superblocks/auth.json";
3
3
  export const RESOURCE_CONFIG_PATH = ".superblocks/superblocks.json";
4
-
5
- /* It's a relative path from resource's directory to a project's root
6
- ├── apps
7
- │ ├── <app_name>
8
- │ │ ├── apis
9
- │ │ │ ├── <api_name1>
10
- ...
11
- │ │ │ ├── <api_nameN>
12
- │ │ ├── application.yaml
13
- │ │ └── page.yaml
14
- ├── backends
15
- │ └── <scheduled job|workflow_name>
16
- │ └── api.yaml
17
- */
18
- export const ROOT_CONFIG_RELATIVE_PATH = "../..";
4
+ export const DEV_ENVIRONMENT_CONFIG_PATH = ".superblocks/dev-environment.json";
19
5
 
20
6
  export const CUSTOM_COMPONENTS_PATH = "components";
21
7
 
package/src/data-types.ts CHANGED
@@ -1,11 +1,4 @@
1
- export const supportedDataTypes = [
2
- "string",
3
- "number",
4
- "boolean",
5
- "any",
6
- ] as const;
7
-
8
- export type DataType = (typeof supportedDataTypes)[number];
1
+ export type DataType = "string" | "number" | "boolean" | "any";
9
2
 
10
3
  interface TypeInfo {
11
4
  tsType: string;
@@ -30,10 +23,3 @@ export const dataTypeDefinions: Record<DataType, TypeInfo> = {
30
23
  prompt: "any (raw js expression)",
31
24
  },
32
25
  };
33
-
34
- export function isValidDataType(input: string): input is DataType {
35
- return Object.prototype.hasOwnProperty.call(
36
- dataTypeDefinions,
37
- input as DataType,
38
- );
39
- }
@@ -0,0 +1,69 @@
1
+ import { afterEach, beforeEach, describe, expect, it } from "vitest";
2
+
3
+ import { getBucketeerUrlFromSuperblocksUrl } from "./file-uploader.js";
4
+
5
+ describe("getBucketeerUrlFromSuperblocksUrl", () => {
6
+ let originalUrl: string | undefined;
7
+
8
+ beforeEach(() => {
9
+ originalUrl = process.env.SUPERBLOCKS_BUCKETEER_URL;
10
+ delete process.env.SUPERBLOCKS_BUCKETEER_URL;
11
+ });
12
+
13
+ afterEach(() => {
14
+ if (originalUrl === undefined) {
15
+ delete process.env.SUPERBLOCKS_BUCKETEER_URL;
16
+ } else {
17
+ process.env.SUPERBLOCKS_BUCKETEER_URL = originalUrl;
18
+ }
19
+ });
20
+
21
+ it("returns the default localhost bucketeer URL for localhost servers", () => {
22
+ expect(getBucketeerUrlFromSuperblocksUrl("http://localhost:8080")).toBe(
23
+ "http://localhost:8030",
24
+ );
25
+ expect(getBucketeerUrlFromSuperblocksUrl("http://127.0.0.1:8080")).toBe(
26
+ "http://localhost:8030",
27
+ );
28
+ });
29
+
30
+ it("honors SUPERBLOCKS_BUCKETEER_URL for localhost servers (slot-aware worktrees)", () => {
31
+ process.env.SUPERBLOCKS_BUCKETEER_URL = "http://localhost:8330";
32
+ expect(getBucketeerUrlFromSuperblocksUrl("http://localhost:8380")).toBe(
33
+ "http://localhost:8330",
34
+ );
35
+ expect(getBucketeerUrlFromSuperblocksUrl("http://127.0.0.1:8380")).toBe(
36
+ "http://localhost:8330",
37
+ );
38
+ });
39
+
40
+ it("falls back to localhost default when the input URL is unparseable", () => {
41
+ expect(getBucketeerUrlFromSuperblocksUrl("not a url")).toBe(
42
+ "http://localhost:8030",
43
+ );
44
+ });
45
+
46
+ it("uses SUPERBLOCKS_BUCKETEER_URL when the input URL is unparseable", () => {
47
+ process.env.SUPERBLOCKS_BUCKETEER_URL = "http://localhost:8330";
48
+ expect(getBucketeerUrlFromSuperblocksUrl("not a url")).toBe(
49
+ "http://localhost:8330",
50
+ );
51
+ });
52
+
53
+ it("ignores SUPERBLOCKS_BUCKETEER_URL for non-localhost hostnames", () => {
54
+ process.env.SUPERBLOCKS_BUCKETEER_URL = "http://localhost:8330";
55
+
56
+ expect(
57
+ getBucketeerUrlFromSuperblocksUrl("https://app.superblocks.com"),
58
+ ).toBe("https://bucketeer.superblocks.com");
59
+ expect(
60
+ getBucketeerUrlFromSuperblocksUrl("https://staging.superblocks.com"),
61
+ ).toBe("https://bucketeer.staging.superblocks.com");
62
+ expect(
63
+ getBucketeerUrlFromSuperblocksUrl("https://eu.superblocks.com"),
64
+ ).toBe("https://bucketeer.eu.superblocks.com");
65
+ expect(
66
+ getBucketeerUrlFromSuperblocksUrl("https://pr-123.superblocks.dev"),
67
+ ).toBe("https://bucketeer.dev.superblocks.com");
68
+ });
69
+ });
@@ -1,28 +1,42 @@
1
- import { isEmpty } from "lodash";
2
-
3
1
  export const COMPONENT_EVENT_HEADER = "x-superblocks-component-event";
4
2
 
3
+ // SUPERBLOCKS_BUCKETEER_URL lets slot-N Tilt worktrees override the default
4
+ // localhost bucketeer URL (http://localhost:8030) when the server runs on a
5
+ // different slot offset. The local-orch Tilt profile injects this variable
6
+ // for the server's serve env.
7
+ const localhostBucketeerUrl = (): string =>
8
+ process.env.SUPERBLOCKS_BUCKETEER_URL ?? "http://localhost:8030";
9
+
5
10
  // retrieves bucketeer base URL given the superblocks server base URL
6
11
  export const getBucketeerUrlFromSuperblocksUrl = (
7
12
  superblocksBaseUrl: string,
8
13
  ): string => {
9
- // if superblocks base URL is an EE, return bucketeer's dev URL
10
- if (!isEmpty(superblocksBaseUrl.match(new RegExp("pr-.*.superblocks.dev")))) {
14
+ let hostname: string;
15
+ try {
16
+ hostname = new URL(superblocksBaseUrl).hostname;
17
+ } catch {
18
+ return localhostBucketeerUrl();
19
+ }
20
+
21
+ if (/^pr-.*\.superblocks\.dev$/u.test(hostname)) {
11
22
  return "https://bucketeer.dev.superblocks.com";
12
23
  }
13
24
 
14
- switch (superblocksBaseUrl) {
15
- case "https://eu.superblocks.com":
25
+ switch (hostname) {
26
+ case "eu.superblocks.com":
27
+ case "prod-eu.superblocks.com":
16
28
  return "https://bucketeer.eu.superblocks.com";
17
- case "https://staging.superblocks.com":
29
+ case "app.staging.superblocks.com":
30
+ case "staging.superblocks.com":
18
31
  return "https://bucketeer.staging.superblocks.com";
19
- case "https://app.superblocks.com":
20
- case "https://app.superblockshq.com":
32
+ case "app.superblocks.com":
33
+ case "app.superblockshq.com":
21
34
  return "https://bucketeer.superblocks.com";
22
- case "https://dev.superblocks.com":
35
+ case "dev.superblocks.com":
23
36
  return "https://bucketeer.dev.superblocks.com";
24
- case "http://localhost:3000":
37
+ case "127.0.0.1":
38
+ case "localhost":
25
39
  default:
26
- return "http://localhost:8030";
40
+ return localhostBucketeerUrl();
27
41
  }
28
42
  };
package/src/index.ts CHANGED
@@ -13,3 +13,4 @@ export * from "./api-files/types.js";
13
13
  export * from "./api-files/index.js";
14
14
  export * from "./api-files/constants.js";
15
15
  export * from "./mask-unix-signals.js";
16
+ export * from "./token-manager.js";
package/src/login.ts CHANGED
@@ -1,6 +1,8 @@
1
1
  import { homedir } from "node:os";
2
- import { join } from "node:path";
3
- import * as fs from "fs-extra";
2
+ import { dirname, join } from "node:path";
3
+
4
+ import fs from "fs-extra";
5
+
4
6
  import { FileAccessError, TOKEN_CONFIG_PATH } from "./constants.js";
5
7
 
6
8
  type BaseUrl = {
@@ -11,20 +13,32 @@ type TokenWithBaseUrl = BaseUrl & {
11
13
  token: string;
12
14
  };
13
15
 
16
+ /**
17
+ * Returns the resolved auth file path, honoring the SUPERBLOCKS_AUTH_FILE
18
+ * environment variable. Both reads and writes MUST use this so the CLI
19
+ * never writes to one file and reads from another.
20
+ */
21
+ export function resolveAuthFilePath(): string {
22
+ return (
23
+ process.env.SUPERBLOCKS_AUTH_FILE || join(homedir(), TOKEN_CONFIG_PATH)
24
+ );
25
+ }
26
+
14
27
  export async function saveApiToken(superblocksBaseUrl: string, token?: string) {
15
28
  try {
16
- await fs.ensureDir(join(homedir(), ".superblocks"));
29
+ const authFile = resolveAuthFilePath();
30
+ await fs.ensureDir(dirname(authFile));
17
31
  if (token) {
18
32
  const tokenConfig: TokenWithBaseUrl = {
19
33
  superblocksBaseUrl,
20
34
  token,
21
35
  };
22
- await fs.writeJSON(join(homedir(), TOKEN_CONFIG_PATH), tokenConfig);
36
+ await fs.writeJSON(authFile, tokenConfig);
23
37
  } else {
24
38
  const tokenConfig: BaseUrl = {
25
39
  superblocksBaseUrl,
26
40
  };
27
- await fs.writeJSON(join(homedir(), TOKEN_CONFIG_PATH), tokenConfig);
41
+ await fs.writeJSON(authFile, tokenConfig);
28
42
  }
29
43
  } catch {
30
44
  throw new FileAccessError("Could not save token");
@@ -46,18 +60,20 @@ export async function getLocalTokenWithUrl(): Promise<
46
60
  > {
47
61
  try {
48
62
  const tokenConfig: TokenWithBaseUrl = await fs.readJSON(
49
- process.env.SUPERBLOCKS_AUTH_FILE || join(homedir(), TOKEN_CONFIG_PATH),
63
+ resolveAuthFilePath(),
50
64
  );
65
+ const superblocksBaseUrl =
66
+ process.env.SUPERBLOCKS_BASE_URL || tokenConfig.superblocksBaseUrl;
51
67
  if (tokenConfig.token) {
52
68
  // user logged in
53
69
  return {
54
70
  token: tokenConfig.token,
55
- superblocksBaseUrl: tokenConfig.superblocksBaseUrl,
71
+ superblocksBaseUrl,
56
72
  };
57
73
  } else {
58
74
  // user not logged in, but set domain
59
75
  return {
60
- superblocksBaseUrl: tokenConfig.superblocksBaseUrl,
76
+ superblocksBaseUrl,
61
77
  };
62
78
  }
63
79
  } catch {
@@ -3,7 +3,7 @@ const unixSignalsToMask: NodeJS.Signals[] = ["SIGINT", "SIGTERM", "SIGHUP"];
3
3
  // The exit code that is used when the process is aborted due to a unix signal
4
4
  const exitCode = 254;
5
5
 
6
- export type ActionResult<T> =
6
+ type ActionResult<T> =
7
7
  | { success: true; returnValue: T }
8
8
  | { success: false; error: unknown };
9
9