@voxgig/sdkgen 3.4.1 → 3.4.2

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.
Files changed (58) hide show
  1. package/package.json +1 -1
  2. package/project/.sdk/src/cmp/c/Config_c.ts +1 -1
  3. package/project/.sdk/src/cmp/c/utility_c.ts +57 -6
  4. package/project/.sdk/src/cmp/clojure/Config_clojure.ts +1 -1
  5. package/project/.sdk/src/cmp/clojure/utility_clojure.ts +57 -6
  6. package/project/.sdk/src/cmp/cpp/Config_cpp.ts +1 -1
  7. package/project/.sdk/src/cmp/cpp/utility_cpp.ts +57 -6
  8. package/project/.sdk/src/cmp/csharp/Config_csharp.ts +1 -1
  9. package/project/.sdk/src/cmp/csharp/utility_csharp.ts +57 -6
  10. package/project/.sdk/src/cmp/dart/Config_dart.ts +1 -1
  11. package/project/.sdk/src/cmp/dart/utility_dart.ts +57 -6
  12. package/project/.sdk/src/cmp/elixir/Config_elixir.ts +1 -1
  13. package/project/.sdk/src/cmp/elixir/utility_elixir.ts +57 -6
  14. package/project/.sdk/src/cmp/go/Config_go.ts +1 -1
  15. package/project/.sdk/src/cmp/go/utility_go.ts +57 -6
  16. package/project/.sdk/src/cmp/haskell/Config_haskell.ts +1 -1
  17. package/project/.sdk/src/cmp/haskell/utility_haskell.ts +57 -6
  18. package/project/.sdk/src/cmp/java/Config_java.ts +1 -1
  19. package/project/.sdk/src/cmp/java/utility_java.ts +57 -6
  20. package/project/.sdk/src/cmp/js/Config_js.ts +1 -1
  21. package/project/.sdk/src/cmp/js/utility_js.ts +57 -6
  22. package/project/.sdk/src/cmp/kotlin/Config_kotlin.ts +1 -1
  23. package/project/.sdk/src/cmp/kotlin/utility_kotlin.ts +57 -6
  24. package/project/.sdk/src/cmp/lean/Config_lean.ts +1 -1
  25. package/project/.sdk/src/cmp/lean/utility_lean.ts +57 -6
  26. package/project/.sdk/src/cmp/lua/Config_lua.ts +1 -1
  27. package/project/.sdk/src/cmp/lua/utility_lua.ts +57 -6
  28. package/project/.sdk/src/cmp/ocaml/Config_ocaml.ts +1 -1
  29. package/project/.sdk/src/cmp/ocaml/utility_ocaml.ts +57 -6
  30. package/project/.sdk/src/cmp/perl/Config_perl.ts +1 -1
  31. package/project/.sdk/src/cmp/perl/utility_perl.ts +57 -6
  32. package/project/.sdk/src/cmp/php/Config_php.ts +1 -1
  33. package/project/.sdk/src/cmp/php/fragment/Entity.fragment.php +22 -0
  34. package/project/.sdk/src/cmp/php/utility_php.ts +57 -6
  35. package/project/.sdk/src/cmp/py/Config_py.ts +1 -1
  36. package/project/.sdk/src/cmp/py/utility_py.ts +57 -6
  37. package/project/.sdk/src/cmp/rb/Config_rb.ts +1 -1
  38. package/project/.sdk/src/cmp/rb/utility_rb.ts +57 -6
  39. package/project/.sdk/src/cmp/rust/Config_rust.ts +1 -1
  40. package/project/.sdk/src/cmp/rust/utility_rust.ts +57 -6
  41. package/project/.sdk/src/cmp/scala/Config_scala.ts +1 -1
  42. package/project/.sdk/src/cmp/scala/utility_scala.ts +57 -6
  43. package/project/.sdk/src/cmp/swift/Config_swift.ts +1 -1
  44. package/project/.sdk/src/cmp/swift/utility_swift.ts +57 -6
  45. package/project/.sdk/src/cmp/ts/Config_ts.ts +1 -1
  46. package/project/.sdk/src/cmp/ts/utility_ts.ts +57 -6
  47. package/project/.sdk/src/cmp/zig/Config_zig.ts +1 -1
  48. package/project/.sdk/src/cmp/zig/utility_zig.ts +57 -6
  49. package/project/.sdk/tm/c/core/point.c +2 -1
  50. package/project/.sdk/tm/csharp/core/Point.cs +3 -1
  51. package/project/.sdk/tm/dart/lib/Point.dart +2 -1
  52. package/project/.sdk/tm/java/core/Point.java +3 -1
  53. package/project/.sdk/tm/js/src/Point.js +3 -1
  54. package/project/.sdk/tm/kotlin/core/Point.kt +3 -1
  55. package/project/.sdk/tm/scala/core/Point.scala +2 -1
  56. package/project/.sdk/tm/swift/Sources/ProjectNameSDK/core/Point.swift +3 -1
  57. package/project/.sdk/tm/ts/src/Point.ts +3 -1
  58. package/project/.sdk/tm/zig/core/point.zig +2 -1
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@voxgig/sdkgen",
3
- "version": "3.4.1",
3
+ "version": "3.4.2",
4
4
  "main": "dist/sdkgen.js",
