@arkstack/console 0.14.18 → 0.14.19
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.
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { readdirSync, writeFileSync } from "node:fs";
|
|
1
|
+
import { existsSync, readFileSync, readdirSync, writeFileSync } from "node:fs";
|
|
2
2
|
import path from "node:path";
|
|
3
3
|
import { Arkstack } from "@arkstack/contract";
|
|
4
4
|
import { Node, Project } from "ts-morph";
|
|
@@ -61,6 +61,113 @@ var BuildInterfaces = class BuildInterfaces {
|
|
|
61
61
|
};
|
|
62
62
|
for (const [file, config] of Object.entries(configs)) writeFileSync(path.join(Arkstack.rootDir(), file), config, "utf8");
|
|
63
63
|
}
|
|
64
|
+
/**
|
|
65
|
+
* Generate an `EnvRegistry` augmentation from the application's `.env`
|
|
66
|
+
* schema, giving `env()` precise return types for app-specific variables.
|
|
67
|
+
*
|
|
68
|
+
* Mirrors {@link configs}: the declaration is appended to
|
|
69
|
+
* `.arkstack/ark.d.ts`. Keys already typed by the framework's own
|
|
70
|
+
* `EnvRegistry` are skipped so declaration merging never conflicts.
|
|
71
|
+
*
|
|
72
|
+
* @param envFile Explicit `.env` path; defaults to `.env.example` then `.env`.
|
|
73
|
+
*/
|
|
74
|
+
static env(envFile) {
|
|
75
|
+
const root = Arkstack.rootDir();
|
|
76
|
+
const file = envFile ?? BuildInterfaces.resolveEnvFile(root);
|
|
77
|
+
if (!file) return;
|
|
78
|
+
const declaration = BuildInterfaces.envRegistryFromEnv(readFileSync(file, "utf8"), [...BuildInterfaces.frameworkEnvKeys()]);
|
|
79
|
+
if (!declaration) return;
|
|
80
|
+
const target = path.join(root, ".arkstack/ark.d.ts");
|
|
81
|
+
let content = `${existsSync(target) ? readFileSync(target, "utf8") : ""}\n${declaration}\n`;
|
|
82
|
+
if (!/^\s*export\s|\bimport\s/m.test(content)) content += "\nexport {}\n";
|
|
83
|
+
writeFileSync(target, content, "utf8");
|
|
84
|
+
}
|
|
85
|
+
/**
|
|
86
|
+
* Render an `EnvRegistry` augmentation for the variables declared in the
|
|
87
|
+
* given `.env` contents. Pure (no filesystem) for testability.
|
|
88
|
+
*
|
|
89
|
+
* @param contents Raw `.env` file contents.
|
|
90
|
+
* @param skip Variable names to omit (e.g. framework-owned keys).
|
|
91
|
+
* @returns The `declare module` block, or `''` when nothing to emit.
|
|
92
|
+
*/
|
|
93
|
+
static envRegistryFromEnv(contents, skip = []) {
|
|
94
|
+
const skipped = new Set(skip);
|
|
95
|
+
const properties = Object.entries(BuildInterfaces.parseEnvFile(contents)).filter(([key]) => !skipped.has(key)).map(([key, value]) => ` ${key}: ${BuildInterfaces.inferEnvType(value)}`);
|
|
96
|
+
if (!properties.length) return "";
|
|
97
|
+
return [
|
|
98
|
+
"declare module '@arkstack/common' {",
|
|
99
|
+
" interface EnvRegistry {",
|
|
100
|
+
...properties,
|
|
101
|
+
" }",
|
|
102
|
+
"}"
|
|
103
|
+
].join("\n");
|
|
104
|
+
}
|
|
105
|
+
/**
|
|
106
|
+
* Prefer `.env.example` (the documented schema), then `.env`.
|
|
107
|
+
*
|
|
108
|
+
* @param root
|
|
109
|
+
* @returns
|
|
110
|
+
*/
|
|
111
|
+
static resolveEnvFile(root) {
|
|
112
|
+
for (const name of [".env.example", ".env"]) {
|
|
113
|
+
const file = path.join(root, name);
|
|
114
|
+
if (existsSync(file)) return file;
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
/**
|
|
118
|
+
* Parse `KEY=VALUE` lines, skipping blanks, comments and invalid names.
|
|
119
|
+
*
|
|
120
|
+
* @param contents
|
|
121
|
+
* @returns
|
|
122
|
+
*/
|
|
123
|
+
static parseEnvFile(contents) {
|
|
124
|
+
const entries = {};
|
|
125
|
+
for (const raw of contents.split(/\r?\n/)) {
|
|
126
|
+
const line = raw.trim();
|
|
127
|
+
if (!line || line.startsWith("#")) continue;
|
|
128
|
+
const eq = line.indexOf("=");
|
|
129
|
+
if (eq === -1) continue;
|
|
130
|
+
const key = line.slice(0, eq).trim();
|
|
131
|
+
if (!/^[A-Za-z_][A-Za-z0-9_]*$/.test(key)) continue;
|
|
132
|
+
let value = line.slice(eq + 1).trim();
|
|
133
|
+
if (value.startsWith("\"") && value.endsWith("\"") || value.startsWith("'") && value.endsWith("'")) value = value.slice(1, -1);
|
|
134
|
+
entries[key] = value;
|
|
135
|
+
}
|
|
136
|
+
return entries;
|
|
137
|
+
}
|
|
138
|
+
/**
|
|
139
|
+
* Infer a TS type from a value, mirroring env()'s runtime coercion.
|
|
140
|
+
*
|
|
141
|
+
* @param value
|
|
142
|
+
* @returns
|
|
143
|
+
*/
|
|
144
|
+
static inferEnvType(value) {
|
|
145
|
+
if (value === "") return "string";
|
|
146
|
+
if ([
|
|
147
|
+
"true",
|
|
148
|
+
"false",
|
|
149
|
+
"on",
|
|
150
|
+
"off"
|
|
151
|
+
].includes(value)) return "boolean";
|
|
152
|
+
if (!Number.isNaN(Number(value))) return "number";
|
|
153
|
+
return "string";
|
|
154
|
+
}
|
|
155
|
+
/**
|
|
156
|
+
* Resolve the framework's own `EnvRegistry` keys to skip during generation.
|
|
157
|
+
*
|
|
158
|
+
* @returns
|
|
159
|
+
*/
|
|
160
|
+
static frameworkEnvKeys() {
|
|
161
|
+
try {
|
|
162
|
+
const keys = new Project({
|
|
163
|
+
tsConfigFilePath: path.join(Arkstack.rootDir(), "tsconfig.json"),
|
|
164
|
+
skipAddingFilesFromTsConfig: true
|
|
165
|
+
}).createSourceFile("__ark_env_probe__.ts", "import type { EnvRegistry } from '@arkstack/common'\ndeclare const value: EnvRegistry\n", { overwrite: true }).getVariableDeclarationOrThrow("value").getType().getProperties().map((prop) => prop.getName());
|
|
166
|
+
return new Set(keys);
|
|
167
|
+
} catch {
|
|
168
|
+
return /* @__PURE__ */ new Set();
|
|
169
|
+
}
|
|
170
|
+
}
|
|
64
171
|
static generateConfig(configDir = path.join(process.cwd(), "src/config")) {
|
|
65
172
|
BuildInterfaces.project = new Project({
|
|
66
173
|
tsConfigFilePath: path.join(process.cwd(), "tsconfig.json"),
|
package/dist/index.d.ts
CHANGED
|
@@ -9,6 +9,53 @@ declare class BuildInterfaces {
|
|
|
9
9
|
*/
|
|
10
10
|
static configs(configDir?: string): void;
|
|
11
11
|
static tsconfig(): void;
|
|
12
|
+
/**
|
|
13
|
+
* Generate an `EnvRegistry` augmentation from the application's `.env`
|
|
14
|
+
* schema, giving `env()` precise return types for app-specific variables.
|
|
15
|
+
*
|
|
16
|
+
* Mirrors {@link configs}: the declaration is appended to
|
|
17
|
+
* `.arkstack/ark.d.ts`. Keys already typed by the framework's own
|
|
18
|
+
* `EnvRegistry` are skipped so declaration merging never conflicts.
|
|
19
|
+
*
|
|
20
|
+
* @param envFile Explicit `.env` path; defaults to `.env.example` then `.env`.
|
|
21
|
+
*/
|
|
22
|
+
static env(envFile?: string): void;
|
|
23
|
+
/**
|
|
24
|
+
* Render an `EnvRegistry` augmentation for the variables declared in the
|
|
25
|
+
* given `.env` contents. Pure (no filesystem) for testability.
|
|
26
|
+
*
|
|
27
|
+
* @param contents Raw `.env` file contents.
|
|
28
|
+
* @param skip Variable names to omit (e.g. framework-owned keys).
|
|
29
|
+
* @returns The `declare module` block, or `''` when nothing to emit.
|
|
30
|
+
*/
|
|
31
|
+
static envRegistryFromEnv(contents: string, skip?: string[]): string;
|
|
32
|
+
/**
|
|
33
|
+
* Prefer `.env.example` (the documented schema), then `.env`.
|
|
34
|
+
*
|
|
35
|
+
* @param root
|
|
36
|
+
* @returns
|
|
37
|
+
*/
|
|
38
|
+
private static resolveEnvFile;
|
|
39
|
+
/**
|
|
40
|
+
* Parse `KEY=VALUE` lines, skipping blanks, comments and invalid names.
|
|
41
|
+
*
|
|
42
|
+
* @param contents
|
|
43
|
+
* @returns
|
|
44
|
+
*/
|
|
45
|
+
private static parseEnvFile;
|
|
46
|
+
/**
|
|
47
|
+
* Infer a TS type from a value, mirroring env()'s runtime coercion.
|
|
48
|
+
*
|
|
49
|
+
* @param value
|
|
50
|
+
* @returns
|
|
51
|
+
*/
|
|
52
|
+
private static inferEnvType;
|
|
53
|
+
/**
|
|
54
|
+
* Resolve the framework's own `EnvRegistry` keys to skip during generation.
|
|
55
|
+
*
|
|
56
|
+
* @returns
|
|
57
|
+
*/
|
|
58
|
+
private static frameworkEnvKeys;
|
|
12
59
|
private static generateConfig;
|
|
13
60
|
private static resolveReturnTypeAnnotation;
|
|
14
61
|
private static findNamedTypeImport;
|
package/dist/index.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import { t as ArkstackConsoleApp } from "./app-DnaQWE9q.js";
|
|
3
|
-
import { n as BaseTCConfig, r as TSConfig, t as BuildInterfaces } from "./BuildInterfaces-
|
|
3
|
+
import { n as BaseTCConfig, r as TSConfig, t as BuildInterfaces } from "./BuildInterfaces-CPmSl41C.js";
|
|
4
4
|
import { Publisher, abort, abortIf, assertFound, config, discoverCommands, env, importFile, initializeGlobalContext, loadPrototypes, outputDir, rebuildOutput } from "@arkstack/common";
|
|
5
5
|
import { cpSync, existsSync, mkdirSync, readFileSync, readdirSync, realpathSync, renameSync, statSync, writeFileSync } from "node:fs";
|
|
6
6
|
import { fileURLToPath, pathToFileURL } from "node:url";
|
package/dist/prepare.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import { t as BuildInterfaces } from "./BuildInterfaces-
|
|
2
|
+
import { t as BuildInterfaces } from "./BuildInterfaces-CPmSl41C.js";
|
|
3
3
|
import { existsSync, mkdirSync } from "node:fs";
|
|
4
4
|
import path from "node:path";
|
|
5
5
|
import { Arkstack } from "@arkstack/contract";
|
|
@@ -8,7 +8,10 @@ import chalk from "chalk";
|
|
|
8
8
|
|
|
9
9
|
//#region dist/prepare.js
|
|
10
10
|
if (!existsSync(path.join(Arkstack.rootDir(), ".arkstack/build"))) mkdirSync(path.join(Arkstack.rootDir(), ".arkstack/build"), { recursive: true });
|
|
11
|
-
if (!process.env.NODE_CI)
|
|
11
|
+
if (!process.env.NODE_CI) {
|
|
12
|
+
BuildInterfaces.configs();
|
|
13
|
+
BuildInterfaces.env();
|
|
14
|
+
}
|
|
12
15
|
BuildInterfaces.tsconfig();
|
|
13
16
|
const LOG_LEVEL = parseInt(process.env.VERBOSITY ?? "0") > 0 ? [] : ["--log-level=silent"];
|
|
14
17
|
const NODE_ENV = process.env.NODE_ENV || "development";
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@arkstack/console",
|
|
3
|
-
"version": "0.14.
|
|
3
|
+
"version": "0.14.19",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"description": "Console module for Arkstack, providing the command-line runtime and console integration layer.",
|
|
6
6
|
"homepage": "https://arkstack.toneflix.net/guide/cli",
|
|
@@ -51,8 +51,8 @@
|
|
|
51
51
|
"chalk": "^5.6.2",
|
|
52
52
|
"resora": "^1.3.27",
|
|
53
53
|
"ts-morph": "^28.0.0",
|
|
54
|
-
"@arkstack/
|
|
55
|
-
"@arkstack/
|
|
54
|
+
"@arkstack/contract": "^0.14.19",
|
|
55
|
+
"@arkstack/common": "^0.14.19"
|
|
56
56
|
},
|
|
57
57
|
"scripts": {
|
|
58
58
|
"build": "tsdown",
|