@storm-software/config-tools 1.21.5 → 1.22.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/src/schema.ts ADDED
@@ -0,0 +1,182 @@
1
+ import * as z from "zod";
2
+
3
+ /**
4
+ * Storm theme color config values used for styling various workspace elements
5
+ */
6
+ export const ColorConfigSchema = z
7
+ .object({
8
+ primary: z
9
+ .string()
10
+ .trim()
11
+ .toLowerCase()
12
+ .regex(/^#([0-9a-f]{3}){1,2}$/i)
13
+ .length(7)
14
+ .default("#0ea5e9")
15
+ .describe("The primary color of the workspace"),
16
+ background: z
17
+ .string()
18
+ .trim()
19
+ .toLowerCase()
20
+ .regex(/^#([0-9a-f]{3}){1,2}$/i)
21
+ .length(7)
22
+ .default("#1d232a")
23
+ .describe("The background color of the workspace"),
24
+ success: z
25
+ .string()
26
+ .trim()
27
+ .toLowerCase()
28
+ .regex(/^#([0-9a-f]{3}){1,2}$/i)
29
+ .length(7)
30
+ .default("#087f5b")
31
+ .describe("The success color of the workspace"),
32
+ info: z
33
+ .string()
34
+ .trim()
35
+ .toLowerCase()
36
+ .regex(/^#([0-9a-f]{3}){1,2}$/i)
37
+ .length(7)
38
+ .default("#0ea5e9")
39
+ .describe("The informational color of the workspace"),
40
+ warning: z
41
+ .string()
42
+ .trim()
43
+ .toLowerCase()
44
+ .regex(/^#([0-9a-f]{3}){1,2}$/i)
45
+ .length(7)
46
+ .default("#fcc419")
47
+ .describe("The warning color of the workspace"),
48
+ error: z
49
+ .string()
50
+ .trim()
51
+ .toLowerCase()
52
+ .regex(/^#([0-9a-f]{3}){1,2}$/i)
53
+ .length(7)
54
+ .default("#990000")
55
+ .describe("The error color of the workspace"),
56
+ fatal: z
57
+ .string()
58
+ .trim()
59
+ .toLowerCase()
60
+ .regex(/^#([0-9a-f]{3}){1,2}$/i)
61
+ .length(7)
62
+ .default("#7d1a1a")
63
+ .describe("The fatal color of the workspace")
64
+ })
65
+ .describe("Colors used for various workspace elements");
66
+
67
+ /**
68
+ * Storm Workspace config values used during various dev-ops processes. It represents the config of the entire monorepo.
69
+ */
70
+ export const StormConfigSchema = z
71
+ .object({
72
+ name: z.string().trim().toLowerCase().optional().describe("The name of the package"),
73
+ namespace: z.string().trim().toLowerCase().optional().describe("The namespace of the package"),
74
+ organization: z
75
+ .string()
76
+ .trim()
77
+ .default("storm-software")
78
+ .describe("The organization of the workspace"),
79
+ repository: z
80
+ .string()
81
+ .trim()
82
+ .url()
83
+ .optional()
84
+ .describe("The repo URL of the workspace (i.e. GitHub)"),
85
+ license: z
86
+ .string()
87
+ .trim()
88
+ .default("Apache License 2.0")
89
+ .describe("The root directory of the package"),
90
+ homepage: z
91
+ .string()
92
+ .trim()
93
+ .url()
94
+ .default("https://stormsoftware.org")
95
+ .describe("The homepage of the workspace"),
96
+ branch: z.string().trim().default("main").describe("The branch of the workspace"),
97
+ preMajor: z
98
+ .boolean()
99
+ .default(false)
100
+ .describe("An indicator specifying if the package is still in it's pre-major version"),
101
+ owner: z
102
+ .string()
103
+ .trim()
104
+ .default("@storm-software/development")
105
+ .describe("The owner of the package"),
106
+ worker: z
107
+ .string()
108
+ .trim()
109
+ .default("stormie-bot")
110
+ .describe(
111
+ "The worker of the package (this is the bot that will be used to perform various tasks)"
112
+ ),
113
+ env: z
114
+ .enum(["development", "staging", "production"])
115
+ .default("production")
116
+ .describe("The current runtime environment of the package"),
117
+ ci: z
118
+ .boolean()
119
+ .default(true)
120
+ .describe("An indicator specifying if the current environment is a CI environment"),
121
+ workspaceRoot: z.string().trim().optional().describe("The root directory of the workspace"),
122
+ packageDirectory: z.string().trim().optional().describe("The root directory of the package"),
123
+ externalPackagePatterns: z
124
+ .array(z.string())
125
+ .default([])
126
+ .describe(
127
+ "The build will use these package patterns to determine if they should be external to the bundle"
128
+ ),
129
+ buildDirectory: z
130
+ .string()
131
+ .trim()
132
+ .default("dist")
133
+ .describe("The build directory for the workspace"),
134
+ runtimeDirectory: z
135
+ .string()
136
+ .trim()
137
+ .default("node_modules/.storm")
138
+ .describe("The runtime directory of Storm"),
139
+ runtimeVersion: z
140
+ .string()
141
+ .trim()
142
+ .regex(
143
+ /^(0|[1-9]\d*)\.(0|[1-9]\d*)\.(0|[1-9]\d*)(?:-((?:0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*)(?:\.(?:0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*))*))?(?:\+([0-9a-zA-Z-]+(?:\.[0-9a-zA-Z-]+)*))?$/
144
+ )
145
+ .default("1.0.0")
146
+ .describe("The global version of the Storm runtime"),
147
+ packageManager: z
148
+ .enum(["npm", "yarn", "pnpm", "bun"])
149
+ .default("npm")
150
+ .describe("The package manager used by the repository"),
151
+ timezone: z
152
+ .string()
153
+ .trim()
154
+ .default("America/New_York")
155
+ .describe("The default timezone of the workspace"),
156
+ locale: z.string().trim().default("en-US").describe("The default locale of the workspace"),
157
+ logLevel: z
158
+ .enum(["silent", "fatal", "error", "warn", "info", "debug", "trace", "all"])
159
+ .default("debug")
160
+ .describe(
161
+ "The log level used to filter out lower priority log messages. If not provided, this is defaulted using the `environment` config value (if `environment` is set to `production` then `level` is `error`, else `level` is `debug`)."
162
+ ),
163
+ configFile: z
164
+ .string()
165
+ .trim()
166
+ .nullable()
167
+ .default(null)
168
+ .describe(
169
+ "The filepath of the Storm config. When this field is null, no config file was found in the current workspace."
170
+ ),
171
+ colors: ColorConfigSchema.describe(
172
+ "Storm theme config values used for styling various package elements"
173
+ ),
174
+ extensions: z
175
+ .record(z.any())
176
+ .optional()
177
+ .default({})
178
+ .describe("Configuration of each used extension")
179
+ })
180
+ .describe(
181
+ "Storm Workspace config values used during various dev-ops processes. This type is a combination of the StormPackageConfig and StormProject types. It represents the config of the entire monorepo."
182
+ );
package/src/types.ts ADDED
@@ -0,0 +1,53 @@
1
+ import type * as z from "zod";
2
+ import type { ColorConfigSchema, StormConfigSchema } from "./schema";
3
+
4
+ export type ColorConfig = z.infer<typeof ColorConfigSchema>;
5
+ export type ColorConfigInput = z.input<typeof ColorConfigSchema>;
6
+
7
+ type TStormConfig = z.infer<typeof StormConfigSchema>;
8
+ export type StormConfigInput = z.input<typeof StormConfigSchema>;
9
+
10
+ export type StormConfig<
11
+ TExtensionName extends keyof TStormConfig["extensions"] = keyof TStormConfig["extensions"],
12
+ TExtensionConfig extends
13
+ TStormConfig["extensions"][TExtensionName] = TStormConfig["extensions"][TExtensionName]
14
+ > = TStormConfig & {
15
+ extensions?:
16
+ | (TStormConfig["extensions"] & {
17
+ [extensionName in TExtensionName]: TExtensionConfig;
18
+ })
19
+ | Record<string, any>;
20
+ };
21
+
22
+ export type LogLevel = 0 | 10 | 20 | 30 | 40 | 45 | 60 | 70 | 100;
23
+ export const LogLevel = {
24
+ SILENT: 0 as LogLevel,
25
+ FATAL: 10 as LogLevel,
26
+ ERROR: 20 as LogLevel,
27
+ WARN: 30 as LogLevel,
28
+ INFO: 40 as LogLevel,
29
+ SUCCESS: 45 as LogLevel,
30
+ DEBUG: 60 as LogLevel,
31
+ TRACE: 70 as LogLevel,
32
+ ALL: 100 as LogLevel
33
+ } as const;
34
+
35
+ export type LogLevelLabel =
36
+ | "silent"
37
+ | "fatal"
38
+ | "error"
39
+ | "warn"
40
+ | "info"
41
+ | "debug"
42
+ | "trace"
43
+ | "all";
44
+ export const LogLevelLabel = {
45
+ SILENT: "silent" as LogLevelLabel,
46
+ FATAL: "fatal" as LogLevelLabel,
47
+ ERROR: "error" as LogLevelLabel,
48
+ WARN: "warn" as LogLevelLabel,
49
+ INFO: "info" as LogLevelLabel,
50
+ DEBUG: "debug" as LogLevelLabel,
51
+ TRACE: "trace" as LogLevelLabel,
52
+ ALL: "all" as LogLevelLabel
53
+ } as const;
@@ -0,0 +1,21 @@
1
+ import { existsSync } from "node:fs";
2
+ import { join } from "node:path";
3
+
4
+ const MAX_PATH_SEARCH_DEPTH = 30;
5
+ let depth = 0;
6
+
7
+ /**
8
+ * Gets the nearest "node_modules" folder by walking up from start path.
9
+ */
10
+ export function findFolderUp(startPath: string, endFileNames: string[]): string | undefined {
11
+ const _startPath = startPath ?? process.cwd();
12
+
13
+ if (endFileNames.some((endFileName) => existsSync(join(_startPath, endFileName)))) {
14
+ return _startPath;
15
+ }
16
+ if (_startPath !== "/" && depth++ < MAX_PATH_SEARCH_DEPTH) {
17
+ const parent = join(_startPath, "..");
18
+ return findFolderUp(parent, endFileNames);
19
+ }
20
+ return undefined;
21
+ }
@@ -0,0 +1,66 @@
1
+ import { findFolderUp } from "./find-up";
2
+
3
+ const rootFiles = [
4
+ "lerna.json",
5
+ "storm.config.js",
6
+ "storm.config.ts",
7
+ ".storm.json",
8
+ ".storm.yaml",
9
+ ".storm.yml",
10
+ ".storm.js",
11
+ ".storm.ts",
12
+ "nx.json",
13
+ "turbo.json",
14
+ "npm-workspace.json",
15
+ "yarn-workspace.json",
16
+ "pnpm-workspace.json",
17
+ "npm-workspace.yaml",
18
+ "yarn-workspace.yaml",
19
+ "pnpm-workspace.yaml",
20
+ "npm-workspace.yml",
21
+ "yarn-workspace.yml",
22
+ "pnpm-workspace.yml",
23
+ "npm-lock.json",
24
+ "yarn-lock.json",
25
+ "pnpm-lock.json",
26
+ "npm-lock.yaml",
27
+ "yarn-lock.yaml",
28
+ "pnpm-lock.yaml",
29
+ "npm-lock.yml",
30
+ "yarn-lock.yml",
31
+ "pnpm-lock.yml",
32
+ "bun.lockb"
33
+ ];
34
+
35
+ /**
36
+ * Find the monorepo root directory, searching upwards from `path`.
37
+ *
38
+ * @param pathInsideMonorepo - The path inside the monorepo to start searching from
39
+ * @returns The monorepo root directory
40
+ */
41
+ export function findWorkspaceRootSafe(pathInsideMonorepo?: string): string | undefined {
42
+ if (process.env.STORM_WORKSPACE_ROOT || process.env.NX_WORKSPACE_ROOT_PATH) {
43
+ return process.env.STORM_WORKSPACE_ROOT ?? process.env.NX_WORKSPACE_ROOT_PATH;
44
+ }
45
+
46
+ return findFolderUp(pathInsideMonorepo ?? process.cwd(), rootFiles);
47
+ }
48
+
49
+ /**
50
+ * Find the monorepo root directory, searching upwards from `path`.
51
+ *
52
+ * @param pathInsideMonorepo - The path inside the monorepo to start searching from
53
+ * @returns The monorepo root directory
54
+ */
55
+ export function findWorkspaceRoot(pathInsideMonorepo?: string): string {
56
+ const result = findWorkspaceRootSafe(pathInsideMonorepo);
57
+ if (!result) {
58
+ throw new Error(
59
+ `Cannot find workspace root upwards from known path. Files search list includes: \n${rootFiles.join(
60
+ "\n"
61
+ )}\nPath: ${pathInsideMonorepo ? pathInsideMonorepo : process.cwd()}`
62
+ );
63
+ }
64
+
65
+ return result;
66
+ }
@@ -0,0 +1,98 @@
1
+ import { existsSync, readFileSync } from "node:fs";
2
+ import { join } from "node:path";
3
+ import { StormConfigSchema } from "../schema";
4
+ import type { ColorConfig, StormConfig } from "../types";
5
+ import { findWorkspaceRoot } from "./find-workspace-root";
6
+
7
+ /**
8
+ * Storm theme config values used for styling various workspace elements
9
+ */
10
+ export const DEFAULT_COLOR_CONFIG: ColorConfig = {
11
+ primary: "#1fb2a6",
12
+ background: "#1d232a",
13
+ success: "#087f5b",
14
+ info: "#0ea5e9",
15
+ warning: "#fcc419",
16
+ error: "#990000",
17
+ fatal: "#7d1a1a"
18
+ };
19
+
20
+ /**
21
+ * Storm Workspace config values used during various dev-ops processes
22
+ */
23
+ export const DEFAULT_STORM_CONFIG: StormConfig = {
24
+ name: "storm",
25
+ namespace: "storm-software",
26
+ license: "Apache License 2.0",
27
+ homepage: "https://stormsoftware.org",
28
+ preMajor: false,
29
+ owner: "@storm-software/development",
30
+ worker: "stormie-bot",
31
+ runtimeDirectory: "node_modules/.storm",
32
+ packageManager: "npm",
33
+ timezone: "America/New_York",
34
+ locale: "en-US",
35
+ env: "production",
36
+ branch: "main",
37
+ organization: "storm-software",
38
+ ci: true,
39
+ configFile: null,
40
+ runtimeVersion: "1.0.0",
41
+ colors: { ...DEFAULT_COLOR_CONFIG },
42
+ extensions: {}
43
+ };
44
+
45
+ /**
46
+ * Get the default Storm config values used during various dev-ops processes
47
+ *
48
+ * @returns The default Storm config values
49
+ */
50
+ export const getDefaultConfig = (config: Partial<StormConfig> = {}, root?: string): StormConfig => {
51
+ let name = "storm-workspace";
52
+ let namespace = "storm-software";
53
+ let repository = "https://github.com/storm-software/storm-ops";
54
+
55
+ let license = DEFAULT_STORM_CONFIG.license;
56
+ let homepage = DEFAULT_STORM_CONFIG.homepage;
57
+
58
+ const workspaceRoot = findWorkspaceRoot(root);
59
+ if (existsSync(join(workspaceRoot, "package.json"))) {
60
+ const file = readFileSync(join(workspaceRoot, "package.json"), {
61
+ encoding: "utf-8"
62
+ });
63
+ if (file) {
64
+ const packageJson = JSON.parse(file);
65
+
66
+ if (packageJson.name) {
67
+ name = packageJson.name;
68
+ }
69
+ if (packageJson.namespace) {
70
+ namespace = packageJson.namespace;
71
+ }
72
+ if (packageJson.repository?.url) {
73
+ repository = packageJson.repository?.url;
74
+ }
75
+ if (packageJson.license) {
76
+ license = packageJson.license;
77
+ }
78
+ if (packageJson.homepage) {
79
+ homepage = packageJson.homepage;
80
+ }
81
+ }
82
+ }
83
+
84
+ return StormConfigSchema.parse({
85
+ ...(DEFAULT_STORM_CONFIG as Required<StormConfig>),
86
+ ...config,
87
+ colors: { ...DEFAULT_COLOR_CONFIG, ...config.colors },
88
+ workspaceRoot,
89
+ name,
90
+ namespace,
91
+ repository,
92
+ license: license ?? DEFAULT_STORM_CONFIG.license,
93
+ homepage: homepage ?? DEFAULT_STORM_CONFIG.homepage,
94
+ extensions: {
95
+ ...config.extensions
96
+ }
97
+ }) as StormConfig;
98
+ };
@@ -0,0 +1,64 @@
1
+ import { LogLevel, LogLevelLabel } from "../types";
2
+
3
+ /**
4
+ * Convert the log level label to a log level
5
+ *
6
+ * @param label - The log level label to convert
7
+ * @returns The log level
8
+ */
9
+ export const getLogLevel = (label: string): LogLevel => {
10
+ switch (label) {
11
+ case "all":
12
+ return LogLevel.ALL;
13
+ case "trace":
14
+ return LogLevel.TRACE;
15
+ case "debug":
16
+ return LogLevel.DEBUG;
17
+ case "info":
18
+ return LogLevel.INFO;
19
+ case "warn":
20
+ return LogLevel.WARN;
21
+ case "error":
22
+ return LogLevel.ERROR;
23
+ case "fatal":
24
+ return LogLevel.FATAL;
25
+ case "silent":
26
+ return LogLevel.SILENT;
27
+ default:
28
+ return LogLevel.INFO;
29
+ }
30
+ };
31
+
32
+ /**
33
+ * Convert the log level to a log level label
34
+ *
35
+ * @param logLevel - The log level to convert
36
+ * @returns The log level label
37
+ */
38
+ export const getLogLevelLabel = (logLevel: number): LogLevelLabel => {
39
+ if (logLevel >= LogLevel.ALL) {
40
+ return LogLevelLabel.ALL;
41
+ }
42
+ if (logLevel >= LogLevel.TRACE) {
43
+ return LogLevelLabel.TRACE;
44
+ }
45
+ if (logLevel >= LogLevel.DEBUG) {
46
+ return LogLevelLabel.DEBUG;
47
+ }
48
+ if (logLevel >= LogLevel.INFO) {
49
+ return LogLevelLabel.INFO;
50
+ }
51
+ if (logLevel >= LogLevel.WARN) {
52
+ return LogLevelLabel.WARN;
53
+ }
54
+ if (logLevel >= LogLevel.ERROR) {
55
+ return LogLevelLabel.ERROR;
56
+ }
57
+ if (logLevel >= LogLevel.FATAL) {
58
+ return LogLevelLabel.FATAL;
59
+ }
60
+ if (logLevel <= LogLevel.SILENT) {
61
+ return LogLevelLabel.SILENT;
62
+ }
63
+ return LogLevelLabel.INFO;
64
+ };
@@ -0,0 +1,6 @@
1
+ export * from "./find-workspace-root";
2
+ export * from "./get-default-config";
3
+ export * from "./get-log-level";
4
+ export * from "./logger";
5
+ export * from "./process-handler";
6
+ export * from "./run";