@arkstack/console 0.11.0 → 0.11.2

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.
@@ -0,0 +1,138 @@
1
+ import path from "node:path";
2
+ import { Arkstack } from "@arkstack/contract";
3
+ import { readdirSync, writeFileSync } from "node:fs";
4
+ import { Project } from "ts-morph";
5
+
6
+ //#region src/prepare/TSConfig.ts
7
+ const TSConfig = {
8
+ compilerOptions: {
9
+ module: "es2022",
10
+ target: "es2022",
11
+ lib: ["es2022", "DOM"],
12
+ moduleResolution: "bundler",
13
+ esModuleInterop: true,
14
+ forceConsistentCasingInFileNames: true,
15
+ strict: true,
16
+ skipLibCheck: true,
17
+ skipDefaultLibCheck: true,
18
+ strictFunctionTypes: true,
19
+ strictPropertyInitialization: true,
20
+ strictBindCallApply: true,
21
+ noImplicitAny: true,
22
+ removeComments: true,
23
+ experimentalDecorators: true,
24
+ emitDecoratorMetadata: true,
25
+ paths: {
26
+ "@": ["../src"],
27
+ "src/*": ["../src/*"],
28
+ "@app/*": ["../src/app/*"],
29
+ "@core/*": ["../src/core/*"],
30
+ "@controllers/*": ["../src/app/http/controllers/*"],
31
+ "@models/*": ["../src/app/models/*"]
32
+ }
33
+ },
34
+ include: [
35
+ "./*.d.ts",
36
+ "../src",
37
+ "../tests"
38
+ ]
39
+ };
40
+ const BaseTCConfig = { extends: "./.arkstack/tsconfig.json" };
41
+
42
+ //#endregion
43
+ //#region src/prepare/BuildInterfaces.ts
44
+ var BuildInterfaces = class BuildInterfaces {
45
+ static project;
46
+ static checker;
47
+ /**
48
+ * Generate configuration interfaces
49
+ *
50
+ * @param configDir
51
+ */
52
+ static configs(configDir) {
53
+ configDir ??= path.join(Arkstack.rootDir(), "src/config");
54
+ const declaration = this.generateConfig(configDir);
55
+ writeFileSync(path.join(Arkstack.rootDir(), ".arkstack/ark.d.ts"), declaration, "utf8");
56
+ }
57
+ static tsconfig() {
58
+ const configs = {
59
+ ".arkstack/tsconfig.json": JSON.stringify(TSConfig, void 0, 2),
60
+ "tsconfig.json": JSON.stringify(BaseTCConfig, void 0, 2)
61
+ };
62
+ for (const [file, config] of Object.entries(configs)) writeFileSync(path.join(Arkstack.rootDir(), file), config, "utf8");
63
+ }
64
+ static generateConfig(configDir = path.join(process.cwd(), "src/config")) {
65
+ BuildInterfaces.project = new Project({
66
+ tsConfigFilePath: path.join(process.cwd(), "tsconfig.json"),
67
+ skipAddingFilesFromTsConfig: true
68
+ });
69
+ BuildInterfaces.checker = BuildInterfaces.project.getTypeChecker();
70
+ const files = readdirSync(configDir).filter((f) => f.endsWith(".ts") && !f.includes("middleware"));
71
+ const properties = [];
72
+ for (const file of files) {
73
+ const configName = path.basename(file, ".ts");
74
+ const exportAssignment = BuildInterfaces.project.addSourceFileAtPath(path.join(configDir, file)).getExportAssignment((e) => !e.isExportEquals());
75
+ if (!exportAssignment) continue;
76
+ const expr = exportAssignment.getExpression();
77
+ const type = BuildInterfaces.checker.getTypeAtLocation(expr);
78
+ const callSignatures = type.getCallSignatures();
79
+ const resolvedType = callSignatures.length ? callSignatures[0].getReturnType() : type;
80
+ const typeStr = BuildInterfaces.resolveType(resolvedType, 2);
81
+ properties.push(` ${configName}: ${typeStr}`);
82
+ }
83
+ return [
84
+ "declare module '@arkstack/common' {",
85
+ " interface ConfigRegistry {",
86
+ ...properties,
87
+ " }",
88
+ "}",
89
+ "",
90
+ "export {}"
91
+ ].join("\n");
92
+ }
93
+ /**
94
+ * ts-morph resolves computed keys like path.join(...) as { [x: number]: any }
95
+ * detect these by checking the type text for an index signature pattern
96
+ *
97
+ * @param type
98
+ * @returns
99
+ */
100
+ static isDynamicMap(type) {
101
+ return /^\{ \[x: (string|number)\]:/.test(type.getText());
102
+ }
103
+ static resolveType(type, indent) {
104
+ const pad = " ".repeat(indent);
105
+ const innerPad = " ".repeat(indent + 1);
106
+ if (type.isString()) return "string";
107
+ if (type.isNumber()) return "number";
108
+ if (type.isBoolean()) return "boolean";
109
+ if (type.isNull()) return "null";
110
+ if (type.isUndefined()) return "undefined";
111
+ if (type.isAny() || type.isUnknown()) return "any";
112
+ if (type.isStringLiteral()) return `'${type.getLiteralValue()}'`;
113
+ if (type.isNumberLiteral()) return String(type.getLiteralValue());
114
+ if (type.isBooleanLiteral()) return String(type.getLiteralValue());
115
+ if (type.isUnion()) return type.getUnionTypes().map((t) => BuildInterfaces.resolveType(t, indent)).join(" | ");
116
+ if (type.isArray()) {
117
+ const elementType = type.getArrayElementTypeOrThrow();
118
+ return `${BuildInterfaces.resolveType(elementType, indent)}[]`;
119
+ }
120
+ if (type.getCallSignatures().length) return "Function";
121
+ if (type.isObject()) {
122
+ if (BuildInterfaces.isDynamicMap(type)) return "Record<string, string>";
123
+ const props = type.getProperties();
124
+ if (!props.length) return "Record<string, any>";
125
+ return `{\n${props.map((prop) => {
126
+ const decl = prop.getDeclarations()[0];
127
+ if (!decl) return `${innerPad}${prop.getName()}: any`;
128
+ const propType = BuildInterfaces.checker.getTypeOfSymbolAtLocation(prop, decl);
129
+ const optional = prop.isOptional() ? "?" : "";
130
+ return `${innerPad}${prop.getName()}${optional}: ${BuildInterfaces.resolveType(propType, indent + 1)}`;
131
+ }).join("\n")}\n${pad}}`;
132
+ }
133
+ return type.getText();
134
+ }
135
+ };
136
+
137
+ //#endregion
138
+ export { BaseTCConfig as n, TSConfig as r, BuildInterfaces as t };
package/dist/index.d.ts CHANGED
@@ -1,10 +1,12 @@
1
1
  //#region src/prepare/BuildInterfaces.d.ts
2
2
  declare class BuildInterfaces {
3
- static configs(): void;
3
+ private static project;
4
+ private static checker;
5
+ static configs(configDir?: string): void;
4
6
  static tsconfig(): void;
7
+ private static generateConfig;
5
8
  private static isDynamicMap;
6
- private static inferType;
7
- private static buildInterface;
9
+ private static resolveType;
8
10
  }
9
11
  //#endregion
10
12
  //#region src/prepare/TSConfig.d.ts
package/dist/index.js CHANGED
@@ -1,6 +1,6 @@
1
1
  #!/usr/bin/env node
2
2
  import { t as ArkstackConsoleApp } from "./app-DGy8It6S.js";
3
- import { n as BaseTCConfig, r as TSConfig, t as BuildInterfaces } from "./BuildInterfaces-DQGcpPu2.js";
3
+ import { n as BaseTCConfig, r as TSConfig, t as BuildInterfaces } from "./BuildInterfaces-BJcYrFZP.js";
4
4
  import { config, env, importFile, initializeGlobalContext, loadPrototypes, outputDir } from "@arkstack/common";
5
5
  import { fileURLToPath, pathToFileURL } from "node:url";
6
6
  import path, { join } from "node:path";
package/dist/prepare.js CHANGED
@@ -1,5 +1,5 @@
1
1
  #!/usr/bin/env node
2
- import { t as BuildInterfaces } from "./BuildInterfaces-DQGcpPu2.js";
2
+ import { t as BuildInterfaces } from "./BuildInterfaces-BJcYrFZP.js";
3
3
  import path from "node:path";
4
4
  import { Arkstack } from "@arkstack/contract";
5
5
  import { existsSync, mkdirSync } from "node:fs";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@arkstack/console",
3
- "version": "0.11.0",
3
+ "version": "0.11.2",
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",
@@ -42,16 +42,17 @@
42
42
  }
