@no22/dison 1.0.0

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,79 @@
1
+ // =====================================================================
2
+ // 共有ランタイムの前置き生成
3
+ // =====================================================================
4
+ // ランタイムの宣言部分(DI_REGISTRY/TYPE_BINDINGS/bindType/resolveType/
5
+ // registerOverride/getOverride)を生成する。exportKeyword に "export " を渡すと
6
+ // 各宣言がexportされる(複数ファイルで共有するランタイムモジュールとして使う
7
+ // 場合)。単一ファイルでインライン生成する場合は ""(空文字)を渡す。
8
+ //
9
+ // DI_REGISTRY(override用)はクラス名の文字列ではなく、クラスの実体そのものを
10
+ // キーにする(WeakMap<Function, ...>)。理由:
11
+ // - override対象のクラス名が実際にスコープ内に存在するか(importし忘れ・
12
+ // タイプミスがないか)をtsc自身が「名前が見つからない」エラーとして
13
+ // 検出できるようになる(従来は文字列一致だったため、タイプミスしても
14
+ // 一切検出されずDI_REGISTRY["Typo"]という誰も参照しないエントリを
15
+ // 静かに作るだけだった)。
16
+ // - 複数ファイルにまたがって同名クラスが存在しても、参照そのものが
17
+ // キーになるため衝突しない(docs/multi-file-support.md参照)。
18
+ //
19
+ // TYPE_BINDINGS(bind用)は従来通り型名の文字列でキー化する。bindの左辺は
20
+ // interface/型エイリアスもあり得るが、これらは実行時に値を持たないため
21
+ // DI_REGISTRYと同じ手法(実体参照でのキー化)が使えない。複数ファイルに
22
+ // またがるinterface/型エイリアスの名前衝突は未解決の課題として残る
23
+ // (docs/multi-file-support.md 3.4節)。
24
+ export function generateRuntimeDeclarations(exportKeyword) {
25
+ return (`// Global dependency registry (per-property override).\n` +
26
+ `// Keying on the class itself (not its name) lets tsc catch a typo in the\n` +
27
+ `// override target class name as a "Cannot find name" error.\n` +
28
+ `${exportKeyword}const DI_REGISTRY = new WeakMap<Function, Record<string, () => any>>();\n\n` +
29
+ `${exportKeyword}function registerOverride(cls: Function, prop: string, factory: () => any): void {\n` +
30
+ ` let entry = DI_REGISTRY.get(cls);\n` +
31
+ ` if (!entry) {\n` +
32
+ ` entry = {};\n` +
33
+ ` DI_REGISTRY.set(cls, entry);\n` +
34
+ ` }\n` +
35
+ ` entry[prop] = factory;\n` +
36
+ `}\n\n` +
37
+ `${exportKeyword}function getOverride(cls: Function, prop: string): (() => any) | undefined {\n` +
38
+ ` return DI_REGISTRY.get(cls)?.[prop];\n` +
39
+ `}\n\n` +
40
+ `// Global type-replacement registry (bind).\n` +
41
+ `// The key is either a type-name string (class, interface, or type alias name)\n` +
42
+ `// or a Symbol explicitly given via an "as <token>" clause (used to avoid\n` +
43
+ `// name collisions between same-named interfaces/type aliases across files).\n` +
44
+ `${exportKeyword}const TYPE_BINDINGS = new Map<string | symbol, () => any>();\n` +
45
+ `const _resolvingTypeBindings = new Set<string | symbol>();\n\n` +
46
+ `// bindType<T> takes T as an explicit type argument, so tsc raises a\n` +
47
+ `// compile error if the replacement factory isn't compatible with the\n` +
48
+ `// original type. T may be an interface or type alias (used only as a\n` +
49
+ `// type argument).\n` +
50
+ `${exportKeyword}function bindType<T>(typeKey: string | symbol, factory: () => T): void {\n` +
51
+ ` TYPE_BINDINGS.set(typeKey, factory);\n` +
52
+ `}\n\n` +
53
+ `// Resolves a value by recursively walking TYPE_BINDINGS. bind chains\n` +
54
+ `// (e.g. bind A = B; bind B = C; makes resolving A eventually reach C).\n` +
55
+ `// A cycle (A -> B -> A) raises a clear error instead of a stack overflow.\n` +
56
+ `${exportKeyword}function resolveType<T>(typeKey: string | symbol, defaultFactory: () => T): T {\n` +
57
+ ` const bound = TYPE_BINDINGS.get(typeKey);\n` +
58
+ ` if (!bound) return defaultFactory();\n` +
59
+ ` if (_resolvingTypeBindings.has(typeKey)) {\n` +
60
+ ` throw new Error('Detected a circular "bind" reference ("' + String(typeKey) + '"). The bind chain loops back on itself.');\n` +
61
+ ` }\n` +
62
+ ` _resolvingTypeBindings.add(typeKey);\n` +
63
+ ` try {\n` +
64
+ ` return bound();\n` +
65
+ ` } finally {\n` +
66
+ ` _resolvingTypeBindings.delete(typeKey);\n` +
67
+ ` }\n` +
68
+ `}\n`);
69
+ }
70
+ // 複数ファイルでランタイム状態(DI_REGISTRY/TYPE_BINDINGS)を共有するための
71
+ // 共有ランタイムモジュールのソース。scripts/generate-runtime-module.tsが
72
+ // これをsrc/generated-runtime.tsとして書き出し、tscがdist/にコンパイルする
73
+ // ことで、"@no22/dison/runtime" として配布される(docs/packaging.md)。
74
+ export const DISON_RUNTIME_MODULE_SOURCE = `// --- Dison shared runtime module ---\n` +
75
+ `// Multiple generated files import this module to share runtime state\n` +
76
+ `// such as DI_REGISTRY/TYPE_BINDINGS.\n` +
77
+ `// This file is auto-generated when the Dison package is built. Do not edit it by hand.\n\n` +
78
+ generateRuntimeDeclarations("export ");
79
+ //# sourceMappingURL=runtime.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"runtime.js","sourceRoot":"","sources":["../src/runtime.ts"],"names":[],"mappings":"AAAA,wEAAwE;AACxE,gBAAgB;AAChB,wEAAwE;AAExE,6DAA6D;AAC7D,oEAAoE;AACpE,2CAA2C;AAC3C,sCAAsC;AACtC,EAAE;AACF,kDAAkD;AAClD,oCAAoC;AACpC,gDAAgD;AAChD,yCAAyC;AACzC,wCAAwC;AACxC,gDAAgD;AAChD,mBAAmB;AACnB,sCAAsC;AACtC,kDAAkD;AAClD,EAAE;AACF,iDAAiD;AACjD,0CAA0C;AAC1C,2CAA2C;AAC3C,wCAAwC;AACxC,qCAAqC;AACrC,MAAM,UAAU,2BAA2B,CAAC,aAA6B;IACvE,OAAO,CACL,0DAA0D;QAC1D,6EAA6E;QAC7E,gEAAgE;QAChE,GAAG,aAAa,6EAA6E;QAC7F,GAAG,aAAa,sFAAsF;QACtG,uCAAuC;QACvC,mBAAmB;QACnB,mBAAmB;QACnB,oCAAoC;QACpC,OAAO;QACP,4BAA4B;QAC5B,OAAO;QACP,GAAG,aAAa,gFAAgF;QAChG,0CAA0C;QAC1C,OAAO;QACP,+CAA+C;QAC/C,kFAAkF;QAClF,6EAA6E;QAC7E,gFAAgF;QAChF,GAAG,aAAa,gEAAgE;QAChF,gEAAgE;QAChE,wEAAwE;QACxE,yEAAyE;QACzE,yEAAyE;QACzE,sBAAsB;QACtB,GAAG,aAAa,4EAA4E;QAC5F,0CAA0C;QAC1C,OAAO;QACP,yEAAyE;QACzE,2EAA2E;QAC3E,8EAA8E;QAC9E,GAAG,aAAa,mFAAmF;QACnG,+CAA+C;QAC/C,0CAA0C;QAC1C,gDAAgD;QAChD,kIAAkI;QAClI,OAAO;QACP,0CAA0C;QAC1C,WAAW;QACX,uBAAuB;QACvB,iBAAiB;QACjB,+CAA+C;QAC/C,OAAO;QACP,KAAK,CACN,CAAC;AACJ,CAAC;AAED,oDAAoD;AACpD,uDAAuD;AACvD,uDAAuD;AACvD,yDAAyD;AACzD,MAAM,CAAC,MAAM,2BAA2B,GACtC,0CAA0C;IAC1C,yEAAyE;IACzE,yCAAyC;IACzC,6FAA6F;IAC7F,2BAA2B,CAAC,SAAS,CAAC,CAAC"}
package/package.json ADDED
@@ -0,0 +1,56 @@
1
+ {
2
+ "name": "@no22/dison",
3
+ "version": "1.0.0",
4
+ "type": "module",
5
+ "description": "An experimental DSL that transpiles to TypeScript, with property injection built into the language itself.",
6
+ "main": "./dist/core.js",
7
+ "types": "./dist/core.d.ts",
8
+ "bin": {
9
+ "dison": "dist/cli.js"
10
+ },
11
+ "exports": {
12
+ ".": {
13
+ "types": "./dist/core.d.ts",
14
+ "default": "./dist/core.js"
15
+ },
16
+ "./runtime": {
17
+ "types": "./dist/generated-runtime.d.ts",
18
+ "default": "./dist/generated-runtime.js"
19
+ }
20
+ },
21
+ "files": [
22
+ "dist",
23
+ "README.md"
24
+ ],
25
+ "publishConfig": {
26
+ "access": "public"
27
+ },
28
+ "repository": {
29
+ "type": "git",
30
+ "url": "git+https://github.com/no22/dison.git"
31
+ },
32
+ "homepage": "https://github.com/no22/dison#readme",
33
+ "bugs": {
34
+ "url": "https://github.com/no22/dison/issues"
35
+ },
36
+ "scripts": {
37
+ "build": "rm -rf dist && tsx scripts/generate-runtime-module.ts && tsc && chmod +x dist/cli.js",
38
+ "prepare": "npm run build",
39
+ "test": "vitest run"
40
+ },
41
+ "keywords": [
42
+ "dependency-injection",
43
+ "dsl",
44
+ "transpiler",
45
+ "typescript"
46
+ ],
47
+ "author": "OHARA Hiroyuki",
48
+ "license": "ISC",
49
+ "devDependencies": {
50
+ "@types/node": "^26.1.1",
51
+ "ts-node": "^10.9.2",
52
+ "tsx": "^4.23.1",
53
+ "typescript": "^7.0.2",
54
+ "vitest": "^4.1.10"
55
+ }
56
+ }