@voxgig/sdkgen 4.2.4 → 4.2.5

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 (69) hide show
  1. package/bin/voxgig-sdkgen +1 -1
  2. package/dist/cmp/AgentGuideTop.js +15 -7
  3. package/dist/cmp/AgentGuideTop.js.map +1 -1
  4. package/dist/cmp/ReadmeStation.js +88 -12
  5. package/dist/cmp/ReadmeStation.js.map +1 -1
  6. package/dist/helpers/station.d.ts +3 -0
  7. package/dist/helpers/station.js +67 -0
  8. package/dist/helpers/station.js.map +1 -0
  9. package/dist/sdkgen.d.ts +2 -1
  10. package/dist/sdkgen.js +41 -15
  11. package/dist/sdkgen.js.map +1 -1
  12. package/dist/tsconfig.tsbuildinfo +1 -1
  13. package/dist/types.d.ts +2 -0
  14. package/dist/utility.js +15 -1
  15. package/dist/utility.js.map +1 -1
  16. package/model/sdkgen.aon +20 -0
  17. package/package.json +1 -1
  18. package/project/.sdk/model/feature/audit.aon +1 -0
  19. package/project/.sdk/model/feature/cache.aon +1 -0
  20. package/project/.sdk/model/feature/clienttrack.aon +1 -0
  21. package/project/.sdk/model/feature/debug.aon +1 -0
  22. package/project/.sdk/model/feature/idempotency.aon +1 -0
  23. package/project/.sdk/model/feature/log.aon +1 -0
  24. package/project/.sdk/model/feature/metrics.aon +1 -0
  25. package/project/.sdk/model/feature/netsim.aon +1 -0
  26. package/project/.sdk/model/feature/paging.aon +1 -0
  27. package/project/.sdk/model/feature/proxy.aon +1 -0
  28. package/project/.sdk/model/feature/ratelimit.aon +1 -0
  29. package/project/.sdk/model/feature/rbac.aon +1 -0
  30. package/project/.sdk/model/feature/retry.aon +1 -0
  31. package/project/.sdk/model/feature/streaming.aon +1 -0
  32. package/project/.sdk/model/feature/telemetry.aon +1 -0
  33. package/project/.sdk/model/feature/test.aon +1 -0
  34. package/project/.sdk/model/feature/timeout.aon +1 -0
  35. package/project/.sdk/src/cmp/c/Config_c.ts +13 -10
  36. package/project/.sdk/src/cmp/clojure/Config_clojure.ts +4 -1
  37. package/project/.sdk/src/cmp/dart/Config_dart.ts +4 -1
  38. package/project/.sdk/src/cmp/elixir/Config_elixir.ts +4 -1
  39. package/project/.sdk/src/cmp/elixir/Main_elixir.ts +21 -2
  40. package/project/.sdk/src/cmp/go/Config_go.ts +4 -1
  41. package/project/.sdk/src/cmp/java/Config_java.ts +11 -8
  42. package/project/.sdk/src/cmp/js/Config_js.ts +4 -1
  43. package/project/.sdk/src/cmp/js/Main_js.ts +20 -1
  44. package/project/.sdk/src/cmp/js/fragment/MainStation.fragment.js +36 -0
  45. package/project/.sdk/src/cmp/kotlin/Config_kotlin.ts +11 -7
  46. package/project/.sdk/src/cmp/lua/Config_lua.ts +4 -1
  47. package/project/.sdk/src/cmp/ocaml/Config_ocaml.ts +3 -1
  48. package/project/.sdk/src/cmp/php/Config_php.ts +4 -1
  49. package/project/.sdk/src/cmp/py/Config_py.ts +4 -1
  50. package/project/.sdk/src/cmp/rb/Config_rb.ts +4 -1
  51. package/project/.sdk/src/cmp/swift/EntityTypes_swift.ts +2 -2
  52. package/project/.sdk/src/cmp/swift/Entity_swift.ts +3 -1
  53. package/project/.sdk/src/cmp/swift/Main_swift.ts +37 -2
  54. package/project/.sdk/src/cmp/swift/Package_swift.ts +9 -6
  55. package/project/.sdk/src/cmp/swift/ReadmeExamplesTest_swift.ts +1 -1
  56. package/project/.sdk/src/cmp/swift/ReadmeExplanation_swift.ts +5 -3
  57. package/project/.sdk/src/cmp/swift/Test_swift.ts +3 -1
  58. package/project/.sdk/src/cmp/swift/utility_swift.ts +16 -0
  59. package/project/.sdk/src/cmp/ts/Config_ts.ts +4 -1
  60. package/project/.sdk/src/cmp/ts/Main_ts.ts +20 -1
  61. package/project/.sdk/src/cmp/ts/fragment/MainStation.fragment.ts +36 -0
  62. package/project/.sdk/src/cmp/zig/Config_zig.ts +4 -2
  63. package/project/sdkgen-package.json +1 -1
  64. package/src/cmp/AgentGuideTop.ts +15 -7
  65. package/src/cmp/ReadmeStation.ts +93 -13
  66. package/src/helpers/station.ts +80 -0
  67. package/src/sdkgen.ts +52 -15
  68. package/src/types.ts +6 -0
  69. package/src/utility.ts +15 -1