5
5
  "type": "commonjs",
6
6
  "engines": {
@@ -66,7 +66,7 @@ const Config = cmp(async function Config(props: any) {
66
66
  name: n.name,
67
67
  op: n.op,
68
68
  relations: n.relations,
69
- }), a), {})
69
+ }, true), a), {})
70
70
 
71
71
  const config = {
72
72
  main: { name: model.const.Name },
@@ -89,13 +89,64 @@ function formatCValue(val: any, indent: number = 0): string {
89
89
 
90
90
 
91
91
  // Deep-remove meta keys (`foo$`) from a model subtree (twin of go/rust clean).
92
- function clean(o: any) {
93
- return walk(clone(o), (k: any, v: any, p: any) => {
94
- if (null != k && k.endsWith('$')) {
95
- delete p[k]
92
+ // Emission-time normalisation of a model subtree (L0).
93
+ //
94
+ // Always drops jostraca's iteration metadata (`$`-suffixed keys: index$,
95
+ // key$, val$). With `dropDefaults`, also drops keys whose value IS the
96
+ // default the runtime already assumes when the key is absent, which is pure
97
+ // payload — see CONFIG_DEFAULT.
98
+ //
99
+ // Rebuilds the tree rather than mutating during a walk. The previous
100
+ // implementation walked a clone calling `delete p[k]`, but walk() assigns its
101
+ // callback's result back over the child (`setprop(out, ckey, walk(...))`), so
102
+ // the delete was undone on the way out and the helper silently did nothing.
103
+ // Returning `undefined` from the callback does not fix it either: setprop
104
+ // stores undefined rather than removing the key, which then emits as a null.
105
+ //
106
+ // `dropDefaults` is opt-in and must be passed ONLY for the entity subtree.
107
+ // `active` means something different in feature config, where absent reads as
108
+ // INACTIVE (see feature_init) — dropping `active: true` there would silently
109
+ // disable the feature.
110
+ // jostraca's iteration metadata, injected by each()/names() while it walks the
111
+ // model. Listed explicitly rather than matched by trailing-dollar suffix: a
112
+ // trailing dollar is not exclusive to jostraca -- Seneca uses entity$ as real
113
+ // data -- so a blanket suffix match can silently drop a legitimate API field.
114
+ const MODEL_META = ['index$', 'key$', 'val$']
115
+
116
+ // Keys whose value IS the default the runtime already assumes when the key is
117
+ // absent, so emitting them is pure payload.
118
+ const CONFIG_DEFAULT: Record<string, any> = {
119
+ active: true,
120
+ req: false,
121
+ reqd: false,
122
+ }
123
+
124
+ // Subtrees carrying user payload rather than schema. An active:true inside an
125
+ // OpenAPI example is DATA, not a default, so default-pruning stops at these
126
+ // keys and everything below them is passed through untouched.
127
+ const PAYLOAD_KEYS = ['default', 'example', 'examples']
128
+
129
+ function clean(o: any, dropDefaults?: boolean): any {
130
+ const prune = (node: any, defaults: boolean): any => {
131
+ if (Array.isArray(node)) {
132
+ return node.map((n: any) => prune(n, defaults))
96
133
  }
97
- return v
98
- })
134
+ if (null != node && 'object' === typeof node) {
135
+ const out: any = {}
136
+ for (const k of Object.keys(node)) {
137
+ if (MODEL_META.includes(k)) {
138
+ continue
139
+ }
140
+ if (defaults && k in CONFIG_DEFAULT && CONFIG_DEFAULT[k] === node[k]) {
141
+ continue
142
+ }
143
+ out[k] = prune(node[k], defaults && !PAYLOAD_KEYS.includes(k))
144
+ }
145
+ return out
146
+ }
147
+ return node
148
+ }
149
+ return prune(o, true === dropDefaults)
99
150
  }
100
151
 
101
152
 
@@ -68,7 +68,7 @@ const Config = cmp(async function Config(props: any) {
68
68
  name: n.name,
69
69
  op: n.op,
70
70
  relations: n.relations,
71
- }), a), {})
71
+ }, true), a), {})
72
72
 
