@voxgig/sdkgen 3.7.3 → 4.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.
- package/bin/voxgig-sdkgen +1 -1
- package/dist/action/action.js +12 -12
- package/dist/action/action.js.map +1 -1
- package/dist/action/check.js +2 -2
- package/dist/action/check.js.map +1 -1
- package/dist/action/doctor.js +4 -4
- package/dist/action/doctor.js.map +1 -1
- package/dist/action/feature.js +1 -1
- package/dist/action/feature.js.map +1 -1
- package/dist/action/kind.js +5 -5
- package/dist/action/kind.js.map +1 -1
- package/dist/action/package.js +1 -1
- package/dist/action/package.js.map +1 -1
- package/dist/action/resolve.js +2 -2
- package/dist/action/resolve.js.map +1 -1
- package/dist/action/target.js +2 -2
- package/dist/action/target.js.map +1 -1
- package/dist/cmp/AgentGuide.js +2 -2
- package/dist/cmp/AgentGuideContent.js +9 -9
- package/dist/cmp/AgentGuideFeature.js +3 -3
- package/dist/cmp/AgentGuideFeature.js.map +1 -1
- package/dist/cmp/AgentGuideTop.js +1 -1
- package/dist/cmp/Deploy.js +3 -3
- package/dist/cmp/Deploy.js.map +1 -1
- package/dist/helpers/definition.js +7 -7
- package/dist/helpers/definition.js.map +1 -1
- package/dist/helpers/featureSource.js +2 -2
- package/dist/helpers/featureSource.js.map +1 -1
- package/dist/helpers/manifest.js +3 -3
- package/dist/helpers/manifest.js.map +1 -1
- package/dist/helpers/modelcheck.js +1 -1
- package/dist/helpers/modelcheck.js.map +1 -1
- package/dist/helpers/packageMeta.js +1 -1
- package/dist/helpers/packageMeta.js.map +1 -1
- package/dist/helpers/shipped.js +2 -2
- package/dist/helpers/shipped.js.map +1 -1
- package/dist/sdkgen.js +2 -2
- package/dist/sdkgen.js.map +1 -1
- package/dist/testkit.js +7 -7
- package/dist/testkit.js.map +1 -1
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/dist/utility.js +1 -1
- package/dist/utility.js.map +1 -1
- package/package.json +3 -3
- package/project/.sdk/model/feature/feature-index.aon +24 -0
- package/project/.sdk/tm/csharp/Makefile +1 -1
- package/project/.sdk/tm/rb/utility/struct/voxgig_struct.rb +31 -11
- package/project/.sdk/tm/swift/Makefile +1 -1
- package/project/sdkgen-package.json +1 -1
- package/src/action/action.ts +12 -12
- package/src/action/check.ts +2 -2
- package/src/action/doctor.ts +5 -5
- package/src/action/feature.ts +1 -1
- package/src/action/kind.ts +5 -5
- package/src/action/package.ts +1 -1
- package/src/action/resolve.ts +2 -2
- package/src/action/target.ts +2 -2
- package/src/cmp/AgentGuide.ts +2 -2
- package/src/cmp/AgentGuideContent.ts +9 -9
- package/src/cmp/AgentGuideFeature.ts +3 -3
- package/src/cmp/AgentGuideTop.ts +1 -1
- package/src/cmp/Deploy.ts +3 -3
- package/src/helpers/definition.ts +7 -7
- package/src/helpers/featureSource.ts +2 -2
- package/src/helpers/manifest.ts +3 -3
- package/src/helpers/modelcheck.ts +1 -1
- package/src/helpers/packageMeta.ts +1 -1
- package/src/helpers/shipped.ts +2 -2
- package/src/sdkgen.ts +2 -2
- package/src/testkit.ts +9 -9
- package/src/utility.ts +1 -1
- package/testkit.js +1 -1
- package/project/.sdk/model/feature/feature-index.aontu +0 -24
- /package/model/{sdkgen.aontu → sdkgen.aon} +0 -0
- /package/project/.sdk/model/feature/{audit.aontu → audit.aon} +0 -0
- /package/project/.sdk/model/feature/{cache.aontu → cache.aon} +0 -0
- /package/project/.sdk/model/feature/{clienttrack.aontu → clienttrack.aon} +0 -0
- /package/project/.sdk/model/feature/{debug.aontu → debug.aon} +0 -0
- /package/project/.sdk/model/feature/{idempotency.aontu → idempotency.aon} +0 -0
- /package/project/.sdk/model/feature/{log.aontu → log.aon} +0 -0
- /package/project/.sdk/model/feature/{metrics.aontu → metrics.aon} +0 -0
- /package/project/.sdk/model/feature/{netsim.aontu → netsim.aon} +0 -0
- /package/project/.sdk/model/feature/{paging.aontu → paging.aon} +0 -0
- /package/project/.sdk/model/feature/{proxy.aontu → proxy.aon} +0 -0
- /package/project/.sdk/model/feature/{ratelimit.aontu → ratelimit.aon} +0 -0
- /package/project/.sdk/model/feature/{rbac.aontu → rbac.aon} +0 -0
- /package/project/.sdk/model/feature/{retry.aontu → retry.aon} +0 -0
- /package/project/.sdk/model/feature/{streaming.aontu → streaming.aon} +0 -0
- /package/project/.sdk/model/feature/{telemetry.aontu → telemetry.aon} +0 -0
- /package/project/.sdk/model/feature/{test.aontu → test.aon} +0 -0
- /package/project/.sdk/model/feature/{timeout.aontu → timeout.aon} +0 -0
- /package/project/.sdk/model/target/{c.aontu → c.aon} +0 -0
- /package/project/.sdk/model/target/{clojure.aontu → clojure.aon} +0 -0
- /package/project/.sdk/model/target/{cpp.aontu → cpp.aon} +0 -0
- /package/project/.sdk/model/target/{csharp.aontu → csharp.aon} +0 -0
- /package/project/.sdk/model/target/{dart.aontu → dart.aon} +0 -0
- /package/project/.sdk/model/target/{elixir.aontu → elixir.aon} +0 -0
- /package/project/.sdk/model/target/{go-cli.aontu → go-cli.aon} +0 -0
- /package/project/.sdk/model/target/{go-mcp.aontu → go-mcp.aon} +0 -0
- /package/project/.sdk/model/target/{go.aontu → go.aon} +0 -0
- /package/project/.sdk/model/target/{java.aontu → java.aon} +0 -0
- /package/project/.sdk/model/target/{js.aontu → js.aon} +0 -0
- /package/project/.sdk/model/target/{kotlin.aontu → kotlin.aon} +0 -0
- /package/project/.sdk/model/target/{lean.aontu → lean.aon} +0 -0
- /package/project/.sdk/model/target/{lua.aontu → lua.aon} +0 -0
- /package/project/.sdk/model/target/{ocaml.aontu → ocaml.aon} +0 -0
- /package/project/.sdk/model/target/{perl.aontu → perl.aon} +0 -0
- /package/project/.sdk/model/target/{php.aontu → php.aon} +0 -0
- /package/project/.sdk/model/target/{py-data.aontu → py-data.aon} +0 -0
- /package/project/.sdk/model/target/{py.aontu → py.aon} +0 -0
- /package/project/.sdk/model/target/{rb.aontu → rb.aon} +0 -0
- /package/project/.sdk/model/target/{rust.aontu → rust.aon} +0 -0
- /package/project/.sdk/model/target/{scala.aontu → scala.aon} +0 -0
- /package/project/.sdk/model/target/{seneca-provider.aontu → seneca-provider.aon} +0 -0
- /package/project/.sdk/model/target/{swift.aontu → swift.aon} +0 -0
- /package/project/.sdk/model/target/{ts.aontu → ts.aon} +0 -0
- /package/project/.sdk/model/target/{zig.aontu → zig.aon} +0 -0
|
@@ -5,8 +5,28 @@ module VoxgigStruct
|
|
|
5
5
|
# --- Debug Logging Configuration ---
|
|
6
6
|
DEBUG = false
|
|
7
7
|
|
|
8
|
-
|
|
9
|
-
|
|
8
|
+
# LAZY. The argument to a Ruby method is evaluated BEFORE the call, so
|
|
9
|
+
# `log("... #{val.inspect} ...")` built its message on every call and then
|
|
10
|
+
# threw it away, because DEBUG is false. `val` here is a node of the API
|
|
11
|
+
# model, and `inspect` serialises the whole subtree — so each property access
|
|
12
|
+
# cost O(size of the tree it was reading from), turning a walk over the model
|
|
13
|
+
# into O(n^2).
|
|
14
|
+
#
|
|
15
|
+
# Measured on gitlab-sdk (276 entities in config.options), which constructs
|
|
16
|
+
# one client per generated test:
|
|
17
|
+
#
|
|
18
|
+
# validate(options) 4.620s -> 0.039s (118x)
|
|
19
|
+
# client construction 5.790s -> 0.041s (141x)
|
|
20
|
+
# per-entity validate 0.0182s -> 0.0001s, and flat instead of climbing
|
|
21
|
+
#
|
|
22
|
+
# The whole rb suite took 7,894s against 431s for ts and 255s for php on the
|
|
23
|
+
# SAME model. Ruby was not slow; this was.
|
|
24
|
+
#
|
|
25
|
+
# A block is not evaluated unless yielded, so with DEBUG false the message
|
|
26
|
+
# now costs nothing. Call sites pass `log { "..." }`, never `log("...")`.
|
|
27
|
+
def self.log(msg = nil)
|
|
28
|
+
return unless DEBUG
|
|
29
|
+
puts "[DEBUG] #{block_given? ? yield : msg}"
|
|
10
30
|
end
|
|
11
31
|
|
|
12
32
|
# --- Helper to convert internal undefined marker to Ruby nil ---
|
|
@@ -137,33 +157,33 @@ module VoxgigStruct
|
|
|
137
157
|
# --- Internal getprop ---
|
|
138
158
|
# Returns the value if found; otherwise returns alt (default is UNDEF)
|
|
139
159
|
def self._getprop(val, key, alt = UNDEF)
|
|
140
|
-
log
|
|
160
|
+
log { "(_getprop) called with val=#{val.inspect} and key=#{key.inspect}" }
|
|
141
161
|
return alt if val.nil? || key.nil?
|
|
142
162
|
if islist(val)
|
|
143
163
|
key = (key.to_s =~ /\A\d+\z/) ? key.to_i : key
|
|
144
164
|
unless key.is_a?(Numeric) && key >= 0 && key < val.size
|
|
145
|
-
log
|
|
165
|
+
log { "(_getprop) index #{key.inspect} out of bounds; returning alt" }
|
|
146
166
|
return alt
|
|
147
167
|
end
|
|
148
168
|
result = val[key]
|
|
149
|
-
log
|
|
169
|
+
log { "(_getprop) returning #{result.inspect} from array for key #{key}" }
|
|
150
170
|
return result
|
|
151
171
|
elsif ismap(val)
|
|
152
172
|
key_str = key.to_s
|
|
153
173
|
if val.key?(key_str)
|
|
154
174
|
result = val[key_str]
|
|
155
|
-
log
|
|
175
|
+
log { "(_getprop) found key #{key_str.inspect} in hash, returning #{result.inspect}" }
|
|
156
176
|
return result
|
|
157
177
|
elsif key.is_a?(String) && val.key?(key.to_sym)
|
|
158
178
|
result = val[key.to_sym]
|
|
159
|
-
log
|
|
179
|
+
log { "(_getprop) found symbol key #{key.to_sym.inspect} in hash, returning #{result.inspect}" }
|
|
160
180
|
return result
|
|
161
181
|
else
|
|
162
|
-
log
|
|
182
|
+
log { "(_getprop) key #{key.inspect} not found; returning alt" }
|
|
163
183
|
return alt
|
|
164
184
|
end
|
|
165
185
|
else
|
|
166
|
-
log
|
|
186
|
+
log { "(_getprop) value is not a node; returning alt" }
|
|
167
187
|
alt
|
|
168
188
|
end
|
|
169
189
|
end
|
|
@@ -210,7 +230,7 @@ module VoxgigStruct
|
|
|
210
230
|
end
|
|
211
231
|
|
|
212
232
|
def self.setprop(parent, key, val = :no_val_provided)
|
|
213
|
-
log
|
|
233
|
+
log { ">>> setprop called with parent=#{parent.inspect}, key=#{key.inspect}, val=#{val.inspect}" }
|
|
214
234
|
return parent unless iskey(key)
|
|
215
235
|
if ismap(parent)
|
|
216
236
|
key_str = key.to_s
|
|
@@ -236,7 +256,7 @@ module VoxgigStruct
|
|
|
236
256
|
end
|
|
237
257
|
end
|
|
238
258
|
end
|
|
239
|
-
log
|
|
259
|
+
log { "<<< setprop result: #{parent.inspect}" }
|
|
240
260
|
parent
|
|
241
261
|
end
|
|
242
262
|
|
|
@@ -12,7 +12,7 @@ clean:
|
|
|
12
12
|
|
|
13
13
|
# --- Release: tag for the SwiftPM registry ---------------------------------
|
|
14
14
|
# SwiftPM has no upload step - publishing IS the git tag. Publication is
|
|
15
|
-
# pending (see model/target/swift.
|
|
15
|
+
# pending (see model/target/swift.aon publish block); publishing a version
|
|
16
16
|
# currently means pushing the tag swift/vX.Y.Z. Run headless under the boru key
|
|
17
17
|
# vault, which injects the GitHub token so nothing lands on disk or argv:
|
|
18
18
|
# boru vault exec --for=github=<alias> -- make publish
|
package/src/action/action.ts
CHANGED
|
@@ -12,7 +12,7 @@ import type {
|
|
|
12
12
|
} from '../types'
|
|
13
13
|
|
|
14
14
|
|
|
15
|
-
const indexEntry = (name: string) => `@"${name}.
|
|
15
|
+
const indexEntry = (name: string) => `@"${name}.aon"`
|
|
16
16
|
|
|
17
17
|
|
|
18
18
|
// An index line that is an ACTIVE include, and the name it includes — or
|
|
@@ -21,17 +21,17 @@ const indexEntry = (name: string) => `@"${name}.aontu"`
|
|
|
21
21
|
// Parsed rather than compared as a string, because both spellings around an
|
|
22
22
|
// include are legal aontu and mean opposite things:
|
|
23
23
|
//
|
|
24
|
-
// @"go.
|
|
25
|
-
// @"go.
|
|
26
|
-
// @"go.
|
|
27
|
-
// # @"go.
|
|
24
|
+
// @"go.aon" -> active, name 'go'
|
|
25
|
+
// @"go.aon" # pinned -> active, name 'go' (trailing comment)
|
|
26
|
+
// @"go.aon" -> active, name 'go' (indented)
|
|
27
|
+
// # @"go.aon" -> NOT active
|
|
28
28
|
//
|
|
29
29
|
// A substring test (what this used to be) reads the commented-out form as
|
|
30
30
|
// present, so `target add go` on a project that had switched the target off
|
|
31
31
|
// by hand appended nothing and reported success while the target stayed
|
|
32
32
|
// absent from the model. A whole-line equality test fixes that but then
|
|
33
33
|
// misses the trailing-comment form, and appends a SECOND active include.
|
|
34
|
-
const INDEX_ENTRY_RE = /^\s*@"([^"]+)\.
|
|
34
|
+
const INDEX_ENTRY_RE = /^\s*@"([^"]+)\.aon"\s*(?:#.*)?$/
|
|
35
35
|
|
|
36
36
|
function indexEntryName(line: string): string | undefined {
|
|
37
37
|
const m = line.match(INDEX_ENTRY_RE)
|
|
@@ -46,7 +46,7 @@ function hasIndexEntry(content: string, name: string): boolean {
|
|
|
46
46
|
}
|
|
47
47
|
|
|
48
48
|
|
|
49
|
-
// Append `@"<name>.
|
|
49
|
+
// Append `@"<name>.aon"` import lines for each name not already present in
|
|
50
50
|
// the index content. Checking against the accumulating result (not the
|
|
51
51
|
// original) means duplicate names in the same call are added at most once.
|
|
52
52
|
function appendIndexEntries(content: string, names: string[]): string {
|
|
@@ -62,7 +62,7 @@ function appendIndexEntries(content: string, names: string[]): string {
|
|
|
62
62
|
}
|
|
63
63
|
|
|
64
64
|
|
|
65
|
-
// Drop the `@"<name>.
|
|
65
|
+
// Drop the `@"<name>.aon"` line for each name — the inverse of
|
|
66
66
|
// appendIndexEntries, matching line-exact for the same reasons.
|
|
67
67
|
//
|
|
68
68
|
// Nothing calls this yet: a `remove` action is the fast-follow this exists
|
|
@@ -100,12 +100,12 @@ function parseAddNames(args: any[]): string[] {
|
|
|
100
100
|
// The current index file for each kind, which `UpdateIndex` appends to.
|
|
101
101
|
//
|
|
102
102
|
// `seed` IS THE UPGRADE PATH. A project scaffolded before a kind existed has
|
|
103
|
-
// no `model/<kind>/<kind>-index.
|
|
103
|
+
// no `model/<kind>/<kind>-index.aon` — every project alive today is in
|
|
104
104
|
// exactly that position for `docs` — and reading it unguarded made the FIRST
|
|
105
105
|
// `docs add` in any existing project fail on ENOENT before it wrote anything.
|
|
106
106
|
//
|
|
107
107
|
// Seeded per call rather than defaulted for every kind: a missing
|
|
108
|
-
// `target-index.
|
|
108
|
+
// `target-index.aon` in a scaffolded project is a broken project, and
|
|
109
109
|
// quietly recreating it would hide that. A kind the project has never used is
|
|
110
110
|
// a different thing, and only its own action knows which case it is in.
|
|
111
111
|
function loadContent(
|
|
@@ -119,7 +119,7 @@ function loadContent(
|
|
|
119
119
|
const modelfolder = Path.dirname(actx.url)
|
|
120
120
|
|
|
121
121
|
which.map((w: string) => {
|
|
122
|
-
const indexfile = Path.join(modelfolder, w, w + '-index.
|
|
122
|
+
const indexfile = Path.join(modelfolder, w, w + '-index.aon')
|
|
123
123
|
|
|
124
124
|
content[`${w}_index`] = (null != seed?.[w] && !fs.existsSync(indexfile)) ?
|
|
125
125
|
seed[w] : fs.readFileSync(indexfile, 'utf8')
|
|
@@ -136,7 +136,7 @@ function loadContent(
|
|
|
136
136
|
// indexes of the kinds that existed then. So a project scaffolded before a
|
|
137
137
|
// kind existed — which is every project alive today, for `docs` — never
|
|
138
138
|
// includes its index, and the item's model file is an orphan: it is on disk,
|
|
139
|
-
// `<kind>-index.
|
|
139
|
+
// `<kind>-index.aon` includes it, and NOTHING includes that. `main.kit.docs`
|
|
140
140
|
// is then absent from the compiled model, so `package list`, `package update`
|
|
141
141
|
// and `doctor` cannot see the item at all.
|
|
142
142
|
//
|
package/src/action/check.ts
CHANGED
|
@@ -302,7 +302,7 @@ function checkDefinition(
|
|
|
302
302
|
return found
|
|
303
303
|
}
|
|
304
304
|
|
|
305
|
-
// 4. Does it declare the key its FILENAME promises? `model/target/iot-go.
|
|
305
|
+
// 4. Does it declare the key its FILENAME promises? `model/target/iot-go.aon`
|
|
306
306
|
// is copied to that name and included by it, so a file still declaring
|
|
307
307
|
// `main: kit: target: go:` installs an item the consumer's model never
|
|
308
308
|
// sees — the exact mistake a package author makes copying a bundled
|
|
@@ -474,7 +474,7 @@ function checkFeatureSource(
|
|
|
474
474
|
level: 'warn', point: 'feature-source-unrecognised', file,
|
|
475
475
|
kind: 'target', name: tname,
|
|
476
476
|
note: 'tm/' + tname + ': ' + strays.map((e) => e.path).join(', ') +
|
|
477
|
-
' — named like feature source, but no `model/feature/<name>.
|
|
477
|
+
' — named like feature source, but no `model/feature/<name>.aon` ' +
|
|
478
478
|
'declares ' + strays.map((e) => e.name).join(', ') +
|
|
479
479
|
', so the trim cannot recognise them and every project gets them ' +
|
|
480
480
|
'whatever its model selects'
|
package/src/action/doctor.ts
CHANGED
|
@@ -109,7 +109,7 @@ const ROOT_COMPONENTS: [string, string][] = [
|
|
|
109
109
|
// What the check found, by category. Categories 1-3 are drift; `additive` is
|
|
110
110
|
// the project's own work and is reported separately, never as a problem.
|
|
111
111
|
type DoctorReport = {
|
|
112
|
-
// `.sdk/src/cmp/**`, or a target's own `.sdk/model/target/<t>.
|
|
112
|
+
// `.sdk/src/cmp/**`, or a target's own `.sdk/model/target/<t>.aon`, that
|
|
113
113
|
// differs from the scaffold. `target add` will silently revert every one of
|
|
114
114
|
// these.
|
|
115
115
|
forked: string[]
|
|
@@ -198,8 +198,8 @@ async function doctor(
|
|
|
198
198
|
|
|
199
199
|
// EVERY KIND, not just targets.
|
|
200
200
|
//
|
|
201
|
-
// `add` writes a copied model file for each kind — `model/target/<t>.
|
|
202
|
-
// and `model/feature/<f>.
|
|
201
|
+
// `add` writes a copied model file for each kind — `model/target/<t>.aon`
|
|
202
|
+
// and `model/feature/<f>.aon` alike — and overwrites it on every resync.
|
|
203
203
|
// Only the target one was ever compared, so a hand-edit to an installed
|
|
204
204
|
// FEATURE definition read as perfectly in sync and was silently reverted by
|
|
205
205
|
// the next `target add` (which re-runs `feature add` for every active
|
|
@@ -777,7 +777,7 @@ function checkFeatureSource(
|
|
|
777
777
|
}
|
|
778
778
|
|
|
779
779
|
|
|
780
|
-
// The copied MODEL FILE — `model/<kind>/<name>.
|
|
780
|
+
// The copied MODEL FILE — `model/<kind>/<name>.aon`, written by add with
|
|
781
781
|
// the `'BASE'` replacement, and overwritten on every resync exactly as
|
|
782
782
|
// `src/cmp` and `tm` are.
|
|
783
783
|
//
|
|
@@ -830,7 +830,7 @@ function checkItemModel(
|
|
|
830
830
|
const aliased = kindDef(kind).alias && name !== origname
|
|
831
831
|
|
|
832
832
|
const project = definitionPath(actx.folder, kind, name)
|
|
833
|
-
const label = 'model/' + kind + '/' + name + '.
|
|
833
|
+
const label = 'model/' + kind + '/' + name + '.aon'
|
|
834
834
|
|
|
835
835
|
if (!fs.existsSync(project)) {
|
|
836
836
|
report.missing.push(label)
|
package/src/action/feature.ts
CHANGED
|
@@ -141,7 +141,7 @@ const FeatureRoot = cmp(function FeatureRoot(props: any) {
|
|
|
141
141
|
Project({}, () => {
|
|
142
142
|
// The names as INSTALLED, which is what the index must list. A ref is
|
|
143
143
|
// not a name: `feature add @acme/sdkgen-iot/circuitbreaker` installs
|
|
144
|
-
// `circuitbreaker`, and writing the raw ref into feature-index.
|
|
144
|
+
// `circuitbreaker`, and writing the raw ref into feature-index.aon
|
|
145
145
|
// would produce an include of a file that does not exist.
|
|
146
146
|
const fnames: string[] = []
|
|
147
147
|
|
package/src/action/kind.ts
CHANGED
|
@@ -11,9 +11,9 @@
|
|
|
11
11
|
// - the ref grammar and resolution, including the fallback to what the
|
|
12
12
|
// model already records for a bare name;
|
|
13
13
|
// - whether the kind may be installed under a different name (`~alias`);
|
|
14
|
-
// - the definition file: `model/<kind>/<name>.
|
|
14
|
+
// - the definition file: `model/<kind>/<name>.aon`, stamped with
|
|
15
15
|
// provenance and landing under the INSTALLED name;
|
|
16
|
-
// - the include list: `model/<kind>/<kind>-index.
|
|
16
|
+
// - the include list: `model/<kind>/<kind>-index.aon`.
|
|
17
17
|
//
|
|
18
18
|
// What a kind adds on top — a target's component and template trees, a
|
|
19
19
|
// feature's per-target source fan-out — stays in that kind's own action. Those
|
|
@@ -293,7 +293,7 @@ function kindModel(props: {
|
|
|
293
293
|
|
|
294
294
|
if (owned) {
|
|
295
295
|
const dest = Path.join(
|
|
296
|
-
ctx$.folder ?? '.', 'model', kind, source.name + '.
|
|
296
|
+
ctx$.folder ?? '.', 'model', kind, source.name + '.aon')
|
|
297
297
|
|
|
298
298
|
if (fs.existsSync(dest)) {
|
|
299
299
|
log.info({
|
|
@@ -308,14 +308,14 @@ function kindModel(props: {
|
|
|
308
308
|
const text = null == def.rename ? src :
|
|
309
309
|
def.rename(src, source.origname, source.name)
|
|
310
310
|
|
|
311
|
-
File({ name: source.name + '.
|
|
311
|
+
File({ name: source.name + '.aon', exclude: owned }, () =>
|
|
312
312
|
Content(template(text, ctx$.model, { replace })))
|
|
313
313
|
}
|
|
314
314
|
else {
|
|
315
315
|
Copy({ from: source.model, replace })
|
|
316
316
|
}
|
|
317
317
|
|
|
318
|
-
File({ name: def.name + '-index.
|
|
318
|
+
File({ name: def.name + '-index.aon' }, () => UpdateIndex({
|
|
319
319
|
content,
|
|
320
320
|
names,
|
|
321
321
|
}))
|
package/src/action/package.ts
CHANGED
|
@@ -1029,7 +1029,7 @@ async function reAdd(
|
|
|
1029
1029
|
skipped.map((i: Installed) => i.origname).join(', ') +
|
|
1030
1030
|
' must be ported by hand: ' +
|
|
1031
1031
|
skipped.map((i: Installed) =>
|
|
1032
|
-
'model/' + i.kind + '/' + i.name + '.
|
|
1032
|
+
'model/' + i.kind + '/' + i.name + '.aon').join(', ')
|
|
1033
1033
|
})
|
|
1034
1034
|
}
|
|
1035
1035
|
|
package/src/action/resolve.ts
CHANGED
|
@@ -86,7 +86,7 @@ function resolveSource(ref: string, kind: string, ctx$: any): Source {
|
|
|
86
86
|
if (1 < aliasing.length) {
|
|
87
87
|
name = aliasing.slice(1).join('~')
|
|
88
88
|
|
|
89
|
-
// The alias becomes a DESTINATION: `model/<kind>/<name>.
|
|
89
|
+
// The alias becomes a DESTINATION: `model/<kind>/<name>.aon`,
|
|
90
90
|
// `src/cmp/<name>/`, `tm/<name>/` — all written, and `target add`
|
|
91
91
|
// overwrites what it writes. `go~..` therefore redirects the copy out of
|
|
92
92
|
// the target-specific directory and over unrelated scaffold. Checked
|
|
@@ -253,7 +253,7 @@ function warnManifest(ctx$: any, file: string, err: string) {
|
|
|
253
253
|
// Teach the IN-MEMORY model about items that have just been installed.
|
|
254
254
|
//
|
|
255
255
|
// An action reads `actx.model`, compiled from `model/sdk.aontu` before the
|
|
256
|
-
// run. Writing `model/target/iotgo.
|
|
256
|
+
// run. Writing `model/target/iotgo.aon` does not change it and nothing
|
|
257
257
|
// recompiles mid-process, so anything later in the SAME command behaves as if
|
|
258
258
|
// the item is not installed.
|
|
259
259
|
//
|
package/src/action/target.ts
CHANGED
|
@@ -431,7 +431,7 @@ function aliasCmpTree(
|
|
|
431
431
|
// refreshed after upstream moved the fh* harness helpers out of it.
|
|
432
432
|
//
|
|
433
433
|
// tm/ is toolchain-owned — the scaffold rewrites it on every add-target, and
|
|
434
|
-
// model/guide/guide.
|
|
434
|
+
// model/guide/guide.aon is the one file a user owns (merged separately by
|
|
435
435
|
// create-sdkgen) — so removing what the toolchain says should not be there is
|
|
436
436
|
// consistent with how the rest of that tree is already treated.
|
|
437
437
|
function pruneStaleTemplates(
|
|
@@ -656,7 +656,7 @@ function readTargetFeature(
|
|
|
656
656
|
const { log } = ctx$
|
|
657
657
|
const fs = ctx$.fs()
|
|
658
658
|
|
|
659
|
-
const path = tfolder + '/model/target/' + torigname + '.
|
|
659
|
+
const path = tfolder + '/model/target/' + torigname + '.aon'
|
|
660
660
|
|
|
661
661
|
try {
|
|
662
662
|
const errs: any[] = []
|
package/src/cmp/AgentGuide.ts
CHANGED
|
@@ -63,7 +63,7 @@ ${langCommandsBlock(lang)}
|
|
|
63
63
|
|
|
64
64
|
| Source | Path | Edit when… |
|
|
65
65
|
| --- | --- | --- |
|
|
66
|
-
| Target definition | \`.sdk/model/target/${lang}.
|
|
66
|
+
| Target definition | \`.sdk/model/target/${lang}.aon\` | deps, module, extension, phases change |
|
|
67
67
|
| Templates | \`.sdk/tm/${lang}/\` | the file is the **same for every API** (runtime, transport, base classes) — copied verbatim with placeholder substitution |
|
|
68
68
|
| Components | \`.sdk/src/cmp/${lang}/\` | the file's shape **depends on the API** (entities, constructor, README, tests) — TypeScript that walks the model |
|
|
69
69
|
|
|
@@ -93,7 +93,7 @@ Each feature's runtime and its own guide live in \`src/feature/<name>/\`.
|
|
|
93
93
|
// go/py/php/rb/lua: flat files in the shared \`feature/\` package — no
|
|
94
94
|
// per-feature directory, so features are documented inline here.
|
|
95
95
|
Content(`Each feature is a flat file in the \`feature/\` package. Its hooks and
|
|
96
|
-
default activation come from \`.sdk/model/feature/<name>.
|
|
96
|
+
default activation come from \`.sdk/model/feature/<name>.aon\`; customise
|
|
97
97
|
the runtime under \`.sdk/tm/${lang}/feature/\` and regenerate.
|
|
98
98
|
|
|
99
99
|
| Feature | Runtime file | Active hooks |
|
|
@@ -180,11 +180,11 @@ npm run build && npm run generate
|
|
|
180
180
|
|
|
181
181
|
To author a **new** feature:
|
|
182
182
|
|
|
183
|
-
1. Define its model at \`.sdk/model/feature/<name>.
|
|
183
|
+
1. Define its model at \`.sdk/model/feature/<name>.aon\` — \`name: key()\`,
|
|
184
184
|
\`title\`, \`version\`, \`active\`, \`config.options.active\`, a \`hook\`
|
|
185
185
|
map (\`<Stage>: active: true\`), and per-language \`deps\`.
|
|
186
|
-
2. Register it in \`.sdk/model/feature/feature-index.
|
|
187
|
-
\`@"<name>.
|
|
186
|
+
2. Register it in \`.sdk/model/feature/feature-index.aon\` with
|
|
187
|
+
\`@"<name>.aon"\`.
|
|
188
188
|
3. Provide the per-language runtime under that target's feature template dir
|
|
189
189
|
(\`.sdk/tm/<lang>/src/feature/<name>/\` for ts/js, \`.sdk/tm/<lang>/feature/\`
|
|
190
190
|
otherwise) — the \`FEATURE_Name\` / \`FEATURE_VERSION\` placeholders are
|
|
@@ -210,24 +210,24 @@ Each language target is generated from **two layers**:
|
|
|
210
210
|
|
|
211
211
|
Placeholders substituted on copy: \`ProjectName\` (Pascal-case SDK name),
|
|
212
212
|
\`GOMODULE\` (Go module path), \`FEATURE_Name\` / \`FEATURE_VERSION\`, and the
|
|
213
|
-
\`$$path$$\` interpolation of a model value (such as the name) in \`.
|
|
213
|
+
\`$$path$$\` interpolation of a model value (such as the name) in \`.aon\`.
|
|
214
214
|
|
|
215
215
|
Propagate a change: edit the template/component → \`npm run build\` (only
|
|
216
216
|
needed if you touched a component) → \`npm run generate\`. Target shape and
|
|
217
|
-
deps live in \`.sdk/model/target/<lang>.
|
|
218
|
-
\`.sdk/model/feature/<name>.
|
|
217
|
+
deps live in \`.sdk/model/target/<lang>.aon\`; features in
|
|
218
|
+
\`.sdk/model/feature/<name>.aon\`.
|
|
219
219
|
`
|
|
220
220
|
}
|
|
221
221
|
|
|
222
222
|
|
|
223
223
|
// (d) how the aontu model language works.
|
|
224
224
|
function aontuSection(): string {
|
|
225
|
-
return `## The model language (aontu, \`.
|
|
225
|
+
return `## The model language (aontu, \`.aon\` files)
|
|
226
226
|
|
|
227
227
|
The model is one structured object assembled by **aontu** (a unification
|
|
228
228
|
engine) from three sources: the API model (entities/operations, from the
|
|
229
229
|
OpenAPI spec via \`@voxgig/apidef\`), the base schema, and the target/feature
|
|
230
|
-
definitions in \`.sdk/model/\`. An \`.
|
|
230
|
+
definitions in \`.sdk/model/\`. An \`.aon\` file is a relaxed JSON (jsonic
|
|
231
231
|
syntax) with unification semantics:
|
|
232
232
|
|
|
233
233
|
| Syntax | Meaning |
|
|
@@ -237,7 +237,7 @@ syntax) with unification semantics:
|
|
|
237
237
|
| \`*default \\| type\` | A default value unified against a type (e.g. \`*true \\| boolean\`). |
|
|
238
238
|
| \`name: key()\` | Bind a field to its map key (so \`feature: log: {}\` gets \`name: 'log'\`). |
|
|
239
239
|
| \`$$path$$\` | Interpolate a model value into a string — e.g. the SDK \`name\`. |
|
|
240
|
-
| \`@"file.
|
|
240
|
+
| \`@"file.aon"\` | Include another fragment (how the index files work). |
|
|
241
241
|
| \`x: .y\` | Reference another path's value (e.g. \`deps: ts: .js\`). |
|
|
242
242
|
|
|
243
243
|
For example, the schema for every feature entry:
|
|
@@ -65,8 +65,8 @@ later feature can override an earlier one.
|
|
|
65
65
|
|
|
66
66
|
| Part | Path |
|
|
67
67
|
| --- | --- |
|
|
68
|
-
| Model definition | \`.sdk/model/feature/${name}.
|
|
69
|
-
| Registered in | \`.sdk/model/feature/feature-index.
|
|
68
|
+
| Model definition | \`.sdk/model/feature/${name}.aon\` (name, title, version, \`config.options.active\`, the \`hook\` map, per-language \`deps\`) |
|
|
69
|
+
| Registered in | \`.sdk/model/feature/feature-index.aon\` (\`@"${name}.aon"\`) |
|
|
70
70
|
| Runtime template | \`.sdk/tm/${lang}/src/feature/${name}/\` (copied here on \`generate\`; \`FEATURE_Name\`/\`FEATURE_VERSION\` substituted) |
|
|
71
71
|
|
|
72
72
|
(Paths are relative to the **project root** — four levels up from here.)
|
|
@@ -74,7 +74,7 @@ later feature can override an earlier one.
|
|
|
74
74
|
## Customising this feature
|
|
75
75
|
|
|
76
76
|
- **Turn hooks on/off**: edit the \`hook\` map in
|
|
77
|
-
\`.sdk/model/feature/${name}.
|
|
77
|
+
\`.sdk/model/feature/${name}.aon\` (\`<Stage>: active: true|false\`).
|
|
78
78
|
- **Change default activation**: set \`config.options.active\` in the same file.
|
|
79
79
|
- **Dependencies**: edit \`deps.<lang>\` in the same file.
|
|
80
80
|
- **Behaviour**: edit the runtime template under
|
package/src/cmp/AgentGuideTop.ts
CHANGED
|
@@ -110,7 +110,7 @@ target's feature container) for the generated adapter.
|
|
|
110
110
|
|
|
111
111
|
\`\`\`
|
|
112
112
|
.sdk/
|
|
113
|
-
model/ the model: target/, feature/, and index .
|
|
113
|
+
model/ the model: target/, feature/, and index .aon files
|
|
114
114
|
src/cmp/<lang>/ components — TypeScript that generates API-specific source
|
|
115
115
|
tm/<lang>/ templates — verbatim source copied with placeholders
|
|
116
116
|
dist/ compiled components (npm run build)
|
package/src/cmp/Deploy.ts
CHANGED
|
@@ -7,7 +7,7 @@ import {
|
|
|
7
7
|
|
|
8
8
|
|
|
9
9
|
// Generate the SDK root deployment Makefile from the model's per-target
|
|
10
|
-
// `publish` sections (see model/sdkgen.
|
|
10
|
+
// `publish` sections (see model/sdkgen.aon):
|
|
11
11
|
//
|
|
12
12
|
// publish.tag — git release tag `<prefix>/vX.Y.Z`; every port has
|
|
13
13
|
// one, pushed with a token from the boru key vault
|
|
@@ -179,7 +179,7 @@ deploy-dry-${t.name}:
|
|
|
179
179
|
|
|
180
180
|
return `# ${model.Name} SDK deployment. GENERATED by @voxgig/sdkgen — regenerated
|
|
181
181
|
# on every \`npm run generate\` in .sdk/; publication details live in the
|
|
182
|
-
# model (.sdk/model/target/<target>.
|
|
182
|
+
# model (.sdk/model/target/<target>.aon, \`publish\` section).
|
|
183
183
|
#
|
|
184
184
|
# Every port gets a git release tag <target>/vX.Y.Z. Ports with an ACTIVE
|
|
185
185
|
# registry also publish a package there. Credentials are injected at exec
|
|
@@ -218,7 +218,7 @@ TARGETS := ${targets.map((t: any) => t.name).join(' ')}
|
|
|
218
218
|
deploy:
|
|
219
219
|
\t@echo "Deployment is per-target — pick one (each upload is irreversible):"
|
|
220
220
|
\t@echo " make deploy-<target> targets: $(TARGETS)"
|
|
221
|
-
\t@echo "Registry state is set in the model (.sdk/model/target/<t>.
|
|
221
|
+
\t@echo "Registry state is set in the model (.sdk/model/target/<t>.aon):"
|
|
222
222
|
${targets.map((t: any) => {
|
|
223
223
|
const reg = registryOf(t)
|
|
224
224
|
const state = reg ? `${reg.name} ${regIsActive(reg) ? 'ACTIVE' : 'publish pending (deploy = git tag only)'}` : 'tag-only'
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
// WHERE A KIND'S DEFINITION FILES LIVE.
|
|
2
2
|
//
|
|
3
|
-
// `model/<kind>/<name>.
|
|
3
|
+
// `model/<kind>/<name>.aon`, with `model/<kind>/<kind>-index.aon` as the
|
|
4
4
|
// include list beside them. One line of path-building — and it was written out
|
|
5
5
|
// longhand in three places (the resolver, the feature catalogue, doctor), each
|
|
6
6
|
// with its own idea of which files in that directory count.
|
|
@@ -21,7 +21,7 @@ import { isJunk } from './junk'
|
|
|
21
21
|
|
|
22
22
|
// The definition file for one item.
|
|
23
23
|
function definitionPath(sdkfolder: string, kind: string, name: string): string {
|
|
24
|
-
return Path.join(sdkfolder, 'model', kind, name + '.
|
|
24
|
+
return Path.join(sdkfolder, 'model', kind, name + '.aon')
|
|
25
25
|
}
|
|
26
26
|
|
|
27
27
|
|
|
@@ -33,7 +33,7 @@ function definitionFolder(sdkfolder: string, kind: string): string {
|
|
|
33
33
|
|
|
34
34
|
// The include list beside them.
|
|
35
35
|
function indexName(kind: string): string {
|
|
36
|
-
return kind + '-index.
|
|
36
|
+
return kind + '-index.aon'
|
|
37
37
|
}
|
|
38
38
|
|
|
39
39
|
|
|
@@ -63,13 +63,13 @@ function definitionNames(fs: any, sdkfolder: string, kind: string): string[] {
|
|
|
63
63
|
return []
|
|
64
64
|
}
|
|
65
65
|
|
|
66
|
-
// The `.
|
|
67
|
-
// `.#target.
|
|
66
|
+
// The `.aon` suffix is not enough on its own: an emacs lock link is named
|
|
67
|
+
// `.#target.aon` and a merge leaves `target.aon.orig`, so an editor open
|
|
68
68
|
// in the wrong window invents an item called `.#target`, which then fails to
|
|
69
69
|
// resolve everywhere it is named. See helpers/junk.
|
|
70
70
|
return entries
|
|
71
|
-
.filter((n: string) => n.endsWith('.
|
|
72
|
-
.map((n: string) => n.replace(/\.
|
|
71
|
+
.filter((n: string) => n.endsWith('.aon') && index !== n && !isJunk(n))
|
|
72
|
+
.map((n: string) => n.replace(/\.aon$/, ''))
|
|
73
73
|
.sort()
|
|
74
74
|
}
|
|
75
75
|
|
|
@@ -27,7 +27,7 @@
|
|
|
27
27
|
//
|
|
28
28
|
// The mapping is deliberately conservative. An entry only counts as feature
|
|
29
29
|
// source when its derived name is one the generator can actually supply
|
|
30
|
-
// (`availableFeatures`, read from `model/feature/*.
|
|
30
|
+
// (`availableFeatures`, read from `model/feature/*.aon`). Everything else
|
|
31
31
|
// inside a feature directory — `feature_options.go`, `FeatureOptions.cs`,
|
|
32
32
|
// `mod.rs`, `support.rs`, `options.hpp`, `__init__.py`, `README.md`, and the
|
|
33
33
|
// `harness.ts` under `test/feature/` — derives a name no feature has, so it
|
|
@@ -103,7 +103,7 @@ function featureOf(entry: string, folder: boolean): string {
|
|
|
103
103
|
|
|
104
104
|
|
|
105
105
|
// Feature names this generator can supply, read from the scaffold's
|
|
106
|
-
// `model/feature/*.
|
|
106
|
+
// `model/feature/*.aon`. This is the authoritative catalogue: a name not in
|
|
107
107
|
// it is not a feature, so nothing outside it is ever excluded.
|
|
108
108
|
//
|
|
109
109
|
// LOWERCASED, unlike `definitionNames`, because these are matched against
|
package/src/helpers/manifest.ts
CHANGED
|
@@ -305,7 +305,7 @@ function validateManifest(
|
|
|
305
305
|
// the directory listing; if this loop asked the filesystem instead
|
|
306
306
|
// (`existsSync`/`statSync`), the two would disagree on a case-insensitive
|
|
307
307
|
// filesystem — APFS and NTFS by default, which is most package authors'
|
|
308
|
-
// machines. A manifest claiming `IoTGo` beside a `model/target/iotgo.
|
|
308
|
+
// machines. A manifest claiming `IoTGo` beside a `model/target/iotgo.aon`
|
|
309
309
|
// then validated CLEAN for the author and failed for every Linux consumer,
|
|
310
310
|
// which is precisely the "validated package that cannot install" this
|
|
311
311
|
// function exists to prevent. It also makes the duplicate check above
|
|
@@ -337,7 +337,7 @@ function validateManifest(
|
|
|
337
337
|
found.push({
|
|
338
338
|
level: 'warn', point: 'manifest-item-unclaimed', file, kind, name,
|
|
339
339
|
note: file + ': model/' + kind + '/' + name +
|
|
340
|
-
'.
|
|
340
|
+
'.aon is in the package but not listed in `provides.' + kind +
|
|
341
341
|
'` — nothing will install it'
|
|
342
342
|
})
|
|
343
343
|
}
|
|
@@ -377,7 +377,7 @@ function missingPaths(
|
|
|
377
377
|
// The definition, by EXACT NAME from the directory listing — see the note
|
|
378
378
|
// at the call site about the two directions needing one oracle.
|
|
379
379
|
if (!defined.has(name)) {
|
|
380
|
-
missing.push('model/' + kind + '/' + name + '.
|
|
380
|
+
missing.push('model/' + kind + '/' + name + '.aon')
|
|
381
381
|
}
|
|
382
382
|
|
|
383
383
|
for (const tree of (def.trees ?? []).filter((t) => t.required)) {
|
|
@@ -176,7 +176,7 @@ function goVersion(model: any, target: string, fallback?: string): string {
|
|
|
176
176
|
//
|
|
177
177
|
// This was the last of the four things the slug derives that had no override,
|
|
178
178
|
// and the only one that came out wrong — see the identity note at the top of
|
|
179
|
-
// model/sdkgen.
|
|
179
|
+
// model/sdkgen.aon.
|
|
180
180
|
function goPackageIdent(model: any, target: string): string {
|
|
181
181
|
const declared = model?.main?.[KIT]?.target?.[target]?.module?.package
|
|
182
182
|
if (null != declared && '' !== declared) {
|
package/src/helpers/shipped.ts
CHANGED
|
@@ -21,9 +21,9 @@ function packageRoot(): string {
|
|
|
21
21
|
}
|
|
22
22
|
|
|
23
23
|
|
|
24
|
-
// The base model schema — `@voxgig/sdkgen/model/sdkgen.
|
|
24
|
+
// The base model schema — `@voxgig/sdkgen/model/sdkgen.aon`.
|
|
25
25
|
function schemaFile(): string {
|
|
26
|
-
return Path.join(packageRoot(), 'model', 'sdkgen.
|
|
26
|
+
return Path.join(packageRoot(), 'model', 'sdkgen.aon')
|
|
27
27
|
}
|
|
28
28
|
|
|
29
29
|
|
package/src/sdkgen.ts
CHANGED
|
@@ -488,7 +488,7 @@ function SdkGen(opts: SdkGenOptions) {
|
|
|
488
488
|
|
|
489
489
|
|
|
490
490
|
function resolveModel(wanted: boolean) {
|
|
491
|
-
const path = './model/sdk.
|
|
491
|
+
const path = './model/sdk.aon'
|
|
492
492
|
const errs: any[] = []
|
|
493
493
|
|
|
494
494
|
// A verb that does not act on a project (see `needsModel`) is run where
|
|
@@ -642,7 +642,7 @@ SdkGen.makeBuild = async function(opts: SdkGenOptions) {
|
|
|
642
642
|
root: opts.root,
|
|
643
643
|
def: opts.def || 'no-def',
|
|
644
644
|
kind: 'openapi-3',
|
|
645
|
-
model: opts.model ? (opts.model.folder + '/api.
|
|
645
|
+
model: opts.model ? (opts.model.folder + '/api.aon') : 'no-model',
|
|
646
646
|
meta: opts.meta || {},
|
|
647
647
|
}
|
|
648
648
|
|