@voxgig/sdkgen 4.2.8 → 4.3.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/helpers/naming.d.ts +2 -1
- package/dist/helpers/naming.js +50 -12
- package/dist/helpers/naming.js.map +1 -1
- package/dist/sdkgen.d.ts +2 -2
- package/dist/sdkgen.js +4 -3
- package/dist/sdkgen.js.map +1 -1
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/package.json +1 -1
- package/project/.sdk/tm/go/test/custom_utility_test.go +103 -0
- package/project/.sdk/tm/go/test/feature_corpus_test.go +550 -0
- package/project/.sdk/tm/go/utility/make_options.go +7 -1
- package/project/.sdk/tm/go/utility/register.go +194 -0
- package/project/.sdk/tm/java/test/CustomUtilityTest.java +55 -0
- package/project/.sdk/tm/java/test/FeatureCorpusTest.java +463 -0
- package/project/.sdk/tm/java/utility/MakeOptions.java +11 -2
- package/project/.sdk/tm/java/utility/Register.java +91 -0
- package/project/.sdk/tm/js/test/feature/Corpus.test.js +285 -0
- package/project/.sdk/tm/perl/t/feature_corpus.t +345 -0
- package/project/.sdk/tm/perl/utility/make_options.pm +33 -1
- package/project/.sdk/tm/php/core/Context.php +3 -0
- package/project/.sdk/tm/php/core/Control.php +13 -0
- package/project/.sdk/tm/php/core/Error.php +12 -0
- package/project/.sdk/tm/php/test/FeatureCorpusTest.php +376 -0
- package/project/.sdk/tm/php/utility/MakeOptions.php +30 -1
- package/project/.sdk/tm/py/pkg/utility/make_options.py +42 -1
- package/project/.sdk/tm/py/test/test_feature_corpus.py +309 -0
- package/project/.sdk/tm/rb/test/feature_corpus_test.rb +281 -0
- package/project/.sdk/tm/rb/utility/make_options.rb +32 -1
- package/project/.sdk/tm/ts/test/feature/Corpus.test.ts +287 -0
- package/project/sdkgen-package.json +1 -1
- package/src/helpers/naming.ts +54 -12
- package/src/sdkgen.ts +2 -1
|
@@ -0,0 +1,287 @@
|
|
|
1
|
+
|
|
2
|
+
// Feature behaviour, driven by the SHARED corpus.
|
|
3
|
+
//
|
|
4
|
+
// This is the route PrimaryUtility.test.ts already takes for the utilities:
|
|
5
|
+
// language-neutral cases in .sdk/test/test.json, executed against the REAL
|
|
6
|
+
// generated SDK. Features here are ordinary classes in ordinary compiled
|
|
7
|
+
// source, unit-tested the ordinary way — no transpiled templates, and no
|
|
8
|
+
// miniature of the pipeline standing in for the pipeline (which is what
|
|
9
|
+
// harness.ts does, and why its assertions can only be as right as the
|
|
10
|
+
// miniature is). A feature is built through the generated config, wrapped
|
|
11
|
+
// into a client built by the generated constructor, and driven by a real
|
|
12
|
+
// entity operation. What is asserted is what ships.
|
|
13
|
+
//
|
|
14
|
+
// Everything in a case is data: features are activated by name, options are
|
|
15
|
+
// plain JSON, the transport is scripted by `res`, and the assertion is a
|
|
16
|
+
// subset of the client's own record. Turning `res` into a fetcher is the one
|
|
17
|
+
// piece each language writes for itself.
|
|
18
|
+
|
|
19
|
+
import { test, describe, before } from 'node:test'
|
|
20
|
+
import { ok, deepStrictEqual } from 'node:assert'
|
|
21
|
+
|
|
22
|
+
import { readFileSync } from 'node:fs'
|
|
23
|
+
import { join } from 'node:path'
|
|
24
|
+
|
|
25
|
+
import { SDK, TEST_JSON_FILE } from '../utility/index'
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
// Features with a corpus section. A name here with no section is a skip, not
|
|
29
|
+
// a failure: an SDK generated without the feature has nothing to run.
|
|
30
|
+
const FEATURES = ['cost']
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
// One operation this SDK can actually perform.
|
|
34
|
+
type OpRef = {
|
|
35
|
+
key: string // '<entity>.<op>' — how features attribute it
|
|
36
|
+
accessor: string // the client method returning the entity
|
|
37
|
+
entity: string
|
|
38
|
+
op: string
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
|
|
42
|
+
// A scripted transport built from a case's `res` list. Responses are consumed
|
|
43
|
+
// in order and the last one repeats, so a case that does not care how many
|
|
44
|
+
// attempts happen need only declare one.
|
|
45
|
+
function scriptedFetcher(res: any[]) {
|
|
46
|
+
let n = -1
|
|
47
|
+
return async function (_ctx: any, _url: string, _fetchdef: any) {
|
|
48
|
+
n++
|
|
49
|
+
const spec = res[n < res.length ? n : res.length - 1] || {}
|
|
50
|
+
|
|
51
|
+
if (true === spec.throw) {
|
|
52
|
+
throw new Error('scripted transport failure')
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
const headers: Record<string, any> = spec.headers || {}
|
|
56
|
+
const status = null == spec.status ? 200 : spec.status
|
|
57
|
+
|
|
58
|
+
return {
|
|
59
|
+
status,
|
|
60
|
+
statusText: status < 400 ? 'OK' : 'ERR',
|
|
61
|
+
body: 'not-used',
|
|
62
|
+
json: async () => (undefined === spec.body ? {} : spec.body),
|
|
63
|
+
headers: {
|
|
64
|
+
get(key: string) {
|
|
65
|
+
const lower = String(key).toLowerCase()
|
|
66
|
+
for (const k of Object.keys(headers)) {
|
|
67
|
+
if (k.toLowerCase() === lower) { return headers[k] }
|
|
68
|
+
}
|
|
69
|
+
return undefined
|
|
70
|
+
},
|
|
71
|
+
forEach(cb: any) { Object.keys(headers).forEach((k) => cb(headers[k], k, this)) },
|
|
72
|
+
},
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
|
|
78
|
+
function makeClient(kase: any): any {
|
|
79
|
+
return new (SDK as any)({
|
|
80
|
+
feature: kase.feature,
|
|
81
|
+
utility: { fetcher: scriptedFetcher(kase.res || [{ status: 200, body: {} }]) },
|
|
82
|
+
})
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
|
|
86
|
+
// Every operation this SDK declares, in a stable order.
|
|
87
|
+
//
|
|
88
|
+
// The corpus cannot name an entity — it is shared by SDKs that have none in
|
|
89
|
+
// common — so the runner finds them here. The generated client exposes one
|
|
90
|
+
// capitalised, zero-argument accessor per entity, and the entity it returns
|
|
91
|
+
// carries the same `name` the config is keyed by; that pairing is what turns
|
|
92
|
+
// a config entry back into a callable method.
|
|
93
|
+
function candidates(client: any): OpRef[] {
|
|
94
|
+
const entities: Record<string, any> = client._rootctx.config.entity || {}
|
|
95
|
+
|
|
96
|
+
const accessor: Record<string, string> = {}
|
|
97
|
+
for (const m of Object.getOwnPropertyNames(Object.getPrototypeOf(client))) {
|
|
98
|
+
if (!/^[A-Z]/.test(m) || 'function' !== typeof client[m]) { continue }
|
|
99
|
+
let inst: any
|
|
100
|
+
try { inst = client[m]() }
|
|
101
|
+
catch (e) { continue }
|
|
102
|
+
if (null != inst && 'string' === typeof inst.name && null != entities[inst.name]) {
|
|
103
|
+
accessor[inst.name] = m
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
const out: OpRef[] = []
|
|
108
|
+
for (const entity of Object.keys(entities).sort()) {
|
|
109
|
+
if (null == accessor[entity]) { continue }
|
|
110
|
+
for (const op of Object.keys(entities[entity].op || {}).sort()) {
|
|
111
|
+
out.push({ key: entity + '.' + op, accessor: accessor[entity], entity, op })
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
return out
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
|
|
118
|
+
// Pick operations the corpus can drive, by DRIVING them: an op is usable when
|
|
119
|
+
// it completes against a plain 200 with no feature active. Declared ops are
|
|
120
|
+
// not all callable with no arguments (a required path parameter, a body), and
|
|
121
|
+
// a case that failed for that reason would look like a feature defect.
|
|
122
|
+
async function usableOps(want: number): Promise<OpRef[]> {
|
|
123
|
+
const picked: OpRef[] = []
|
|
124
|
+
for (const cand of candidates(makeClient({}))) {
|
|
125
|
+
const client = makeClient({})
|
|
126
|
+
try {
|
|
127
|
+
await client[cand.accessor]()[cand.op]({}, {})
|
|
128
|
+
}
|
|
129
|
+
catch (e) { continue }
|
|
130
|
+
picked.push(cand)
|
|
131
|
+
if (want <= picked.length) { break }
|
|
132
|
+
}
|
|
133
|
+
return picked
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
|
|
137
|
+
// Replace #OP1/#OP2 throughout a case, keys included.
|
|
138
|
+
function resolve(node: any, tokens: Record<string, string>): any {
|
|
139
|
+
if ('string' === typeof node) {
|
|
140
|
+
let s = node
|
|
141
|
+
for (const t of Object.keys(tokens)) { s = s.split(t).join(tokens[t]) }
|
|
142
|
+
return s
|
|
143
|
+
}
|
|
144
|
+
if (Array.isArray(node)) {
|
|
145
|
+
return node.map((n) => resolve(n, tokens))
|
|
146
|
+
}
|
|
147
|
+
if (null != node && 'object' === typeof node) {
|
|
148
|
+
const out: any = {}
|
|
149
|
+
for (const k of Object.keys(node)) {
|
|
150
|
+
out[resolve(k, tokens)] = resolve(node[k], tokens)
|
|
151
|
+
}
|
|
152
|
+
return out
|
|
153
|
+
}
|
|
154
|
+
return node
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
|
|
158
|
+
// Which #OPn tokens a case uses. A case wanting more operations than this SDK
|
|
159
|
+
// has is skipped rather than failed.
|
|
160
|
+
function tokensUsed(kase: any): number {
|
|
161
|
+
const m = JSON.stringify(kase).match(/#OP(\d+)/g) || []
|
|
162
|
+
return m.reduce((max, t) => Math.max(max, Number(t.slice(3))), 0)
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
|
|
166
|
+
// Assert that `actual` contains `expect`, recursively. Cases assert only the
|
|
167
|
+
// fields they are about, so a full deepStrictEqual would force every case to
|
|
168
|
+
// restate the whole record.
|
|
169
|
+
function subset(actual: any, expect: any, path: string) {
|
|
170
|
+
if (null != expect && 'object' === typeof expect && !Array.isArray(expect)) {
|
|
171
|
+
for (const k of Object.keys(expect)) {
|
|
172
|
+
ok(null != actual, `${path}.${k}: nothing at ${path}`)
|
|
173
|
+
subset(actual[k], expect[k], `${path}.${k}`)
|
|
174
|
+
}
|
|
175
|
+
return
|
|
176
|
+
}
|
|
177
|
+
deepStrictEqual(actual, expect, path)
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
|
|
181
|
+
describe('FeatureCorpus', () => {
|
|
182
|
+
|
|
183
|
+
let corpus: any
|
|
184
|
+
let ops: OpRef[] = []
|
|
185
|
+
let byKey: Record<string, OpRef> = {}
|
|
186
|
+
|
|
187
|
+
|
|
188
|
+
before(async () => {
|
|
189
|
+
corpus = JSON.parse(readFileSync(join(__dirname, '..', TEST_JSON_FILE), 'utf8'))
|
|
190
|
+
ops = await usableOps(2)
|
|
191
|
+
byKey = {}
|
|
192
|
+
for (const o of ops) { byKey[o.key] = o }
|
|
193
|
+
})
|
|
194
|
+
|
|
195
|
+
|
|
196
|
+
// A corpus with no `feature` section is a SKIP, not a failure.
|
|
197
|
+
//
|
|
198
|
+
// Each project carries its OWN materialised copy of .sdk/test/test.json, so
|
|
199
|
+
// a project scaffolded before the section existed legitimately has no cases
|
|
200
|
+
// to run - and a hard assertion here turned that into a red suite in every
|
|
201
|
+
// SDK on the fleet, for a corpus the project had simply not re-pulled yet.
|
|
202
|
+
//
|
|
203
|
+
// The strict check belongs where the corpus is CONTROLLED, not where it is
|
|
204
|
+
// consumed: sdkgen's own end-to-end lane generates against a corpus it
|
|
205
|
+
// supplies and requires the cases to actually run, so a section that goes
|
|
206
|
+
// missing there still fails loudly.
|
|
207
|
+
test('the corpus carries a feature section', (t) => {
|
|
208
|
+
if (null == corpus.feature) {
|
|
209
|
+
return t.skip(
|
|
210
|
+
'this project\'s test.json has no `feature` section - recompile the ' +
|
|
211
|
+
'corpus (create-sdkgen .sdk/test/feature/) to run these cases')
|
|
212
|
+
}
|
|
213
|
+
})
|
|
214
|
+
|
|
215
|
+
|
|
216
|
+
// At least one operation, or every case below would skip and the whole
|
|
217
|
+
// suite would report green having run nothing.
|
|
218
|
+
test('this SDK has an operation the corpus can drive', () => {
|
|
219
|
+
ok(0 < ops.length,
|
|
220
|
+
'no declared operation completed against a plain 200 — the corpus ' +
|
|
221
|
+
'cannot exercise a feature without one')
|
|
222
|
+
})
|
|
223
|
+
|
|
224
|
+
|
|
225
|
+
for (const name of FEATURES) {
|
|
226
|
+
|
|
227
|
+
test(name, async (t) => {
|
|
228
|
+
const section = corpus.feature?.[name]
|
|
229
|
+
if (null == section) {
|
|
230
|
+
return t.skip(`no corpus section for ${name}`)
|
|
231
|
+
}
|
|
232
|
+
|
|
233
|
+
const probe: any = makeClient({})
|
|
234
|
+
if (!probe._rootctx.config.hasFeature(name)) {
|
|
235
|
+
return t.skip(`this SDK was generated without the ${name} feature`)
|
|
236
|
+
}
|
|
237
|
+
|
|
238
|
+
const cases: any[] = section.basic?.set || []
|
|
239
|
+
ok(0 < cases.length,
|
|
240
|
+
`corpus section feature.${name} ran ZERO cases — a renamed section ` +
|
|
241
|
+
`or an emptied fixture must fail loudly, not pass silently`)
|
|
242
|
+
|
|
243
|
+
let ran = 0
|
|
244
|
+
for (const raw of cases) {
|
|
245
|
+
const need = tokensUsed(raw)
|
|
246
|
+
if (ops.length < need) {
|
|
247
|
+
t.diagnostic(`skip "${raw.name}": needs ${need} operations, this SDK offers ${ops.length}`)
|
|
248
|
+
continue
|
|
249
|
+
}
|
|
250
|
+
|
|
251
|
+
const tokens: Record<string, string> = {}
|
|
252
|
+
for (let i = 0; i < need; i++) { tokens['#OP' + (i + 1)] = ops[i].key }
|
|
253
|
+
|
|
254
|
+
const kase = resolve(raw, tokens)
|
|
255
|
+
const client = makeClient(kase)
|
|
256
|
+
|
|
257
|
+
for (const step of (kase.op || [])) {
|
|
258
|
+
const ref = byKey[step.op]
|
|
259
|
+
ok(null != ref, `${kase.name}: no operation ${step.op}`)
|
|
260
|
+
try {
|
|
261
|
+
await client[ref.accessor]()[ref.op]({}, step.ctrl || {})
|
|
262
|
+
ok(null == step.err,
|
|
263
|
+
`${kase.name}: ${step.op} was expected to fail, and did not`)
|
|
264
|
+
}
|
|
265
|
+
catch (err: any) {
|
|
266
|
+
if (null == step.err) { throw err }
|
|
267
|
+
if ('string' === typeof step.err) {
|
|
268
|
+
deepStrictEqual(err.code, step.err, `${kase.name}: wrong error code`)
|
|
269
|
+
}
|
|
270
|
+
}
|
|
271
|
+
}
|
|
272
|
+
|
|
273
|
+
subset(client[`_${name}`], kase.out, `${kase.name}: _${name}`)
|
|
274
|
+
ran++
|
|
275
|
+
}
|
|
276
|
+
|
|
277
|
+
ok(0 < ran, `every feature.${name} case was skipped`)
|
|
278
|
+
// Say how many ran. A partial run is legitimate (an SDK with one
|
|
279
|
+
// operation skips the cases needing two) but it should be visible
|
|
280
|
+
// rather than inferred from a green tick - and it is the one line
|
|
281
|
+
// sdkgen's end-to-end lane reads, in the same wording, from every
|
|
282
|
+
// language's runner.
|
|
283
|
+
t.diagnostic(`feature.${name}: ran ${ran} of ${cases.length} ` +
|
|
284
|
+
`case(s) against ${ops.length} operation(s)`)
|
|
285
|
+
})
|
|
286
|
+
}
|
|
287
|
+
})
|
package/src/helpers/naming.ts
CHANGED
|
@@ -149,9 +149,9 @@ const RB_SDK_CONSTANTS = new Set<string>([
|
|
|
149
149
|
'StructRunner', 'StructTestClient', 'StructUtilityTest', 'VoxgigStruct',
|
|
150
150
|
'STRUCT_TEST_JSON_FILE',
|
|
151
151
|
// the generated/templated test classes
|
|
152
|
-
'ExistsTest', '
|
|
153
|
-
'
|
|
154
|
-
'TestInitFeature',
|
|
152
|
+
'ExistsTest', 'FeatureCorpusTest', 'FeatureTest', 'NetsimTest',
|
|
153
|
+
'PipelineTest', 'PrimaryUtilityTest', 'ReadmeExamplesTest',
|
|
154
|
+
'TestHookFeature', 'TestInitFeature',
|
|
155
155
|
])
|
|
156
156
|
|
|
157
157
|
|
|
@@ -304,18 +304,59 @@ function isPhpReservedType(Name: string): boolean {
|
|
|
304
304
|
}
|
|
305
305
|
|
|
306
306
|
|
|
307
|
-
//
|
|
308
|
-
//
|
|
309
|
-
//
|
|
310
|
-
//
|
|
311
|
-
//
|
|
307
|
+
// CLASSES THE GENERATED PHP SDK ITSELF DECLARES — the second half of "already
|
|
308
|
+
// taken", exactly as RB_SDK_CONSTANTS is for ruby. `PHP_RESERVED_TYPES` covers
|
|
309
|
+
// what the LANGUAGE owns; this covers what OUR OWN scaffolding claims, which a
|
|
310
|
+
// keyword list can never catch.
|
|
311
|
+
//
|
|
312
|
+
// The generated PHP SDK uses NO NAMESPACES, and composer classmaps both the
|
|
313
|
+
// runtime (`types/`) and the tests (`autoload-dev`: `test/`). An entity named
|
|
314
|
+
// `feature_test` emits `class FeatureTest` in `<Sdk>Types.php` while
|
|
315
|
+
// `tm/php/test/FeatureTest.php` declares one too: composer maps one name to
|
|
316
|
+
// two files, and loading both fatals on redeclaration. Ruby's equivalent only
|
|
317
|
+
// warns; PHP does not.
|
|
318
|
+
//
|
|
319
|
+
// Only UNPREFIXED, UNNAMESPACED declarations are listed. `ProjectNameUtility`
|
|
320
|
+
// substitutes to `<Sdk>Utility`, which no bare entity type can equal, and
|
|
321
|
+
// `utility/struct/Struct.php` and `test/StructRunner.php` declare inside a
|
|
322
|
+
// namespace — neither is reachable from the global name an entity type takes.
|
|
323
|
+
//
|
|
324
|
+
// `php-sdk-classes.test.ts` re-derives this from the templates AND the
|
|
325
|
+
// components and fails on drift, the same discipline as the rb and swift
|
|
326
|
+
// guards, and for the same reason: a hand-collected list rots.
|
|
327
|
+
//
|
|
328
|
+
// Folded, and matched folded: PHP class names are case-insensitive, so
|
|
329
|
+
// `FeatureTest` and `featuretest` are one identifier.
|
|
330
|
+
const PHP_SDK_CLASSES = new Set<string>([
|
|
331
|
+
// the generated/templated test classes
|
|
332
|
+
'existstest', 'featurecorpustest', 'featuretest', 'netsimtest',
|
|
333
|
+
'pipelinetest', 'primaryutilitytest', 'readmeexamplestest',
|
|
334
|
+
'structutilitytest',
|
|
335
|
+
// helper classes those suites declare beside them
|
|
336
|
+
'ftclient', 'ftclock', 'ftctrl', 'ftentity', 'ftharness', 'ftrecorder',
|
|
337
|
+
'plclient', 'plentity', 'plentityitem',
|
|
338
|
+
])
|
|
339
|
+
|
|
340
|
+
|
|
341
|
+
// Does `Name` collide with a class the generated PHP SDK already declares?
|
|
342
|
+
function isPhpSdkClass(Name: string): boolean {
|
|
343
|
+
return PHP_SDK_CLASSES.has(String(Name).toLowerCase())
|
|
344
|
+
}
|
|
345
|
+
|
|
346
|
+
|
|
347
|
+
// A declarable PHP class name for a generated type: unchanged, unless the name
|
|
348
|
+
// is ALREADY TAKEN — by PHP itself, or by the SDK's own scaffolding — in which
|
|
349
|
+
// case `Type` is appended (`Namespace` -> `NamespaceType`). Mirrors
|
|
350
|
+
// rbSafeTypeName and swiftSafeTypeName deliberately — same suffix, same "only
|
|
351
|
+
// rename on an actual collision" rule, so every SDK that does not collide is
|
|
352
|
+
// byte-identical to before.
|
|
312
353
|
//
|
|
313
354
|
// Applied ONLY to the bare entity data class. Per-op type names already carry
|
|
314
|
-
// their own suffix (`NamespaceLoadData`, `NamespaceCreateData`), which
|
|
315
|
-
//
|
|
316
|
-
//
|
|
355
|
+
// their own suffix (`NamespaceLoadData`, `NamespaceCreateData`), which neither
|
|
356
|
+
// set matches, and the entity ACCESSOR is a method rather than a class — PHP
|
|
357
|
+
// resolves those separately — so the public surface is unchanged.
|
|
317
358
|
function phpSafeTypeName(Name: string): string {
|
|
318
|
-
return isPhpReservedType(Name) ? Name + 'Type' : Name
|
|
359
|
+
return isPhpReservedType(Name) || isPhpSdkClass(Name) ? Name + 'Type' : Name
|
|
319
360
|
}
|
|
320
361
|
|
|
321
362
|
|
|
@@ -496,6 +537,7 @@ export {
|
|
|
496
537
|
isSwiftSdkType,
|
|
497
538
|
swiftSafeTypeName,
|
|
498
539
|
isPhpReservedType,
|
|
540
|
+
isPhpSdkClass,
|
|
499
541
|
phpSafeTypeName,
|
|
500
542
|
isTsReservedType,
|
|
501
543
|
tsSafeTypeName,
|
package/src/sdkgen.ts
CHANGED
|
@@ -59,7 +59,7 @@ import { collectDeps } from './helpers/collectDeps'
|
|
|
59
59
|
import type { DepEntry } from './helpers/collectDeps'
|
|
60
60
|
import { canonToType, canonToDtype, canonKey, canonScalarKey } from './helpers/canonType'
|
|
61
61
|
import { OP_SUFFIX, opTypeName, opParams, ownPoint, opActions, entityActions, entityPath, opRequestShape, entityIdField, entityDataIdField, entityOps, entityPrimaryOp, pickExampleEntity, entityClassName, entityTypeCollisions, warnEntityTypeCollisions, deriveEntityNames, entityCollection } from './helpers/opShape'
|
|
62
|
-
import { isReservedName, safeVarName, exampleVarName, phpEntityAccessor, entityCacheField, isRbCoreConstant, isRbSdkConstant, rbSafeTypeName, isSwiftSdkType, swiftSafeTypeName, isPhpReservedType, phpSafeTypeName, isTsReservedType, tsSafeTypeName, jsProp, jsOptProp, jsKey } from './helpers/naming'
|
|
62
|
+
import { isReservedName, safeVarName, exampleVarName, phpEntityAccessor, entityCacheField, isRbCoreConstant, isRbSdkConstant, rbSafeTypeName, isSwiftSdkType, swiftSafeTypeName, isPhpReservedType, isPhpSdkClass, phpSafeTypeName, isTsReservedType, tsSafeTypeName, jsProp, jsOptProp, jsKey } from './helpers/naming'
|
|
63
63
|
import { serverVariables, hasServerVariables } from './helpers/serverVars'
|
|
64
64
|
import { primaryOpCall, idLiteral, matchArg, dataArg, litFor } from './helpers/opExample'
|
|
65
65
|
import type { ExampleLang } from './helpers/opExample'
|
|
@@ -1126,6 +1126,7 @@ export {
|
|
|
1126
1126
|
isSwiftSdkType,
|
|
1127
1127
|
swiftSafeTypeName,
|
|
1128
1128
|
isPhpReservedType,
|
|
1129
|
+
isPhpSdkClass,
|
|
1129
1130
|
phpSafeTypeName,
|
|
1130
1131
|
isTsReservedType,
|
|
1131
1132
|
tsSafeTypeName,
|