73
73
  const config = {
74
74
  main: { name: model.const.Name },
@@ -64,13 +64,64 @@ function cljString(s: string): string {
64
64
 
65
65
 
66
66
  // Remove `$`-suffixed model annotation keys (mirrors utility_rb.clean).
67
- function clean(o: any) {
68
- return walk(clone(o), (k: any, v: any, p: any) => {
69
- if (null != k && k.endsWith('$')) {
70
- delete p[k]
67
+ // Emission-time normalisation of a model subtree (L0).
68
+ //
69
+ // Always drops jostraca's iteration metadata (`$`-suffixed keys: index$,
70
+ // key$, val$). With `dropDefaults`, also drops keys whose value IS the
71
+ // default the runtime already assumes when the key is absent, which is pure
72
+ // payload — see CONFIG_DEFAULT.
73
+ //
74
+ // Rebuilds the tree rather than mutating during a walk. The previous
75
+ // implementation walked a clone calling `delete p[k]`, but walk() assigns its
76
+ // callback's result back over the child (`setprop(out, ckey, walk(...))`), so
77
+ // the delete was undone on the way out and the helper silently did nothing.
78
+ // Returning `undefined` from the callback does not fix it either: setprop
79
+ // stores undefined rather than removing the key, which then emits as a null.
80
+ //
81
+ // `dropDefaults` is opt-in and must be passed ONLY for the entity subtree.
82
+ // `active` means something different in feature config, where absent reads as
83
+ // INACTIVE (see feature_init) — dropping `active: true` there would silently
84
+ // disable the feature.
85
+ // jostraca's iteration metadata, injected by each()/names() while it walks the
86
+ // model. Listed explicitly rather than matched by trailing-dollar suffix: a
87
+ // trailing dollar is not exclusive to jostraca -- Seneca uses entity$ as real
88
+ // data -- so a blanket suffix match can silently drop a legitimate API field.
89
+ const MODEL_META = ['index$', 'key$', 'val$']
90
+
91
+ // Keys whose value IS the default the runtime already assumes when the key is
92
+ // absent, so emitting them is pure payload.
93
+ const CONFIG_DEFAULT: Record<string, any> = {
94
+ active: true,
95
+ req: false,
96
+ reqd: false,
97
+ }
98
+
99
+ // Subtrees carrying user payload rather than schema. An active:true inside an
100
+ // OpenAPI example is DATA, not a default, so default-pruning stops at these
101
+ // keys and everything below them is passed through untouched.
102
+ const PAYLOAD_KEYS = ['default', 'example', 'examples']
103
+
104
+ function clean(o: any, dropDefaults?: boolean): any {
105
+ const prune = (node: any, defaults: boolean): any => {
106
+ if (Array.isArray(node)) {
107
+ return node.map((n: any) => prune(n, defaults))
108
+ }
109
+ if (null != node && 'object' === typeof node) {
110
+ const out: any = {}
111
+ for (const k of Object.keys(node)) {
112
+ if (MODEL_META.includes(k)) {
113
+ continue
114
+ }
115
+ if (defaults && k in CONFIG_DEFAULT && CONFIG_DEFAULT[k] === node[k]) {
116
+ continue
117
+ }
118
+ out[k] = prune(node[k], defaults && !PAYLOAD_KEYS.includes(k))
119
+ }
120
+ return out
71
121
  }
72
- return v
73
- })
122
+ return node
123
+ }
124
+ return prune(o, true === dropDefaults)
74
125
  }
75
126
 
76
127
 
@@ -68,7 +68,7 @@ const Config = cmp(async function Config(props: any) {
68
68
  name: n.name,
69
69
  op: n.op,
70
70
  relations: n.relations,
71
- }), a), {})
71
+ }, true), a), {})
72
72
 