package/src/sdkgen.ts CHANGED
@@ -73,6 +73,7 @@ import {
73
73
  srcFeatureExcludes,
74
74
  } from './helpers/featureSource'
75
75
  import type { FeatureSource } from './helpers/featureSource'
76
+ import { stationLibrary } from './helpers/station'
76
77
  import {
77
78
  definitionPath,
78
79
  definitionFolder,
@@ -299,7 +300,13 @@ function SdkGen(opts: SdkGenOptions) {
299
300
  // so resolve it ONCE: every destination is compared against it, and a
300
301
  // comparison between a relative and an absolute path is meaningless.
301
302
  const root = Path.resolve(folder)
302
- const external = externalItems(model, root, ['target', 'docs'])
303
+ // Snapshot the decision before preflight. In particular, do not check a
304
+ // missing optional destination once for safety and AGAIN before writing:
305
+ // if it appeared between those checks, the pass could write into content
306
+ // that was never ownership-validated.
307
+ const external: ExternalPlan[] =
308
+ externalItems(model, root, ['target', 'docs'])
309
+ .map((ext) => ({ ...ext, skip: externalSkipReason(ext, fs) }))
303
310
 
304
311
  // Before ANY file is written, in-tree included: a destination that turns
305
312
  // out to be wrong must abort the whole generation, not leave half of it
@@ -382,17 +389,13 @@ function SdkGen(opts: SdkGenOptions) {
382
389
  }
383
390
 
384
391
  for (const ext of external) {
385
- // `active: false` is the project's only lever to stop the generator
386
- // writing into a repo it does not own, so it has to be honoured HERE —
387
- // the consumer Root iterates targets raw and does not check it. The
388
- // target is still removed from the in-tree model above (withoutExternal
389
- // takes every `output: path` target, active or not), so switching one
390
- // off generates it nowhere rather than relocating it into
391
- // `<sdk-repo>/<target>/`.
392
- if (!ext.active) {
392
+ // A skipped external target is still removed from the in-tree model
393
+ // above: neither `active: false` nor a missing `output.create: false`
394
+ // destination may relocate it into `<sdk-repo>/<target>/`.
395
+ if (null != ext.skip) {
393
396
  log.info({
394
397
  point: 'generate-external-skip', target: ext.name, folder: ext.folder,
395
- note: ext.name + ' inactive, not generated'
398
+ note: ext.skip
396
399
  })
397
400
  continue
398
401
  }
@@ -673,6 +676,13 @@ type ExternalSpec = {
673
676
  }
674
677
 
675
678
 
679
+ type ExternalPlan = ExternalSpec & {
680
+ // Snapshotted before destination validation and consumed unchanged by the
681
+ // generation loop, so a filesystem race cannot bypass the safety guard.
682
+ skip: string | null
683
+ }
684
+
685
+
676
686
  // Targets declaring `output: path` — generated into their own repo rather
677
687
  // than into `<sdk-repo>/<target>/`.
678
688
  //
@@ -715,6 +725,32 @@ function externalItems(
715
725
  }
716
726
 
717
727
 
728
+ // Why this external item should not get a generation pass RIGHT NOW.
729
+ //
730
+ // `active: false` disables the target itself. `output.create: false` does
731
+ // something deliberately narrower: the target stays active in the model but
732
+ // an absent destination is treated as an optional checkout rather than a
733
+ // folder sdkgen should fabricate. If that repo is checked out later, the same
734
+ // unchanged model generates it normally.
735
+ //
736
+ // Snapshotted into ExternalPlan because both the pre-write destination guard
737
+ // and the actual pass must make the identical decision. If the guard skipped
738
+ // an item that the pass did not, generation could write outside the project
739
+ // without any of the ownership checks below.
740
+ function externalSkipReason(ext: ExternalSpec, fs: any): string | null {
741
+ if (!ext.active) {
742
+ return ext.name + ' inactive, not generated'
743
+ }
744
+
745
+ if (false === ext.target.output?.create && !fs.existsSync(ext.folder)) {
746
+ return ext.name + ' output folder does not exist and ' +
747
+ 'output.create=false, not generated'
748
+ }
749
+
750
+ return null
751
+ }
752
+
753
+
718
754
  // The `.jostraca` bookkeeping tree (meta log + a duplicate of the last
719
755
  // generated output) that jostraca leaves at an output root. It is the only
720
756
  // on-disk evidence that this toolchain has generated into a directory
@@ -754,14 +790,14 @@ const EXTERNAL_MARKER = '.jostraca'
754
790
  // generating somewhere other than it believes must be told. A destination
755
791
  // that legitimately holds other content first (a repo seeded with a README
756
792
  // and LICENCE) says so once in the model, with `output: adopt: true`.
757
- function checkExternalFolders(external: ExternalSpec[], root: string, fs: any) {
793
+ function checkExternalFolders(external: ExternalPlan[], root: string, fs: any) {
758
794
  const claimed: Record<string, string> = {}
759
795
 
760
796
  for (const ext of external) {
761
- // An inactive target writes nothing, so its destination is not a hazard
762
- // and switching a target off must not require keeping its now-unused
763
- // path valid.
764
- if (!ext.active) continue
797
+ // A skipped item writes nothing, so its destination is not a hazard. The
798
+ // snapshotted decision gates the actual pass too; keeping it identical is
799
+ // what makes the pre-write check complete.
800
+ if (null != ext.skip) continue
765
801
 
766
802
  const label = ext.kind.charAt(0).toUpperCase() + ext.kind.slice(1)
767
803
 
@@ -1107,6 +1143,7 @@ export {
1107
1143
  featureExcludes,
1108
1144
  fullsetExcludes,
1109
1145
  srcFeatureExcludes,
1146
+ stationLibrary,
1110
1147
 
1111
1148
  definitionPath,
1112
1149
  definitionFolder,
package/src/types.ts CHANGED
@@ -47,6 +47,11 @@ type ModelFeature = NameCases & {
47
47
  active?: boolean
48
48
  title?: string
49
49
  version?: string
50
+ // Transport role (station design §8.4): 'base' replaces the transport
51
+ // slot (only `test`), 'wrap' wraps it, 'none' is hook-only. Schema
52
+ // default is 'none'; configDefinition carries it into the embedded
53
+ // config beside the feature's `config.options`.
54
+ transport?: string
50
55
  hook?: Record<string, ModelHook>
51
56
  deps?: Record<string, Record<string, ModelDep>>
52
57
  [extra: string]: any
@@ -71,6 +76,7 @@ type ModelTarget = NameCases & {
71
76
  output?: {
72
77
  path?: string
73
78
  repo?: string
79
+ create?: boolean
74
80
  adopt?: boolean
75
81
  sdkrel?: string
76
82
  }
package/src/utility.ts CHANGED
@@ -318,7 +318,21 @@ function configDefinition(model: any, targetname?: string): { def: any, json: st
318
318
 
319
319
  const featureDefs: any = {}
320
320
  each(feature, (f: any) => {
321
- featureDefs[f.name] = f.config || {}
321
+ // The feature's declared config (its `options` key set with typed
322
+ // defaults) PLUS its transport role (station design §8.4): 'base'
323
+ // replaces the transport slot, 'wrap' wraps it, 'none' is hook-only.
324
+ // Station's descriptor (normalizeDescriptor in voxgig/station) reads
325
+ // `transport` beside `options` to validate the resolved feature order.
326
+ // The role is DECLARED in the feature model, never inferred - an empty
327
+ // `hook: {}` is wrong for station, which both wraps and dispatches
328
+ // hooks. Additive: a model unified without the schema's `transport`
329
+ // default simply omits the key, which station tolerates by degrading
330
+ // its role checks to nothing.
331
+ const fdef: any = { ...(f.config || {}) }
332
+ if (null != f.transport && '' !== f.transport) {
333
+ fdef.transport = String(f.transport)
334
+ }
335
+ featureDefs[f.name] = fdef
322
336
  })
323
337
 
324
338
  const options: any = { base: baseUrl }