@voxgig/sdkgen 1.0.1 → 1.2.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/package.json +2 -2
- package/project/.sdk/src/cmp/go/TestEntity_go.ts +2 -13
- package/project/.sdk/src/cmp/lua/TestEntity_lua.ts +2 -11
- package/project/.sdk/src/cmp/php/TestEntity_php.ts +2 -11
- package/project/.sdk/src/cmp/py/TestEntity_py.ts +2 -11
- package/project/.sdk/src/cmp/rb/TestEntity_rb.ts +2 -11
- package/project/.sdk/src/cmp/ts/TestEntity_ts.ts +5 -9
- package/project/.sdk/tm/go/feature/test_feature.go +9 -5
- package/project/.sdk/tm/lua/feature/test_feature.lua +9 -5
- package/project/.sdk/tm/php/feature/TestFeature.php +9 -3
- package/project/.sdk/tm/py/feature/test_feature.py +8 -4
- package/project/.sdk/tm/rb/feature/test_feature.rb +7 -5
- package/project/.sdk/tm/ts/src/feature/test/TestFeature.ts +4 -5
package/bin/voxgig-sdkgen
CHANGED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@voxgig/sdkgen",
|
|
3
|
-
"version": "1.0
|
|
3
|
+
"version": "1.2.0",
|
|
4
4
|
"main": "dist/sdkgen.js",
|
|
5
5
|
"type": "commonjs",
|
|
6
6
|
"types": "dist/sdkgen.d.ts",
|
|
@@ -41,7 +41,7 @@
|
|
|
41
41
|
],
|
|
42
42
|
"devDependencies": {
|
|
43
43
|
"@types/js-yaml": "4.0.9",
|
|
44
|
-
"@types/node": "25.
|
|
44
|
+
"@types/node": "25.8.0",
|
|
45
45
|
"json-schema-to-ts": "3.1.1",
|
|
46
46
|
"memfs": "4.57.2",
|
|
47
47
|
"typescript": "6.0.3"
|
|
@@ -593,16 +593,14 @@ const generateRemove: OpGen = (ctx, step, index) => {
|
|
|
593
593
|
// otherwise reuse the `err` from a prior op step.
|
|
594
594
|
const errOp = needsEnt ? ':=' : '='
|
|
595
595
|
|
|
596
|
-
const hasEntIdR = null != entity.id
|
|
597
|
-
|
|
598
596
|
Content(` // REMOVE
|
|
599
597
|
`)
|
|
600
598
|
if (needsEnt) {
|
|
601
599
|
Content(` ${entvar} := client.${entity.Name}(nil)
|
|
602
600
|
`)
|
|
603
601
|
}
|
|
604
|
-
|
|
605
|
-
|
|
602
|
+
// Always match the prior-created entity by id to avoid mock-order flakes.
|
|
603
|
+
Content(` ${matchvar} := map[string]any{
|
|
606
604
|
"id": ${srcdatavar}["id"],
|
|
607
605
|
}
|
|
608
606
|
_, err ${errOp} ${entvar}.Remove(${matchvar}, nil)
|
|
@@ -610,15 +608,6 @@ const generateRemove: OpGen = (ctx, step, index) => {
|
|
|
610
608
|
t.Fatalf("remove failed: %v", err)
|
|
611
609
|
}
|
|
612
610
|
`)
|
|
613
|
-
}
|
|
614
|
-
else {
|
|
615
|
-
Content(` ${matchvar} := map[string]any{}
|
|
616
|
-
_, err ${errOp} ${entvar}.Remove(${matchvar}, nil)
|
|
617
|
-
if err != nil {
|
|
618
|
-
t.Fatalf("remove failed: %v", err)
|
|
619
|
-
}
|
|
620
|
-
`)
|
|
621
|
-
}
|
|
622
611
|
}
|
|
623
612
|
|
|
624
613
|
|
|
@@ -502,28 +502,19 @@ const generateRemove: OpGen = (ctx, step, index) => {
|
|
|
502
502
|
const needsEnt = !priorSteps.some((s: any) =>
|
|
503
503
|
['create', 'list', 'load', 'update', 'remove'].includes(s.op))
|
|
504
504
|
|
|
505
|
-
const hasEntIdR = null != entity.id
|
|
506
|
-
|
|
507
505
|
Content(` -- REMOVE
|
|
508
506
|
`)
|
|
509
507
|
if (needsEnt) {
|
|
510
508
|
Content(` local ${entvar} = client:${entity.Name}(nil)
|
|
511
509
|
`)
|
|
512
510
|
}
|
|
513
|
-
|
|
514
|
-
|
|
511
|
+
// Always match the prior-created entity by id to avoid mock-order flakes.
|
|
512
|
+
Content(` local ${matchvar} = {
|
|
515
513
|
id = ${srcdatavar}["id"],
|
|
516
514
|
}
|
|
517
515
|
local _, err = ${entvar}:remove(${matchvar}, nil)
|
|
518
516
|
assert.is_nil(err)
|
|
519
517
|
`)
|
|
520
|
-
}
|
|
521
|
-
else {
|
|
522
|
-
Content(` local ${matchvar} = {}
|
|
523
|
-
local _, err = ${entvar}:remove(${matchvar}, nil)
|
|
524
|
-
assert.is_nil(err)
|
|
525
|
-
`)
|
|
526
|
-
}
|
|
527
518
|
}
|
|
528
519
|
|
|
529
520
|
|
|
@@ -507,28 +507,19 @@ const generateRemove: OpGen = (ctx, step, index) => {
|
|
|
507
507
|
const needsEnt = !priorSteps.some((s: any) =>
|
|
508
508
|
['create', 'list', 'load', 'update', 'remove'].includes(s.op))
|
|
509
509
|
|
|
510
|
-
const hasEntIdR = null != entity.id
|
|
511
|
-
|
|
512
510
|
Content(` // REMOVE
|
|
513
511
|
`)
|
|
514
512
|
if (needsEnt) {
|
|
515
513
|
Content(` $${entvar} = $client->${accessor}(null);
|
|
516
514
|
`)
|
|
517
515
|
}
|
|
518
|
-
|
|
519
|
-
|
|
516
|
+
// Always match the prior-created entity by id to avoid mock-order flakes.
|
|
517
|
+
Content(` $${matchvar} = [
|
|
520
518
|
"id" => $${srcdatavar}["id"],
|
|
521
519
|
];
|
|
522
520
|
[$_, $err] = $${entvar}->remove($${matchvar}, null);
|
|
523
521
|
$this->assertNull($err);
|
|
524
522
|
`)
|
|
525
|
-
}
|
|
526
|
-
else {
|
|
527
|
-
Content(` $${matchvar} = [];
|
|
528
|
-
[$_, $err] = $${entvar}->remove($${matchvar}, null);
|
|
529
|
-
$this->assertNull($err);
|
|
530
|
-
`)
|
|
531
|
-
}
|
|
532
523
|
}
|
|
533
524
|
|
|
534
525
|
|
|
@@ -500,28 +500,19 @@ const generateRemove: OpGen = (ctx, step, index) => {
|
|
|
500
500
|
const needsEnt = !priorSteps.some((s: any) =>
|
|
501
501
|
['create', 'list', 'load', 'update', 'remove'].includes(s.op))
|
|
502
502
|
|
|
503
|
-
const hasEntIdR = null != entity.id
|
|
504
|
-
|
|
505
503
|
Content(` # REMOVE
|
|
506
504
|
`)
|
|
507
505
|
if (needsEnt) {
|
|
508
506
|
Content(` ${entvar} = client.${entity.Name}(None)
|
|
509
507
|
`)
|
|
510
508
|
}
|
|
511
|
-
|
|
512
|
-
|
|
509
|
+
// Always match the prior-created entity by id to avoid mock-order flakes.
|
|
510
|
+
Content(` ${matchvar} = {
|
|
513
511
|
"id": ${srcdatavar}["id"],
|
|
514
512
|
}
|
|
515
513
|
_, err = ${entvar}.remove(${matchvar}, None)
|
|
516
514
|
assert err is None
|
|
517
515
|
`)
|
|
518
|
-
}
|
|
519
|
-
else {
|
|
520
|
-
Content(` ${matchvar} = {}
|
|
521
|
-
_, err = ${entvar}.remove(${matchvar}, None)
|
|
522
|
-
assert err is None
|
|
523
|
-
`)
|
|
524
|
-
}
|
|
525
516
|
}
|
|
526
517
|
|
|
527
518
|
|
|
@@ -493,28 +493,19 @@ const generateRemove: OpGen = (ctx, step, index) => {
|
|
|
493
493
|
const needsEnt = !priorSteps.some((s: any) =>
|
|
494
494
|
['create', 'list', 'load', 'update', 'remove'].includes(s.op))
|
|
495
495
|
|
|
496
|
-
const hasEntIdR = null != entity.id
|
|
497
|
-
|
|
498
496
|
Content(` # REMOVE
|
|
499
497
|
`)
|
|
500
498
|
if (needsEnt) {
|
|
501
499
|
Content(` ${entvar} = client.${entity.Name}(nil)
|
|
502
500
|
`)
|
|
503
501
|
}
|
|
504
|
-
|
|
505
|
-
|
|
502
|
+
// Always match the prior-created entity by id to avoid mock-order flakes.
|
|
503
|
+
Content(` ${matchvar} = {
|
|
506
504
|
"id" => ${srcdatavar}["id"],
|
|
507
505
|
}
|
|
508
506
|
_, err = ${entvar}.remove(${matchvar}, nil)
|
|
509
507
|
assert_nil err
|
|
510
508
|
`)
|
|
511
|
-
}
|
|
512
|
-
else {
|
|
513
|
-
Content(` ${matchvar} = {}
|
|
514
|
-
_, err = ${entvar}.remove(${matchvar}, nil)
|
|
515
|
-
assert_nil err
|
|
516
|
-
`)
|
|
517
|
-
}
|
|
518
509
|
}
|
|
519
510
|
|
|
520
511
|
|
|
@@ -516,8 +516,6 @@ const generateRemove: OpGen = (ctx, step, index) => {
|
|
|
516
516
|
const needsEnt = !priorSteps.some(s =>
|
|
517
517
|
['create', 'list', 'load', 'update', 'remove'].includes(s.op))
|
|
518
518
|
|
|
519
|
-
const hasEntIdR = null != entity.id
|
|
520
|
-
|
|
521
519
|
Content(`
|
|
522
520
|
// REMOVE
|
|
523
521
|
`)
|
|
@@ -525,13 +523,11 @@ const generateRemove: OpGen = (ctx, step, index) => {
|
|
|
525
523
|
Content(` const ${entvar} = client.${nom(entity, 'Name')}()
|
|
526
524
|
`)
|
|
527
525
|
}
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
}
|
|
534
|
-
Content(` await ${entvar}.remove(${matchvar})
|
|
526
|
+
// Always match the prior-created entity by id. The mock test feature
|
|
527
|
+
// removes the first match in entmap, so without a specific id the
|
|
528
|
+
// result depends on hash-sort order and flakes (see cheapshark).
|
|
529
|
+
Content(` const ${matchvar}: any = { id: ${srcdatavar}.id }
|
|
530
|
+
await ${entvar}.remove(${matchvar})
|
|
535
531
|
`)
|
|
536
532
|
}
|
|
537
533
|
|
|
@@ -114,8 +114,10 @@ func (f *TestFeature) Init(ctx *core.Context, options map[string]any) {
|
|
|
114
114
|
// Match the existing entity by id only (or its alias). Reqdata
|
|
115
115
|
// also contains the new field values, which would otherwise
|
|
116
116
|
// cause Select to filter out the entity we want to update.
|
|
117
|
-
//
|
|
118
|
-
//
|
|
117
|
+
// When reqdata has no id, fall back to the id the entity
|
|
118
|
+
// client carries from a prior create/load (in ctx.Match /
|
|
119
|
+
// ctx.Data), mirroring the TS mock where param(ctx,'id')
|
|
120
|
+
// resolves from accumulated state.
|
|
119
121
|
updateMatch := map[string]any{}
|
|
120
122
|
if ctx.Reqdata != nil {
|
|
121
123
|
if v, has := ctx.Reqdata["id"]; has {
|
|
@@ -131,6 +133,9 @@ func (f *TestFeature) Init(ctx *core.Context, options map[string]any) {
|
|
|
131
133
|
}
|
|
132
134
|
}
|
|
133
135
|
}
|
|
136
|
+
if len(updateMatch) == 0 {
|
|
137
|
+
updateMatch = resolveMatch(map[string]any{})
|
|
138
|
+
}
|
|
134
139
|
args := self.buildArgs(ctx, op, updateMatch)
|
|
135
140
|
found := vs.Select(entmap, args)
|
|
136
141
|
ent := vs.GetElem(found, 0)
|
|
@@ -160,9 +165,8 @@ func (f *TestFeature) Init(ctx *core.Context, options map[string]any) {
|
|
|
160
165
|
args := self.buildArgs(ctx, op, resolveMatch(ctx.Reqmatch))
|
|
161
166
|
found := vs.Select(entmap, args)
|
|
162
167
|
ent := vs.GetElem(found, 0)
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
}
|
|
168
|
+
// Remove only the first matched entity. If nothing matches,
|
|
169
|
+
// succeed as a no-op rather than erroring.
|
|
166
170
|
if entm, ok := ent.(map[string]any); ok {
|
|
167
171
|
id := vs.GetProp(entm, "id")
|
|
168
172
|
vs.DelProp(entmap, id)
|
|
@@ -109,8 +109,10 @@ function TestFeature:init(ctx, options)
|
|
|
109
109
|
elseif op.name == "update" then
|
|
110
110
|
-- Match the existing entity by id only (or its alias). reqdata also
|
|
111
111
|
-- contains the new field values, which would otherwise cause select
|
|
112
|
-
-- to filter out the entity we want to update.
|
|
113
|
-
--
|
|
112
|
+
-- to filter out the entity we want to update. When reqdata has no id,
|
|
113
|
+
-- fall back to the id the entity client carries from a prior
|
|
114
|
+
-- create/load (in fctx.match / fctx.data), mirroring the TS mock
|
|
115
|
+
-- where param(ctx,'id') resolves from accumulated state.
|
|
114
116
|
local update_match = {}
|
|
115
117
|
if type(fctx.reqdata) == "table" then
|
|
116
118
|
if fctx.reqdata["id"] ~= nil then update_match["id"] = fctx.reqdata["id"] end
|
|
@@ -121,6 +123,9 @@ function TestFeature:init(ctx, options)
|
|
|
121
123
|
end
|
|
122
124
|
end
|
|
123
125
|
end
|
|
126
|
+
if next(update_match) == nil then
|
|
127
|
+
update_match = resolve_match({})
|
|
128
|
+
end
|
|
124
129
|
local args = test_self:build_args(fctx, op, update_match)
|
|
125
130
|
local found = vs.select(entmap, args)
|
|
126
131
|
local ent = vs.getelem(found, 0)
|
|
@@ -148,9 +153,8 @@ function TestFeature:init(ctx, options)
|
|
|
148
153
|
local args = test_self:build_args(fctx, op, resolve_match(fctx.reqmatch))
|
|
149
154
|
local found = vs.select(entmap, args)
|
|
150
155
|
local ent = vs.getelem(found, 0)
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
end
|
|
156
|
+
-- Remove only the first matched entity. If nothing matches,
|
|
157
|
+
-- succeed as a no-op rather than erroring.
|
|
154
158
|
if type(ent) == "table" then
|
|
155
159
|
local id = vs.getprop(ent, "id")
|
|
156
160
|
vs.delprop(entmap, id)
|
|
@@ -162,6 +162,10 @@ class ProjectNameTestFeature extends ProjectNameBaseFeature
|
|
|
162
162
|
// Match the existing entity by id only (or its alias). reqdata
|
|
163
163
|
// also contains the new field values, which would otherwise
|
|
164
164
|
// cause find_first to filter out the entity we want to update.
|
|
165
|
+
// When reqdata has no id, fall back to the id the entity
|
|
166
|
+
// client carries from a prior create/load (in $fctx->match /
|
|
167
|
+
// $fctx->data), mirroring the TS mock where param(ctx,'id')
|
|
168
|
+
// resolves from accumulated state.
|
|
165
169
|
$update_match = [];
|
|
166
170
|
if (is_array($fctx->reqdata)) {
|
|
167
171
|
if (array_key_exists('id', $fctx->reqdata)) {
|
|
@@ -172,6 +176,9 @@ class ProjectNameTestFeature extends ProjectNameBaseFeature
|
|
|
172
176
|
$update_match[$id_alias] = $fctx->reqdata[$id_alias];
|
|
173
177
|
}
|
|
174
178
|
}
|
|
179
|
+
if (empty($update_match)) {
|
|
180
|
+
$update_match = $resolve_match([]);
|
|
181
|
+
}
|
|
175
182
|
$ent = $find_first($entmap, $update_match, $alias);
|
|
176
183
|
if ($ent === null) {
|
|
177
184
|
return $respond(404, null, ['statusText' => 'Not found']);
|
|
@@ -192,9 +199,8 @@ class ProjectNameTestFeature extends ProjectNameBaseFeature
|
|
|
192
199
|
|
|
193
200
|
} elseif ($op->name === 'remove') {
|
|
194
201
|
$ent = $find_first($entmap, $resolve_match($fctx->reqmatch), $alias);
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
}
|
|
202
|
+
// Remove only the first matched entity. If nothing matches,
|
|
203
|
+
// succeed as a no-op rather than erroring.
|
|
198
204
|
$id = is_array($ent) ? ($ent['id'] ?? null) : null;
|
|
199
205
|
if ($id !== null) {
|
|
200
206
|
unset($entmap[$id]);
|
|
@@ -90,8 +90,10 @@ class ProjectNameTestFeature(ProjectNameBaseFeature):
|
|
|
90
90
|
# Match the existing entity by id only (or its alias). reqdata
|
|
91
91
|
# also contains the new field values, which would otherwise
|
|
92
92
|
# cause select to filter out the entity we want to update.
|
|
93
|
-
#
|
|
94
|
-
#
|
|
93
|
+
# When reqdata has no id, fall back to the id the entity
|
|
94
|
+
# client carries from a prior create/load (in fctx.match /
|
|
95
|
+
# fctx.data), mirroring the TS mock where param(ctx,'id')
|
|
96
|
+
# resolves from accumulated state.
|
|
95
97
|
update_match = {}
|
|
96
98
|
if isinstance(fctx.reqdata, dict):
|
|
97
99
|
if "id" in fctx.reqdata:
|
|
@@ -101,6 +103,8 @@ class ProjectNameTestFeature(ProjectNameBaseFeature):
|
|
|
101
103
|
alias_id = vs.getprop(alias_map, "id")
|
|
102
104
|
if alias_id is not None and alias_id in fctx.reqdata:
|
|
103
105
|
update_match[alias_id] = fctx.reqdata[alias_id]
|
|
106
|
+
if not update_match:
|
|
107
|
+
update_match = _resolve_match({})
|
|
104
108
|
args = test_self.build_args(fctx, op, update_match)
|
|
105
109
|
found = vs.select(entmap, args)
|
|
106
110
|
ent = vs.getelem(found, 0)
|
|
@@ -124,8 +128,8 @@ class ProjectNameTestFeature(ProjectNameBaseFeature):
|
|
|
124
128
|
args = test_self.build_args(fctx, op, _resolve_match(fctx.reqmatch))
|
|
125
129
|
found = vs.select(entmap, args)
|
|
126
130
|
ent = vs.getelem(found, 0)
|
|
127
|
-
|
|
128
|
-
|
|
131
|
+
# Remove only the first matched entity. If nothing matches,
|
|
132
|
+
# succeed as a no-op rather than erroring.
|
|
129
133
|
if isinstance(ent, dict):
|
|
130
134
|
eid = vs.getprop(ent, "id")
|
|
131
135
|
vs.delprop(entmap, eid)
|
|
@@ -84,10 +84,10 @@ class ProjectNameTestFeature < ProjectNameBaseFeature
|
|
|
84
84
|
elsif op.name == "update"
|
|
85
85
|
# Match the existing entity by id only (or its alias). reqdata also
|
|
86
86
|
# contains the new field values, which would otherwise cause select
|
|
87
|
-
# to filter out the entity we want to update.
|
|
88
|
-
#
|
|
89
|
-
#
|
|
90
|
-
#
|
|
87
|
+
# to filter out the entity we want to update. When reqdata has no id,
|
|
88
|
+
# fall back to the id the entity client carries from a prior
|
|
89
|
+
# create/load (in fctx.match / fctx.data), mirroring the TS mock
|
|
90
|
+
# where param(ctx,'id') resolves from accumulated state.
|
|
91
91
|
update_match = {}
|
|
92
92
|
if fctx.reqdata.is_a?(Hash)
|
|
93
93
|
update_match["id"] = fctx.reqdata["id"] if fctx.reqdata.key?("id")
|
|
@@ -98,6 +98,7 @@ class ProjectNameTestFeature < ProjectNameBaseFeature
|
|
|
98
98
|
end
|
|
99
99
|
end
|
|
100
100
|
end
|
|
101
|
+
update_match = resolve_match.call({}) if update_match.empty?
|
|
101
102
|
args = test_self.build_args(fctx, op, update_match)
|
|
102
103
|
found = VoxgigStruct.select(entmap, args)
|
|
103
104
|
ent = VoxgigStruct.getelem(found, 0)
|
|
@@ -116,7 +117,8 @@ class ProjectNameTestFeature < ProjectNameBaseFeature
|
|
|
116
117
|
args = test_self.build_args(fctx, op, resolve_match.call(fctx.reqmatch))
|
|
117
118
|
found = VoxgigStruct.select(entmap, args)
|
|
118
119
|
ent = VoxgigStruct.getelem(found, 0)
|
|
119
|
-
|
|
120
|
+
# Remove only the first matched entity. If nothing matches,
|
|
121
|
+
# succeed as a no-op rather than erroring.
|
|
120
122
|
if ent.is_a?(Hash)
|
|
121
123
|
id = VoxgigStruct.getprop(ent, "id")
|
|
122
124
|
VoxgigStruct.delprop(entmap, id)
|
|
@@ -124,13 +124,12 @@ class TestFeature extends BaseFeature {
|
|
|
124
124
|
const args = self.buildArgs(ctx, op, ctx.reqmatch)
|
|
125
125
|
const found = select(entmap, args)
|
|
126
126
|
const ent = getelem(found, 0)
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
else {
|
|
127
|
+
// Remove only the first matched entity. If nothing matches,
|
|
128
|
+
// succeed as a no-op rather than erroring.
|
|
129
|
+
if (null != ent) {
|
|
131
130
|
delprop(entmap, getprop(ent, 'id'))
|
|
132
|
-
return respond(200)
|
|
133
131
|
}
|
|
132
|
+
return respond(200)
|
|
134
133
|
}
|
|
135
134
|
else if ('create' === op.name) {
|
|
136
135
|
const args = self.buildArgs(ctx, op, ctx.reqdata)
|