73
73
  const config = {
74
74
  main: { name: model.const.Name },
@@ -30,13 +30,64 @@ function cppVarName(name: string): string {
30
30
 
31
31
 
32
32
  // Deep-remove meta keys (`foo$`) from a model subtree.
33
- function cleanModel(o: any) {
34
- return walk(clone(o), (k: any, v: any, p: any) => {
35
- if (null != k && k.endsWith('$')) {
36
- delete p[k]
33
+ // Emission-time normalisation of a model subtree (L0).
34
+ //
35
+ // Always drops jostraca's iteration metadata (`$`-suffixed keys: index$,
36
+ // key$, val$). With `dropDefaults`, also drops keys whose value IS the
37
+ // default the runtime already assumes when the key is absent, which is pure
38
+ // payload — see CONFIG_DEFAULT.
39
+ //
40
+ // Rebuilds the tree rather than mutating during a walk. The previous
41
+ // implementation walked a clone calling `delete p[k]`, but walk() assigns its
42
+ // callback's result back over the child (`setprop(out, ckey, walk(...))`), so
43
+ // the delete was undone on the way out and the helper silently did nothing.
44
+ // Returning `undefined` from the callback does not fix it either: setprop
45
+ // stores undefined rather than removing the key, which then emits as a null.
46
+ //
47
+ // `dropDefaults` is opt-in and must be passed ONLY for the entity subtree.
48
+ // `active` means something different in feature config, where absent reads as
49
+ // INACTIVE (see feature_init) — dropping `active: true` there would silently
50
+ // disable the feature.
51
+ // jostraca's iteration metadata, injected by each()/names() while it walks the
52
+ // model. Listed explicitly rather than matched by trailing-dollar suffix: a
53
+ // trailing dollar is not exclusive to jostraca -- Seneca uses entity$ as real
54
+ // data -- so a blanket suffix match can silently drop a legitimate API field.
55
+ const MODEL_META = ['index$', 'key$', 'val$']
56
+
57
+ // Keys whose value IS the default the runtime already assumes when the key is
58
+ // absent, so emitting them is pure payload.
59
+ const CONFIG_DEFAULT: Record<string, any> = {
60
+ active: true,
61
+ req: false,
62
+ reqd: false,
63
+ }
64
+
65
+ // Subtrees carrying user payload rather than schema. An active:true inside an
66
+ // OpenAPI example is DATA, not a default, so default-pruning stops at these
67
+ // keys and everything below them is passed through untouched.
68
+ const PAYLOAD_KEYS = ['default', 'example', 'examples']
69
+
70
+ function cleanModel(o: any, dropDefaults?: boolean): any {
71
+ const prune = (node: any, defaults: boolean): any => {
72
+ if (Array.isArray(node)) {
73
+ return node.map((n: any) => prune(n, defaults))
74
+ }
75
+ if (null != node && 'object' === typeof node) {
76
+ const out: any = {}
77
+ for (const k of Object.keys(node)) {
78
+ if (MODEL_META.includes(k)) {
79
+ continue
80
+ }
81
+ if (defaults && k in CONFIG_DEFAULT && CONFIG_DEFAULT[k] === node[k]) {
82
+ continue
83
+ }
84
+ out[k] = prune(node[k], defaults && !PAYLOAD_KEYS.includes(k))
85
+ }
86
+ return out
37
87
  }
38
- return v
39
- })
88
+ return node
89
+ }
90
+ return prune(o, true === dropDefaults)
40
91
  }
41
92
 
42
93
 
@@ -100,7 +100,7 @@ ${authBlock} ["headers"] = ${formatCsMap(headers, 4)},
100
100
  name: n.name,
101
101
  op: n.op,
102
102
  relations: n.relations,
103
- }), a), {}), 3)},
103
+ }, true), a), {}), 3)},
104
104
  };
105
105
  }
106
106
 
@@ -122,13 +122,64 @@ function formatCsValue(val: any, indent: number = 0): string {
122
122
  }
123
123
 
124
124
 
