cddl2py 0.0.1 → 0.1.1

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/src/index.ts DELETED
@@ -1,658 +0,0 @@
1
- import {
2
- isCDDLArray, isGroup, isNamedGroupReference, isLiteralWithValue,
3
- isNativeTypeWithOperator, isUnNamedProperty, isPropertyReference,
4
- isRange, isVariable, pascalCase,
5
- type Assignment, type PropertyType, type PropertyReference,
6
- type Property, type Array as CDDLArray, type Operator, type Group,
7
- type Variable, type Comment, type Tag
8
- } from 'cddl'
9
-
10
- import { snakeCase } from './utils.js'
11
- import { pkg, NATIVE_TYPE_MAP } from './constants.js'
12
-
13
- export interface TransformOptions {
14
- pydantic?: boolean
15
- }
16
-
17
- interface Context {
18
- pydantic: boolean
19
- typingImports: Set<string>
20
- typingExtensionsImports: Set<string>
21
- pydanticImports: Set<string>
22
- }
23
-
24
- export function transform (assignments: Assignment[], options?: TransformOptions): string {
25
- const ctx: Context = {
26
- pydantic: options?.pydantic ?? false,
27
- typingImports: new Set(),
28
- typingExtensionsImports: new Set(),
29
- pydanticImports: new Set(),
30
- }
31
-
32
- const blocks: string[] = []
33
-
34
- for (const assignment of assignments) {
35
- const block = generateAssignment(assignment, ctx)
36
- if (block) {
37
- blocks.push(block)
38
- }
39
- }
40
-
41
- return renderOutput(ctx, blocks)
42
- }
43
-
44
- function renderOutput (ctx: Context, blocks: string[]): string {
45
- const lines: string[] = []
46
-
47
- lines.push(`# compiled with https://www.npmjs.com/package/cddl2py v${pkg.version}`)
48
- lines.push('')
49
- lines.push('from __future__ import annotations')
50
- lines.push('')
51
-
52
- if (ctx.typingImports.size > 0) {
53
- lines.push(`from typing import ${[...ctx.typingImports].sort().join(', ')}`)
54
- }
55
-
56
- if (ctx.pydantic) {
57
- if (ctx.pydanticImports.size > 0) {
58
- lines.push(`from pydantic import ${[...ctx.pydanticImports].sort().join(', ')}`)
59
- }
60
- } else if (ctx.typingExtensionsImports.size > 0) {
61
- lines.push(`from typing_extensions import ${[...ctx.typingExtensionsImports].sort().join(', ')}`)
62
- }
63
-
64
- if (ctx.typingImports.size > 0 || ctx.pydanticImports.size > 0 || ctx.typingExtensionsImports.size > 0) {
65
- lines.push('')
66
- }
67
-
68
- lines.push(blocks.join('\n\n'))
69
- lines.push('')
70
-
71
- return lines.join('\n')
72
- }
73
-
74
- function generateAssignment (assignment: Assignment, ctx: Context): string | null {
75
- if (isVariable(assignment)) {
76
- return generateVariable(assignment, ctx)
77
- }
78
- if (isGroup(assignment)) {
79
- return generateGroup(assignment as Group, ctx)
80
- }
81
- if (isCDDLArray(assignment)) {
82
- return generateArrayAssignment(assignment as CDDLArray, ctx)
83
- }
84
- return null
85
- }
86
-
87
- // ---------------------------------------------------------------------------
88
- // Variable
89
- // ---------------------------------------------------------------------------
90
-
91
- function generateVariable (v: Variable, ctx: Context): string {
92
- const name = pascalCase(v.Name)
93
- const propTypes = Array.isArray(v.PropertyType) ? v.PropertyType : [v.PropertyType]
94
- const comments = formatLeadingComments(v.Comments)
95
-
96
- if (propTypes.length === 1 && isRange(propTypes[0])) {
97
- return `${comments}${name} = int`
98
- }
99
-
100
- const types = propTypes.map(t => resolveType(t, ctx))
101
-
102
- if (types.length === 1) {
103
- return `${comments}${name} = ${types[0]}`
104
- }
105
-
106
- ctx.typingImports.add('Union')
107
- return `${comments}${name} = Union[${types.join(', ')}]`
108
- }
109
-
110
- // ---------------------------------------------------------------------------
111
- // Group
112
- // ---------------------------------------------------------------------------
113
-
114
- function generateGroup (group: Group, ctx: Context): string {
115
- const name = pascalCase(group.Name)
116
- const properties = group.Properties
117
- const hasChoices = properties.some(p => Array.isArray(p))
118
- const comments = formatLeadingComments(group.Comments)
119
-
120
- if (hasChoices) {
121
- return comments + generateGroupWithChoices(name, properties, ctx)
122
- }
123
-
124
- const props = properties as Property[]
125
-
126
- if (props.length === 1) {
127
- const prop = props[0]
128
- const propType = Array.isArray(prop.Type) ? prop.Type : [prop.Type]
129
- if (propType.length === 1 && Object.keys(NATIVE_TYPE_MAP).includes(prop.Name)) {
130
- const keyType = NATIVE_TYPE_MAP[prop.Name]
131
- if (keyType === 'Any') {
132
- ctx.typingImports.add('Any')
133
- }
134
- const valType = resolveType(propType[0], ctx)
135
- return `${comments}${name} = dict[${keyType}, ${valType}]`
136
- }
137
- }
138
-
139
- const mixins = props.filter(isUnNamedProperty)
140
- const ownProps = props.filter(p => !isUnNamedProperty(p))
141
-
142
- const simpleMixinBases: string[] = []
143
- const unionMixinGroups: string[][] = []
144
-
145
- for (const mixin of mixins) {
146
- if (Array.isArray(mixin.Type) && mixin.Type.length > 1) {
147
- const unionTypes = mixin.Type.map(t => resolveType(t, ctx))
148
- unionMixinGroups.push(unionTypes)
149
- } else {
150
- const typeVal = Array.isArray(mixin.Type) ? mixin.Type[0] : mixin.Type
151
- if (isNamedGroupReference(typeVal)) {
152
- simpleMixinBases.push(pascalCase(typeVal.Value))
153
- } else if (isGroup(typeVal) && !isNamedGroupReference(typeVal) && (typeVal as Group).Properties) {
154
- const inlineGroup = typeVal as Group
155
- const inlineProps = inlineGroup.Properties as Property[]
156
- const inlineMixinBases: string[] = []
157
- for (const p of inlineProps) {
158
- if (isUnNamedProperty(p)) {
159
- const innerType = Array.isArray(p.Type) ? p.Type[0] : p.Type
160
- if (isNamedGroupReference(innerType)) {
161
- inlineMixinBases.push(pascalCase(innerType.Value))
162
- }
163
- }
164
- }
165
- simpleMixinBases.push(...inlineMixinBases)
166
- }
167
- }
168
- }
169
-
170
- if (unionMixinGroups.length > 0) {
171
- return comments + generateGroupWithUnionMixins(name, simpleMixinBases, unionMixinGroups, ownProps, ctx)
172
- }
173
-
174
- return comments + generateClass(name, simpleMixinBases, ownProps, ctx)
175
- }
176
-
177
- function generateGroupWithChoices (name: string, properties: (Property | Property[])[], ctx: Context): string {
178
- const blocks: string[] = []
179
- const unionTypes: string[] = []
180
- let variantIndex = 0
181
-
182
- for (let i = 0; i < properties.length; i++) {
183
- const prop = properties[i]
184
-
185
- if (Array.isArray(prop)) {
186
- const choiceOptions = [...prop]
187
- const nextProp = properties[i + 1]
188
- if (nextProp && !Array.isArray(nextProp)) {
189
- choiceOptions.push(nextProp)
190
- i++
191
- }
192
-
193
- for (const option of choiceOptions) {
194
- const typeVal = Array.isArray(option.Type) ? option.Type[0] : option.Type
195
-
196
- if (isUnNamedProperty(option)) {
197
- if (isNamedGroupReference(typeVal)) {
198
- unionTypes.push(pascalCase(typeVal.Value as string))
199
- } else {
200
- unionTypes.push(resolveType(typeVal, ctx))
201
- }
202
- } else {
203
- const variantName = `_${name}Variant${variantIndex}`
204
- variantIndex++
205
- blocks.push(generateClass(variantName, [], [option], ctx))
206
- unionTypes.push(variantName)
207
- }
208
- }
209
- } else if (isUnNamedProperty(prop)) {
210
- const typeVal = Array.isArray(prop.Type) ? prop.Type[0] : prop.Type
211
- if (isNamedGroupReference(typeVal)) {
212
- unionTypes.push(pascalCase(typeVal.Value as string))
213
- } else if (Array.isArray(prop.Type) && prop.Type.length > 1) {
214
- for (const t of prop.Type) {
215
- unionTypes.push(resolveType(t, ctx))
216
- }
217
- } else {
218
- unionTypes.push(resolveType(typeVal, ctx))
219
- }
220
- } else {
221
- const variantName = `_${name}Variant${variantIndex}`
222
- variantIndex++
223
- blocks.push(generateClass(variantName, [], [prop], ctx))
224
- unionTypes.push(variantName)
225
- }
226
- }
227
-
228
- if (unionTypes.length === 1) {
229
- blocks.push(`${name} = ${unionTypes[0]}`)
230
- } else {
231
- ctx.typingImports.add('Union')
232
- blocks.push(`${name} = Union[${unionTypes.join(', ')}]`)
233
- }
234
-
235
- return blocks.join('\n\n')
236
- }
237
-
238
- function generateGroupWithUnionMixins (
239
- name: string,
240
- simpleBases: string[],
241
- unionGroups: string[][],
242
- ownProps: Property[],
243
- ctx: Context
244
- ): string {
245
- if (ownProps.length === 0 && simpleBases.length === 0) {
246
- const allTypes = unionGroups.flat()
247
- if (allTypes.length === 1) {
248
- return `${name} = ${allTypes[0]}`
249
- }
250
- ctx.typingImports.add('Union')
251
- return `${name} = Union[${allTypes.join(', ')}]`
252
- }
253
-
254
- const blocks: string[] = []
255
- const variantNames: string[] = []
256
-
257
- if (unionGroups.length === 1) {
258
- const unionTypes = unionGroups[0]
259
-
260
- if (ownProps.length > 0) {
261
- const baseName = `_${name}Fields`
262
- blocks.push(generateClass(baseName, [], ownProps, ctx))
263
-
264
- for (let i = 0; i < unionTypes.length; i++) {
265
- const variantName = `_${name}Variant${i}`
266
- variantNames.push(variantName)
267
- const bases = [baseName, unionTypes[i], ...simpleBases]
268
- blocks.push(generateClass(variantName, bases, [], ctx))
269
- }
270
- } else {
271
- for (let i = 0; i < unionTypes.length; i++) {
272
- const variantName = `_${name}Variant${i}`
273
- variantNames.push(variantName)
274
- const bases = [unionTypes[i], ...simpleBases]
275
- blocks.push(generateClass(variantName, bases, [], ctx))
276
- }
277
- }
278
- } else {
279
- const allTypes = [...simpleBases, ...unionGroups.flat()]
280
- ctx.typingImports.add('Union')
281
- blocks.push(`${name} = Union[${allTypes.join(', ')}]`)
282
- return blocks.join('\n\n')
283
- }
284
-
285
- ctx.typingImports.add('Union')
286
- blocks.push(`${name} = Union[${variantNames.join(', ')}]`)
287
-
288
- return blocks.join('\n\n')
289
- }
290
-
291
- // ---------------------------------------------------------------------------
292
- // Array
293
- // ---------------------------------------------------------------------------
294
-
295
- function generateArrayAssignment (arr: CDDLArray, ctx: Context): string {
296
- const name = pascalCase(arr.Name)
297
- const comments = formatLeadingComments(arr.Comments)
298
-
299
- const values = arr.Values
300
- if (values.length === 0) {
301
- ctx.typingImports.add('Any')
302
- return `${comments}${name} = list[Any]`
303
- }
304
-
305
- const firstVal = values[0]
306
-
307
- if (Array.isArray(firstVal)) {
308
- const options = firstVal.map(p => {
309
- const t = Array.isArray(p.Type) ? p.Type[0] : p.Type
310
- return resolveType(t, ctx)
311
- })
312
- if (options.length === 1) {
313
- return `${comments}${name} = list[${options[0]}]`
314
- }
315
- ctx.typingImports.add('Union')
316
- return `${comments}${name} = list[Union[${options.join(', ')}]]`
317
- }
318
-
319
- const firstType = firstVal.Type
320
- const types = Array.isArray(firstType) ? firstType : [firstType]
321
-
322
- if (types.length === 1 && isCDDLArray(types[0])) {
323
- const innerArr = types[0] as CDDLArray
324
- const innerVal = innerArr.Values[0] as Property
325
- const innerTypes = Array.isArray(innerVal.Type) ? innerVal.Type : [innerVal.Type]
326
- const typeStrs = innerTypes.map(v => resolveType(v, ctx))
327
-
328
- if (typeStrs.length === 1) {
329
- return `${comments}${name} = list[${typeStrs[0]}]`
330
- }
331
- ctx.typingImports.add('Union')
332
- return `${comments}${name} = list[Union[${typeStrs.join(', ')}]]`
333
- }
334
-
335
- const typeStrs = types.map(t => resolveType(t, ctx))
336
-
337
- if (typeStrs.length === 1) {
338
- return `${comments}${name} = list[${typeStrs[0]}]`
339
- }
340
-
341
- ctx.typingImports.add('Union')
342
- return `${comments}${name} = list[Union[${typeStrs.join(', ')}]]`
343
- }
344
-
345
- // ---------------------------------------------------------------------------
346
- // Class generation (TypedDict or Pydantic BaseModel)
347
- // ---------------------------------------------------------------------------
348
-
349
- function generateClass (name: string, bases: string[], props: Property[], ctx: Context): string {
350
- const lines: string[] = []
351
-
352
- let classDecl: string
353
- if (ctx.pydantic) {
354
- ctx.pydanticImports.add('BaseModel')
355
- if (bases.length > 0) {
356
- classDecl = `class ${name}(${bases.join(', ')}):`
357
- } else {
358
- classDecl = `class ${name}(BaseModel):`
359
- }
360
- } else {
361
- ctx.typingExtensionsImports.add('TypedDict')
362
- if (bases.length > 0) {
363
- classDecl = `class ${name}(${bases.join(', ')}):`
364
- } else {
365
- classDecl = `class ${name}(TypedDict):`
366
- }
367
- }
368
-
369
- lines.push(classDecl)
370
-
371
- if (props.length === 0) {
372
- lines.push(' pass')
373
- return lines.join('\n')
374
- }
375
-
376
- for (const prop of props) {
377
- const fieldLine = generateField(prop, ctx)
378
- if (fieldLine) {
379
- lines.push(fieldLine)
380
- }
381
- }
382
-
383
- if (lines.length === 1) {
384
- lines.push(' pass')
385
- }
386
-
387
- return lines.join('\n')
388
- }
389
-
390
- function generateField (prop: Property, ctx: Context): string | null {
391
- if (isUnNamedProperty(prop)) {
392
- return null
393
- }
394
-
395
- const propName = snakeCase(prop.Name)
396
- const cddlTypes: PropertyType[] = Array.isArray(prop.Type) ? prop.Type : [prop.Type]
397
- const isOptional = prop.Occurrence.n === 0
398
-
399
- let typeStr: string
400
- const types = cddlTypes.map(t => resolveType(t, ctx))
401
-
402
- if (types.length === 1) {
403
- typeStr = types[0]
404
- } else {
405
- ctx.typingImports.add('Union')
406
- typeStr = `Union[${types.join(', ')}]`
407
- }
408
-
409
- const inlineComment = prop.Comments
410
- .filter(c => !c.Leading)
411
- .map(c => c.Content.trim())
412
- .join('; ')
413
- const commentSuffix = inlineComment ? ` # ${inlineComment}` : ''
414
-
415
- let defaultExpr = ''
416
- if (prop.Operator && prop.Operator.Type === 'default') {
417
- defaultExpr = formatDefaultValue(prop.Operator)
418
- }
419
- for (const t of cddlTypes) {
420
- if (isPropertyReference(t) && (t as PropertyReference).Operator?.Type === 'default') {
421
- const val = formatDefaultValue((t as PropertyReference).Operator!)
422
- if (val) {
423
- defaultExpr = val
424
- }
425
- }
426
- }
427
-
428
- if (ctx.pydantic) {
429
- if (isOptional) {
430
- ctx.typingImports.add('Optional')
431
- if (defaultExpr) {
432
- ctx.pydanticImports.add('Field')
433
- return ` ${propName}: Optional[${typeStr}] = Field(default=${defaultExpr})${commentSuffix}`
434
- }
435
- return ` ${propName}: Optional[${typeStr}] = None${commentSuffix}`
436
- }
437
- if (defaultExpr) {
438
- ctx.pydanticImports.add('Field')
439
- return ` ${propName}: ${typeStr} = Field(default=${defaultExpr})${commentSuffix}`
440
- }
441
- return ` ${propName}: ${typeStr}${commentSuffix}`
442
- }
443
-
444
- if (isOptional) {
445
- ctx.typingExtensionsImports.add('NotRequired')
446
- return ` ${propName}: NotRequired[${typeStr}]${commentSuffix}`
447
- }
448
- return ` ${propName}: ${typeStr}${commentSuffix}`
449
- }
450
-
451
- // ---------------------------------------------------------------------------
452
- // Type resolution
453
- // ---------------------------------------------------------------------------
454
-
455
- function resolveType (t: PropertyType, ctx: Context): string {
456
- if (typeof t === 'string') {
457
- const mapped = NATIVE_TYPE_MAP[t]
458
- if (mapped) {
459
- if (mapped === 'Any') {
460
- ctx.typingImports.add('Any')
461
- }
462
- return mapped
463
- }
464
- throw new Error(`Unknown native type: "${t}"`)
465
- }
466
-
467
- if ((t as any).Type && typeof (t as any).Type === 'string' && NATIVE_TYPE_MAP[(t as any).Type]) {
468
- const mapped = NATIVE_TYPE_MAP[(t as any).Type]
469
- if (mapped === 'Any') {
470
- ctx.typingImports.add('Any')
471
- }
472
- return mapped
473
- }
474
-
475
- if (isNativeTypeWithOperator(t) && NATIVE_TYPE_MAP[(t.Type as any).Type]) {
476
- const mapped = NATIVE_TYPE_MAP[(t.Type as any).Type]
477
- if (mapped === 'Any') {
478
- ctx.typingImports.add('Any')
479
- }
480
- return mapped
481
- }
482
-
483
- if (isPropertyReference(t) && (t as PropertyReference).Value === 'null') {
484
- return 'None'
485
- }
486
-
487
- if (isGroup(t)) {
488
- if (isNamedGroupReference(t)) {
489
- return pascalCase((t as unknown as PropertyReference).Value as string)
490
- }
491
-
492
- const group = t as unknown as Group
493
- if (group.Properties) {
494
- const props = group.Properties
495
-
496
- if (props.some(p => Array.isArray(p))) {
497
- const options: string[] = []
498
- for (const choice of props) {
499
- const subProps = Array.isArray(choice) ? choice : [choice]
500
- if (subProps.length === 1 && isUnNamedProperty(subProps[0])) {
501
- const subType = Array.isArray(subProps[0].Type) ? subProps[0].Type[0] : subProps[0].Type
502
- options.push(resolveType(subType as PropertyType, ctx))
503
- continue
504
- }
505
- if (subProps.every(isUnNamedProperty)) {
506
- const tupleItems = subProps.map(p => {
507
- const subType = Array.isArray(p.Type) ? p.Type[0] : p.Type
508
- return resolveType(subType as PropertyType, ctx)
509
- })
510
- ctx.typingImports.add('Tuple')
511
- options.push(`Tuple[${tupleItems.join(', ')}]`)
512
- continue
513
- }
514
- }
515
- if (options.length > 1) {
516
- ctx.typingImports.add('Union')
517
- return `Union[${options.join(', ')}]`
518
- }
519
- if (options.length === 1) {
520
- return options[0]
521
- }
522
- }
523
-
524
- if ((props as Property[]).every(isUnNamedProperty)) {
525
- const items = (props as Property[]).map(p => {
526
- const subType = Array.isArray(p.Type) ? p.Type[0] : p.Type
527
- return resolveType(subType as PropertyType, ctx)
528
- })
529
- if (items.length === 1) {
530
- return items[0]
531
- }
532
- ctx.typingImports.add('Tuple')
533
- return `Tuple[${items.join(', ')}]`
534
- }
535
-
536
- if (props.length === 1 && Object.keys(NATIVE_TYPE_MAP).includes((props[0] as Property).Name)) {
537
- const keyType = NATIVE_TYPE_MAP[(props[0] as Property).Name]
538
- if (keyType === 'Any') {
539
- ctx.typingImports.add('Any')
540
- }
541
- const valType = resolveType(((props[0] as Property).Type as PropertyType[])[0], ctx)
542
- return `dict[${keyType}, ${valType}]`
543
- }
544
-
545
- ctx.typingImports.add('Any')
546
- return 'dict[str, Any]'
547
- }
548
-
549
- throw new Error(`Unknown group type: ${JSON.stringify(t)}`)
550
- }
551
-
552
- if (isLiteralWithValue(t)) {
553
- ctx.typingImports.add('Literal')
554
- if (typeof t.Value === 'string') {
555
- return `Literal["${t.Value}"]`
556
- }
557
- if (typeof t.Value === 'number') {
558
- return `Literal[${t.Value}]`
559
- }
560
- if (typeof t.Value === 'boolean') {
561
- return `Literal[${t.Value ? 'True' : 'False'}]`
562
- }
563
- if (typeof t.Value === 'bigint') {
564
- return `Literal[${t.Value.toString()}]`
565
- }
566
- if (t.Value === null) {
567
- return 'None'
568
- }
569
- throw new Error(`Unsupported literal: ${JSON.stringify(t)}`)
570
- }
571
-
572
- if (isCDDLArray(t)) {
573
- const arrValues = (t as unknown as CDDLArray).Values
574
- if (arrValues.length === 0) {
575
- ctx.typingImports.add('Any')
576
- return 'list[Any]'
577
- }
578
- const firstVal = arrValues[0] as Property
579
- const innerTypes = Array.isArray(firstVal.Type) ? firstVal.Type : [firstVal.Type]
580
- const typeStrs = innerTypes.map(v => resolveType(v, ctx))
581
-
582
- if (typeStrs.length === 1) {
583
- return `list[${typeStrs[0]}]`
584
- }
585
- ctx.typingImports.add('Union')
586
- return `list[Union[${typeStrs.join(', ')}]]`
587
- }
588
-
589
- if (isRange(t)) {
590
- return 'int'
591
- }
592
-
593
- if (isPropertyReference(t) && (t as PropertyReference).Type === 'range') {
594
- return 'int'
595
- }
596
-
597
- if (isNativeTypeWithOperator(t) && isNamedGroupReference(t.Type)) {
598
- return pascalCase((t.Type as unknown as PropertyReference).Value as string)
599
- }
600
-
601
- if (isPropertyReference(t)) {
602
- const ref = t as PropertyReference
603
- if (ref.Type === 'group_array' && typeof ref.Value === 'string') {
604
- return `list[${pascalCase(ref.Value)}]`
605
- }
606
- if (ref.Type === 'tag') {
607
- const tag = ref.Value as Tag
608
- const mapped = NATIVE_TYPE_MAP[tag.TypePart]
609
- if (mapped) {
610
- if (mapped === 'Any') {
611
- ctx.typingImports.add('Any')
612
- }
613
- return mapped
614
- }
615
- return pascalCase(tag.TypePart)
616
- }
617
- }
618
-
619
- throw new Error(`Unknown type: ${JSON.stringify(t)}`)
620
- }
621
-
622
- // ---------------------------------------------------------------------------
623
- // Helpers
624
- // ---------------------------------------------------------------------------
625
-
626
- function formatLeadingComments (comments: Comment[]): string {
627
- const leading = comments.filter(c => c.Leading)
628
- if (leading.length === 0) {
629
- return ''
630
- }
631
- return leading.map(c => `# ${c.Content}`).join('\n') + '\n'
632
- }
633
-
634
- function formatDefaultValue (operator: Operator): string {
635
- if (operator.Type !== 'default') {
636
- return ''
637
- }
638
-
639
- const val = operator.Value
640
- if (val === 'null') {
641
- return 'None'
642
- }
643
-
644
- const ref = val as PropertyReference
645
- if (ref.Type === 'literal') {
646
- if (typeof ref.Value === 'string') {
647
- return `"${ref.Value}"`
648
- }
649
- if (typeof ref.Value === 'number') {
650
- return String(ref.Value)
651
- }
652
- if (typeof ref.Value === 'boolean') {
653
- return ref.Value ? 'True' : 'False'
654
- }
655
- }
656
-
657
- return ''
658
- }
package/src/utils.ts DELETED
@@ -1,12 +0,0 @@
1
- /**
2
- * Convert a string to snake_case
3
- * @param name - The string to convert
4
- * @returns The snake_case string
5
- */
6
- export function snakeCase(name: string): string {
7
- return name
8
- .replace(/([a-z0-9])([A-Z])/g, '$1_$2')
9
- .replace(/([A-Z])([A-Z][a-z])/g, '$1_$2')
10
- .replace(/[-.\s]+/g, '_')
11
- .toLowerCase()
12
- }