43
43
  },
44
44
  "peerDependencies": {
45
- "clear-router": "^2.7.7",
46
- "arkormx": "^ 2.4.1"
45
+ "arkormx": "^ 2.4.1",
46
+ "clear-router": "^2.7.7"
47
47
  },
48
48
  "dependencies": {
49
49
  "@h3ravel/musket": "^0.10.1",
50
50
  "@h3ravel/support": "^0.15.11",
51
51
  "chalk": "^5.6.2",
52
52
  "resora": "^1.3.6",
53
- "@arkstack/common": "^0.11.0",
54
- "@arkstack/contract": "^0.11.0"
53
+ "ts-morph": "^28.0.0",
54
+ "@arkstack/common": "^0.11.2",
55
+ "@arkstack/contract": "^0.11.2"
55
56
  },
56
57
  "scripts": {
57
58
  "build": "tsdown",
@@ -1,98 +0,0 @@
1
- import { config } from "@arkstack/common";
2
- import path from "node:path";
3
- import { Arkstack } from "@arkstack/contract";
4
- import { writeFileSync } from "node:fs";
5
-
6
- //#region src/prepare/TSConfig.ts
7
- const TSConfig = {
8
- compilerOptions: {
9
- module: "es2022",
10
- target: "es2022",
11
- lib: ["es2022", "DOM"],
12
- moduleResolution: "bundler",
13
- esModuleInterop: true,
14
- forceConsistentCasingInFileNames: true,
15
- strict: true,
16
- skipLibCheck: true,
17
- skipDefaultLibCheck: true,
18
- strictFunctionTypes: true,
19
- strictPropertyInitialization: true,
20
- strictBindCallApply: true,
21
- noImplicitAny: true,
22
- removeComments: true,
23
- experimentalDecorators: true,
24
- emitDecoratorMetadata: true,
25
- paths: {
26
- "@": ["../src"],
27
- "src/*": ["../src/*"],
28
- "@app/*": ["../src/app/*"],
29
- "@core/*": ["../src/core/*"],
30
- "@controllers/*": ["../src/app/http/controllers/*"],
31
- "@models/*": ["../src/app/models/*"]
32
- }
33
- },
34
- include: [
35
- "./*.d.ts",
36
- "../src",
37
- "../tests"
38
- ]
39
- };
40
- const BaseTCConfig = { extends: "./.arkstack/tsconfig.json" };
41
-
42
- //#endregion
43
- //#region src/prepare/BuildInterfaces.ts
44
- var BuildInterfaces = class {
45
- static configs() {
46
- const items = config();
47
- const declaration = [
48
- "export {}",
49
- "",
50
- "declare module '@arkstack/common' {",
51
- this.buildInterface("ConfigRegistry", items),
52
- "}"
53
- ].join("\n");
54
- writeFileSync(path.join(Arkstack.rootDir(), ".arkstack/ark.d.ts"), declaration, "utf8");
55
- }
56
- static tsconfig() {
57
- const configs = {
58
- ".arkstack/tsconfig.json": JSON.stringify(TSConfig, void 0, 2),
59
- "tsconfig.json": JSON.stringify(BaseTCConfig, void 0, 2)
60
- };
61
- for (const [file, config] of Object.entries(configs)) writeFileSync(path.join(Arkstack.rootDir(), file), config, "utf8");
62
- }
63
- static isDynamicMap(obj) {
64
- const keys = Object.keys(obj);
65
- if (keys.length === 0) return false;
66
- return keys.every((key) => path.isAbsolute(key) || /[^a-zA-Z0-9_$]/.test(key) || /^\d/.test(key));
67
- }
68
- static inferType(value, indent) {
69
- if (value === null) return "null";
70
- if (typeof value === "undefined") return "any";
71
- if (typeof value === "function") return "Function";
72
- if (Array.isArray(value)) {
73
- if (value.length === 0) return "unknown[]";
74
- const itemTypes = [...new Set(value.map((v) => this.inferType(v, indent)))];
75
- return itemTypes.length === 1 ? `${itemTypes[0]}[]` : `(${itemTypes.join(" | ")})[]`;
76
- }
77
- if (typeof value === "object") {
78
- const obj = value;
79
- if (this.isDynamicMap(obj)) {
80
- const valueTypes = [...new Set(Object.values(obj).map((v) => this.inferType(v, indent)))];
81
- return `Record<string, ${valueTypes.length === 1 ? valueTypes[0] : valueTypes.join(" | ")}>`;
82
- }
83
- return this.buildInterface(void 0, obj, indent);
84
- }
85
- return typeof value;
86
- }
87
- static buildInterface(name, obj, indent = 0) {
88
- const pad = " ".repeat(indent);
89
- const innerPad = " ".repeat(indent + 1);
90
- const body = Object.entries(obj).map(([key, value]) => {
91
- return `${innerPad}${key}: ${this.inferType(value, indent + 1)}`;
92
- }).join("\n");
93
- return name ? `${pad}interface ${name} {\n${body}\n${pad}}` : `{\n${body}\n${pad}}`;
94
- }
95
- };
96
-
97
- //#endregion
98
- export { BaseTCConfig as n, TSConfig as r, BuildInterfaces as t };