125
- function clean(o: any) {
126
- return walk(clone(o), (k: any, v: any, p: any) => {
127
- if (null != k && k.endsWith('$')) {
128
- delete p[k]
125
+ // Emission-time normalisation of a model subtree (L0).
126
+ //
127
+ // Always drops jostraca's iteration metadata (`$`-suffixed keys: index$,
128
+ // key$, val$). With `dropDefaults`, also drops keys whose value IS the
129
+ // default the runtime already assumes when the key is absent, which is pure
130
+ // payload — see CONFIG_DEFAULT.
131
+ //
132
+ // Rebuilds the tree rather than mutating during a walk. The previous
133
+ // implementation walked a clone calling `delete p[k]`, but walk() assigns its
134
+ // callback's result back over the child (`setprop(out, ckey, walk(...))`), so
135
+ // the delete was undone on the way out and the helper silently did nothing.
136
+ // Returning `undefined` from the callback does not fix it either: setprop
137
+ // stores undefined rather than removing the key, which then emits as a null.
138
+ //
139
+ // `dropDefaults` is opt-in and must be passed ONLY for the entity subtree.
140
+ // `active` means something different in feature config, where absent reads as
141
+ // INACTIVE (see feature_init) — dropping `active: true` there would silently
142
+ // disable the feature.
143
+ // jostraca's iteration metadata, injected by each()/names() while it walks the
144
+ // model. Listed explicitly rather than matched by trailing-dollar suffix: a
145
+ // trailing dollar is not exclusive to jostraca -- Seneca uses entity$ as real
146
+ // data -- so a blanket suffix match can silently drop a legitimate API field.
147
+ const MODEL_META = ['index$', 'key$', 'val$']
148
+
149
+ // Keys whose value IS the default the runtime already assumes when the key is
150
+ // absent, so emitting them is pure payload.
151
+ const CONFIG_DEFAULT: Record<string, any> = {
152
+ active: true,
153
+ req: false,
154
+ reqd: false,
155
+ }
156
+
157
+ // Subtrees carrying user payload rather than schema. An active:true inside an
158
+ // OpenAPI example is DATA, not a default, so default-pruning stops at these
159
+ // keys and everything below them is passed through untouched.
160
+ const PAYLOAD_KEYS = ['default', 'example', 'examples']
161
+
162
+ function clean(o: any, dropDefaults?: boolean): any {
163
+ const prune = (node: any, defaults: boolean): any => {
164
+ if (Array.isArray(node)) {
165
+ return node.map((n: any) => prune(n, defaults))
129
166
  }
130
- return v
131
- })
167
+ if (null != node && 'object' === typeof node) {
168
+ const out: any = {}
169
+ for (const k of Object.keys(node)) {
170
+ if (MODEL_META.includes(k)) {
171
+ continue
172
+ }
173
+ if (defaults && k in CONFIG_DEFAULT && CONFIG_DEFAULT[k] === node[k]) {
174
+ continue
175
+ }
176
+ out[k] = prune(node[k], defaults && !PAYLOAD_KEYS.includes(k))
177
+ }
178
+ return out
179
+ }
180
+ return node
181
+ }
182
+ return prune(o, true === dropDefaults)
132
183
  }
133
184
 
134
185
 
@@ -93,7 +93,7 @@ const Config = cmp(async function Config(props: any) {
93
93
  name: n.name,
94
94
  op: n.op,
95
95
  relations: n.relations,
96
- }), a), {}), 1),
96
+ }, true), a), {}), 1),
97
97
  }
98
98
  })
99
99
  })
@@ -68,13 +68,64 @@ function projectPath(suffix?: string): string {
68
68
  }
69
69
 
70
70
 
