@webpieces/openapi-generator 0.0.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.
Files changed (68) hide show
  1. package/README.md +118 -0
  2. package/package.json +32 -0
  3. package/src/OpenApiGenerationError.d.ts +41 -0
  4. package/src/OpenApiGenerationError.js +45 -0
  5. package/src/OpenApiGenerationError.js.map +1 -0
  6. package/src/cli/OpenApiCli.d.ts +33 -0
  7. package/src/cli/OpenApiCli.js +100 -0
  8. package/src/cli/OpenApiCli.js.map +1 -0
  9. package/src/cli/WpOpenApiMain.d.ts +25 -0
  10. package/src/cli/WpOpenApiMain.js +62 -0
  11. package/src/cli/WpOpenApiMain.js.map +1 -0
  12. package/src/cli/wp-openapi.d.ts +2 -0
  13. package/src/cli/wp-openapi.js +18 -0
  14. package/src/cli/wp-openapi.js.map +1 -0
  15. package/src/emit/ArtifactWriter.d.ts +44 -0
  16. package/src/emit/ArtifactWriter.js +75 -0
  17. package/src/emit/ArtifactWriter.js.map +1 -0
  18. package/src/generate/DocumentSelection.d.ts +96 -0
  19. package/src/generate/DocumentSelection.js +153 -0
  20. package/src/generate/DocumentSelection.js.map +1 -0
  21. package/src/generate/GenerationInputs.d.ts +67 -0
  22. package/src/generate/GenerationInputs.js +88 -0
  23. package/src/generate/GenerationInputs.js.map +1 -0
  24. package/src/generate/OpenApiGenerator.d.ts +113 -0
  25. package/src/generate/OpenApiGenerator.js +306 -0
  26. package/src/generate/OpenApiGenerator.js.map +1 -0
  27. package/src/generate/OperationRenderer.d.ts +129 -0
  28. package/src/generate/OperationRenderer.js +256 -0
  29. package/src/generate/OperationRenderer.js.map +1 -0
  30. package/src/generate/SchemaRenderer.d.ts +89 -0
  31. package/src/generate/SchemaRenderer.js +236 -0
  32. package/src/generate/SchemaRenderer.js.map +1 -0
  33. package/src/generate/SecurityDeriver.d.ts +39 -0
  34. package/src/generate/SecurityDeriver.js +81 -0
  35. package/src/generate/SecurityDeriver.js.map +1 -0
  36. package/src/index.d.ts +32 -0
  37. package/src/index.js +70 -0
  38. package/src/index.js.map +1 -0
  39. package/src/json/JsonObject.d.ts +35 -0
  40. package/src/json/JsonObject.js +32 -0
  41. package/src/json/JsonObject.js.map +1 -0
  42. package/src/json/JsonWriter.d.ts +18 -0
  43. package/src/json/JsonWriter.js +48 -0
  44. package/src/json/JsonWriter.js.map +1 -0
  45. package/src/json/YamlReader.d.ts +35 -0
  46. package/src/json/YamlReader.js +111 -0
  47. package/src/json/YamlReader.js.map +1 -0
  48. package/src/json/YamlWriter.d.ts +35 -0
  49. package/src/json/YamlWriter.js +88 -0
  50. package/src/json/YamlWriter.js.map +1 -0
  51. package/src/load/ExportedConstantFolder.d.ts +21 -0
  52. package/src/load/ExportedConstantFolder.js +57 -0
  53. package/src/load/ExportedConstantFolder.js.map +1 -0
  54. package/src/load/ForeignFailure.d.ts +24 -0
  55. package/src/load/ForeignFailure.js +41 -0
  56. package/src/load/ForeignFailure.js.map +1 -0
  57. package/src/load/InputsLoader.d.ts +43 -0
  58. package/src/load/InputsLoader.js +148 -0
  59. package/src/load/InputsLoader.js.map +1 -0
  60. package/src/manifest/JsonReader.d.ts +37 -0
  61. package/src/manifest/JsonReader.js +109 -0
  62. package/src/manifest/JsonReader.js.map +1 -0
  63. package/src/manifest/ManifestLoader.d.ts +20 -0
  64. package/src/manifest/ManifestLoader.js +69 -0
  65. package/src/manifest/ManifestLoader.js.map +1 -0
  66. package/src/manifest/OpenApiManifest.d.ts +116 -0
  67. package/src/manifest/OpenApiManifest.js +142 -0
  68. package/src/manifest/OpenApiManifest.js.map +1 -0
