@voxgig/sdkgen 1.3.17 → 1.3.18
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/bin/voxgig-sdkgen +1 -1
- package/dist/cmp/Entity.js +5 -1
- package/dist/cmp/Entity.js.map +1 -1
- package/dist/cmp/Feature.js +2 -1
- package/dist/cmp/Feature.js.map +1 -1
- package/dist/helpers/canonType.js +8 -3
- package/dist/helpers/canonType.js.map +1 -1
- package/dist/helpers/collectDeps.d.ts +1 -1
- package/dist/helpers/collectDeps.js +36 -13
- package/dist/helpers/collectDeps.js.map +1 -1
- package/dist/helpers/naming.d.ts +3 -1
- package/dist/helpers/naming.js +53 -0
- package/dist/helpers/naming.js.map +1 -1
- package/dist/helpers/opShape.d.ts +3 -1
- package/dist/helpers/opShape.js +87 -8
- package/dist/helpers/opShape.js.map +1 -1
- package/dist/sdkgen.d.ts +3 -3
- package/dist/sdkgen.js +6 -2
- package/dist/sdkgen.js.map +1 -1
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/package.json +15 -10
- package/project/.sdk/model/target/cpp.aontu +4 -4
- package/project/.sdk/model/target/go-cli.aontu +17 -17
- package/project/.sdk/model/target/go-mcp.aontu +11 -11
- package/project/.sdk/model/target/go.aontu +1 -1
- package/project/.sdk/model/target/java.aontu +4 -4
- package/project/.sdk/model/target/kotlin.aontu +4 -4
- package/project/.sdk/model/target/lean.aontu +51 -0
- package/project/.sdk/model/target/scala.aontu +4 -4
- package/project/.sdk/src/cmp/c/EntityTypes_c.ts +3 -4
- package/project/.sdk/src/cmp/c/Entity_c.ts +3 -3
- package/project/.sdk/src/cmp/c/ReadmeExamplesTest_c.ts +24 -7
- package/project/.sdk/src/cmp/c/TestDirect_c.ts +3 -3
- package/project/.sdk/src/cmp/c/TestEntity_c.ts +1 -1
- package/project/.sdk/src/cmp/clojure/Entity_clojure.ts +1 -1
- package/project/.sdk/src/cmp/clojure/ReadmeExamplesTest_clojure.ts +19 -8
- package/project/.sdk/src/cmp/cpp/EntityTypes_cpp.ts +2 -2
- package/project/.sdk/src/cmp/cpp/Entity_cpp.ts +3 -3
- package/project/.sdk/src/cmp/cpp/MainEntity_cpp.ts +2 -2
- package/project/.sdk/src/cmp/cpp/ReadmeExamplesTest_cpp.ts +136 -0
- package/project/.sdk/src/cmp/cpp/TestDirect_cpp.ts +3 -3
- package/project/.sdk/src/cmp/cpp/Test_cpp.ts +4 -0
- package/project/.sdk/src/cmp/csharp/EntityTypes_csharp.ts +2 -3
- package/project/.sdk/src/cmp/csharp/Entity_csharp.ts +3 -3
- package/project/.sdk/src/cmp/csharp/MainEntity_csharp.ts +2 -2
- package/project/.sdk/src/cmp/csharp/Package_csharp.ts +1 -1
- package/project/.sdk/src/cmp/csharp/ReadmeExamplesTest_csharp.ts +13 -1
- package/project/.sdk/src/cmp/csharp/TestDirect_csharp.ts +3 -3
- package/project/.sdk/src/cmp/dart/EntityTypes_dart.ts +2 -3
- package/project/.sdk/src/cmp/dart/Entity_dart.ts +3 -3
- package/project/.sdk/src/cmp/dart/MainEntity_dart.ts +2 -2
- package/project/.sdk/src/cmp/dart/Main_dart.ts +3 -3
- package/project/.sdk/src/cmp/dart/Package_dart.ts +1 -1
- package/project/.sdk/src/cmp/dart/TestDirect_dart.ts +4 -4
- package/project/.sdk/src/cmp/elixir/EntityTypes_elixir.ts +2 -3
- package/project/.sdk/src/cmp/elixir/Entity_elixir.ts +1 -1
- package/project/.sdk/src/cmp/elixir/ReadmeExamplesTest_elixir.ts +21 -3
- package/project/.sdk/src/cmp/go/Config_go.ts +4 -1
- package/project/.sdk/src/cmp/go/EntityTypes_go.ts +110 -18
- package/project/.sdk/src/cmp/go/Entity_go.ts +3 -3
- package/project/.sdk/src/cmp/go/Main_go.ts +7 -6
- package/project/.sdk/src/cmp/go/Package_go.ts +1 -1
- package/project/.sdk/src/cmp/go/TestDirect_go.ts +3 -3
- package/project/.sdk/src/cmp/go/TestEntity_go.ts +1 -1
- package/project/.sdk/src/cmp/go/utility_go.ts +25 -0
- package/project/.sdk/src/cmp/go-cli/Main_go-cli.ts +9 -1
- package/project/.sdk/src/cmp/go-mcp/Main_go-mcp.ts +9 -1
- package/project/.sdk/src/cmp/haskell/ReadmeExamplesTest_haskell.ts +28 -18
- package/project/.sdk/src/cmp/java/EntityTypes_java.ts +2 -3
- package/project/.sdk/src/cmp/java/Entity_java.ts +3 -3
- package/project/.sdk/src/cmp/java/MainEntity_java.ts +2 -2
- package/project/.sdk/src/cmp/java/Package_java.ts +1 -1
- package/project/.sdk/src/cmp/java/ReadmeExamplesTest_java.ts +23 -1
- package/project/.sdk/src/cmp/java/TestDirect_java.ts +3 -3
- package/project/.sdk/src/cmp/js/EntityTypes_js.ts +2 -3
- package/project/.sdk/src/cmp/js/Entity_js.ts +3 -3
- package/project/.sdk/src/cmp/js/MainEntity_js.ts +2 -2
- package/project/.sdk/src/cmp/js/Main_js.ts +2 -2
- package/project/.sdk/src/cmp/js/TestDirect_js.ts +4 -4
- package/project/.sdk/src/cmp/kotlin/EntityTypes_kotlin.ts +2 -3
- package/project/.sdk/src/cmp/kotlin/Entity_kotlin.ts +3 -3
- package/project/.sdk/src/cmp/kotlin/MainEntity_kotlin.ts +2 -2
- package/project/.sdk/src/cmp/kotlin/Package_kotlin.ts +1 -1
- package/project/.sdk/src/cmp/kotlin/ReadmeExamplesTest_kotlin.ts +27 -2
- package/project/.sdk/src/cmp/kotlin/TestDirect_kotlin.ts +3 -3
- package/project/.sdk/src/cmp/lean/Config_lean.ts +88 -0
- package/project/.sdk/src/cmp/lean/Entity_lean.ts +9 -0
- package/project/.sdk/src/cmp/lean/Gitignore_lean.ts +18 -0
- package/project/.sdk/src/cmp/lean/Main_lean.ts +120 -0
- package/project/.sdk/src/cmp/lean/Package_lean.ts +68 -0
- package/project/.sdk/src/cmp/lean/ReadmeEntity_lean.ts +29 -0
- package/project/.sdk/src/cmp/lean/ReadmeExplanation_lean.ts +19 -0
- package/project/.sdk/src/cmp/lean/ReadmeHowto_lean.ts +25 -0
- package/project/.sdk/src/cmp/lean/ReadmeInstall_lean.ts +38 -0
- package/project/.sdk/src/cmp/lean/ReadmeIntro_lean.ts +25 -0
- package/project/.sdk/src/cmp/lean/ReadmeModel_lean.ts +24 -0
- package/project/.sdk/src/cmp/lean/ReadmeOptions_lean.ts +22 -0
- package/project/.sdk/src/cmp/lean/ReadmeQuick_lean.ts +50 -0
- package/project/.sdk/src/cmp/lean/ReadmeRef_lean.ts +16 -0
- package/project/.sdk/src/cmp/lean/ReadmeTopHowto_lean.ts +16 -0
- package/project/.sdk/src/cmp/lean/ReadmeTopQuick_lean.ts +23 -0
- package/project/.sdk/src/cmp/lean/ReadmeTopTest_lean.ts +18 -0
- package/project/.sdk/src/cmp/lean/Test_lean.ts +207 -0
- package/project/.sdk/src/cmp/lean/utility_lean.ts +78 -0
- package/project/.sdk/src/cmp/lua/EntityTypes_lua.ts +2 -3
- package/project/.sdk/src/cmp/lua/Entity_lua.ts +3 -3
- package/project/.sdk/src/cmp/lua/Package_lua.ts +1 -1
- package/project/.sdk/src/cmp/lua/TestDirect_lua.ts +3 -3
- package/project/.sdk/src/cmp/lua/TestEntity_lua.ts +1 -1
- package/project/.sdk/src/cmp/ocaml/ReadmeExamplesTest_ocaml.ts +29 -14
- package/project/.sdk/src/cmp/perl/Entity_perl.ts +3 -3
- package/project/.sdk/src/cmp/perl/MainEntity_perl.ts +2 -2
- package/project/.sdk/src/cmp/perl/Package_perl.ts +1 -1
- package/project/.sdk/src/cmp/perl/TestDirect_perl.ts +3 -3
- package/project/.sdk/src/cmp/php/EntityTypes_php.ts +2 -3
- package/project/.sdk/src/cmp/php/Entity_php.ts +3 -3
- package/project/.sdk/src/cmp/php/MainEntity_php.ts +2 -2
- package/project/.sdk/src/cmp/php/Package_php.ts +1 -1
- package/project/.sdk/src/cmp/php/TestDirect_php.ts +3 -3
- package/project/.sdk/src/cmp/php/TestEntity_php.ts +1 -1
- package/project/.sdk/src/cmp/py/EntityTypes_py.ts +2 -3
- package/project/.sdk/src/cmp/py/Entity_py.ts +3 -3
- package/project/.sdk/src/cmp/py/MainEntity_py.ts +2 -2
- package/project/.sdk/src/cmp/py/Main_py.ts +2 -2
- package/project/.sdk/src/cmp/py/Package_py.ts +1 -1
- package/project/.sdk/src/cmp/py/TestDirect_py.ts +3 -3
- package/project/.sdk/src/cmp/py/TestEntity_py.ts +1 -1
- package/project/.sdk/src/cmp/rb/EntityTypes_rb.ts +15 -5
- package/project/.sdk/src/cmp/rb/Entity_rb.ts +3 -3
- package/project/.sdk/src/cmp/rb/MainEntity_rb.ts +2 -2
- package/project/.sdk/src/cmp/rb/Package_rb.ts +2 -2
- package/project/.sdk/src/cmp/rb/TestDirect_rb.ts +3 -3
- package/project/.sdk/src/cmp/rb/TestEntity_rb.ts +1 -1
- package/project/.sdk/src/cmp/rust/EntityBase_rust.ts +2 -2
- package/project/.sdk/src/cmp/rust/EntityTypes_rust.ts +3 -4
- package/project/.sdk/src/cmp/rust/Entity_rust.ts +3 -3
- package/project/.sdk/src/cmp/rust/MainEntity_rust.ts +2 -2
- package/project/.sdk/src/cmp/rust/Package_rust.ts +1 -1
- package/project/.sdk/src/cmp/rust/ReadmeExamplesTest_rust.ts +22 -10
- package/project/.sdk/src/cmp/rust/TestDirect_rust.ts +3 -3
- package/project/.sdk/src/cmp/scala/EntityTypes_scala.ts +2 -3
- package/project/.sdk/src/cmp/scala/Entity_scala.ts +3 -3
- package/project/.sdk/src/cmp/scala/MainEntity_scala.ts +2 -2
- package/project/.sdk/src/cmp/scala/ReadmeExamplesTest_scala.ts +22 -3
- package/project/.sdk/src/cmp/scala/TestDirect_scala.ts +3 -3
- package/project/.sdk/src/cmp/scala/Test_scala.ts +1 -1
- package/project/.sdk/src/cmp/swift/EntityTypes_swift.ts +3 -4
- package/project/.sdk/src/cmp/swift/Entity_swift.ts +3 -3
- package/project/.sdk/src/cmp/swift/MainEntity_swift.ts +2 -2
- package/project/.sdk/src/cmp/swift/Package_swift.ts +1 -1
- package/project/.sdk/src/cmp/swift/ReadmeExamplesTest_swift.ts +18 -1
- package/project/.sdk/src/cmp/swift/TestDirect_swift.ts +1 -1
- package/project/.sdk/src/cmp/ts/EntityTypes_ts.ts +2 -3
- package/project/.sdk/src/cmp/ts/Entity_ts.ts +3 -3
- package/project/.sdk/src/cmp/ts/MainEntity_ts.ts +2 -2
- package/project/.sdk/src/cmp/ts/Main_ts.ts +2 -2
- package/project/.sdk/src/cmp/ts/TestDirect_ts.ts +4 -4
- package/project/.sdk/src/cmp/zig/Entity_zig.ts +3 -3
- package/project/.sdk/src/cmp/zig/MainEntity_zig.ts +2 -2
- package/project/.sdk/src/cmp/zig/Package_zig.ts +10 -2
- package/project/.sdk/tm/cpp/test/primary_utility_test.cpp +8 -16
- package/project/.sdk/tm/csharp/test/PrimaryUtilityTest.cs +10 -28
- package/project/.sdk/tm/dart/test/primary_test.dart +7 -0
- package/project/.sdk/tm/go/feature/test_feature.go +33 -1
- package/project/.sdk/tm/go/test/primary_utility_test.go +41 -42
- package/project/.sdk/tm/go/test/runner_test.go +30 -1
- package/project/.sdk/tm/java/test/PrimaryUtilityTest.java +7 -24
- package/project/.sdk/tm/js/src/feature/test/TestFeature.js +18 -1
- package/project/.sdk/tm/js/test/utility/PrimaryUtility.test.js +8 -0
- package/project/.sdk/tm/kotlin/test/PrimaryUtilityTest.kt +7 -20
- package/project/.sdk/tm/lean/LICENSE +21 -0
- package/project/.sdk/tm/lean/VERSION +1 -0
- package/project/.sdk/tm/lean/src/SdkFeature.lean +171 -0
- package/project/.sdk/tm/lean/src/SdkFeatures.lean +602 -0
- package/project/.sdk/tm/lean/src/SdkJson.lean +134 -0
- package/project/.sdk/tm/lean/src/SdkRuntime.lean +356 -0
- package/project/.sdk/tm/lean/src/SdkUtility.lean +617 -0
- package/project/.sdk/tm/lean/src/VoxgigStruct.lean +2880 -0
- package/project/.sdk/tm/lean/src/Vregex.lean +412 -0
- package/project/.sdk/tm/lean/src/feature/README.md +5 -0
- package/project/.sdk/tm/lean/src/feature/audit/.gitkeep +0 -0
- package/project/.sdk/tm/lean/src/feature/base/.gitkeep +0 -0
- package/project/.sdk/tm/lean/src/feature/cache/.gitkeep +0 -0
- package/project/.sdk/tm/lean/src/feature/clienttrack/.gitkeep +0 -0
- package/project/.sdk/tm/lean/src/feature/debug/.gitkeep +0 -0
- package/project/.sdk/tm/lean/src/feature/idempotency/.gitkeep +0 -0
- package/project/.sdk/tm/lean/src/feature/log/.gitkeep +0 -0
- package/project/.sdk/tm/lean/src/feature/metrics/.gitkeep +0 -0
- package/project/.sdk/tm/lean/src/feature/netsim/.gitkeep +0 -0
- package/project/.sdk/tm/lean/src/feature/paging/.gitkeep +0 -0
- package/project/.sdk/tm/lean/src/feature/proxy/.gitkeep +0 -0
- package/project/.sdk/tm/lean/src/feature/ratelimit/.gitkeep +0 -0
- package/project/.sdk/tm/lean/src/feature/rbac/.gitkeep +0 -0
- package/project/.sdk/tm/lean/src/feature/retry/.gitkeep +0 -0
- package/project/.sdk/tm/lean/src/feature/streaming/.gitkeep +0 -0
- package/project/.sdk/tm/lean/src/feature/telemetry/.gitkeep +0 -0
- package/project/.sdk/tm/lean/src/feature/test/.gitkeep +0 -0
- package/project/.sdk/tm/lean/src/feature/timeout/.gitkeep +0 -0
- package/project/.sdk/tm/lean/test/StructCorpus.lean +697 -0
- package/project/.sdk/tm/lean/test/TFeature.lean +268 -0
- package/project/.sdk/tm/lean/test/TPrimaryUtility.lean +349 -0
- package/project/.sdk/tm/lua/test/primary_utility_test.lua +10 -8
- package/project/.sdk/tm/perl/t/primary_utility.t +8 -17
- package/project/.sdk/tm/php/test/PrimaryUtilityTest.php +9 -7
- package/project/.sdk/tm/py/feature/test_feature.py +28 -1
- package/project/.sdk/tm/py/test/test_primary_utility.py +13 -18
- package/project/.sdk/tm/rb/feature/test_feature.rb +24 -1
- package/project/.sdk/tm/rb/test/primary_utility_test.rb +7 -8
- package/project/.sdk/tm/rust/tests/common/mod.rs +37 -1
- package/project/.sdk/tm/rust/tests/primary_utility_test.rs +12 -26
- package/project/.sdk/tm/swift/Tests/ProjectNameSDKTests/PrimaryUtilityTest.swift +7 -8
- package/project/.sdk/tm/ts/src/feature/test/TestFeature.ts +18 -1
- package/project/.sdk/tm/ts/test/utility/PrimaryUtility.test.ts +65 -21
- package/src/cmp/Entity.ts +5 -1
- package/src/cmp/Feature.ts +2 -1
- package/src/helpers/canonType.ts +8 -3
- package/src/helpers/collectDeps.ts +39 -12
- package/src/helpers/naming.ts +59 -0
- package/src/helpers/opShape.ts +99 -12
- package/src/sdkgen.ts +7 -3
|
@@ -27,21 +27,53 @@ function collectDeps(
|
|
|
27
27
|
model: SdkModel,
|
|
28
28
|
targetName: string,
|
|
29
29
|
targetDeps: Record<string, ModelDep> | undefined,
|
|
30
|
+
log?: any,
|
|
30
31
|
): DepEntry[] {
|
|
31
32
|
const out: DepEntry[] = []
|
|
32
33
|
const feature = getModelPath(model, `main.${KIT}.feature`)
|
|
33
34
|
|
|
35
|
+
// Deduplicate by package name. Two features can require the same package
|
|
36
|
+
// (or a feature and the target itself can), and every Package_<lang>.ts
|
|
37
|
+
// renders one manifest line per entry — a duplicate key is a hard parse
|
|
38
|
+
// error in go.mod and Cargo.toml, and silently last-wins in package.json.
|
|
39
|
+
// FIRST occurrence wins, so the deterministic (sorted-key) feature order
|
|
40
|
+
// decides; a conflicting version is reported rather than silently dropped.
|
|
41
|
+
const seen: Record<string, DepEntry> = {}
|
|
42
|
+
|
|
43
|
+
const add = (dep: any, source: 'feature' | 'target', owner: string) => {
|
|
44
|
+
const name = dep.key$
|
|
45
|
+
if (null == name) return
|
|
46
|
+
|
|
47
|
+
const prev = seen[name]
|
|
48
|
+
if (null != prev) {
|
|
49
|
+
if (log?.warn && prev.version !== dep.version) {
|
|
50
|
+
log.warn({
|
|
51
|
+
point: 'dep-version-conflict', target: targetName, dep: name,
|
|
52
|
+
kept: prev.version, dropped: dep.version, from: owner,
|
|
53
|
+
note: `${targetName}: dependency ${name} declared twice with ` +
|
|
54
|
+
`different versions — keeping ${prev.version} (${prev.source}), ` +
|
|
55
|
+
`ignoring ${dep.version} (${source} ${owner})`,
|
|
56
|
+
})
|
|
57
|
+
}
|
|
58
|
+
return
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
const entry: DepEntry = {
|
|
62
|
+
name,
|
|
63
|
+
version: dep.version,
|
|
64
|
+
source,
|
|
65
|
+
raw: dep,
|
|
66
|
+
}
|
|
67
|
+
seen[name] = entry
|
|
68
|
+
out.push(entry)
|
|
69
|
+
}
|
|
70
|
+
|
|
34
71
|
each(feature, (f: any) => {
|
|
35
72
|
const langDeps = f?.deps?.[targetName]
|
|
36
73
|
if (!langDeps) return
|
|
37
74
|
each(langDeps, (dep: any) => {
|
|
38
75
|
if (dep?.active) {
|
|
39
|
-
|
|
40
|
-
name: dep.key$,
|
|
41
|
-
version: dep.version,
|
|
42
|
-
source: 'feature',
|
|
43
|
-
raw: dep,
|
|
44
|
-
})
|
|
76
|
+
add(dep, 'feature', f.name)
|
|
45
77
|
}
|
|
46
78
|
})
|
|
47
79
|
})
|
|
@@ -49,12 +81,7 @@ function collectDeps(
|
|
|
49
81
|
if (targetDeps) {
|
|
50
82
|
each(targetDeps, (dep: any) => {
|
|
51
83
|
if (dep?.active !== false) {
|
|
52
|
-
|
|
53
|
-
name: dep.key$,
|
|
54
|
-
version: dep.version,
|
|
55
|
-
source: 'target',
|
|
56
|
-
raw: dep,
|
|
57
|
-
})
|
|
84
|
+
add(dep, 'target', targetName)
|
|
58
85
|
}
|
|
59
86
|
})
|
|
60
87
|
}
|
package/src/helpers/naming.ts
CHANGED
|
@@ -69,6 +69,63 @@ const RESERVED: Record<string, Set<string>> = {
|
|
|
69
69
|
}
|
|
70
70
|
|
|
71
71
|
|
|
72
|
+
// Ruby CORE CONSTANTS — a different hazard from the keyword sets above.
|
|
73
|
+
//
|
|
74
|
+
// The keyword sets guard local-variable BINDINGS. This set guards generated
|
|
75
|
+
// top-level CONSTANTS. Ruby constants share one namespace with the core
|
|
76
|
+
// classes, and reassigning one is not an error — it silently replaces it:
|
|
77
|
+
//
|
|
78
|
+
// File = Struct.new(:name) # ::File is now a Struct
|
|
79
|
+
// File.join('a', 'b') # NoMethodError — every later caller breaks
|
|
80
|
+
//
|
|
81
|
+
// The typed model emits `<Name> = Struct.new(...)` per entity, so an API with
|
|
82
|
+
// a `/files` collection (entity `File`) used to clobber Ruby's File class and
|
|
83
|
+
// take the whole SDK down with it — the generated test runner calls
|
|
84
|
+
// `File.join` to locate `.env.local`, so `rb` failed at require time.
|
|
85
|
+
//
|
|
86
|
+
// Only names Ruby itself defines at top level are listed: reassigning any of
|
|
87
|
+
// them breaks working code somewhere. Names that merely LOOK builtin but are
|
|
88
|
+
// not core constants (e.g. `Response`, `Record`) are safe and stay untouched,
|
|
89
|
+
// which keeps the rename off every SDK that does not actually collide.
|
|
90
|
+
const RB_CORE_CONSTANTS = new Set<string>([
|
|
91
|
+
// classes an entity name plausibly lands on
|
|
92
|
+
'Array', 'Binding', 'Class', 'Comparable', 'Complex', 'Data', 'Dir',
|
|
93
|
+
'Encoding', 'Enumerator', 'Exception', 'Fiber', 'File', 'Float', 'Hash',
|
|
94
|
+
'IO', 'Integer', 'Method', 'Module', 'Mutex', 'Numeric', 'Object', 'Proc',
|
|
95
|
+
'Queue', 'Random', 'Range', 'Rational', 'Regexp', 'Set', 'Signal', 'String',
|
|
96
|
+
'Struct', 'Symbol', 'Thread', 'Time', 'UnboundMethod',
|
|
97
|
+
// modules / singletons
|
|
98
|
+
'Enumerable', 'GC', 'Kernel', 'Marshal', 'Math', 'ObjectSpace', 'Process',
|
|
99
|
+
'Warning',
|
|
100
|
+
// the rest of the exception hierarchy an API might name an entity after
|
|
101
|
+
'ArgumentError', 'IndexError', 'IOError', 'KeyError', 'NameError',
|
|
102
|
+
'NotImplementedError', 'RangeError', 'RuntimeError', 'StandardError',
|
|
103
|
+
'StopIteration', 'SystemExit', 'TypeError', 'ZeroDivisionError',
|
|
104
|
+
// literal singletons
|
|
105
|
+
'FalseClass', 'NilClass', 'TrueClass',
|
|
106
|
+
])
|
|
107
|
+
|
|
108
|
+
|
|
109
|
+
// Is `Name` a constant Ruby already defines at top level?
|
|
110
|
+
function isRbCoreConstant(Name: string): boolean {
|
|
111
|
+
return RB_CORE_CONSTANTS.has(Name)
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
|
|
115
|
+
// A top-level-safe Ruby constant name for a generated type: the name
|
|
116
|
+
// unchanged, unless Ruby core already owns it, in which case `Type` is
|
|
117
|
+
// appended (`File` -> `FileType`). Applied ONLY to the bare entity data type
|
|
118
|
+
// — the per-op type names always carry a suffix (`FileCreateData`,
|
|
119
|
+
// `FileLoadMatch`), which no core constant matches.
|
|
120
|
+
//
|
|
121
|
+
// The entity ACCESSOR keeps its original name (`client.File(...)`): methods
|
|
122
|
+
// and constants live in separate namespaces in Ruby, so the accessor never
|
|
123
|
+
// collided and the public surface is unchanged.
|
|
124
|
+
function rbSafeTypeName(Name: string): string {
|
|
125
|
+
return isRbCoreConstant(Name) ? Name + 'Type' : Name
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
|
|
72
129
|
// Is `name` a reserved word (an illegal identifier) in the target language?
|
|
73
130
|
function isReservedName(name: string, lang: string): boolean {
|
|
74
131
|
const set = RESERVED[lang]
|
|
@@ -130,6 +187,8 @@ export {
|
|
|
130
187
|
isReservedName,
|
|
131
188
|
safeVarName,
|
|
132
189
|
exampleVarName,
|
|
190
|
+
isRbCoreConstant,
|
|
191
|
+
rbSafeTypeName,
|
|
133
192
|
jsProp,
|
|
134
193
|
jsOptProp,
|
|
135
194
|
jsKey,
|
package/src/helpers/opShape.ts
CHANGED
|
@@ -26,7 +26,60 @@
|
|
|
26
26
|
// flag) and render them in the target language's struct/interface/TypedDict
|
|
27
27
|
// syntax; the policy itself is language-neutral and tested in isolation.
|
|
28
28
|
|
|
29
|
-
import { each } from 'jostraca'
|
|
29
|
+
import { each, names } from 'jostraca'
|
|
30
|
+
import { KIT, getModelPath } from '@voxgig/apidef'
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
// THE entity collection for a model — resolved once, with a stable identity.
|
|
34
|
+
//
|
|
35
|
+
// Two problems this solves, both caused by every component calling
|
|
36
|
+
// `getModelPath(model, 'main.<KIT>.entity')` for itself:
|
|
37
|
+
//
|
|
38
|
+
// * CORRECTNESS. getModelPath drops `active: false` entries by default, but
|
|
39
|
+
// the consumer scaffold (create-sdkgen Root.ts) generates entity code for
|
|
40
|
+
// EVERY entity and every EntityTypes_<lang> emits data types with
|
|
41
|
+
// `only_active: false`. Class-name assignment done against the filtered
|
|
42
|
+
// view cannot see the inactive entities whose data types it must avoid.
|
|
43
|
+
// This resolver always returns the unfiltered collection.
|
|
44
|
+
//
|
|
45
|
+
// * PERFORMANCE. getModelPath REBUILDS the container object on every call
|
|
46
|
+
// when filtering, so the WeakMap memos below never hit across callers —
|
|
47
|
+
// the O(n·ops) class-name assignment re-ran per entity per target. At 500
|
|
48
|
+
// entities x 22 targets that was ~15s of pure recomputation; caching the
|
|
49
|
+
// resolved collection on the model makes it ~3ms.
|
|
50
|
+
const _entityCollCache = new WeakMap<object, any>()
|
|
51
|
+
|
|
52
|
+
function entityCollection(model: any): any {
|
|
53
|
+
if (null == model || 'object' !== typeof model) {
|
|
54
|
+
return {}
|
|
55
|
+
}
|
|
56
|
+
const cached = _entityCollCache.get(model)
|
|
57
|
+
if (null != cached) {
|
|
58
|
+
return cached
|
|
59
|
+
}
|
|
60
|
+
const coll = getModelPath(model, `main.${KIT}.entity`,
|
|
61
|
+
{ only_active: false, required: false }) || {}
|
|
62
|
+
deriveEntityNames(coll)
|
|
63
|
+
_entityCollCache.set(model, coll)
|
|
64
|
+
return coll
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
|
|
68
|
+
// Derive the PascalCase `Name` on every entity in a collection.
|
|
69
|
+
//
|
|
70
|
+
// `Name` is injected LAZILY by jostraca's names(), historically by whichever
|
|
71
|
+
// component happened to run first (create-sdkgen Root.ts, or an EntityTypes
|
|
72
|
+
// emitter). Anything reading `e.Name` before that ran saw `undefined` — and
|
|
73
|
+
// because the helpers below MEMOISE, one early read poisoned the result for
|
|
74
|
+
// the whole run (`undefinedEntity` class names; a permanently empty collision
|
|
75
|
+
// list). The helpers therefore derive `Name` themselves, up front, so they
|
|
76
|
+
// never depend on component ordering. Idempotent: names() is only called for
|
|
77
|
+
// an entity that lacks `Name`.
|
|
78
|
+
function deriveEntityNames(entityColl: any): any[] {
|
|
79
|
+
const ents = each(entityColl).filter((e: any) => e && null != e.name)
|
|
80
|
+
ents.forEach((e: any) => { if (null == e.Name) names(e, e.name) })
|
|
81
|
+
return ents
|
|
82
|
+
}
|
|
30
83
|
|
|
31
84
|
|
|
32
85
|
// The five ops, and whether their request payload is a `Match` (query/id) or
|
|
@@ -156,8 +209,21 @@ function opRequestShape(ent: any, opname: string):
|
|
|
156
209
|
return { items: [], fromParams: false }
|
|
157
210
|
}
|
|
158
211
|
|
|
212
|
+
// Ops that carry a BODY are the exception to "op-declared params win":
|
|
213
|
+
// their request payload is BOTH. `PUT /v1/todo/item/{id}` declares the path
|
|
214
|
+
// param `id`, which the SDK resolves out of reqdata (see the param
|
|
215
|
+
// utility's reqmatch -> match -> reqdata search), while the fields the
|
|
216
|
+
// caller wants to change come from the entity. Params alone produced
|
|
217
|
+
// `<Name>UpdateData = { id }` — no way to send anything to update.
|
|
218
|
+
//
|
|
219
|
+
// The param stays in the payload because the path needs it; keeping it out
|
|
220
|
+
// of the request BODY is the model's job, via the op's `transform.req`
|
|
221
|
+
// (@voxgig/apidef restricts the body to a closed request schema's declared
|
|
222
|
+
// properties).
|
|
223
|
+
const isbodyop = 'create' === opname || 'update' === opname || 'patch' === opname
|
|
224
|
+
|
|
159
225
|
const params = opParams(op)
|
|
160
|
-
if (0 < params.length) {
|
|
226
|
+
if (0 < params.length && !isbodyop) {
|
|
161
227
|
const items = params.map((p: any) => ({
|
|
162
228
|
name: p.name,
|
|
163
229
|
type: p.type,
|
|
@@ -166,15 +232,25 @@ function opRequestShape(ent: any, opname: string):
|
|
|
166
232
|
return { items, fromParams: true }
|
|
167
233
|
}
|
|
168
234
|
|
|
235
|
+
const paramItems = isbodyop ? params.map((p: any) => ({
|
|
236
|
+
name: p.name,
|
|
237
|
+
type: p.type,
|
|
238
|
+
optional: false === p.reqd,
|
|
239
|
+
})) : []
|
|
240
|
+
const paramNames = new Set(paramItems.map((p: any) => p.name))
|
|
241
|
+
|
|
169
242
|
const fields = (ent.fields ? each(ent.fields) : [])
|
|
170
243
|
.filter((f: any) => f.active !== false)
|
|
171
244
|
.filter((f: any) => fieldInOp(f, opname))
|
|
172
245
|
|
|
173
|
-
const items =
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
246
|
+
const items = paramItems.concat(
|
|
247
|
+
fields
|
|
248
|
+
.filter((f: any) => !paramNames.has(f.name))
|
|
249
|
+
.map((f: any) => ({
|
|
250
|
+
name: f.name,
|
|
251
|
+
type: f.type,
|
|
252
|
+
optional: fieldOptional(f, opname),
|
|
253
|
+
})))
|
|
178
254
|
|
|
179
255
|
return { items, fromParams: false }
|
|
180
256
|
}
|
|
@@ -250,6 +326,16 @@ function entityPrimaryOp(ent: any): string | null {
|
|
|
250
326
|
// … The DATA type keeps its canonical `<Name>` — only the suffixed class
|
|
251
327
|
// yields. Deterministic (sorted-key iteration) and stable across runs.
|
|
252
328
|
//
|
|
329
|
+
// Covers EVERY entity, active or not: the consumer scaffold (create-sdkgen
|
|
330
|
+
// Root.ts) iterates the RAW entity collection, and every EntityTypes_<lang>
|
|
331
|
+
// emits with `only_active: false`, so an inactive entity still contributes a
|
|
332
|
+
// generated data type AND still needs a class name. Filtering to actives here
|
|
333
|
+
// left inactive entities on the un-deduped `<Name>Entity` fallback and left
|
|
334
|
+
// their data types out of `taken` — so an ACTIVE entity's class could collide
|
|
335
|
+
// with an INACTIVE entity's emitted data type (e.g. active `project` ->
|
|
336
|
+
// class `ProjectEntity` vs inactive `project-entity` -> type `ProjectEntity`,
|
|
337
|
+
// a redeclaration in Go).
|
|
338
|
+
//
|
|
253
339
|
// Memoised per entity-collection object so the O(n) assignment runs once.
|
|
254
340
|
const _classNameCache = new WeakMap<object, Record<string, string>>()
|
|
255
341
|
|
|
@@ -259,7 +345,7 @@ function entityClassNames(entityColl: any): Record<string, string> {
|
|
|
259
345
|
return cached
|
|
260
346
|
}
|
|
261
347
|
|
|
262
|
-
const ents =
|
|
348
|
+
const ents = deriveEntityNames(entityColl)
|
|
263
349
|
|
|
264
350
|
// 1. Every top-level DATA-type name the target emits.
|
|
265
351
|
const taken: Record<string, boolean> = {}
|
|
@@ -314,8 +400,8 @@ function entityClassName(ent: any, entityColl: any): string {
|
|
|
314
400
|
// merging in ts. The names cannot be auto-renamed here — the generated
|
|
315
401
|
// entity classes and op fragments reference them by token — so the guard
|
|
316
402
|
// surfaces the collision loudly instead. Returns the sorted duplicate names
|
|
317
|
-
// (empty when clean).
|
|
318
|
-
//
|
|
403
|
+
// (empty when clean). `Name` is derived here (deriveEntityNames), so the
|
|
404
|
+
// guard cannot be silently disabled by running before an emitter.
|
|
319
405
|
//
|
|
320
406
|
// Memoised per entity-collection object, like entityClassNames.
|
|
321
407
|
const _typeCollisionCache = new WeakMap<object, string[]>()
|
|
@@ -329,8 +415,7 @@ function entityTypeCollisions(entityColl: any): string[] {
|
|
|
329
415
|
const counts: Record<string, number> = {}
|
|
330
416
|
const bump = (n: string) => { counts[n] = (counts[n] || 0) + 1 }
|
|
331
417
|
|
|
332
|
-
|
|
333
|
-
.filter((e: any) => e && null != e.name && null != e.Name)
|
|
418
|
+
deriveEntityNames(entityColl)
|
|
334
419
|
.forEach((e: any) => {
|
|
335
420
|
bump(e.Name)
|
|
336
421
|
for (const op of ['load', 'list', 'create', 'update', 'remove']) {
|
|
@@ -444,6 +529,8 @@ function entityDataIdField(ent: any): string | null {
|
|
|
444
529
|
|
|
445
530
|
export {
|
|
446
531
|
OP_SUFFIX,
|
|
532
|
+
deriveEntityNames,
|
|
533
|
+
entityCollection,
|
|
447
534
|
opTypeName,
|
|
448
535
|
opParams,
|
|
449
536
|
opRequestShape,
|
package/src/sdkgen.ts
CHANGED
|
@@ -5,7 +5,7 @@ import Path from 'node:path'
|
|
|
5
5
|
|
|
6
6
|
import { prettyPino, Pino } from '@voxgig/util'
|
|
7
7
|
|
|
8
|
-
import { Jsonic } from 'jsonic'
|
|
8
|
+
import { Jsonic } from '@tabnas/jsonic'
|
|
9
9
|
import * as JostracaModule from 'jostraca'
|
|
10
10
|
import { Aontu } from 'aontu'
|
|
11
11
|
|
|
@@ -51,8 +51,8 @@ import { getMatchEntries } from './helpers/getMatchEntries'
|
|
|
51
51
|
import { collectDeps } from './helpers/collectDeps'
|
|
52
52
|
import type { DepEntry } from './helpers/collectDeps'
|
|
53
53
|
import { canonToType, canonKey } from './helpers/canonType'
|
|
54
|
-
import { OP_SUFFIX, opTypeName, opParams, opRequestShape, entityIdField, entityDataIdField, entityOps, entityPrimaryOp, pickExampleEntity, entityClassName, entityTypeCollisions, warnEntityTypeCollisions } from './helpers/opShape'
|
|
55
|
-
import { isReservedName, safeVarName, exampleVarName, jsProp, jsOptProp, jsKey } from './helpers/naming'
|
|
54
|
+
import { OP_SUFFIX, opTypeName, opParams, opRequestShape, entityIdField, entityDataIdField, entityOps, entityPrimaryOp, pickExampleEntity, entityClassName, entityTypeCollisions, warnEntityTypeCollisions, deriveEntityNames, entityCollection } from './helpers/opShape'
|
|
55
|
+
import { isReservedName, safeVarName, exampleVarName, isRbCoreConstant, rbSafeTypeName, jsProp, jsOptProp, jsKey } from './helpers/naming'
|
|
56
56
|
import {
|
|
57
57
|
packageName,
|
|
58
58
|
installCommand,
|
|
@@ -473,9 +473,13 @@ export {
|
|
|
473
473
|
entityClassName,
|
|
474
474
|
entityTypeCollisions,
|
|
475
475
|
warnEntityTypeCollisions,
|
|
476
|
+
deriveEntityNames,
|
|
477
|
+
entityCollection,
|
|
476
478
|
isReservedName,
|
|
477
479
|
safeVarName,
|
|
478
480
|
exampleVarName,
|
|
481
|
+
isRbCoreConstant,
|
|
482
|
+
rbSafeTypeName,
|
|
479
483
|
jsProp,
|
|
480
484
|
jsOptProp,
|
|
481
485
|
jsKey,
|