71
- function clean(o: any) {
72
- return walk(clone(o), (k: any, v: any, p: any) => {
73
- if (null != k && k.endsWith('$')) {
74
- delete p[k]
71
+ // Emission-time normalisation of a model subtree (L0).
72
+ //
73
+ // Always drops jostraca's iteration metadata (`$`-suffixed keys: index$,
74
+ // key$, val$). With `dropDefaults`, also drops keys whose value IS the
75
+ // default the runtime already assumes when the key is absent, which is pure
76
+ // payload — see CONFIG_DEFAULT.
77
+ //
78
+ // Rebuilds the tree rather than mutating during a walk. The previous
79
+ // implementation walked a clone calling `delete p[k]`, but walk() assigns its
80
+ // callback's result back over the child (`setprop(out, ckey, walk(...))`), so
81
+ // the delete was undone on the way out and the helper silently did nothing.
82
+ // Returning `undefined` from the callback does not fix it either: setprop
83
+ // stores undefined rather than removing the key, which then emits as a null.
84
+ //
85
+ // `dropDefaults` is opt-in and must be passed ONLY for the entity subtree.
86
+ // `active` means something different in feature config, where absent reads as
87
+ // INACTIVE (see feature_init) — dropping `active: true` there would silently
88
+ // disable the feature.
89
+ // jostraca's iteration metadata, injected by each()/names() while it walks the
90
+ // model. Listed explicitly rather than matched by trailing-dollar suffix: a
91
+ // trailing dollar is not exclusive to jostraca -- Seneca uses entity$ as real
92
+ // data -- so a blanket suffix match can silently drop a legitimate API field.
93
+ const MODEL_META = ['index$', 'key$', 'val$']
94
+
95
+ // Keys whose value IS the default the runtime already assumes when the key is
96
+ // absent, so emitting them is pure payload.
97
+ const CONFIG_DEFAULT: Record<string, any> = {
98
+ active: true,
99
+ req: false,
100
+ reqd: false,
101
+ }
102
+
103
+ // Subtrees carrying user payload rather than schema. An active:true inside an
104
+ // OpenAPI example is DATA, not a default, so default-pruning stops at these
105
+ // keys and everything below them is passed through untouched.
106
+ const PAYLOAD_KEYS = ['default', 'example', 'examples']
107
+
108
+ function clean(o: any, dropDefaults?: boolean): any {
109
+ const prune = (node: any, defaults: boolean): any => {
110
+ if (Array.isArray(node)) {
111
+ return node.map((n: any) => prune(n, defaults))
112
+ }
113
+ if (null != node && 'object' === typeof node) {
114
+ const out: any = {}
115
+ for (const k of Object.keys(node)) {
116
+ if (MODEL_META.includes(k)) {
117
+ continue
118
+ }
119
+ if (defaults && k in CONFIG_DEFAULT && CONFIG_DEFAULT[k] === node[k]) {
120
+ continue
121
+ }
122
+ out[k] = prune(node[k], defaults && !PAYLOAD_KEYS.includes(k))
123
+ }
124
+ return out
75
125
  }
76
- return v
77
- })
126
+ return node
127
+ }
128
+ return prune(o, true === dropDefaults)
78
129
  }
79
130
 
80
131
 
@@ -50,7 +50,7 @@ const Config = cmp(async function Config(props: any) {
50
50
  name: n.name,
51
51
  op: n.op,
52
52
  relations: n.relations,
53
- }), a), {})
53
+ }, true), a), {})
54
54
 
55
55
  Folder({ name: 'lib' }, () => {
56
56
  File({ name: 'config.ex' }, () => {
@@ -97,13 +97,64 @@ function elixirString(s: string): string {
97
97
  }
98
98
 
99
99
 
100
- function clean(o: any) {
101
- return walk(clone(o), (k: any, v: any, p: any) => {
102
- if (null != k && k.endsWith('$')) {
103
- delete p[k]
100
+ // Emission-time normalisation of a model subtree (L0).
101
+ //
102
+ // Always drops jostraca's iteration metadata (`$`-suffixed keys: index$,
103
+ // key$, val$). With `dropDefaults`, also drops keys whose value IS the
104
+ // default the runtime already assumes when the key is absent, which is pure
105
+ // payload — see CONFIG_DEFAULT.
106
+ //
107
+ // Rebuilds the tree rather than mutating during a walk. The previous
108
+ // implementation walked a clone calling `delete p[k]`, but walk() assigns its
109
+ // callback's result back over the child (`setprop(out, ckey, walk(...))`), so
110
+ // the delete was undone on the way out and the helper silently did nothing.
111
+ // Returning `undefined` from the callback does not fix it either: setprop
112
+ // stores undefined rather than removing the key, which then emits as a null.
113
+ //
114
+ // `dropDefaults` is opt-in and must be passed ONLY for the entity subtree.
115
+ // `active` means something different in feature config, where absent reads as
116
+ // INACTIVE (see feature_init) — dropping `active: true` there would silently
117
+ // disable the feature.
118
+ // jostraca's iteration metadata, injected by each()/names() while it walks the
119
+ // model. Listed explicitly rather than matched by trailing-dollar suffix: a
120
+ // trailing dollar is not exclusive to jostraca -- Seneca uses entity$ as real
121
+ // data -- so a blanket suffix match can silently drop a legitimate API field.
122
+ const MODEL_META = ['index$', 'key$', 'val$']
123
+
124
+ // Keys whose value IS the default the runtime already assumes when the key is
125
+ // absent, so emitting them is pure payload.
126
+ const CONFIG_DEFAULT: Record<string, any> = {
127
+ active: true,
128
+ req: false,
129
+ reqd: false,
130
+ }
131
+
132
+ // Subtrees carrying user payload rather than schema. An active:true inside an
133
+ // OpenAPI example is DATA, not a default, so default-pruning stops at these
134
+ // keys and everything below them is passed through untouched.
135
+ const PAYLOAD_KEYS = ['default', 'example', 'examples']
136
+
137
+ function clean(o: any, dropDefaults?: boolean): any {
138
+ const prune = (node: any, defaults: boolean): any => {
139
+ if (Array.isArray(node)) {
140
+ return node.map((n: any) => prune(n, defaults))
104
141
  }
105
- return v
106
- })
142
+ if (null != node && 'object' === typeof node) {
143
+ const out: any = {}
144
+ for (const k of Object.keys(node)) {
145
+ if (MODEL_META.includes(k)) {
146
+ continue
147
+ }
148
+ if (defaults && k in CONFIG_DEFAULT && CONFIG_DEFAULT[k] === node[k]) {
149
+ continue
150
+ }
151
+ out[k] = prune(node[k], defaults && !PAYLOAD_KEYS.includes(k))
152
+ }
153
+ return out
154
+ }
155
+ return node
156
+ }
157
+ return prune(o, true === dropDefaults)
107
158
  }
108
159
 
109
160
 
@@ -110,7 +110,7 @@ ${serverBlock}${authBlock} "headers": ${formatGoMap(headers, 3)},
110
110
  name: n.name,
111
111
  op: n.op,
112
112
  relations: n.relations,
113
- }), a), {}), 2)},
113
+ }, true), a), {}), 2)},
114
114
  }
