@voxgig/sdkgen 4.2.4 → 4.2.6
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/AgentGuideTop.js +15 -7
- package/dist/cmp/AgentGuideTop.js.map +1 -1
- package/dist/cmp/ReadmeStation.js +88 -12
- package/dist/cmp/ReadmeStation.js.map +1 -1
- package/dist/helpers/station.d.ts +3 -0
- package/dist/helpers/station.js +67 -0
- package/dist/helpers/station.js.map +1 -0
- package/dist/sdkgen.d.ts +2 -1
- package/dist/sdkgen.js +41 -15
- package/dist/sdkgen.js.map +1 -1
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/dist/types.d.ts +2 -0
- package/dist/utility.js +15 -1
- package/dist/utility.js.map +1 -1
- package/model/sdkgen.aon +20 -0
- package/package.json +1 -1
- package/project/.sdk/model/feature/audit.aon +1 -0
- package/project/.sdk/model/feature/cache.aon +1 -0
- package/project/.sdk/model/feature/clienttrack.aon +1 -0
- package/project/.sdk/model/feature/debug.aon +1 -0
- package/project/.sdk/model/feature/idempotency.aon +1 -0
- package/project/.sdk/model/feature/log.aon +1 -0
- package/project/.sdk/model/feature/metrics.aon +1 -0
- package/project/.sdk/model/feature/netsim.aon +1 -0
- package/project/.sdk/model/feature/paging.aon +1 -0
- package/project/.sdk/model/feature/proxy.aon +1 -0
- package/project/.sdk/model/feature/ratelimit.aon +1 -0
- package/project/.sdk/model/feature/rbac.aon +1 -0
- package/project/.sdk/model/feature/retry.aon +1 -0
- package/project/.sdk/model/feature/streaming.aon +1 -0
- package/project/.sdk/model/feature/telemetry.aon +1 -0
- package/project/.sdk/model/feature/test.aon +1 -0
- package/project/.sdk/model/feature/timeout.aon +1 -0
- package/project/.sdk/src/cmp/c/Config_c.ts +13 -10
- package/project/.sdk/src/cmp/clojure/Config_clojure.ts +4 -1
- package/project/.sdk/src/cmp/dart/Config_dart.ts +4 -1
- package/project/.sdk/src/cmp/elixir/Config_elixir.ts +4 -1
- package/project/.sdk/src/cmp/elixir/Main_elixir.ts +21 -2
- package/project/.sdk/src/cmp/go/Config_go.ts +4 -1
- package/project/.sdk/src/cmp/go/utility_go.ts +20 -7
- package/project/.sdk/src/cmp/java/Config_java.ts +11 -8
- package/project/.sdk/src/cmp/js/Config_js.ts +4 -1
- package/project/.sdk/src/cmp/js/Main_js.ts +20 -1
- package/project/.sdk/src/cmp/js/fragment/MainStation.fragment.js +36 -0
- package/project/.sdk/src/cmp/js/utility_js.ts +20 -7
- package/project/.sdk/src/cmp/kotlin/Config_kotlin.ts +11 -7
- package/project/.sdk/src/cmp/lua/Config_lua.ts +4 -1
- package/project/.sdk/src/cmp/ocaml/Config_ocaml.ts +3 -1
- package/project/.sdk/src/cmp/php/Config_php.ts +4 -1
- package/project/.sdk/src/cmp/php/ReadmeExamplesTest_php.ts +144 -12
- package/project/.sdk/src/cmp/py/Config_py.ts +4 -1
- package/project/.sdk/src/cmp/py/ReadmeExamplesTest_py.ts +88 -3
- package/project/.sdk/src/cmp/rb/Config_rb.ts +4 -1
- package/project/.sdk/src/cmp/rb/ReadmeExamplesTest_rb.ts +83 -10
- package/project/.sdk/src/cmp/swift/EntityTypes_swift.ts +2 -2
- package/project/.sdk/src/cmp/swift/Entity_swift.ts +3 -1
- package/project/.sdk/src/cmp/swift/Main_swift.ts +37 -2
- package/project/.sdk/src/cmp/swift/Package_swift.ts +9 -6
- package/project/.sdk/src/cmp/swift/ReadmeExamplesTest_swift.ts +1 -1
- package/project/.sdk/src/cmp/swift/ReadmeExplanation_swift.ts +5 -3
- package/project/.sdk/src/cmp/swift/Test_swift.ts +3 -1
- package/project/.sdk/src/cmp/swift/utility_swift.ts +16 -0
- package/project/.sdk/src/cmp/ts/Config_ts.ts +4 -1
- package/project/.sdk/src/cmp/ts/Main_ts.ts +20 -1
- package/project/.sdk/src/cmp/ts/fragment/MainStation.fragment.ts +36 -0
- package/project/.sdk/src/cmp/ts/utility_ts.ts +20 -7
- package/project/.sdk/src/cmp/zig/Config_zig.ts +4 -2
- package/project/sdkgen-package.json +1 -1
- package/src/cmp/AgentGuideTop.ts +15 -7
- package/src/cmp/ReadmeStation.ts +93 -13
- package/src/helpers/station.ts +80 -0
- package/src/sdkgen.ts +52 -15
- package/src/types.ts +6 -0
- package/src/utility.ts +15 -1
package/model/sdkgen.aon
CHANGED
|
@@ -270,6 +270,15 @@ main: kit: target: &: {
|
|
|
270
270
|
output: {
|
|
271
271
|
path: *'' | string
|
|
272
272
|
|
|
273
|
+
# Whether generation may create a destination folder that does not yet
|
|
274
|
+
# exist. true preserves the ordinary behaviour: jostraca creates it and
|
|
275
|
+
# any missing parents. false keeps the target active but skips its
|
|
276
|
+
# out-of-tree generation pass until the destination folder exists — for
|
|
277
|
+
# example when a separate provider fleet is only checked out on some
|
|
278
|
+
# machines. An existing destination still goes through every ownership
|
|
279
|
+
# and overwrite-safety check below.
|
|
280
|
+
create: *true | boolean
|
|
281
|
+
|
|
273
282
|
# Write into a destination that already holds content this generator did
|
|
274
283
|
# not write.
|
|
275
284
|
#
|
|
@@ -411,6 +420,16 @@ main: kit: feature: &: {
|
|
|
411
420
|
# TODO: version '0.0.1' | semver # where semver is a string format type as per semver.org
|
|
412
421
|
version: *'0.0.1' | string
|
|
413
422
|
|
|
423
|
+
# Transport role (station design §8.4): how the feature relates to the
|
|
424
|
+
# transport slot. 'base' REPLACES ctx.utility.fetcher outright (only the
|
|
425
|
+
# `test` feature); 'wrap' wraps it in init() (netsim, retry, cache,
|
|
426
|
+
# ratelimit, timeout, proxy - and station's own feature); 'none' is
|
|
427
|
+
# hook-only. Carried into the embedded config by configDefinition so
|
|
428
|
+
# station can validate the resolved feature order. Declared, never
|
|
429
|
+
# inferred: the obvious signal, an empty `hook: {}`, is wrong for a
|
|
430
|
+
# feature that both wraps AND dispatches hooks (station does).
|
|
431
|
+
transport: *'none' | 'base' | 'wrap'
|
|
432
|
+
|
|
414
433
|
hook: &: {
|
|
415
434
|
active: *false | boolean
|
|
416
435
|
await: *false | boolean
|
|
@@ -480,6 +499,7 @@ main: kit: docs: &: {
|
|
|
480
499
|
output: {
|
|
481
500
|
path: *'' | string
|
|
482
501
|
repo: *'' | string
|
|
502
|
+
create: *true | boolean
|
|
483
503
|
adopt: *false | boolean
|
|
484
504
|
sdkrel: *'' | string
|
|
485
505
|
}
|
package/package.json
CHANGED
|
@@ -46,9 +46,21 @@ const Config = cmp(async function Config(props: any) {
|
|
|
46
46
|
let baseUrl = ''
|
|
47
47
|
try { baseUrl = getModelPath(model, `main.${KIT}.info.servers.0.url`) } catch (_e) { }
|
|
48
48
|
|
|
49
|
+
// The same config as an OBJECT, built by the shared helper so this target's
|
|
50
|
+
// literal and the data that replaces it above the threshold are the same
|
|
51
|
+
// config by construction. The JSON is what the threshold is measured on -
|
|
52
|
+
// emitted source size varies by language, the model does not. Passing
|
|
53
|
+
// target.name opts this target into the main slug/version/target identity
|
|
54
|
+
// fields (read by station's descriptor - see configDefinition).
|
|
55
|
+
const { def: configDef, json: configJson } = configDefinition(model, target.name)
|
|
56
|
+
const asData = isConfigData(configJson, configReprSetting(model))
|
|
57
|
+
|
|
58
|
+
// The feature block comes from configDefinition's def, not from f.config,
|
|
59
|
+
// so the literal carries each feature's `transport` role (station design
|
|
60
|
+
// §8.4) beside its options and cannot drift from the data rep.
|
|
49
61
|
const featureConfig: any = {}
|
|
50
62
|
each(feature, (f: any) => {
|
|
51
|
-
featureConfig[f.name] = f.
|
|
63
|
+
featureConfig[f.name] = configDef.feature[f.name] || {}
|
|
52
64
|
})
|
|
53
65
|
|
|
54
66
|
const entityOptions: any = {}
|
|
@@ -73,15 +85,6 @@ const Config = cmp(async function Config(props: any) {
|
|
|
73
85
|
relations: n.relations,
|
|
74
86
|
}, true), a), {})
|
|
75
87
|
|
|
76
|
-
// The same config as an OBJECT, built by the shared helper so this target's
|
|
77
|
-
// literal and the data that replaces it above the threshold are the same
|
|
78
|
-
// config by construction. The JSON is what the threshold is measured on -
|
|
79
|
-
// emitted source size varies by language, the model does not. Passing
|
|
80
|
-
// target.name opts this target into the main slug/version/target identity
|
|
81
|
-
// fields (read by station's descriptor - see configDefinition).
|
|
82
|
-
const { def: configDef, json: configJson } = configDefinition(model, target.name)
|
|
83
|
-
const asData = isConfigData(configJson, configReprSetting(model))
|
|
84
|
-
|
|
85
88
|
const config = {
|
|
86
89
|
// main from configDefinition's def, not re-derived here, so the literal
|
|
87
90
|
// rep and the data rep cannot disagree on identity (the Config_ts
|
|
@@ -32,6 +32,7 @@ import {
|
|
|
32
32
|
// N-feature-safe: an empty feature/entity map renders as (vs/jm).
|
|
33
33
|
const Config = cmp(async function Config(props: any) {
|
|
34
34
|
const ctx$ = props.ctx$
|
|
35
|
+
const target = props.target
|
|
35
36
|
|
|
36
37
|
const model: Model = ctx$.model
|
|
37
38
|
|
|
@@ -39,7 +40,9 @@ const Config = cmp(async function Config(props: any) {
|
|
|
39
40
|
// representations render from the same `def`, so they cannot describe
|
|
40
41
|
// different configs - and this target picks up `options.server` (the OpenAPI
|
|
41
42
|
// server-variable defaults), which the hand-rolled build here omitted.
|
|
42
|
-
|
|
43
|
+
// Passing target.name opts this target into the main slug/version/target
|
|
44
|
+
// identity fields (read by station's descriptor - see configDefinition).
|
|
45
|
+
const { def: config, json: configJson } = configDefinition(model, target.name)
|
|
43
46
|
const asData = isConfigData(configJson, configReprSetting(model))
|
|
44
47
|
|
|
45
48
|
File({ name: 'config.clj' }, () => {
|
|
@@ -143,8 +143,11 @@ const Config = cmp(async function Config(props: any) {
|
|
|
143
143
|
Line(` '${f.name}': () => ${nom(f, 'Name')}Feature(),`)
|
|
144
144
|
}),
|
|
145
145
|
|
|
146
|
+
// Rendered from configDefinition's def, not from f.config, so the
|
|
147
|
+
// literal carries the feature's `transport` role (station design
|
|
148
|
+
// §8.4) beside its options and cannot drift from the data rep.
|
|
146
149
|
'// #FeatureConfigs': () => each(feature, (f: any) => {
|
|
147
|
-
Line(` '${f.name}': ${dartValue(f.
|
|
150
|
+
Line(` '${f.name}': ${dartValue(configDef.feature[f.name], 2)},`)
|
|
148
151
|
}),
|
|
149
152
|
|
|
150
153
|
|
|
@@ -174,7 +174,10 @@ defmodule ${Name}.Config do
|
|
|
174
174
|
`)
|
|
175
175
|
|
|
176
176
|
each(feature, (f: any) => {
|
|
177
|
-
|
|
177
|
+
// From configDefinition's def, not f.config, so the literal carries
|
|
178
|
+
// the feature's `transport` role (station design §8.4) beside its
|
|
179
|
+
// options and cannot drift from the data rep.
|
|
180
|
+
Content(` ${elixirString(f.name)} => ${formatElixir(configDef.feature[f.name] || {}, 4)},
|
|
178
181
|
`)
|
|
179
182
|
})
|
|
180
183
|
|
|
@@ -48,15 +48,34 @@ const Main = cmp(async function Main(props: any) {
|
|
|
48
48
|
// Generate the documented typespec module (lib/<app>_types.ex).
|
|
49
49
|
EntityTypes({ target })
|
|
50
50
|
|
|
51
|
-
// Copy tm/elixir
|
|
51
|
+
// Copy tm/elixir (with ProjectName/projectname substitution).
|
|
52
|
+
//
|
|
53
|
+
// THE RUNTIME DIRECTORY HAS TO CARRY THE APP NAME. Copy substitutes file
|
|
54
|
+
// CONTENTS, never path components, so a blanket copy shipped the runtime as
|
|
55
|
+
// lib/projectname/ in every generated SDK. Nothing broke — Elixir resolves
|
|
56
|
+
// modules by their `defmodule`, not by path, and those were substituted
|
|
57
|
+
// correctly — so it compiled, tested green, and published looking wrong.
|
|
58
|
+
//
|
|
59
|
+
// Copy's `to` prop names the destination, so lib/projectname is copied
|
|
60
|
+
// explicitly under the app's own name and excluded from the blanket copy.
|
|
52
61
|
Copy({
|
|
53
62
|
from: 'tm/' + target.name,
|
|
54
|
-
exclude: [/src\//],
|
|
63
|
+
exclude: [/src\//, /lib\/projectname\//],
|
|
55
64
|
replace: {
|
|
56
65
|
...stdrep,
|
|
57
66
|
}
|
|
58
67
|
})
|
|
59
68
|
|
|
69
|
+
Folder({ name: 'lib' }, () => {
|
|
70
|
+
Copy({
|
|
71
|
+
from: 'tm/' + target.name + '/lib/projectname',
|
|
72
|
+
to: model.const.name,
|
|
73
|
+
replace: {
|
|
74
|
+
...stdrep,
|
|
75
|
+
}
|
|
76
|
+
})
|
|
77
|
+
})
|
|
78
|
+
|
|
60
79
|
Folder({ name: 'lib' }, () => {
|
|
61
80
|
|
|
62
81
|
// Main SDK module (entity factory fns injected at the slot).
|
|
@@ -173,7 +173,10 @@ func MakeConfig() map[string]any {
|
|
|
173
173
|
`)
|
|
174
174
|
|
|
175
175
|
each(feature, (f: any) => {
|
|
176
|
-
|
|
176
|
+
// From configDefinition's def, not f.config, so the literal carries
|
|
177
|
+
// the feature's `transport` role (station design §8.4) beside its
|
|
178
|
+
// options and cannot drift from the data rep.
|
|
179
|
+
const fconfig = configDef.feature[f.name] || {}
|
|
177
180
|
Content(` "${f.name}": ${formatGoMap(fconfig, 3)},
|
|
178
181
|
`)
|
|
179
182
|
})
|
|
@@ -7,6 +7,7 @@ import {
|
|
|
7
7
|
canonKey,
|
|
8
8
|
canonScalarKey,
|
|
9
9
|
each,
|
|
10
|
+
opParams,
|
|
10
11
|
exampleVarName,
|
|
11
12
|
names,
|
|
12
13
|
} from '@voxgig/sdkgen'
|
|
@@ -36,13 +37,25 @@ function projectPath(suffix?: string): string {
|
|
|
36
37
|
// has no params and the request shape mirrors the entity fields). Returns
|
|
37
38
|
// undefined when neither is present.
|
|
38
39
|
function paramCanonType(entity: any, op: any, paramName: string): unknown {
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
40
|
+
// opParams, NOT a raw walk of op.points.
|
|
41
|
+
//
|
|
42
|
+
// opParams drops points flagged with select['$action'] and merges what is
|
|
43
|
+
// left; the typed-model generator reaches the op's params through it, so
|
|
44
|
+
// anything else is a DIFFERENT set of params wearing the same name.
|
|
45
|
+
//
|
|
46
|
+
// A raw walk returned the first match on ANY point, action points included.
|
|
47
|
+
// github's `action` entity has a field `owner` (`$OBJECT`, "A GitHub user")
|
|
48
|
+
// and seven create points whose path carries `{owner}` (a string) — so the
|
|
49
|
+
// type said Record<string, any> and the doc example said 'example_owner',
|
|
50
|
+
// and ts/README.md stopped compiling. Same for workflow_id: `number` in the
|
|
51
|
+
// type, quoted string in the example.
|
|
52
|
+
//
|
|
53
|
+
// Deriving from opParams is what actually makes good on the promise below —
|
|
54
|
+
// that the docs and the generated types cannot disagree.
|
|
55
|
+
const params = op ? each(opParams(op)) : []
|
|
56
|
+
const found = (params as any[]).find((p: any) => p && p.name === paramName)
|
|
57
|
+
if (found) {
|
|
58
|
+
return found.type
|
|
46
59
|
}
|
|
47
60
|
const field = (entity && entity.fields ? each(entity.fields) : [])
|
|
48
61
|
.find((f: any) => f && f.name === paramName) as any
|
|
@@ -48,10 +48,19 @@ const Config = cmp(async function Config(props: any) {
|
|
|
48
48
|
let baseUrl = ''
|
|
49
49
|
try { baseUrl = getModelPath(model, `main.${KIT}.info.servers.0.url`) } catch (_e) { }
|
|
50
50
|
|
|
51
|
-
//
|
|
51
|
+
// Identity comes from configDefinition's def, not re-derived here, so
|
|
52
|
+
// this target cannot disagree with the shared emitter on main.slug /
|
|
53
|
+
// main.version / main.target (the three station descriptor fields,
|
|
54
|
+
// station design §4) — passing target.name is what opts this target in.
|
|
55
|
+
const { def: configDef } = configDefinition(model, target.name)
|
|
56
|
+
|
|
57
|
+
// Assemble the config shape (mirrors Config_go's emitted map). The
|
|
58
|
+
// feature block comes from configDefinition's def, not from f.config,
|
|
59
|
+
// so it carries each feature's `transport` role (station design §8.4)
|
|
60
|
+
// beside its options and cannot drift from the shared emitter.
|
|
52
61
|
const featureConfig: Record<string, any> = {}
|
|
53
62
|
each(feature, (f: any) => {
|
|
54
|
-
featureConfig[f.name] = cleanModel(f.
|
|
63
|
+
featureConfig[f.name] = cleanModel(configDef.feature[f.name] || {})
|
|
55
64
|
})
|
|
56
65
|
|
|
57
66
|
const optionsEntity: Record<string, any> = {}
|
|
@@ -76,12 +85,6 @@ const Config = cmp(async function Config(props: any) {
|
|
|
76
85
|
relations: n.relations,
|
|
77
86
|
}, true), a), {})
|
|
78
87
|
|
|
79
|
-
// Identity comes from configDefinition's def, not re-derived here, so
|
|
80
|
-
// this target cannot disagree with the shared emitter on main.slug /
|
|
81
|
-
// main.version / main.target (the three station descriptor fields,
|
|
82
|
-
// station design §4) — passing target.name is what opts this target in.
|
|
83
|
-
const { def: configDef } = configDefinition(model, target.name)
|
|
84
|
-
|
|
85
88
|
const config = {
|
|
86
89
|
main: configDef.main,
|
|
87
90
|
feature: featureConfig,
|
|
@@ -142,8 +142,11 @@ const Config = cmp(async function Config(props: any) {
|
|
|
142
142
|
Line(` ${f.name}: ${nom(f, 'Name')}Feature,`)
|
|
143
143
|
}),
|
|
144
144
|
|
|
145
|
+
// Rendered from configDefinition's def, not from f.config, so the
|
|
146
|
+
// literal carries the feature's `transport` role (station design
|
|
147
|
+
// §8.4) beside its options and cannot drift from the data rep.
|
|
145
148
|
'// #FeatureConfigs': () => each(feature, (f: any) => {
|
|
146
|
-
Line(` ${f.name}: ${formatJson(f.
|
|
149
|
+
Line(` ${f.name}: ${formatJson(configDef.feature[f.name], { margin: 4 })},`)
|
|
147
150
|
}),
|
|
148
151
|
|
|
149
152
|
|
|
@@ -4,7 +4,7 @@ import * as Path from 'node:path'
|
|
|
4
4
|
import {
|
|
5
5
|
cmp, each, names, cmap,
|
|
6
6
|
List, File, Content, Copy, Folder, Fragment, Line, FeatureHook,
|
|
7
|
-
entityClassName, entityCollection, srcFeatureExcludes,
|
|
7
|
+
entityClassName, entityCollection, srcFeatureExcludes, stationLibrary,
|
|
8
8
|
} from '@voxgig/sdkgen'
|
|
9
9
|
|
|
10
10
|
|
|
@@ -102,6 +102,25 @@ if (fres instanceof Promise) { await fres }
|
|
|
102
102
|
MainEntity(entprops)
|
|
103
103
|
})
|
|
104
104
|
})
|
|
105
|
+
|
|
106
|
+
// Station self-registration (station design §6.2 path 1;
|
|
107
|
+
// station-declarative-config §11 item 2): emitted ONLY when the model
|
|
108
|
+
// carries an ACTIVE station feature (installed via
|
|
109
|
+
// `package add @voxgig/sdkgen-station`). The library package name
|
|
110
|
+
// comes from the feature model's own `deps.js` block — the same entry
|
|
111
|
+
// collectDeps flows into package.json — so the manifest dependency
|
|
112
|
+
// and the emitted require cannot disagree.
|
|
113
|
+
const stationPkg = stationLibrary(model, target.name)
|
|
114
|
+
if (null != stationPkg) {
|
|
115
|
+
Fragment({
|
|
116
|
+
from: Path.normalize(
|
|
117
|
+
__dirname + '/../../../src/cmp/js/fragment/MainStation.fragment.js'),
|
|
118
|
+
replace: {
|
|
119
|
+
...props.ctx$.stdrep,
|
|
120
|
+
"'STATIONPKG'": JSON.stringify(stationPkg),
|
|
121
|
+
}
|
|
122
|
+
})
|
|
123
|
+
}
|
|
105
124
|
})
|
|
106
125
|
|
|
107
126
|
Config({ target })
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
|
|
2
|
+
|
|
3
|
+
// Station self-registration (voxgig/station design §6.2, path 1): linking
|
|
4
|
+
// this package is the whole bootstrap. When the station library is
|
|
5
|
+
// installed beside this SDK, the {construct, config} factory pair is
|
|
6
|
+
// registered under the api slug (config.main.slug, the descriptor slug) at
|
|
7
|
+
// module init, so `station.sdk('<name>')` needs no imports in application
|
|
8
|
+
// code. Registration is SOFT — the station library is a peer dependency of
|
|
9
|
+
// the station feature, and a project without it skips registration and
|
|
10
|
+
// gets exactly the SDK it always had. Only a genuine module-not-found is
|
|
11
|
+
// swallowed: a station that RESOLVES but throws while loading must
|
|
12
|
+
// propagate (a silently empty factory table has no visible cause), and so
|
|
13
|
+
// must station_factory_conflict — two different builds of one SDK in one
|
|
14
|
+
// process is not a thing to pick between quietly.
|
|
15
|
+
let stationInstalled = true
|
|
16
|
+
try { require.resolve('STATIONPKG') }
|
|
17
|
+
catch (err) {
|
|
18
|
+
// MODULE_NOT_FOUND is the absent case. Anything else - an invalid
|
|
19
|
+
// package config, a root entry the package does not export - is a
|
|
20
|
+
// real failure to load a station that IS installed, and swallowing
|
|
21
|
+
// it would leave an empty factory table with no visible cause.
|
|
22
|
+
if ('MODULE_NOT_FOUND' !== (err && err.code)) { throw err }
|
|
23
|
+
stationInstalled = false
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
if (stationInstalled) {
|
|
27
|
+
const { provide } = require('STATIONPKG')
|
|
28
|
+
// A station library predating the factory table has no provide() —
|
|
29
|
+
// there is nothing to register with, which is not this SDK's error.
|
|
30
|
+
if ('function' === typeof provide) {
|
|
31
|
+
provide(config.main.slug, {
|
|
32
|
+
construct: (options) => new ProjectNameSDK(options),
|
|
33
|
+
config,
|
|
34
|
+
})
|
|
35
|
+
}
|
|
36
|
+
}
|
|
@@ -6,6 +6,7 @@ import {
|
|
|
6
6
|
canonKey,
|
|
7
7
|
canonScalarKey,
|
|
8
8
|
each,
|
|
9
|
+
opParams,
|
|
9
10
|
} from '@voxgig/sdkgen'
|
|
10
11
|
|
|
11
12
|
import {
|
|
@@ -28,13 +29,25 @@ import {
|
|
|
28
29
|
// does. Falls back to the entity field of the same name (used when the op
|
|
29
30
|
// has no params). Returns undefined when neither is present.
|
|
30
31
|
function paramCanonType(entity: any, op: any, paramName: string): unknown {
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
32
|
+
// opParams, NOT a raw walk of op.points.
|
|
33
|
+
//
|
|
34
|
+
// opParams drops points flagged with select['$action'] and merges what is
|
|
35
|
+
// left; the typed-model generator reaches the op's params through it, so
|
|
36
|
+
// anything else is a DIFFERENT set of params wearing the same name.
|
|
37
|
+
//
|
|
38
|
+
// A raw walk returned the first match on ANY point, action points included.
|
|
39
|
+
// github's `action` entity has a field `owner` (`$OBJECT`, "A GitHub user")
|
|
40
|
+
// and seven create points whose path carries `{owner}` (a string) — so the
|
|
41
|
+
// type said Record<string, any> and the doc example said 'example_owner',
|
|
42
|
+
// and ts/README.md stopped compiling. Same for workflow_id: `number` in the
|
|
43
|
+
// type, quoted string in the example.
|
|
44
|
+
//
|
|
45
|
+
// Deriving from opParams is what actually makes good on the promise below —
|
|
46
|
+
// that the docs and the generated types cannot disagree.
|
|
47
|
+
const params = op ? each(opParams(op)) : []
|
|
48
|
+
const found = (params as any[]).find((p: any) => p && p.name === paramName)
|
|
49
|
+
if (found) {
|
|
50
|
+
return found.type
|
|
38
51
|
}
|
|
39
52
|
const field = (entity && entity.fields ? each(entity.fields) : [])
|
|
40
53
|
.find((f: any) => f && f.name === paramName) as any
|
|
@@ -46,9 +46,19 @@ const Config = cmp(async function Config(props: any) {
|
|
|
46
46
|
let baseUrl = ''
|
|
47
47
|
try { baseUrl = getModelPath(model, `main.${KIT}.info.servers.0.url`) } catch (_e) { }
|
|
48
48
|
|
|
49
|
+
// Identity comes from configDefinition's def, not re-derived here, so
|
|
50
|
+
// this target cannot disagree with the shared emitter on main.slug /
|
|
51
|
+
// main.version / main.target (the three station descriptor fields,
|
|
52
|
+
// station design §4) — passing target.name is what opts this target in.
|
|
53
|
+
const { def: configDef } = configDefinition(model, target.name)
|
|
54
|
+
|
|
55
|
+
// The feature block comes from configDefinition's def, not from
|
|
56
|
+
// f.config, so it carries each feature's `transport` role (station
|
|
57
|
+
// design §8.4) beside its options and cannot drift from the shared
|
|
58
|
+
// emitter.
|
|
49
59
|
const featureConfig: Record<string, any> = {}
|
|
50
60
|
each(feature, (f: any) => {
|
|
51
|
-
featureConfig[f.name] = cleanModel(f.
|
|
61
|
+
featureConfig[f.name] = cleanModel(configDef.feature[f.name] || {})
|
|
52
62
|
})
|
|
53
63
|
|
|
54
64
|
const optionsEntity: Record<string, any> = {}
|
|
@@ -73,12 +83,6 @@ const Config = cmp(async function Config(props: any) {
|
|
|
73
83
|
relations: n.relations,
|
|
74
84
|
}, true), a), {})
|
|
75
85
|
|
|
76
|
-
// Identity comes from configDefinition's def, not re-derived here, so
|
|
77
|
-
// this target cannot disagree with the shared emitter on main.slug /
|
|
78
|
-
// main.version / main.target (the three station descriptor fields,
|
|
79
|
-
// station design §4) — passing target.name is what opts this target in.
|
|
80
|
-
const { def: configDef } = configDefinition(model, target.name)
|
|
81
|
-
|
|
82
86
|
const config = {
|
|
83
87
|
main: configDef.main,
|
|
84
88
|
feature: featureConfig,
|
|
@@ -133,7 +133,10 @@ local function make_config()
|
|
|
133
133
|
`)
|
|
134
134
|
|
|
135
135
|
each(feature, (f: any) => {
|
|
136
|
-
|
|
136
|
+
// From configDefinition's def, not f.config, so the literal carries
|
|
137
|
+
// the feature's `transport` role (station design §8.4) beside its
|
|
138
|
+
// options and cannot drift from the data rep.
|
|
139
|
+
const fconfig = configDef.feature[f.name] || {}
|
|
137
140
|
Content(` ["${f.name}"] = ${formatLuaTable(fconfig, 3)},
|
|
138
141
|
`)
|
|
139
142
|
})
|
|
@@ -40,7 +40,9 @@ const Config = cmp(async function Config(props: any) {
|
|
|
40
40
|
// representations render from the same `def`, so they cannot describe
|
|
41
41
|
// different configs - and this target picks up `options.server` (the OpenAPI
|
|
42
42
|
// server-variable defaults), which the hand-rolled build here omitted.
|
|
43
|
-
|
|
43
|
+
// Passing target.name opts this target into the main slug/version/target
|
|
44
|
+
// identity fields (read by station's descriptor - see configDefinition).
|
|
45
|
+
const { def: config, json: configJson } = configDefinition(model, target.name)
|
|
44
46
|
const asData = isConfigData(configJson, configReprSetting(model))
|
|
45
47
|
|
|
46
48
|
File({ name: 'sdk_config.' + target.ext }, () => {
|
|
@@ -197,7 +197,10 @@ class ${model.const.Name}Config
|
|
|
197
197
|
`)
|
|
198
198
|
|
|
199
199
|
each(feature, (f: any) => {
|
|
200
|
-
|
|
200
|
+
// From configDefinition's def, not f.config, so the literal carries
|
|
201
|
+
// the feature's `transport` role (station design §8.4) beside its
|
|
202
|
+
// options and cannot drift from the data rep.
|
|
203
|
+
const fconfig = configDef.feature[f.name] || {}
|
|
201
204
|
Content(` "${f.name}" => ${formatPhpArray(fconfig, 4)},
|
|
202
205
|
`)
|
|
203
206
|
})
|