@@ -0,0 +1 @@
1
+ {"version":3,"file":"SchemaRenderer.js","sourceRoot":"","sources":["../../../../../../packages/docs/openapi-generator/src/generate/SchemaRenderer.ts"],"names":[],"mappings":";;;AACA,mDAA2D;AAE3D,qGAAqG;AACrG,MAAa,aAAa;IAGT;IAEA;IAJb;IACI,qEAAqE;IAC5D,OAAe;IACxB,qFAAqF;IAC5E,QAAgB;QAFhB,YAAO,GAAP,OAAO,CAAQ;QAEf,aAAQ,GAAR,QAAQ,CAAQ;IAC1B,CAAC;CACP;AAPD,sCAOC;AAED;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,MAAa,cAAc;IAIM;IAHZ,OAAO,GAAG,IAAI,GAAG,EAAU,CAAC;IAC5B,cAAc,GAAoB,EAAE,CAAC;IAEtD,YAA6B,KAA0C;QAA1C,UAAK,GAAL,KAAK,CAAqC;IAAG,CAAC;IAE3E,wFAAwF;IACxF,YAAY;QACR,OAAO,IAAI,CAAC,OAAO,CAAC;IACxB,CAAC;IAED,4FAA4F;IAC5F,QAAQ;QACJ,OAAO,IAAI,CAAC,cAAc,CAAC;IAC/B,CAAC;IAED;;;;;;;OAOG;IACH,UAAU;QACN,MAAM,QAAQ,GAAG,IAAI,GAAG,EAAkC,CAAC;QAC3D,IAAI,IAAI,GAAG,IAAI,CAAC;QAChB,OAAO,IAAI,EAAE,CAAC;YACV,IAAI,GAAG,KAAK,CAAC;YACb,KAAK,MAAM,IAAI,IAAI,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,EAAE,CAAC;gBAC1C,IAAI,QAAQ,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC;oBACrB,SAAS;gBACb,CAAC;gBACD,MAAM,IAAI,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;gBAClC,qFAAqF;gBACrF,QAAQ,CAAC,GAAG,CAAC,IAAI,EAAE,IAAI,KAAK,SAAS,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC,CAAC;gBAC1E,IAAI,GAAG,IAAI,CAAC;YAChB,CAAC;QACL,CAAC;QACD,MAAM,OAAO,GAAG,IAAI,uBAAU,EAAE,CAAC;QACjC,6FAA6F;QAC7F,wFAAwF;QACxF,KAAK,MAAM,IAAI,IAAI,KAAK,CAAC,IAAI,CAAC,QAAQ,CAAC,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC;YACpD,OAAO,CAAC,GAAG,CAAC,IAAI,EAAE,QAAQ,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC,CAAC;QAC1C,CAAC;QACD,OAAO,OAAO,CAAC;IACnB,CAAC;IAED,+FAA+F;IACvF,SAAS,CAAC,IAAoB;QAClC,MAAM,OAAO,GAAG,wBAAwB,IAAI,CAAC,IAAI,EAAE,CAAC;QACpD,IAAI,IAAI,CAAC,UAAU,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YAC7B,OAAO,IAAI,uBAAU,EAAE;iBAClB,GAAG,CAAC,MAAM,EAAE,QAAQ,CAAC;iBACrB,GAAG,CAAC,aAAa,EAAE,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC;iBAChD,GAAG,CAAC,MAAM,EAAE,IAAI,CAAC,UAAU,CAAC,KAAK,EAAE,CAAC,CAAC;QAC9C,CAAC;QACD,IAAI,IAAI,CAAC,aAAa,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YAChC,OAAO,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;QAC5B,CAAC;QACD,MAAM,UAAU,GAAG,IAAI,uBAAU,EAAE,CAAC;QACpC,MAAM,QAAQ,GAAa,EAAE,CAAC;QAC9B,KAAK,MAAM,KAAK,IAAI,IAAI,CAAC,MAAM,EAAE,CAAC;YAC9B,UAAU,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,EAAE,IAAI,CAAC,KAAK,CAAC,KAAK,EAAE,GAAG,OAAO,eAAe,KAAK,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC;YACrF,IAAI,CAAC,KAAK,CAAC,QAAQ,EAAE,CAAC;gBAClB,QAAQ,CAAC,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;YAC9B,CAAC;QACL,CAAC;QACD,OAAO,IAAI,uBAAU,EAAE;aAClB,GAAG,CAAC,MAAM,EAAE,QAAQ,CAAC;aACrB,GAAG,CAAC,aAAa,EAAE,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC;aAChD,GAAG,CAAC,YAAY,EAAE,UAAU,CAAC,OAAO,EAAE,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,UAAU,CAAC;aAChE,GAAG,CAAC,UAAU,EAAE,QAAQ,CAAC,MAAM,KAAK,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,QAAQ,CAAC;aAC7D,GAAG,CACA,sBAAsB,EACtB,IAAI,CAAC,mBAAmB,KAAK,SAAS;YAClC,CAAC,CAAC,SAAS;YACX,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,mBAAmB,EAAE,GAAG,OAAO,uBAAuB,CAAC,CAC/E,CAAC;IACV,CAAC;IAED;;;;OAIG;IACK,KAAK,CAAC,IAAoB;QAC9B,MAAM,QAAQ,GAAgB,IAAI,CAAC,aAAa,CAAC,GAAG,CAAC,CAAC,IAAY,EAAE,EAAE,CAClE,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,CACvB,CAAC;QACF,MAAM,MAAM,GAAG,IAAI,uBAAU,EAAE;aAC1B,GAAG,CAAC,aAAa,EAAE,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC;aAChD,GAAG,CAAC,OAAO,EAAE,QAAQ,CAAC,CAAC;QAC5B,IAAI,IAAI,CAAC,aAAa,KAAK,SAAS,EAAE,CAAC;YACnC,OAAO,MAAM,CAAC;QAClB,CAAC;QACD,MAAM,OAAO,GAAG,IAAI,uBAAU,EAAE,CAAC;QACjC,KAAK,MAAM,MAAM,IAAI,IAAI,CAAC,aAAa,EAAE,CAAC;YACtC,MAAM,KAAK,GAAG,IAAI,CAAC,aAAa,CAAC,YAAY,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC;YAC1D,IAAI,KAAK,KAAK,SAAS,EAAE,CAAC;gBACtB,OAAO,CAAC,GAAG,CAAC,KAAK,EAAE,wBAAwB,MAAM,EAAE,CAAC,CAAC;YACzD,CAAC;QACL,CAAC;QACD,OAAO,MAAM,CAAC,GAAG,CACb,eAAe,EACf,IAAI,uBAAU,EAAE;aACX,GAAG,CAAC,cAAc,EAAE,IAAI,CAAC,aAAa,CAAC,YAAY,CAAC;aACpD,GAAG,CAAC,SAAS,EAAE,OAAO,CAAC,CAC/B,CAAC;IACN,CAAC;IAED;;;;OAIG;IACH,KAAK,CAAC,KAAsB,EAAE,OAAe;QACzC,MAAM,OAAO,GAAG,KAAK,CAAC,IAAI,CAAC,IAAI,KAAK,OAAO,CAAC;QAC5C,MAAM,WAAW,GAAG,OAAO,CAAC,CAAC,CAAC,GAAG,OAAO,QAAQ,CAAC,CAAC,CAAC,OAAO,CAAC;QAC3D,MAAM,IAAI,GAAG,IAAI,CAAC,SAAS,CACvB,OAAO,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,KAAM,EAAE,WAAW,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,IAAI,EAAE,OAAO,CAAC,EACpF,KAAK,CACR,CAAC;QACF,MAAM,MAAM,GAAG,OAAO;YAClB,CAAC,CAAC,IAAI,uBAAU,EAAE,CAAC,GAAG,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,GAAG,CAAC,OAAO,EAAE,IAAI,CAAC;YAC1D,CAAC,CAAC,IAAI,CAAC,QAAQ,CAAC,IAAI,EAAE,KAAK,CAAC,QAAQ,CAAC,CAAC;QAC1C,IAAI,OAAO,IAAI,KAAK,CAAC,QAAQ,EAAE,CAAC;YAC5B,OAAO,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,QAAQ,CAAC,MAAM,EAAE,IAAI,CAAC,EAAE,KAAK,CAAC,CAAC;QAC9D,CAAC;QACD,OAAO,IAAI,CAAC,SAAS,CAAC,MAAM,EAAE,KAAK,CAAC,CAAC;IACzC,CAAC;IAED,+FAA+F;IACvF,SAAS,CAAC,MAAkB,EAAE,KAAsB;QACxD,OAAO,MAAM;aACR,GAAG,CAAC,aAAa,EAAE,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,WAAW,CAAC,CAAC;aACjD,GAAG,CAAC,mBAAmB,EAAE,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,cAAc,CAAC,CAAC,CAAC;IACpE,CAAC;IAEO,SAAS,CAAC,IAAgB,EAAE,KAAsB;QACtD,OAAO,IAAI,CAAC,GAAG,CAAC,QAAQ,EAAE,KAAK,CAAC,MAAM,CAAC,CAAC,GAAG,CAAC,SAAS,EAAE,KAAK,CAAC,GAAG,CAAC,CAAC,GAAG,CAAC,SAAS,EAAE,KAAK,CAAC,GAAG,CAAC,CAAC;IAChG,CAAC;IAED,+FAA+F;IACvF,QAAQ,CAAC,MAAkB,EAAE,UAAmB;QACpD,IAAI,CAAC,UAAU,EAAE,CAAC;YACd,OAAO,MAAM,CAAC;QAClB,CAAC;QACD,MAAM,QAAQ,GAAG,MAAM,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC;QACpC,IAAI,OAAO,QAAQ,KAAK,QAAQ,EAAE,CAAC;YAC/B,OAAO,MAAM,CAAC,GAAG,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE,MAAM,CAAC,CAAC,CAAC;QAClD,CAAC;QACD,OAAO,IAAI,uBAAU,EAAE,CAAC,GAAG,CAAC,OAAO,EAAE,CAAC,MAAM,EAAE,IAAI,uBAAU,EAAE,CAAC,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAAC,CAAC;IACzF,CAAC;IAED,yEAAyE;IACzE,IAAI,CAAC,GAAY,EAAE,OAAe;QAC9B,QAAQ,GAAG,CAAC,IAAI,EAAE,CAAC;YACf,KAAK,WAAW;gBACZ,OAAO,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,CAAC;YAC/B,KAAK,KAAK;gBACN,OAAO,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,OAAQ,CAAC,CAAC;YACxC,KAAK,OAAO;gBACR,OAAO,IAAI,uBAAU,EAAE;qBAClB,GAAG,CAAC,MAAM,EAAE,OAAO,CAAC;qBACpB,GAAG,CAAC,OAAO,EAAE,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,KAAM,EAAE,GAAG,OAAO,QAAQ,CAAC,CAAC,CAAC;YACjE,KAAK,SAAS;gBACV,OAAO,IAAI,uBAAU,EAAE;qBAClB,GAAG,CAAC,MAAM,EAAE,QAAQ,CAAC;qBACrB,GAAG,CACA,sBAAsB,EACtB,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,MAAO,EAAE,GAAG,OAAO,uBAAuB,CAAC,CAC5D,CAAC;YACV,KAAK,MAAM;gBACP,OAAO,IAAI,uBAAU,EAAE,CAAC,GAAG,CAAC,MAAM,EAAE,QAAQ,CAAC,CAAC,GAAG,CAAC,MAAM,EAAE,GAAG,CAAC,UAAU,CAAC,KAAK,EAAE,CAAC,CAAC;YACtF,KAAK,OAAO;gBACR,OAAO,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,CAAC;YAChC;gBACI,IAAI,CAAC,cAAc,CAAC,IAAI,CACpB,IAAI,aAAa,CAAC,OAAO,EAAE,GAAG,CAAC,YAAY,IAAI,WAAW,CAAC,CAC9D,CAAC;gBACF,OAAO,IAAI,uBAAU,EAAE,CAAC;QAChC,CAAC;IACL,CAAC;IAED;;;;;;;;OAQG;IACK,UAAU,CAAC,GAAY;QAC3B,MAAM,QAAQ,GAAG,GAAG,CAAC,aAAa,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;QAC7C,KAAK,MAAM,IAAI,IAAI,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,IAAI,EAAE,CAAC,EAAE,CAAC;YAC/C,IAAI,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,IAAI,CAAE,CAAC,aAAa,CAAC,IAAI,CAAC,GAAG,CAAC,KAAK,QAAQ,EAAE,CAAC;gBAC7D,OAAO,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC;YAChC,CAAC;QACL,CAAC;QACD,OAAO,IAAI,uBAAU,EAAE,CAAC,GAAG,CACvB,OAAO,EACP,GAAG,CAAC,aAAa,CAAC,GAAG,CAAC,CAAC,IAAY,EAAE,EAAE,CAAC,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC,CAChE,CAAC;IACN,CAAC;IAEO,SAAS,CAAC,GAAY;QAC1B,IAAI,GAAG,CAAC,SAAS,KAAK,SAAS,EAAE,CAAC;YAC9B,0FAA0F;YAC1F,mEAAmE;YACnE,OAAO,IAAI,uBAAU,EAAE,CAAC;QAC5B,CAAC;QACD,OAAO,IAAI,uBAAU,EAAE,CAAC,GAAG,CAAC,MAAM,EAAE,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,GAAG,CAAC,SAAU,CAAC,CAAC;IAClF,CAAC;IAEO,SAAS,CAAC,IAAY;QAC1B,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;QACvB,OAAO,IAAI,uBAAU,EAAE,CAAC,GAAG,CAAC,MAAM,EAAE,wBAAwB,IAAI,EAAE,CAAC,CAAC;IACxE,CAAC;IAED,+FAA+F;IACvF,KAAK,CAAC,IAAwB;QAClC,OAAO,IAAI,KAAK,SAAS,IAAI,IAAI,CAAC,IAAI,EAAE,KAAK,EAAE,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,IAAI,CAAC;IACvE,CAAC;CACJ;AAjOD,wCAiOC","sourcesContent":["import { DocumentedField, DocumentedType, TypeRef } from '@webpieces/api-doc-model';\nimport { JsonObject, JsonValue } from '../json/JsonObject';\n\n/** ONE field the renderer could not give a shape to, and WHERE in the document it would have sat. */\nexport class UnmappedField {\n constructor(\n /** A JSON pointer into the document that would have been written. */\n readonly pointer: string,\n /** The verbatim TypeScript type text, so the cure names the thing to go and type. */\n readonly typeText: string,\n ) {}\n}\n\n/**\n * {@link TypeRef} / {@link DocumentedType} -> JSON Schema 2020-12, which IS OpenAPI 3.1's schema\n * dialect and IS what MCP `tools/list` speaks. That identity is the reason #982 specifies 3.1 rather\n * than 3.0: the two are not \"similar dialects\", they are the same schemas, so the MCP projection\n * (#984) is a selection and an inline pass, not a translation.\n *\n * ## Three things 3.1 lets this renderer state HONESTLY that 3.0 could not\n *\n * - `type: [T, \"null\"]` for a nullable field, instead of 3.0's `nullable: true` keyword, which is not\n * JSON Schema at all.\n * - `description` BESIDE a `$ref`. In 3.0 a sibling of `$ref` is ignored, so a documented field whose\n * type is a named DTO simply lost its prose.\n * - OPTIONAL and NULLABLE as separate facts — absent from `required` versus `\"null\"` in `type`. `{}`\n * and `{x: null}` are different wire documents and a schema that conflates them rejects one.\n *\n * ## It records what it cannot map rather than emitting an untyped field\n *\n * An unmapped type yields an EMPTY schema, which in JSON Schema means \"anything\". That is precisely\n * the green-build-publishes-a-shapeless-field defect the guard exists to stop, so every one is\n * recorded with the pointer it would have occupied and {@link OpenApiGenerator} refuses on the set.\n */\nexport class SchemaRenderer {\n private readonly reached = new Set<string>();\n private readonly unmappedFields: UnmappedField[] = [];\n\n constructor(private readonly types: ReadonlyMap<string, DocumentedType>) {}\n\n /** Named types this renderer has been asked for, directly or through another schema. */\n reachedTypes(): ReadonlySet<string> {\n return this.reached;\n }\n\n /** Every field with no shape, with its pointer. Empty means the document is fully typed. */\n unmapped(): readonly UnmappedField[] {\n return this.unmappedFields;\n }\n\n /**\n * `components.schemas` for everything reachable from whatever has been rendered so far, expanded\n * to a FIXPOINT.\n *\n * A worklist and not recursion-with-a-guard because rendering a type reaches more types, and the\n * set has to close over that. It terminates for the same reason the extractor's walk does: a\n * named type is registered once, so the worklist strictly shrinks.\n */\n components(): JsonObject {\n const rendered = new Map<string, JsonObject | undefined>();\n let grew = true;\n while (grew) {\n grew = false;\n for (const name of Array.from(this.reached)) {\n if (rendered.has(name)) {\n continue;\n }\n const type = this.types.get(name);\n // Rendering it can add MORE names to `reached`, which is what the outer loop is for.\n rendered.set(name, type === undefined ? undefined : this.namedType(type));\n grew = true;\n }\n }\n const schemas = new JsonObject();\n // Alphabetical, because `components.schemas` is a lookup table and nothing reads it in order\n // — whereas discovery order would move every time an operation was added above another.\n for (const name of Array.from(rendered.keys()).sort()) {\n schemas.set(name, rendered.get(name));\n }\n return schemas;\n }\n\n /** One named type: an object DTO, a string enum, or a union with its DERIVED discriminator. */\n private namedType(type: DocumentedType): JsonObject {\n const pointer = `#/components/schemas/${type.name}`;\n if (type.enumValues.length > 0) {\n return new JsonObject()\n .set('type', 'string')\n .set('description', this.prose(type.description))\n .set('enum', type.enumValues.slice());\n }\n if (type.unionRefNames.length > 0) {\n return this.union(type);\n }\n const properties = new JsonObject();\n const required: string[] = [];\n for (const field of type.fields) {\n properties.set(field.name, this.field(field, `${pointer}/properties/${field.name}`));\n if (!field.optional) {\n required.push(field.name);\n }\n }\n return new JsonObject()\n .set('type', 'object')\n .set('description', this.prose(type.description))\n .set('properties', properties.isEmpty() ? undefined : properties)\n .set('required', required.length === 0 ? undefined : required)\n .set(\n 'additionalProperties',\n type.indexSignatureValue === undefined\n ? undefined\n : this.type(type.indexSignatureValue, `${pointer}/additionalProperties`),\n );\n }\n\n /**\n * A union, with a `discriminator` ONLY when the model derived one — which it does only when every\n * branch carries the same property typed as a single string literal. An invented discriminator\n * would claim a narrowing TypeScript itself cannot do.\n */\n private union(type: DocumentedType): JsonObject {\n const branches: JsonValue[] = type.unionRefNames.map((name: string) =>\n this.reference(name),\n );\n const schema = new JsonObject()\n .set('description', this.prose(type.description))\n .set('oneOf', branches);\n if (type.discriminator === undefined) {\n return schema;\n }\n const mapping = new JsonObject();\n for (const branch of type.unionRefNames) {\n const value = type.discriminator.branchValues.get(branch);\n if (value !== undefined) {\n mapping.set(value, `#/components/schemas/${branch}`);\n }\n }\n return schema.set(\n 'discriminator',\n new JsonObject()\n .set('propertyName', type.discriminator.propertyName)\n .set('mapping', mapping),\n );\n }\n\n /**\n * One FIELD: its type, plus the prose and the constraints that hang off the field rather than the\n * type. `@format`, `@WpMin` and `@WpMax` land on the SCALAR — on an array, on the ITEM — because\n * `minimum` on an array means nothing and a reader would have to guess which half was meant.\n */\n field(field: DocumentedField, pointer: string): JsonObject {\n const isArray = field.type.kind === 'array';\n const leafPointer = isArray ? `${pointer}/items` : pointer;\n const leaf = this.constrain(\n isArray ? this.type(field.type.items!, leafPointer) : this.type(field.type, pointer),\n field,\n );\n const schema = isArray\n ? new JsonObject().set('type', 'array').set('items', leaf)\n : this.nullable(leaf, field.nullable);\n if (isArray && field.nullable) {\n return this.described(this.nullable(schema, true), field);\n }\n return this.described(schema, field);\n }\n\n /** `description`, and the `@mcp` override as `x-mcp-description` when the author wrote one. */\n private described(schema: JsonObject, field: DocumentedField): JsonObject {\n return schema\n .set('description', this.prose(field.description))\n .set('x-mcp-description', this.prose(field.mcpDescription));\n }\n\n private constrain(leaf: JsonObject, field: DocumentedField): JsonObject {\n return leaf.set('format', field.format).set('minimum', field.min).set('maximum', field.max);\n }\n\n /** `type: [T, \"null\"]` where there is a type to widen; `anyOf` where the shape is a `$ref`. */\n private nullable(schema: JsonObject, isNullable: boolean): JsonObject {\n if (!isNullable) {\n return schema;\n }\n const declared = schema.get('type');\n if (typeof declared === 'string') {\n return schema.set('type', [declared, 'null']);\n }\n return new JsonObject().set('anyOf', [schema, new JsonObject().set('type', 'null')]);\n }\n\n /** One resolved type, with no field-level prose or constraints on it. */\n type(ref: TypeRef, pointer: string): JsonObject {\n switch (ref.kind) {\n case 'primitive':\n return this.primitive(ref);\n case 'ref':\n return this.reference(ref.refName!);\n case 'array':\n return new JsonObject()\n .set('type', 'array')\n .set('items', this.type(ref.items!, `${pointer}/items`));\n case 'openMap':\n return new JsonObject()\n .set('type', 'object')\n .set(\n 'additionalProperties',\n this.type(ref.values!, `${pointer}/additionalProperties`),\n );\n case 'enum':\n return new JsonObject().set('type', 'string').set('enum', ref.enumValues.slice());\n case 'union':\n return this.namedUnion(ref);\n default:\n this.unmappedFields.push(\n new UnmappedField(pointer, ref.unmappedText ?? '<unknown>'),\n );\n return new JsonObject();\n }\n }\n\n /**\n * A union, as a `$ref` at the NAMED alias when the model registered one.\n *\n * The model records a `type X = A | B` alias as its own entry — carrying the DERIVED\n * discriminator — while the FIELD that used it holds a bare union of branch names. Rendering the\n * field's union inline would therefore publish the `oneOf` and silently drop the discriminator,\n * which is the one part of a union a client actually needs to narrow on. So the alias is looked\n * up by its branch list and referenced.\n */\n private namedUnion(ref: TypeRef): JsonObject {\n const branches = ref.unionRefNames.join(',');\n for (const name of Array.from(this.types.keys())) {\n if (this.types.get(name)!.unionRefNames.join(',') === branches) {\n return this.reference(name);\n }\n }\n return new JsonObject().set(\n 'oneOf',\n ref.unionRefNames.map((each: string) => this.reference(each)),\n );\n }\n\n private primitive(ref: TypeRef): JsonObject {\n if (ref.primitive === 'unknown') {\n // No `type` at all: JSON Schema's honest spelling of \"any shape\". It is only ever reached\n // by a `void` return, which is why it is not the unmapped refusal.\n return new JsonObject();\n }\n return new JsonObject().set('type', ref.integer ? 'integer' : ref.primitive!);\n }\n\n private reference(name: string): JsonObject {\n this.reached.add(name);\n return new JsonObject().set('$ref', `#/components/schemas/${name}`);\n }\n\n /** Empty prose is ABSENT prose. An empty `description` key is noise in every rendered page. */\n private prose(text: string | undefined): string | undefined {\n return text === undefined || text.trim() === '' ? undefined : text;\n }\n}\n"]}
@@ -0,0 +1,39 @@
1
+ import { DocumentedApiKey } from '@webpieces/api-doc-model';
2
+ import { JsonObject, JsonValue } from '../json/JsonObject';
3
+ /**
4
+ * `components.securitySchemes` and the `security` requirement, DERIVED from the contract's own
5
+ * `@WpAuthApiKey(regime, credentials)`. The manifest contributes the published KEYS and nothing else.
6
+ *
7
+ * ## Why the schemes are not in the manifest
8
+ *
9
+ * A `components.securitySchemes` block in a JSON file would be a second copy of header names the
10
+ * running server never reads — and nothing could contradict it. Deriving them from the decorator
11
+ * means the published document and the hook that enforces the credential are the same declaration,
12
+ * so the document cannot say `x-api-key` while the server checks `x-partner-key`. The manifest keeps
13
+ * the KEYS because a scheme key is partner-visible naming, which is a product decision.
14
+ *
15
+ * ## ONE requirement object holding every scheme, never a list of one-key objects
16
+ *
17
+ * OpenAPI's `security` is a list of ALTERNATIVES, and each alternative is an object whose keys must
18
+ * ALL be satisfied. So:
19
+ *
20
+ * ```
21
+ * [{ PartnerApiKey: [], PartnerOrg: [] }] // AND — present both. What a real regime means.
22
+ * [{ PartnerApiKey: [] }, { PartnerOrg: [] }] // OR — "either header alone suffices". A lie.
23
+ * ```
24
+ *
25
+ * The second form is the dangerous default because it is what "a list of credentials" reads like,
26
+ * and NO BUILD COULD CONTRADICT IT: the document would be well-formed, the tooling green, and a
27
+ * partner told they may skip the organization header. Hence one object, always.
28
+ */
29
+ export declare class SecurityDeriver {
30
+ /** Every scheme, keyed by the manifest's published names, in declaration order. */
31
+ schemes(apiKey: DocumentedApiKey, schemeNames: readonly string[], manifestPath: string): JsonObject;
32
+ /**
33
+ * ONE credential -> ONE scheme. The two shapes are STRUCTURALLY different documents, which is
34
+ * exactly why `ApiKeyCredential` is a union in the framework rather than one optional field.
35
+ */
36
+ private scheme;
37
+ /** The ONE AND-ed requirement — see the class doc for why it is one object and not a list. */
38
+ requirement(schemeNames: readonly string[]): readonly JsonValue[];
39
+ }
@@ -0,0 +1,81 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.SecurityDeriver = void 0;
4
+ const JsonObject_1 = require("../json/JsonObject");
5
+ const OpenApiGenerationError_1 = require("../OpenApiGenerationError");
6
+ /**
7
+ * `components.securitySchemes` and the `security` requirement, DERIVED from the contract's own
8
+ * `@WpAuthApiKey(regime, credentials)`. The manifest contributes the published KEYS and nothing else.
9
+ *
10
+ * ## Why the schemes are not in the manifest
11
+ *
12
+ * A `components.securitySchemes` block in a JSON file would be a second copy of header names the
13
+ * running server never reads — and nothing could contradict it. Deriving them from the decorator
14
+ * means the published document and the hook that enforces the credential are the same declaration,
15
+ * so the document cannot say `x-api-key` while the server checks `x-partner-key`. The manifest keeps
16
+ * the KEYS because a scheme key is partner-visible naming, which is a product decision.
17
+ *
18
+ * ## ONE requirement object holding every scheme, never a list of one-key objects
19
+ *
20
+ * OpenAPI's `security` is a list of ALTERNATIVES, and each alternative is an object whose keys must
21
+ * ALL be satisfied. So:
22
+ *
23
+ * ```
24
+ * [{ PartnerApiKey: [], PartnerOrg: [] }] // AND — present both. What a real regime means.
25
+ * [{ PartnerApiKey: [] }, { PartnerOrg: [] }] // OR — "either header alone suffices". A lie.
26
+ * ```
27
+ *
28
+ * The second form is the dangerous default because it is what "a list of credentials" reads like,
29
+ * and NO BUILD COULD CONTRADICT IT: the document would be well-formed, the tooling green, and a
30
+ * partner told they may skip the organization header. Hence one object, always.
31
+ */
32
+ class SecurityDeriver {
33
+ /** Every scheme, keyed by the manifest's published names, in declaration order. */
34
+ schemes(apiKey, schemeNames, manifestPath) {
35
+ if (schemeNames.length !== apiKey.credentials.length) {
36
+ throw new OpenApiGenerationError_1.OpenApiGenerationError(`securitySchemeNames has ${schemeNames.length} name(s) but the '${apiKey.regime}' ` +
37
+ `regime declares ${apiKey.credentials.length} credential(s)`, manifestPath, 'Give exactly one published scheme name per credential, in the order the ' +
38
+ 'contract declares them. The names are partner-visible; the credentials are not ' +
39
+ 'the manifest to choose.');
40
+ }
41
+ const schemes = new JsonObject_1.JsonObject();
42
+ for (let i = 0; i < schemeNames.length; i++) {
43
+ schemes.set(schemeNames[i], this.scheme(apiKey.credentials[i], manifestPath));
44
+ }
45
+ return schemes;
46
+ }
47
+ /**
48
+ * ONE credential -> ONE scheme. The two shapes are STRUCTURALLY different documents, which is
49
+ * exactly why `ApiKeyCredential` is a union in the framework rather than one optional field.
50
+ */
51
+ scheme(credential, manifestPath) {
52
+ if (credential.location === 'bearer') {
53
+ return new JsonObject_1.JsonObject()
54
+ .set('type', 'http')
55
+ .set('scheme', 'bearer')
56
+ .set('description', credential.description);
57
+ }
58
+ if (credential.location !== 'header') {
59
+ throw new OpenApiGenerationError_1.OpenApiGenerationError(`unknown api-key credential location '${credential.location}'`, manifestPath, "A credential rides `in: 'header'` with a name, or `in: 'bearer'`.");
60
+ }
61
+ if (credential.name === undefined) {
62
+ throw new OpenApiGenerationError_1.OpenApiGenerationError('a header api-key credential declares no header name', manifestPath, "Write `{ in: 'header', name: 'x-api-key' }`; a header credential with no name " +
63
+ 'is unusable and cannot be published.');
64
+ }
65
+ return new JsonObject_1.JsonObject()
66
+ .set('type', 'apiKey')
67
+ .set('in', 'header')
68
+ .set('name', credential.name)
69
+ .set('description', credential.description);
70
+ }
71
+ /** The ONE AND-ed requirement — see the class doc for why it is one object and not a list. */
72
+ requirement(schemeNames) {
73
+ const anded = new JsonObject_1.JsonObject();
74
+ for (const name of schemeNames) {
75
+ anded.set(name, []);
76
+ }
77
+ return [anded];
78
+ }
79
+ }
80
+ exports.SecurityDeriver = SecurityDeriver;
81
+ //# sourceMappingURL=SecurityDeriver.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"SecurityDeriver.js","sourceRoot":"","sources":["../../../../../../packages/docs/openapi-generator/src/generate/SecurityDeriver.ts"],"names":[],"mappings":";;;AACA,mDAA2D;AAC3D,sEAAmE;AAEnE;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AACH,MAAa,eAAe;IACxB,mFAAmF;IACnF,OAAO,CACH,MAAwB,EACxB,WAA8B,EAC9B,YAAoB;QAEpB,IAAI,WAAW,CAAC,MAAM,KAAK,MAAM,CAAC,WAAW,CAAC,MAAM,EAAE,CAAC;YACnD,MAAM,IAAI,+CAAsB,CAC5B,2BAA2B,WAAW,CAAC,MAAM,qBAAqB,MAAM,CAAC,MAAM,IAAI;gBAC/E,mBAAmB,MAAM,CAAC,WAAW,CAAC,MAAM,gBAAgB,EAChE,YAAY,EACZ,0EAA0E;gBACtE,iFAAiF;gBACjF,yBAAyB,CAChC,CAAC;QACN,CAAC;QACD,MAAM,OAAO,GAAG,IAAI,uBAAU,EAAE,CAAC;QACjC,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,WAAW,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;YAC1C,OAAO,CAAC,GAAG,CAAC,WAAW,CAAC,CAAC,CAAE,EAAE,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC,WAAW,CAAC,CAAC,CAAE,EAAE,YAAY,CAAC,CAAC,CAAC;QACpF,CAAC;QACD,OAAO,OAAO,CAAC;IACnB,CAAC;IAED;;;OAGG;IACK,MAAM,CAAC,UAAsC,EAAE,YAAoB;QACvE,IAAI,UAAU,CAAC,QAAQ,KAAK,QAAQ,EAAE,CAAC;YACnC,OAAO,IAAI,uBAAU,EAAE;iBAClB,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC;iBACnB,GAAG,CAAC,QAAQ,EAAE,QAAQ,CAAC;iBACvB,GAAG,CAAC,aAAa,EAAE,UAAU,CAAC,WAAW,CAAC,CAAC;QACpD,CAAC;QACD,IAAI,UAAU,CAAC,QAAQ,KAAK,QAAQ,EAAE,CAAC;YACnC,MAAM,IAAI,+CAAsB,CAC5B,wCAAwC,UAAU,CAAC,QAAQ,GAAG,EAC9D,YAAY,EACZ,mEAAmE,CACtE,CAAC;QACN,CAAC;QACD,IAAI,UAAU,CAAC,IAAI,KAAK,SAAS,EAAE,CAAC;YAChC,MAAM,IAAI,+CAAsB,CAC5B,qDAAqD,EACrD,YAAY,EACZ,gFAAgF;gBAC5E,sCAAsC,CAC7C,CAAC;QACN,CAAC;QACD,OAAO,IAAI,uBAAU,EAAE;aAClB,GAAG,CAAC,MAAM,EAAE,QAAQ,CAAC;aACrB,GAAG,CAAC,IAAI,EAAE,QAAQ,CAAC;aACnB,GAAG,CAAC,MAAM,EAAE,UAAU,CAAC,IAAI,CAAC;aAC5B,GAAG,CAAC,aAAa,EAAE,UAAU,CAAC,WAAW,CAAC,CAAC;IACpD,CAAC;IAED,8FAA8F;IAC9F,WAAW,CAAC,WAA8B;QACtC,MAAM,KAAK,GAAG,IAAI,uBAAU,EAAE,CAAC;QAC/B,KAAK,MAAM,IAAI,IAAI,WAAW,EAAE,CAAC;YAC7B,KAAK,CAAC,GAAG,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC;QACxB,CAAC;QACD,OAAO,CAAC,KAAK,CAAC,CAAC;IACnB,CAAC;CACJ;AAjED,0CAiEC","sourcesContent":["import { DocumentedApiKey, DocumentedApiKeyCredential } from '@webpieces/api-doc-model';\nimport { JsonObject, JsonValue } from '../json/JsonObject';\nimport { OpenApiGenerationError } from '../OpenApiGenerationError';\n\n/**\n * `components.securitySchemes` and the `security` requirement, DERIVED from the contract's own\n * `@WpAuthApiKey(regime, credentials)`. The manifest contributes the published KEYS and nothing else.\n *\n * ## Why the schemes are not in the manifest\n *\n * A `components.securitySchemes` block in a JSON file would be a second copy of header names the\n * running server never reads — and nothing could contradict it. Deriving them from the decorator\n * means the published document and the hook that enforces the credential are the same declaration,\n * so the document cannot say `x-api-key` while the server checks `x-partner-key`. The manifest keeps\n * the KEYS because a scheme key is partner-visible naming, which is a product decision.\n *\n * ## ONE requirement object holding every scheme, never a list of one-key objects\n *\n * OpenAPI's `security` is a list of ALTERNATIVES, and each alternative is an object whose keys must\n * ALL be satisfied. So:\n *\n * ```\n * [{ PartnerApiKey: [], PartnerOrg: [] }] // AND — present both. What a real regime means.\n * [{ PartnerApiKey: [] }, { PartnerOrg: [] }] // OR — \"either header alone suffices\". A lie.\n * ```\n *\n * The second form is the dangerous default because it is what \"a list of credentials\" reads like,\n * and NO BUILD COULD CONTRADICT IT: the document would be well-formed, the tooling green, and a\n * partner told they may skip the organization header. Hence one object, always.\n */\nexport class SecurityDeriver {\n /** Every scheme, keyed by the manifest's published names, in declaration order. */\n schemes(\n apiKey: DocumentedApiKey,\n schemeNames: readonly string[],\n manifestPath: string,\n ): JsonObject {\n if (schemeNames.length !== apiKey.credentials.length) {\n throw new OpenApiGenerationError(\n `securitySchemeNames has ${schemeNames.length} name(s) but the '${apiKey.regime}' ` +\n `regime declares ${apiKey.credentials.length} credential(s)`,\n manifestPath,\n 'Give exactly one published scheme name per credential, in the order the ' +\n 'contract declares them. The names are partner-visible; the credentials are not ' +\n 'the manifest to choose.',\n );\n }\n const schemes = new JsonObject();\n for (let i = 0; i < schemeNames.length; i++) {\n schemes.set(schemeNames[i]!, this.scheme(apiKey.credentials[i]!, manifestPath));\n }\n return schemes;\n }\n\n /**\n * ONE credential -> ONE scheme. The two shapes are STRUCTURALLY different documents, which is\n * exactly why `ApiKeyCredential` is a union in the framework rather than one optional field.\n */\n private scheme(credential: DocumentedApiKeyCredential, manifestPath: string): JsonObject {\n if (credential.location === 'bearer') {\n return new JsonObject()\n .set('type', 'http')\n .set('scheme', 'bearer')\n .set('description', credential.description);\n }\n if (credential.location !== 'header') {\n throw new OpenApiGenerationError(\n `unknown api-key credential location '${credential.location}'`,\n manifestPath,\n \"A credential rides `in: 'header'` with a name, or `in: 'bearer'`.\",\n );\n }\n if (credential.name === undefined) {\n throw new OpenApiGenerationError(\n 'a header api-key credential declares no header name',\n manifestPath,\n \"Write `{ in: 'header', name: 'x-api-key' }`; a header credential with no name \" +\n 'is unusable and cannot be published.',\n );\n }\n return new JsonObject()\n .set('type', 'apiKey')\n .set('in', 'header')\n .set('name', credential.name)\n .set('description', credential.description);\n }\n\n /** The ONE AND-ed requirement — see the class doc for why it is one object and not a list. */\n requirement(schemeNames: readonly string[]): readonly JsonValue[] {\n const anded = new JsonObject();\n for (const name of schemeNames) {\n anded.set(name, []);\n }\n return [anded];\n }\n}\n"]}
package/src/index.d.ts ADDED
@@ -0,0 +1,32 @@
1
+ /**
2
+ * `@webpieces/openapi-generator` — render an `ApiDocModel` to OpenAPI 3.1.0.
3
+ *
4
+ * ONE generation pass produces TWO documents: the CANONICAL internal one, which carries every
5
+ * operation including hidden ones plus the `x-mcp-*` extensions, and the CUSTOMER one, from which a
6
+ * hidden endpoint is absent entirely. They are byte-identical when nothing is hidden, which is the
7
+ * property that makes hiding reviewable — see `responsibilities.md`.
8
+ *
9
+ * It ships the `wp-openapi` bin, and depends on `typescript` and `@webpieces/api-doc-model` alone.
10
+ */
11
+ export { OpenApiGenerationError } from './OpenApiGenerationError';
12
+ export { JsonObject } from './json/JsonObject';
13
+ export type { JsonValue } from './json/JsonObject';
14
+ export { JsonWriter } from './json/JsonWriter';
15
+ export { YamlWriter } from './json/YamlWriter';
16
+ export { YamlReader } from './json/YamlReader';
17
+ export { ApiEntry, ErrorResponseEntry, ErrorsEntry, OpenApiManifest, ResponseHeaderEntry, ServerEntry, } from './manifest/OpenApiManifest';
18
+ export { JsonReader } from './manifest/JsonReader';
19
+ export { ManifestLoader } from './manifest/ManifestLoader';
20
+ export { ContractModel, GeneratedDocument, GeneratedDocuments, GenerationInputs, ResolvedResponseHeader, } from './generate/GenerationInputs';
21
+ export { DocumentSelection, INTERNAL_ONLY_LINE, OPERATION_SEMANTICS, } from './generate/DocumentSelection';
22
+ export { OpenApiGenerator } from './generate/OpenApiGenerator';
23
+ export { OperationRenderer, ResponseContract } from './generate/OperationRenderer';
24
+ export { SchemaRenderer, UnmappedField } from './generate/SchemaRenderer';
25
+ export { SecurityDeriver } from './generate/SecurityDeriver';
26
+ export { ExportedConstantFolder } from './load/ExportedConstantFolder';
27
+ export { ForeignFailure } from './load/ForeignFailure';
28
+ export { InputsLoader } from './load/InputsLoader';
29
+ export { ArtifactWriter, GeneratedArtifact } from './emit/ArtifactWriter';
30
+ export type { OutputFormat } from './emit/ArtifactWriter';
31
+ export { CliResult, OpenApiCli, USAGE } from './cli/OpenApiCli';
32
+ export { WpOpenApiMain } from './cli/WpOpenApiMain';
package/src/index.js ADDED
@@ -0,0 +1,70 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.WpOpenApiMain = exports.USAGE = exports.OpenApiCli = exports.CliResult = exports.GeneratedArtifact = exports.ArtifactWriter = exports.InputsLoader = exports.ForeignFailure = exports.ExportedConstantFolder = exports.SecurityDeriver = exports.UnmappedField = exports.SchemaRenderer = exports.ResponseContract = exports.OperationRenderer = exports.OpenApiGenerator = exports.OPERATION_SEMANTICS = exports.INTERNAL_ONLY_LINE = exports.DocumentSelection = exports.ResolvedResponseHeader = exports.GenerationInputs = exports.GeneratedDocuments = exports.GeneratedDocument = exports.ContractModel = exports.ManifestLoader = exports.JsonReader = exports.ServerEntry = exports.ResponseHeaderEntry = exports.OpenApiManifest = exports.ErrorsEntry = exports.ErrorResponseEntry = exports.ApiEntry = exports.YamlReader = exports.YamlWriter = exports.JsonWriter = exports.JsonObject = exports.OpenApiGenerationError = void 0;
4
+ /**
5
+ * `@webpieces/openapi-generator` — render an `ApiDocModel` to OpenAPI 3.1.0.
6
+ *
7
+ * ONE generation pass produces TWO documents: the CANONICAL internal one, which carries every
8
+ * operation including hidden ones plus the `x-mcp-*` extensions, and the CUSTOMER one, from which a
9
+ * hidden endpoint is absent entirely. They are byte-identical when nothing is hidden, which is the
10
+ * property that makes hiding reviewable — see `responsibilities.md`.
11
+ *
12
+ * It ships the `wp-openapi` bin, and depends on `typescript` and `@webpieces/api-doc-model` alone.
13
+ */
14
+ var OpenApiGenerationError_1 = require("./OpenApiGenerationError");
15
+ Object.defineProperty(exports, "OpenApiGenerationError", { enumerable: true, get: function () { return OpenApiGenerationError_1.OpenApiGenerationError; } });
16
+ var JsonObject_1 = require("./json/JsonObject");
17
+ Object.defineProperty(exports, "JsonObject", { enumerable: true, get: function () { return JsonObject_1.JsonObject; } });
18
+ var JsonWriter_1 = require("./json/JsonWriter");
19
+ Object.defineProperty(exports, "JsonWriter", { enumerable: true, get: function () { return JsonWriter_1.JsonWriter; } });
20
+ var YamlWriter_1 = require("./json/YamlWriter");
21
+ Object.defineProperty(exports, "YamlWriter", { enumerable: true, get: function () { return YamlWriter_1.YamlWriter; } });
22
+ var YamlReader_1 = require("./json/YamlReader");
23
+ Object.defineProperty(exports, "YamlReader", { enumerable: true, get: function () { return YamlReader_1.YamlReader; } });
24
+ var OpenApiManifest_1 = require("./manifest/OpenApiManifest");
25
+ Object.defineProperty(exports, "ApiEntry", { enumerable: true, get: function () { return OpenApiManifest_1.ApiEntry; } });
26
+ Object.defineProperty(exports, "ErrorResponseEntry", { enumerable: true, get: function () { return OpenApiManifest_1.ErrorResponseEntry; } });
27
+ Object.defineProperty(exports, "ErrorsEntry", { enumerable: true, get: function () { return OpenApiManifest_1.ErrorsEntry; } });
28
+ Object.defineProperty(exports, "OpenApiManifest", { enumerable: true, get: function () { return OpenApiManifest_1.OpenApiManifest; } });
29
+ Object.defineProperty(exports, "ResponseHeaderEntry", { enumerable: true, get: function () { return OpenApiManifest_1.ResponseHeaderEntry; } });
30
+ Object.defineProperty(exports, "ServerEntry", { enumerable: true, get: function () { return OpenApiManifest_1.ServerEntry; } });
31
+ var JsonReader_1 = require("./manifest/JsonReader");
32
+ Object.defineProperty(exports, "JsonReader", { enumerable: true, get: function () { return JsonReader_1.JsonReader; } });
33
+ var ManifestLoader_1 = require("./manifest/ManifestLoader");
34
+ Object.defineProperty(exports, "ManifestLoader", { enumerable: true, get: function () { return ManifestLoader_1.ManifestLoader; } });
35
+ var GenerationInputs_1 = require("./generate/GenerationInputs");
36
+ Object.defineProperty(exports, "ContractModel", { enumerable: true, get: function () { return GenerationInputs_1.ContractModel; } });
37
+ Object.defineProperty(exports, "GeneratedDocument", { enumerable: true, get: function () { return GenerationInputs_1.GeneratedDocument; } });
38
+ Object.defineProperty(exports, "GeneratedDocuments", { enumerable: true, get: function () { return GenerationInputs_1.GeneratedDocuments; } });
39
+ Object.defineProperty(exports, "GenerationInputs", { enumerable: true, get: function () { return GenerationInputs_1.GenerationInputs; } });
40
+ Object.defineProperty(exports, "ResolvedResponseHeader", { enumerable: true, get: function () { return GenerationInputs_1.ResolvedResponseHeader; } });
41
+ var DocumentSelection_1 = require("./generate/DocumentSelection");
42
+ Object.defineProperty(exports, "DocumentSelection", { enumerable: true, get: function () { return DocumentSelection_1.DocumentSelection; } });
43
+ Object.defineProperty(exports, "INTERNAL_ONLY_LINE", { enumerable: true, get: function () { return DocumentSelection_1.INTERNAL_ONLY_LINE; } });
44
+ Object.defineProperty(exports, "OPERATION_SEMANTICS", { enumerable: true, get: function () { return DocumentSelection_1.OPERATION_SEMANTICS; } });
45
+ var OpenApiGenerator_1 = require("./generate/OpenApiGenerator");
46
+ Object.defineProperty(exports, "OpenApiGenerator", { enumerable: true, get: function () { return OpenApiGenerator_1.OpenApiGenerator; } });
47
+ var OperationRenderer_1 = require("./generate/OperationRenderer");
48
+ Object.defineProperty(exports, "OperationRenderer", { enumerable: true, get: function () { return OperationRenderer_1.OperationRenderer; } });
49
+ Object.defineProperty(exports, "ResponseContract", { enumerable: true, get: function () { return OperationRenderer_1.ResponseContract; } });
50
+ var SchemaRenderer_1 = require("./generate/SchemaRenderer");
51
+ Object.defineProperty(exports, "SchemaRenderer", { enumerable: true, get: function () { return SchemaRenderer_1.SchemaRenderer; } });
52
+ Object.defineProperty(exports, "UnmappedField", { enumerable: true, get: function () { return SchemaRenderer_1.UnmappedField; } });
53
+ var SecurityDeriver_1 = require("./generate/SecurityDeriver");
54
+ Object.defineProperty(exports, "SecurityDeriver", { enumerable: true, get: function () { return SecurityDeriver_1.SecurityDeriver; } });
55
+ var ExportedConstantFolder_1 = require("./load/ExportedConstantFolder");
56
+ Object.defineProperty(exports, "ExportedConstantFolder", { enumerable: true, get: function () { return ExportedConstantFolder_1.ExportedConstantFolder; } });
57
+ var ForeignFailure_1 = require("./load/ForeignFailure");
58
+ Object.defineProperty(exports, "ForeignFailure", { enumerable: true, get: function () { return ForeignFailure_1.ForeignFailure; } });
59
+ var InputsLoader_1 = require("./load/InputsLoader");
60
+ Object.defineProperty(exports, "InputsLoader", { enumerable: true, get: function () { return InputsLoader_1.InputsLoader; } });
61
+ var ArtifactWriter_1 = require("./emit/ArtifactWriter");
62
+ Object.defineProperty(exports, "ArtifactWriter", { enumerable: true, get: function () { return ArtifactWriter_1.ArtifactWriter; } });
63
+ Object.defineProperty(exports, "GeneratedArtifact", { enumerable: true, get: function () { return ArtifactWriter_1.GeneratedArtifact; } });
64
+ var OpenApiCli_1 = require("./cli/OpenApiCli");
65
+ Object.defineProperty(exports, "CliResult", { enumerable: true, get: function () { return OpenApiCli_1.CliResult; } });
66
+ Object.defineProperty(exports, "OpenApiCli", { enumerable: true, get: function () { return OpenApiCli_1.OpenApiCli; } });
67
+ Object.defineProperty(exports, "USAGE", { enumerable: true, get: function () { return OpenApiCli_1.USAGE; } });
68
+ var WpOpenApiMain_1 = require("./cli/WpOpenApiMain");
69
+ Object.defineProperty(exports, "WpOpenApiMain", { enumerable: true, get: function () { return WpOpenApiMain_1.WpOpenApiMain; } });
70
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../../packages/docs/openapi-generator/src/index.ts"],"names":[],"mappings":";;;AAAA;;;;;;;;;GASG;AACH,mEAAkE;AAAzD,gIAAA,sBAAsB,OAAA;AAC/B,gDAA+C;AAAtC,wGAAA,UAAU,OAAA;AAEnB,gDAA+C;AAAtC,wGAAA,UAAU,OAAA;AACnB,gDAA+C;AAAtC,wGAAA,UAAU,OAAA;AACnB,gDAA+C;AAAtC,wGAAA,UAAU,OAAA;AACnB,8DAOoC;AANhC,2GAAA,QAAQ,OAAA;AACR,qHAAA,kBAAkB,OAAA;AAClB,8GAAA,WAAW,OAAA;AACX,kHAAA,eAAe,OAAA;AACf,sHAAA,mBAAmB,OAAA;AACnB,8GAAA,WAAW,OAAA;AAEf,oDAAmD;AAA1C,wGAAA,UAAU,OAAA;AACnB,4DAA2D;AAAlD,gHAAA,cAAc,OAAA;AACvB,gEAMqC;AALjC,iHAAA,aAAa,OAAA;AACb,qHAAA,iBAAiB,OAAA;AACjB,sHAAA,kBAAkB,OAAA;AAClB,oHAAA,gBAAgB,OAAA;AAChB,0HAAA,sBAAsB,OAAA;AAE1B,kEAIsC;AAHlC,sHAAA,iBAAiB,OAAA;AACjB,uHAAA,kBAAkB,OAAA;AAClB,wHAAA,mBAAmB,OAAA;AAEvB,gEAA+D;AAAtD,oHAAA,gBAAgB,OAAA;AACzB,kEAAmF;AAA1E,sHAAA,iBAAiB,OAAA;AAAE,qHAAA,gBAAgB,OAAA;AAC5C,4DAA0E;AAAjE,gHAAA,cAAc,OAAA;AAAE,+GAAA,aAAa,OAAA;AACtC,8DAA6D;AAApD,kHAAA,eAAe,OAAA;AACxB,wEAAuE;AAA9D,gIAAA,sBAAsB,OAAA;AAC/B,wDAAuD;AAA9C,gHAAA,cAAc,OAAA;AACvB,oDAAmD;AAA1C,4GAAA,YAAY,OAAA;AACrB,wDAA0E;AAAjE,gHAAA,cAAc,OAAA;AAAE,mHAAA,iBAAiB,OAAA;AAE1C,+CAAgE;AAAvD,uGAAA,SAAS,OAAA;AAAE,wGAAA,UAAU,OAAA;AAAE,mGAAA,KAAK,OAAA;AACrC,qDAAoD;AAA3C,8GAAA,aAAa,OAAA","sourcesContent":["/**\n * `@webpieces/openapi-generator` — render an `ApiDocModel` to OpenAPI 3.1.0.\n *\n * ONE generation pass produces TWO documents: the CANONICAL internal one, which carries every\n * operation including hidden ones plus the `x-mcp-*` extensions, and the CUSTOMER one, from which a\n * hidden endpoint is absent entirely. They are byte-identical when nothing is hidden, which is the\n * property that makes hiding reviewable — see `responsibilities.md`.\n *\n * It ships the `wp-openapi` bin, and depends on `typescript` and `@webpieces/api-doc-model` alone.\n */\nexport { OpenApiGenerationError } from './OpenApiGenerationError';\nexport { JsonObject } from './json/JsonObject';\nexport type { JsonValue } from './json/JsonObject';\nexport { JsonWriter } from './json/JsonWriter';\nexport { YamlWriter } from './json/YamlWriter';\nexport { YamlReader } from './json/YamlReader';\nexport {\n ApiEntry,\n ErrorResponseEntry,\n ErrorsEntry,\n OpenApiManifest,\n ResponseHeaderEntry,\n ServerEntry,\n} from './manifest/OpenApiManifest';\nexport { JsonReader } from './manifest/JsonReader';\nexport { ManifestLoader } from './manifest/ManifestLoader';\nexport {\n ContractModel,\n GeneratedDocument,\n GeneratedDocuments,\n GenerationInputs,\n ResolvedResponseHeader,\n} from './generate/GenerationInputs';\nexport {\n DocumentSelection,\n INTERNAL_ONLY_LINE,\n OPERATION_SEMANTICS,\n} from './generate/DocumentSelection';\nexport { OpenApiGenerator } from './generate/OpenApiGenerator';\nexport { OperationRenderer, ResponseContract } from './generate/OperationRenderer';\nexport { SchemaRenderer, UnmappedField } from './generate/SchemaRenderer';\nexport { SecurityDeriver } from './generate/SecurityDeriver';\nexport { ExportedConstantFolder } from './load/ExportedConstantFolder';\nexport { ForeignFailure } from './load/ForeignFailure';\nexport { InputsLoader } from './load/InputsLoader';\nexport { ArtifactWriter, GeneratedArtifact } from './emit/ArtifactWriter';\nexport type { OutputFormat } from './emit/ArtifactWriter';\nexport { CliResult, OpenApiCli, USAGE } from './cli/OpenApiCli';\nexport { WpOpenApiMain } from './cli/WpOpenApiMain';\n"]}
@@ -0,0 +1,35 @@
1
+ /**
2
+ * An ORDERED JSON object, built by explicit `set` calls.
3
+ *
4
+ * ## Why a class and not an object literal
5
+ *
6
+ * An OpenAPI document is a JSON tree, and the obvious way to build one is a nest of object literals.
7
+ * `CLAUDE.md` §3 forbids that, and the rule earns its keep here rather than merely applying: this
8
+ * generator's contract with the repo is a COMMITTED GOLDEN document that a spec regenerates and
9
+ * diffs. A literal's key order is whatever the code happened to type, spread over a dozen branches
10
+ * that each add a key conditionally — so "the same document" would render differently depending on
11
+ * which branch ran, and the golden would go red on a change that moved nothing a reader can see.
12
+ *
13
+ * `set` appends in call order and a `Map` preserves it, so the document's byte layout is a property
14
+ * of the RENDERER, stated in one place, rather than an emergent one.
15
+ *
16
+ * ## `undefined` is "omit", not "null"
17
+ *
18
+ * Nearly every field of an OpenAPI object is optional, and the difference between an absent key and a
19
+ * `null` one is the difference between "not stated" and "stated to be nothing". `set(key, undefined)`
20
+ * therefore writes NOTHING, which lets a caller pass an optional straight through without an `if`
21
+ * around every line — and `null` stays available for the places 3.1 genuinely means it.
22
+ */
23
+ export type JsonValue = string | number | boolean | null | readonly JsonValue[] | JsonObject;
24
+ export declare class JsonObject {
25
+ private readonly entries;
26
+ /** Append one key. `undefined` writes nothing — see the class doc. */
27
+ set(key: string, value: JsonValue | undefined): this;
28
+ get(key: string): JsonValue | undefined;
29
+ has(key: string): boolean;
30
+ isEmpty(): boolean;
31
+ /** The keys in INSERTION order — the order both writers emit them in. */
32
+ keys(): readonly string[];
33
+ /** This object, or `undefined` when nothing was ever set on it. For an optional section. */
34
+ orUndefined(): JsonObject | undefined;
35
+ }
@@ -0,0 +1,32 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.JsonObject = void 0;
4
+ class JsonObject {
5
+ entries = new Map();
6
+ /** Append one key. `undefined` writes nothing — see the class doc. */
7
+ set(key, value) {
8
+ if (value !== undefined) {
9
+ this.entries.set(key, value);
10
+ }
11
+ return this;
12
+ }
13
+ get(key) {
14
+ return this.entries.get(key);
15
+ }
16
+ has(key) {
17
+ return this.entries.has(key);
18
+ }
19
+ isEmpty() {
20
+ return this.entries.size === 0;
21
+ }
22
+ /** The keys in INSERTION order — the order both writers emit them in. */
23
+ keys() {
24
+ return Array.from(this.entries.keys());
25
+ }
26
+ /** This object, or `undefined` when nothing was ever set on it. For an optional section. */
27
+ orUndefined() {
28
+ return this.isEmpty() ? undefined : this;
29
+ }
30
+ }
31
+ exports.JsonObject = JsonObject;
32
+ //# sourceMappingURL=JsonObject.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"JsonObject.js","sourceRoot":"","sources":["../../../../../../packages/docs/openapi-generator/src/json/JsonObject.ts"],"names":[],"mappings":";;;AAwBA,MAAa,UAAU;IACF,OAAO,GAAG,IAAI,GAAG,EAAqB,CAAC;IAExD,sEAAsE;IACtE,GAAG,CAAC,GAAW,EAAE,KAA4B;QACzC,IAAI,KAAK,KAAK,SAAS,EAAE,CAAC;YACtB,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,GAAG,EAAE,KAAK,CAAC,CAAC;QACjC,CAAC;QACD,OAAO,IAAI,CAAC;IAChB,CAAC;IAED,GAAG,CAAC,GAAW;QACX,OAAO,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;IACjC,CAAC;IAED,GAAG,CAAC,GAAW;QACX,OAAO,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;IACjC,CAAC;IAED,OAAO;QACH,OAAO,IAAI,CAAC,OAAO,CAAC,IAAI,KAAK,CAAC,CAAC;IACnC,CAAC;IAED,yEAAyE;IACzE,IAAI;QACA,OAAO,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,IAAI,EAAE,CAAC,CAAC;IAC3C,CAAC;IAED,4FAA4F;IAC5F,WAAW;QACP,OAAO,IAAI,CAAC,OAAO,EAAE,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,IAAI,CAAC;IAC7C,CAAC;CACJ;AAhCD,gCAgCC","sourcesContent":["/**\n * An ORDERED JSON object, built by explicit `set` calls.\n *\n * ## Why a class and not an object literal\n *\n * An OpenAPI document is a JSON tree, and the obvious way to build one is a nest of object literals.\n * `CLAUDE.md` §3 forbids that, and the rule earns its keep here rather than merely applying: this\n * generator's contract with the repo is a COMMITTED GOLDEN document that a spec regenerates and\n * diffs. A literal's key order is whatever the code happened to type, spread over a dozen branches\n * that each add a key conditionally — so \"the same document\" would render differently depending on\n * which branch ran, and the golden would go red on a change that moved nothing a reader can see.\n *\n * `set` appends in call order and a `Map` preserves it, so the document's byte layout is a property\n * of the RENDERER, stated in one place, rather than an emergent one.\n *\n * ## `undefined` is \"omit\", not \"null\"\n *\n * Nearly every field of an OpenAPI object is optional, and the difference between an absent key and a\n * `null` one is the difference between \"not stated\" and \"stated to be nothing\". `set(key, undefined)`\n * therefore writes NOTHING, which lets a caller pass an optional straight through without an `if`\n * around every line — and `null` stays available for the places 3.1 genuinely means it.\n */\nexport type JsonValue = string | number | boolean | null | readonly JsonValue[] | JsonObject;\n\nexport class JsonObject {\n private readonly entries = new Map<string, JsonValue>();\n\n /** Append one key. `undefined` writes nothing — see the class doc. */\n set(key: string, value: JsonValue | undefined): this {\n if (value !== undefined) {\n this.entries.set(key, value);\n }\n return this;\n }\n\n get(key: string): JsonValue | undefined {\n return this.entries.get(key);\n }\n\n has(key: string): boolean {\n return this.entries.has(key);\n }\n\n isEmpty(): boolean {\n return this.entries.size === 0;\n }\n\n /** The keys in INSERTION order — the order both writers emit them in. */\n keys(): readonly string[] {\n return Array.from(this.entries.keys());\n }\n\n /** This object, or `undefined` when nothing was ever set on it. For an optional section. */\n orUndefined(): JsonObject | undefined {\n return this.isEmpty() ? undefined : this;\n }\n}\n"]}
@@ -0,0 +1,18 @@
1
+ import { JsonObject } from './JsonObject';
2
+ /**
3
+ * {@link JsonObject} -> pretty JSON text, 4-space indented, with a trailing newline.
4
+ *
5
+ * `JSON.stringify` cannot be used directly because a {@link JsonObject} is a class holding a `Map`,
6
+ * not a plain object — and converting to plain objects first would throw away the insertion order
7
+ * that makes a committed golden document stable (see {@link JsonObject}).
8
+ *
9
+ * 4 spaces and a trailing newline because that is what this repo's prettier writes for every other
10
+ * committed JSON file; a golden that disagreed with the formatter would be reformatted on the next
11
+ * commit and diff against itself.
12
+ */
13
+ export declare class JsonWriter {
14
+ write(root: JsonObject): string;
15
+ private value;
16
+ private object;
17
+ private array;
18
+ }
@@ -0,0 +1,48 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.JsonWriter = void 0;
4
+ const JsonObject_1 = require("./JsonObject");
5
+ /**
6
+ * {@link JsonObject} -> pretty JSON text, 4-space indented, with a trailing newline.
7
+ *
8
+ * `JSON.stringify` cannot be used directly because a {@link JsonObject} is a class holding a `Map`,
9
+ * not a plain object — and converting to plain objects first would throw away the insertion order
10
+ * that makes a committed golden document stable (see {@link JsonObject}).
11
+ *
12
+ * 4 spaces and a trailing newline because that is what this repo's prettier writes for every other
13
+ * committed JSON file; a golden that disagreed with the formatter would be reformatted on the next
14
+ * commit and diff against itself.
15
+ */
16
+ class JsonWriter {
17
+ write(root) {
18
+ return `${this.value(root, '')}\n`;
19
+ }
20
+ value(value, indent) {
21
+ if (value instanceof JsonObject_1.JsonObject) {
22
+ return this.object(value, indent);
23
+ }
24
+ if (Array.isArray(value)) {
25
+ return this.array(value, indent);
26
+ }
27
+ return JSON.stringify(value);
28
+ }
29
+ object(object, indent) {
30
+ const keys = object.keys();
31
+ if (keys.length === 0) {
32
+ return '{}';
33
+ }
34
+ const inner = `${indent} `;
35
+ const lines = keys.map((key) => `${inner}${JSON.stringify(key)}: ${this.value(object.get(key), inner)}`);
36
+ return `{\n${lines.join(',\n')}\n${indent}}`;
37
+ }
38
+ array(items, indent) {
39
+ if (items.length === 0) {
40
+ return '[]';
41
+ }
42
+ const inner = `${indent} `;
43
+ const lines = items.map((item) => `${inner}${this.value(item, inner)}`);
44
+ return `[\n${lines.join(',\n')}\n${indent}]`;
45
+ }
46
+ }
47
+ exports.JsonWriter = JsonWriter;
48
+ //# sourceMappingURL=JsonWriter.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"JsonWriter.js","sourceRoot":"","sources":["../../../../../../packages/docs/openapi-generator/src/json/JsonWriter.ts"],"names":[],"mappings":";;;AAAA,6CAAqD;AAErD;;;;;;;;;;GAUG;AACH,MAAa,UAAU;IACnB,KAAK,CAAC,IAAgB;QAClB,OAAO,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC;IACvC,CAAC;IAEO,KAAK,CAAC,KAAgB,EAAE,MAAc;QAC1C,IAAI,KAAK,YAAY,uBAAU,EAAE,CAAC;YAC9B,OAAO,IAAI,CAAC,MAAM,CAAC,KAAK,EAAE,MAAM,CAAC,CAAC;QACtC,CAAC;QACD,IAAI,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,EAAE,CAAC;YACvB,OAAO,IAAI,CAAC,KAAK,CAAC,KAAK,EAAE,MAAM,CAAC,CAAC;QACrC,CAAC;QACD,OAAO,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,CAAC;IACjC,CAAC;IAEO,MAAM,CAAC,MAAkB,EAAE,MAAc;QAC7C,MAAM,IAAI,GAAG,MAAM,CAAC,IAAI,EAAE,CAAC;QAC3B,IAAI,IAAI,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YACpB,OAAO,IAAI,CAAC;QAChB,CAAC;QACD,MAAM,KAAK,GAAG,GAAG,MAAM,MAAM,CAAC;QAC9B,MAAM,KAAK,GAAG,IAAI,CAAC,GAAG,CAClB,CAAC,GAAW,EAAE,EAAE,CACZ,GAAG,KAAK,GAAG,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,KAAK,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,GAAG,CAAC,GAAG,CAAE,EAAE,KAAK,CAAC,EAAE,CAC/E,CAAC;QACF,OAAO,MAAM,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,KAAK,MAAM,GAAG,CAAC;IACjD,CAAC;IAEO,KAAK,CAAC,KAA2B,EAAE,MAAc;QACrD,IAAI,KAAK,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YACrB,OAAO,IAAI,CAAC;QAChB,CAAC;QACD,MAAM,KAAK,GAAG,GAAG,MAAM,MAAM,CAAC;QAC9B,MAAM,KAAK,GAAG,KAAK,CAAC,GAAG,CAAC,CAAC,IAAe,EAAE,EAAE,CAAC,GAAG,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,EAAE,KAAK,CAAC,EAAE,CAAC,CAAC;QACnF,OAAO,MAAM,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,KAAK,MAAM,GAAG,CAAC;IACjD,CAAC;CACJ;AApCD,gCAoCC","sourcesContent":["import { JsonObject, JsonValue } from './JsonObject';\n\n/**\n * {@link JsonObject} -> pretty JSON text, 4-space indented, with a trailing newline.\n *\n * `JSON.stringify` cannot be used directly because a {@link JsonObject} is a class holding a `Map`,\n * not a plain object — and converting to plain objects first would throw away the insertion order\n * that makes a committed golden document stable (see {@link JsonObject}).\n *\n * 4 spaces and a trailing newline because that is what this repo's prettier writes for every other\n * committed JSON file; a golden that disagreed with the formatter would be reformatted on the next\n * commit and diff against itself.\n */\nexport class JsonWriter {\n write(root: JsonObject): string {\n return `${this.value(root, '')}\\n`;\n }\n\n private value(value: JsonValue, indent: string): string {\n if (value instanceof JsonObject) {\n return this.object(value, indent);\n }\n if (Array.isArray(value)) {\n return this.array(value, indent);\n }\n return JSON.stringify(value);\n }\n\n private object(object: JsonObject, indent: string): string {\n const keys = object.keys();\n if (keys.length === 0) {\n return '{}';\n }\n const inner = `${indent} `;\n const lines = keys.map(\n (key: string) =>\n `${inner}${JSON.stringify(key)}: ${this.value(object.get(key)!, inner)}`,\n );\n return `{\\n${lines.join(',\\n')}\\n${indent}}`;\n }\n\n private array(items: readonly JsonValue[], indent: string): string {\n if (items.length === 0) {\n return '[]';\n }\n const inner = `${indent} `;\n const lines = items.map((item: JsonValue) => `${inner}${this.value(item, inner)}`);\n return `[\\n${lines.join(',\\n')}\\n${indent}]`;\n }\n}\n"]}
@@ -0,0 +1,35 @@
1
+ /**
2
+ * A reader for the block-YAML subset this package emits.
3
+ *
4
+ * It exists for ONE job: proving that an emitted YAML document is the same document as its JSON
5
+ * counterpart. It is exported because the consumer that needs it is a golden spec in a DIFFERENT
6
+ * project (`apps/app-example/partner-api`), and a reader that only the emitter's own package could
7
+ * reach would leave every downstream golden with no way to check its YAML at all.
8
+ *
9
+ * ## Why it exists rather than a YAML dependency
10
+ *
11
+ * The goldens commit JSON only: committing both serializations would double the review surface every
12
+ * decorator change has to be diffed against, for a second file that is the first one restated. What
13
+ * proves the YAML instead is one spec that PARSES it and asserts deep equality with its JSON
14
+ * counterpart — and doing that with a real YAML library would put a dependency into a package whose
15
+ * whole story is `typescript` plus two webpieces packages.
16
+ *
17
+ * ## Why a mirror bug is unlikely
18
+ *
19
+ * It is written in the OPPOSITE direction from {@link YamlWriter}: indentation and quoting are
20
+ * re-derived here from the text rather than shared with the emitter, so the two do not fail together
21
+ * for the same reason. It understands exactly what the writer produces — double-quoted keys and
22
+ * string scalars, bare numbers/booleans/null, `{}` and `[]` for empties, `- ` list items — and
23
+ * anything else is a parse failure rather than a guess. It is NOT a general YAML parser and must not
24
+ * be used as one.
25
+ */
26
+ export declare class YamlReader {
27
+ private lines;
28
+ private index;
29
+ read(text: string): unknown;
30
+ /** The value whose first line is at `indent`, consuming every line that belongs to it. */
31
+ private value;
32
+ private map;
33
+ private list;
34
+ private scalar;
35
+ }
@@ -0,0 +1,111 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.YamlReader = void 0;
4
+ /**
5
+ * A reader for the block-YAML subset this package emits.
6
+ *
7
+ * It exists for ONE job: proving that an emitted YAML document is the same document as its JSON
8
+ * counterpart. It is exported because the consumer that needs it is a golden spec in a DIFFERENT
9
+ * project (`apps/app-example/partner-api`), and a reader that only the emitter's own package could
10
+ * reach would leave every downstream golden with no way to check its YAML at all.
11
+ *
12
+ * ## Why it exists rather than a YAML dependency
13
+ *
14
+ * The goldens commit JSON only: committing both serializations would double the review surface every
15
+ * decorator change has to be diffed against, for a second file that is the first one restated. What
16
+ * proves the YAML instead is one spec that PARSES it and asserts deep equality with its JSON
17
+ * counterpart — and doing that with a real YAML library would put a dependency into a package whose
18
+ * whole story is `typescript` plus two webpieces packages.
19
+ *
20
+ * ## Why a mirror bug is unlikely
21
+ *
22
+ * It is written in the OPPOSITE direction from {@link YamlWriter}: indentation and quoting are
23
+ * re-derived here from the text rather than shared with the emitter, so the two do not fail together
24
+ * for the same reason. It understands exactly what the writer produces — double-quoted keys and
25
+ * string scalars, bare numbers/booleans/null, `{}` and `[]` for empties, `- ` list items — and
26
+ * anything else is a parse failure rather than a guess. It is NOT a general YAML parser and must not
27
+ * be used as one.
28
+ */
29
+ // webpieces-disable no-any-unknown -- it parses arbitrary JSON-shaped YAML; `unknown` IS the honest return type, and the caller compares it against a JSON.parse result
30
+ class YamlReader {
31
+ lines = [];
32
+ index = 0;
33
+ // webpieces-disable no-any-unknown -- see the class doc: a JSON-shaped value read from text
34
+ read(text) {
35
+ this.lines = text.split('\n').filter((line) => line.trim() !== '');
36
+ this.index = 0;
37
+ return this.lines.length === 0 ? {} : this.value(0);
38
+ }
39
+ /** The value whose first line is at `indent`, consuming every line that belongs to it. */
40
+ // webpieces-disable no-any-unknown -- see the class doc: a JSON-shaped value read from text
41
+ value(indent) {
42
+ const line = this.lines[this.index];
43
+ if (line === undefined) {
44
+ return {};
45
+ }
46
+ return line.trimStart().startsWith('-') ? this.list(indent) : this.map(indent);
47
+ }
48
+ // webpieces-disable no-any-unknown -- see the class doc: a JSON-shaped value read from text
49
+ map(indent) {
50
+ // webpieces-disable no-any-unknown -- see the class doc: a JSON-shaped value read from text
51
+ const out = {};
52
+ while (this.index < this.lines.length) {
53
+ const line = this.lines[this.index];
54
+ const depth = line.length - line.trimStart().length;
55
+ if (depth < indent) {
56
+ break;
57
+ }
58
+ const text = line.trim();
59
+ const split = text.indexOf('": ');
60
+ if (split === -1) {
61
+ // `"key":` with the value nested under it.
62
+ const key = JSON.parse(text.slice(0, text.length - 1));
63
+ this.index += 1;
64
+ out[key] = this.value(depth + 4);
65
+ continue;
66
+ }
67
+ out[JSON.parse(text.slice(0, split + 1))] = this.scalar(text.slice(split + 3));
68
+ this.index += 1;
69
+ }
70
+ return out;
71
+ }
72
+ // webpieces-disable no-any-unknown -- see the class doc: a JSON-shaped value read from text
73
+ list(indent) {
74
+ // webpieces-disable no-any-unknown -- see the class doc: a JSON-shaped value read from text
75
+ const out = [];
76
+ while (this.index < this.lines.length) {
77
+ const line = this.lines[this.index];
78
+ const depth = line.length - line.trimStart().length;
79
+ const text = line.trim();
80
+ if (depth < indent || !text.startsWith('-')) {
81
+ break;
82
+ }
83
+ const rest = text.slice(1).trim();
84
+ if (rest.startsWith('"') && rest.includes('": ')) {
85
+ // An object whose FIRST key shares the `- ` line; the rest align under it.
86
+ this.lines[this.index] = ' '.repeat(depth + 2) + rest;
87
+ out.push(this.map(depth + 2));
88
+ continue;
89
+ }
90
+ this.index += 1;
91
+ out.push(this.scalar(rest));
92
+ }
93
+ return out;
94
+ }
95
+ // webpieces-disable no-any-unknown -- see the class doc: a JSON-shaped value read from text
96
+ scalar(text) {
97
+ if (text === '{}') {
98
+ return {};
99
+ }
100
+ if (text === '[]') {
101
+ return [];
102
+ }
103
+ if (text === 'null') {
104
+ return null;
105
+ }
106
+ // webpieces-disable no-any-unknown -- see the class doc: a JSON-shaped value read from text
107
+ return JSON.parse(text);
108
+ }
109
+ }
110
+ exports.YamlReader = YamlReader;
111
+ //# sourceMappingURL=YamlReader.js.map