115
115
  }
116
116
 
@@ -140,13 +140,64 @@ function formatGoValue(val: any, indent: number = 0): string {
140
140
  }
141
141
 
142
142
 
143
- function clean(o: any) {
144
- return walk(clone(o), (k: any, v: any, p: any) => {
145
- if (null != k && k.endsWith('$')) {
146
- delete p[k]
143
+ // Emission-time normalisation of a model subtree (L0).
144
+ //
145
+ // Always drops jostraca's iteration metadata (`$`-suffixed keys: index$,
146
+ // key$, val$). With `dropDefaults`, also drops keys whose value IS the
147
+ // default the runtime already assumes when the key is absent, which is pure
148
+ // payload — see CONFIG_DEFAULT.
149
+ //
150
+ // Rebuilds the tree rather than mutating during a walk. The previous
151
+ // implementation walked a clone calling `delete p[k]`, but walk() assigns its
152
+ // callback's result back over the child (`setprop(out, ckey, walk(...))`), so
153
+ // the delete was undone on the way out and the helper silently did nothing.
154
+ // Returning `undefined` from the callback does not fix it either: setprop
155
+ // stores undefined rather than removing the key, which then emits as a null.
156
+ //
157
+ // `dropDefaults` is opt-in and must be passed ONLY for the entity subtree.
158
+ // `active` means something different in feature config, where absent reads as
159
+ // INACTIVE (see feature_init) — dropping `active: true` there would silently
160
+ // disable the feature.
161
+ // jostraca's iteration metadata, injected by each()/names() while it walks the
162
+ // model. Listed explicitly rather than matched by trailing-dollar suffix: a
163
+ // trailing dollar is not exclusive to jostraca -- Seneca uses entity$ as real
164
+ // data -- so a blanket suffix match can silently drop a legitimate API field.
165
+ const MODEL_META = ['index$', 'key$', 'val$']
166
+
167
+ // Keys whose value IS the default the runtime already assumes when the key is
168
+ // absent, so emitting them is pure payload.
169
+ const CONFIG_DEFAULT: Record<string, any> = {
170
+ active: true,
171
+ req: false,
172
+ reqd: false,
173
+ }
174
+
175
+ // Subtrees carrying user payload rather than schema. An active:true inside an
176
+ // OpenAPI example is DATA, not a default, so default-pruning stops at these
177
+ // keys and everything below them is passed through untouched.
178
+ const PAYLOAD_KEYS = ['default', 'example', 'examples']
179
+
180
+ function clean(o: any, dropDefaults?: boolean): any {
181
+ const prune = (node: any, defaults: boolean): any => {
182
+ if (Array.isArray(node)) {
183
+ return node.map((n: any) => prune(n, defaults))
147
184
  }
148
- return v
149
- })
185
+ if (null != node && 'object' === typeof node) {
186
+ const out: any = {}
187
+ for (const k of Object.keys(node)) {
188
+ if (MODEL_META.includes(k)) {
189
+ continue
190
+ }
191
+ if (defaults && k in CONFIG_DEFAULT && CONFIG_DEFAULT[k] === node[k]) {
192
+ continue
193
+ }
194
+ out[k] = prune(node[k], defaults && !PAYLOAD_KEYS.includes(k))
195
+ }
196
+ return out
197
+ }
198
+ return node
199
+ }
200
+ return prune(o, true === dropDefaults)
150
201
  }
151
202
 
152
203
 
@@ -74,7 +74,7 @@ const Config = cmp(async function Config(props: any) {
74
74
  name: n.name,
75
75
  op: n.op,
76
76
  relations: n.relations,
77
- }), a), {})
77
+ }, true), a), {})
78
78
 
79
79
  const config = {
80
80
  main: { name: model.const.Name },
@@ -86,13 +86,64 @@ function formatHsValue(val: any): string {
86
86
 
87
87
 
88
88
  // Remove `$`-suffixed model annotation keys.
89
- function clean(o: any) {
90
- return walk(clone(o), (k: any, v: any, p: any) => {
91
- if (null != k && k.endsWith('$')) {
92
- delete p[k]
89
+ // Emission-time normalisation of a model subtree (L0).
90
+ //
91
+ // Always drops jostraca's iteration metadata (`$`-suffixed keys: index$,
92
+ // key$, val$). With `dropDefaults`, also drops keys whose value IS the
93
+ // default the runtime already assumes when the key is absent, which is pure
94
+ // payload — see CONFIG_DEFAULT.
95
+ //
96
+ // Rebuilds the tree rather than mutating during a walk. The previous
97
+ // implementation walked a clone calling `delete p[k]`, but walk() assigns its
98
+ // callback's result back over the child (`setprop(out, ckey, walk(...))`), so
99
+ // the delete was undone on the way out and the helper silently did nothing.
100
+ // Returning `undefined` from the callback does not fix it either: setprop
101
+ // stores undefined rather than removing the key, which then emits as a null.
102
+ //
103
+ // `dropDefaults` is opt-in and must be passed ONLY for the entity subtree.
104
+ // `active` means something different in feature config, where absent reads as
105
+ // INACTIVE (see feature_init) — dropping `active: true` there would silently
106
+ // disable the feature.
107
+ // jostraca's iteration metadata, injected by each()/names() while it walks the
108
+ // model. Listed explicitly rather than matched by trailing-dollar suffix: a
109
+ // trailing dollar is not exclusive to jostraca -- Seneca uses entity$ as real
110
+ // data -- so a blanket suffix match can silently drop a legitimate API field.
111
+ const MODEL_META = ['index$', 'key$', 'val$']
112
+
113
+ // Keys whose value IS the default the runtime already assumes when the key is
114
+ // absent, so emitting them is pure payload.
115
+ const CONFIG_DEFAULT: Record<string, any> = {
116
+ active: true,
117
+ req: false,
118
+ reqd: false,
119
+ }
120
+
121
+ // Subtrees carrying user payload rather than schema. An active:true inside an
122
+ // OpenAPI example is DATA, not a default, so default-pruning stops at these
123
+ // keys and everything below them is passed through untouched.
124
+ const PAYLOAD_KEYS = ['default', 'example', 'examples']
125
+
126
+ function clean(o: any, dropDefaults?: boolean): any {
127
+ const prune = (node: any, defaults: boolean): any => {
128
+ if (Array.isArray(node)) {
129
+ return node.map((n: any) => prune(n, defaults))
130
+ }
131
+ if (null != node && 'object' === typeof node) {
132
+ const out: any = {}
133
+ for (const k of Object.keys(node)) {
134
+ if (MODEL_META.includes(k)) {
135
+ continue
136
+ }
137
+ if (defaults && k in CONFIG_DEFAULT && CONFIG_DEFAULT[k] === node[k]) {
138
+ continue
139
+ }
140
+ out[k] = prune(node[k], defaults && !PAYLOAD_KEYS.includes(k))
141
+ }
142
+ return out
93
143
  }
94
- return v
95
- })
144
+ return node
145
+ }
146
+ return prune(o, true === dropDefaults)
96
147
  }
97
148
 
98
149