@redocly/client-generator 0.5.3 → 0.7.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +1 -1
- package/eject-assets/generators/cli/docs.ts +1 -1
- package/eject-assets/generators/cli/engine-source.ts +1 -1
- package/eject-assets/generators/cli/index.ts +2 -2
- package/eject-assets/generators/cli/render.ts +1 -1
- package/eject-assets/generators/go/client.ts +1 -1
- package/eject-assets/generators/go/descriptor.ts +2 -1
- package/eject-assets/generators/go/index.ts +2 -2
- package/eject-assets/generators/go/models.ts +1 -1
- package/eject-assets/generators/go/naming.ts +1 -1
- package/eject-assets/generators/go/operations.ts +1 -1
- package/eject-assets/generators/go/pagination.ts +1 -1
- package/eject-assets/generators/go/types.ts +1 -1
- package/eject-assets/generators/mock/faker.ts +1 -1
- package/eject-assets/generators/mock/index.ts +2 -2
- package/eject-assets/generators/mock/render.ts +1 -1
- package/eject-assets/generators/mock/sample.ts +1 -1
- package/eject-assets/generators/mock/values.ts +1 -1
- package/eject-assets/generators/php/client.ts +1 -1
- package/eject-assets/generators/php/descriptor.ts +2 -1
- package/eject-assets/generators/php/index.ts +2 -2
- package/eject-assets/generators/php/models.ts +1 -1
- package/eject-assets/generators/php/naming.ts +1 -1
- package/eject-assets/generators/php/operations.ts +1 -1
- package/eject-assets/generators/php/pagination.ts +1 -1
- package/eject-assets/generators/php/types.ts +1 -1
- package/eject-assets/generators/python/client.ts +1 -1
- package/eject-assets/generators/python/descriptor.ts +2 -1
- package/eject-assets/generators/python/index.ts +2 -2
- package/eject-assets/generators/python/models.ts +1 -1
- package/eject-assets/generators/python/naming.ts +1 -1
- package/eject-assets/generators/python/operations.ts +1 -1
- package/eject-assets/generators/python/pagination.ts +1 -1
- package/eject-assets/generators/python/types.ts +1 -1
- package/eject-assets/generators/swr/index.ts +2 -2
- package/eject-assets/generators/swr/render.ts +1 -1
- package/eject-assets/generators/tanstack-query/index.ts +2 -2
- package/eject-assets/generators/tanstack-query/render.ts +56 -9
- package/eject-assets/generators/transformers/index.ts +2 -2
- package/eject-assets/generators/transformers/render.ts +1 -1
- package/eject-assets/generators/typescript/banner.ts +1 -1
- package/eject-assets/generators/typescript/client.ts +1 -1
- package/eject-assets/generators/typescript/descriptor.ts +1 -1
- package/eject-assets/generators/typescript/index.ts +29 -3
- package/eject-assets/generators/typescript/inline-runtime.ts +1 -1
- package/eject-assets/generators/typescript/operation-signature.ts +1 -1
- package/eject-assets/generators/typescript/operation-types.ts +1 -1
- package/eject-assets/generators/typescript/operations.ts +1 -1
- package/eject-assets/generators/typescript/response-headers.ts +1 -1
- package/eject-assets/generators/typescript/type-guards.ts +1 -1
- package/eject-assets/generators/typescript/types.ts +1 -1
- package/eject-assets/generators/zod/index.ts +2 -2
- package/eject-assets/generators/zod/schemas.ts +1 -1
- package/eject-assets/skills/tanstack-query-generator/SKILL.md +5 -2
- package/eject-assets/skills/typescript-generator/SKILL.md +24 -0
- package/lib/authoring/pagination.d.ts +5 -4
- package/lib/authoring/pagination.d.ts.map +1 -1
- package/lib/authoring/pagination.js +32 -12
- package/lib/authoring/pagination.js.map +1 -1
- package/lib/authoring/reference-page.d.ts.map +1 -1
- package/lib/authoring/reference-page.js +3 -3
- package/lib/authoring/reference-page.js.map +1 -1
- package/lib/generators/go/descriptor.d.ts.map +1 -1
- package/lib/generators/go/descriptor.js +1 -0
- package/lib/generators/go/descriptor.js.map +1 -1
- package/lib/generators/meta.d.ts.map +1 -1
- package/lib/generators/meta.js +3 -0
- package/lib/generators/meta.js.map +1 -1
- package/lib/generators/php/descriptor.d.ts.map +1 -1
- package/lib/generators/php/descriptor.js +1 -0
- package/lib/generators/php/descriptor.js.map +1 -1
- package/lib/generators/python/descriptor.d.ts.map +1 -1
- package/lib/generators/python/descriptor.js +1 -0
- package/lib/generators/python/descriptor.js.map +1 -1
- package/lib/generators/tanstack-query/render.d.ts.map +1 -1
- package/lib/generators/tanstack-query/render.js +48 -7
- package/lib/generators/tanstack-query/render.js.map +1 -1
- package/lib/generators/types.d.ts +1 -0
- package/lib/generators/types.d.ts.map +1 -1
- package/lib/generators/typescript/index.d.ts.map +1 -1
- package/lib/generators/typescript/index.js +18 -2
- package/lib/generators/typescript/index.js.map +1 -1
- package/lib/generators/typescript/runtime/create-client.d.ts +1 -1
- package/lib/generators/typescript/runtime/create-client.d.ts.map +1 -1
- package/lib/generators/typescript/runtime/create-client.js +2 -2
- package/lib/generators/typescript/runtime/create-client.js.map +1 -1
- package/lib/generators/typescript/runtime/paginate.d.ts +9 -7
- package/lib/generators/typescript/runtime/paginate.d.ts.map +1 -1
- package/lib/generators/typescript/runtime/paginate.js +18 -12
- package/lib/generators/typescript/runtime/paginate.js.map +1 -1
- package/lib/generators/typescript/runtime/send.d.ts +2 -1
- package/lib/generators/typescript/runtime/send.d.ts.map +1 -1
- package/lib/generators/typescript/runtime/send.js +144 -59
- package/lib/generators/typescript/runtime/send.js.map +1 -1
- package/lib/generators/typescript/runtime/types.d.ts +1 -1
- package/lib/generators/typescript/runtime/types.d.ts.map +1 -1
- package/lib/generators/typescript/telemetry/telemetry.d.ts +24 -0
- package/lib/generators/typescript/telemetry/telemetry.d.ts.map +1 -0
- package/lib/generators/typescript/telemetry/telemetry.js +265 -0
- package/lib/generators/typescript/telemetry/telemetry.js.map +1 -0
- package/lib/index.d.ts +1 -1
- package/lib/index.d.ts.map +1 -1
- package/lib/index.js.map +1 -1
- package/lib/pagination.d.ts +17 -5
- package/lib/pagination.d.ts.map +1 -1
- package/lib/pagination.js +26 -6
- package/lib/pagination.js.map +1 -1
- package/lib/pipeline.d.ts.map +1 -1
- package/lib/pipeline.js +1 -0
- package/lib/pipeline.js.map +1 -1
- package/lib/reserved-names.d.ts.map +1 -1
- package/lib/reserved-names.js +1 -0
- package/lib/reserved-names.js.map +1 -1
- package/lib/runtime-contract.d.ts +8 -1
- package/lib/runtime-contract.d.ts.map +1 -1
- package/lib/runtime-contract.js.map +1 -1
- package/lib/runtime-sources/go.d.ts +1 -1
- package/lib/runtime-sources/go.d.ts.map +1 -1
- package/lib/runtime-sources/go.js +1 -1
- package/lib/runtime-sources/go.js.map +1 -1
- package/lib/runtime-sources/php.d.ts +1 -1
- package/lib/runtime-sources/php.d.ts.map +1 -1
- package/lib/runtime-sources/php.js +1 -1
- package/lib/runtime-sources/php.js.map +1 -1
- package/lib/runtime-sources/python.d.ts +1 -1
- package/lib/runtime-sources/python.js +1 -1
- package/lib/runtime-sources/python.js.map +1 -1
- package/lib/runtime-sources/telemetry.d.ts +2 -0
- package/lib/runtime-sources/telemetry.d.ts.map +1 -0
- package/lib/runtime-sources/telemetry.js +3 -0
- package/lib/runtime-sources/telemetry.js.map +1 -0
- package/lib/runtime-sources/typescript.d.ts +9 -9
- package/lib/runtime-sources/typescript.d.ts.map +1 -1
- package/lib/runtime-sources/typescript.js +11 -8
- package/lib/runtime-sources/typescript.js.map +1 -1
- package/lib/runtime-sources.d.ts +1 -0
- package/lib/runtime-sources.d.ts.map +1 -1
- package/lib/runtime-sources.js +1 -0
- package/lib/runtime-sources.js.map +1 -1
- package/lib/types.d.ts +1 -0
- package/lib/types.d.ts.map +1 -1
- package/package.json +2 -2
package/lib/pipeline.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"pipeline.js","sourceRoot":"","sources":["../src/pipeline.ts"],"names":[],"mappings":"AAAA,6EAA6E;AAC7E,uEAAuE;AACvE,qEAAqE;AACrE,8EAA8E;AAC9E,4EAA4E;AAC5E,2EAA2E;AAC3E,qCAAqC;AAErC,OAAO,EACL,KAAK,EACL,MAAM,EACN,aAAa,EACb,uBAAuB,GAExB,MAAM,uBAAuB,CAAC;AAC/B,OAAO,EAAE,KAAK,EAAE,QAAQ,EAAE,SAAS,EAAE,MAAM,kBAAkB,CAAC;AAC9D,OAAO,EAAE,OAAO,EAAE,KAAK,EAAE,OAAO,EAAE,GAAG,EAAE,MAAM,WAAW,CAAC;AAEzD,OAAO,EAAE,iBAAiB,EAAE,MAAM,aAAa,CAAC;AAChD,OAAO,EAAE,iBAAiB,EAAE,MAAM,sBAAsB,CAAC;AACzD,OAAO,EAAE,uBAAuB,EAAE,MAAM,yBAAyB,CAAC;AAClE,OAAO,EAAE,iBAAiB,EAAE,MAAM,yBAAyB,CAAC;AAQ5D,OAAO,EAAE,aAAa,EAAE,MAAM,wCAAwC,CAAC;AACvE,OAAO,EAAE,aAAa,EAAiB,MAAM,wCAAwC,CAAC;AACtF,OAAO,EAAE,iBAAiB,EAAE,MAAM,qDAAqD,CAAC;AACxF,OAAO,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAC;AACvC,OAAO,EAAE,sBAAsB,EAAwB,MAAM,iBAAiB,CAAC;AAG/E;;;;GAIG;AACH,uFAAuF;AACvF,sFAAsF;AACtF,MAAM,YAAY,GAAG;IACnB,+DAA+D;IAC/D,0EAA0E;CAC3E,CAAC;AAEF,MAAM,UAAU,aAAa,CAC3B,KAAe,EACf,OAUC;IAED,MAAM,KAAK,GAAoB,EAAE,CAAC;IAClC,MAAM,IAAI,GAAG,IAAI,GAAG,EAAU,CAAC;IAC/B,mFAAmF;IACnF,iFAAiF;IACjF,MAAM,UAAU,GAAG,OAAO,CAAC,OAAO,CAAC,OAAO,CAAC,UAAU,CAAC,CAAC,CAAC;IACxD,MAAM,EAAE,GAAG,EAAE,IAAI,EAAE,IAAI,EAAE,GAAG,EAAE,GAAG,KAAK,CAAC,OAAO,CAAC,UAAU,CAAC,CAAC;IAC3D,MAAM,MAAM,GAAG,EAAE,IAAI,EAAE,OAAO,CAAC,UAAU,EAAE,GAAG,EAAE,IAAI,EAAE,GAAG,EAAE,CAAC;IAC5D,MAAM,MAAM,GAAG,YAAY,CAAC;IAC5B,IAAI,UAAU,GAAG,KAAK,CAAC;IACvB,KAAK,MAAM,IAAI,IAAI,OAAO,CAAC,UAAU,EAAE,CAAC;QACtC,MAAM,SAAS,GAAG,OAAO,CAAC,QAAQ,CAAC,GAAG,CAAC,IAAI,CAAE,CAAC;QAC9C,MAAM,KAAK,GAAG;YACZ,KAAK;YACL,MAAM;YACN,MAAM;YACN,UAAU,EAAE,OAAO,CAAC,UAAU;YAC9B,IAAI,EAAE,OAAO,CAAC,IAAI;YAClB,UAAU,EAAE,OAAO,CAAC,UAAU;YAC9B,QAAQ,EAAE,OAAO,CAAC,UAAU;YAC5B,OAAO,EAAE,OAAO,CAAC,gBAAgB,EAAE,GAAG,CAAC,IAAI,CAAC,IAAI,EAAE;SACnD,CAAC;QACF,IAAI,SAA0B,CAAC;QAC/B,IAAI,CAAC;YACH,gFAAgF;YAChF,6EAA6E;YAC7E,IAAI,OAAO,CAAC,IAAI,CAAC,IAAI,KAAK,IAAI,IAAI,SAAS,CAAC,IAAI,KAAK,SAAS,EAAE,CAAC;gBAC/D,SAAS,GAAG,CAAC,GAAG,SAAS,CAAC,GAAG,CAAC,KAAK,CAAC,EAAE,GAAG,SAAS,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC;gBAChE,UAAU,GAAG,IAAI,CAAC;YACpB,CAAC;iBAAM,CAAC;gBACN,SAAS,GAAG,SAAS,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC;YACnC,CAAC;QACH,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,MAAM,OAAO,GAAG,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;YACvE,MAAM,IAAI,KAAK,CAAC,cAAc,IAAI,aAAa,OAAO,EAAE,CAAC,CAAC;QAC5D,CAAC;QACD,IACE,CAAC,KAAK,CAAC,OAAO,CAAC,SAAS,CAAC;YACzB,SAAS,CAAC,IAAI,CACZ,CAAC,IAAI,EAAE,EAAE,CACP,OAAO,IAAI,EAAE,IAAI,KAAK,QAAQ,IAAI,IAAI,CAAC,IAAI,KAAK,EAAE,IAAI,OAAO,IAAI,CAAC,OAAO,KAAK,QAAQ,CACzF,EACD,CAAC;YACD,MAAM,IAAI,KAAK,CACb,cAAc,IAAI,kEAAkE,CACrF,CAAC;QACJ,CAAC;QACD,KAAK,MAAM,IAAI,IAAI,SAAS,EAAE,CAAC;YAC7B,MAAM,QAAQ,GAAG,OAAO,CAAC,UAAU,EAAE,IAAI,CAAC,IAAI,CAAC,CAAC;YAChD,IAAI,QAAQ,KAAK,UAAU,IAAI,CAAC,QAAQ,CAAC,UAAU,CAAC,UAAU,GAAG,GAAG,CAAC,EAAE,CAAC;gBACtE,MAAM,IAAI,KAAK,CACb,cAAc,IAAI,qDAAqD,IAAI,CAAC,IAAI,EAAE,CACnF,CAAC;YACJ,CAAC;YACD,IAAI,IAAI,CAAC,GAAG,CAAC,QAAQ,CAAC,EAAE,CAAC;gBACvB,MAAM,IAAI,KAAK,CAAC,uBAAuB,IAAI,CAAC,IAAI,0CAA0C,CAAC,CAAC;YAC9F,CAAC;YACD,IAAI,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC;YACnB,6EAA6E;YAC7E,gFAAgF;YAChF,KAAK,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,QAAQ,EAAE,OAAO,EAAE,IAAI,CAAC,OAAO,EAAE,CAAC,CAAC;QACxD,CAAC;IACH,CAAC;IACD,qFAAqF;IACrF,0EAA0E;IAC1E,IAAI,OAAO,CAAC,IAAI,CAAC,IAAI,KAAK,IAAI,IAAI,CAAC,UAAU,EAAE,CAAC;QAC9C,MAAM,CAAC,IAAI,CACT,gFAAgF,OAAO,CAAC,UAAU,CAAC,IAAI,CAAC,IAAI,CAAC,MAAM,CACpH,CAAC;IACJ,CAAC;IACD,OAAO,KAAK,CAAC;AACf,CAAC;AAED;;;;;GAKG;AACH,SAAS,sBAAsB,CAAC,KAAe;IAC7C,KAAK,MAAM,OAAO,IAAI,KAAK,CAAC,QAAQ,EAAE,CAAC;QACrC,KAAK,MAAM,EAAE,IAAI,OAAO,CAAC,UAAU,EAAE,CAAC;YACpC,MAAM,IAAI,GAAG,IAAI,GAAG,EAAU,CAAC;YAC/B,MAAM,QAAQ,GAAG,IAAI,GAAG,EAAU,CAAC;YACnC,KAAK,MAAM,KAAK,IAAI;gBAClB,GAAG,EAAE,CAAC,UAAU;gBAChB,GAAG,EAAE,CAAC,WAAW;gBACjB,GAAG,EAAE,CAAC,YAAY;gBAClB,GAAG,EAAE,CAAC,YAAY;aACnB,EAAE,CAAC;gBACF,IAAI,IAAI,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC;oBAAE,QAAQ,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;gBACnD,IAAI,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;YACvB,CAAC;YACD,IAAI,QAAQ,CAAC,IAAI,KAAK,CAAC;gBAAE,SAAS;YAClC,MAAM,CAAC,IAAI,CACT,+BAA+B,EAAE,CAAC,QAAQ,IAAI,EAAE,CAAC,IAAI,UAAU,CAAC,GAAG,QAAQ,CAAC;iBACzE,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,IAAI,GAAG,CAAC;iBAC1B,IAAI,CACH,IAAI,CACL,yNAAyN,CAC7N,CAAC;QACJ,CAAC;IACH,CAAC;AACH,CAAC;AAED;;;;;GAKG;AACH,SAAS,kBAAkB,CACzB,QAAwB,EACxB,KAAe,EACf,IAAiB,EACjB,QAAkB,EAClB,QAA0C,EAC1C,UAAkB,EAClB,UAA4B;IAE5B,MAAM,OAAO,GAAG,EAAE,CAAC;IACnB,MAAM,OAAO,GAAG,IAAI,GAAG,EAAU,CAAC;IAClC,KAAK,MAAM,EAAE,IAAI,aAAa,CAAC,KAAK,CAAC,QAAQ,CAAC,EAAE,CAAC;QAC/C,MAAM,MAAM,GAAG,eAAe,CAAC,QAAQ,EAAE,EAAE,CAAC,IAAI,EAAE,EAAE,CAAC,MAAM,CAAC,CAAC;QAC7D,6FAA6F;QAC7F,IAAI,OAAO,CAAC,GAAG,CAAC,MAAM,CAAC;YAAE,SAAS;QAClC,OAAO,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC;QACpB,MAAM,OAAO,GAAG,QAAQ;aACrB,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,QAAQ,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,EAAE,EAAE,KAAK,EAAE,IAAI,EAAE,UAAU,EAAE,UAAU,EAAE,CAAC,CAAC;aACxF,MAAM,CAAC,CAAC,MAAM,EAAwB,EAAE,CAAC,MAAM,KAAK,SAAS,CAAC,CAAC;QAClE,IAAI,OAAO,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YACvB,OAAO,CAAC,IAAI,CAAC,EAAE,MAAM,EAAE,MAAM,EAAE,EAAE,eAAe,EAAE,OAAO,EAAE,EAAE,CAAC,CAAC;QACjE,CAAC;IACH,CAAC;IACD,IAAI,OAAO,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,SAAS,CAAC;IAC3C,OAAO,aAAa,CAAC;QACnB,OAAO,EAAE,OAAO;QAChB,IAAI,EAAE,EAAE,KAAK,EAAE,oBAAoB,KAAK,CAAC,KAAK,EAAE,EAAE,OAAO,EAAE,KAAK,CAAC,OAAO,EAAE;QAC1E,OAAO;KACR,CAAC,CAAC;AACL,CAAC;AAED,kGAAkG;AAClG,SAAS,eAAe,CAAC,QAAwB,EAAE,IAAY,EAAE,MAAc;IAC7E,kEAAkE;IAClE,MAAM,MAAM,GAAG,CAAC,IAAY,EAAE,EAAE,CAAC,KAAK,IAAI,CAAC,UAAU,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC,UAAU,CAAC,GAAG,EAAE,KAAK,CAAC,IAAI,CAAC;IAC/F,MAAM,QAAQ,GAAG,QAAQ,CAAC,KAAK,EAAE,CAAC,IAAI,CAAC,CAAC;IACxC,MAAM,cAAc,GAClB,KAAK,CAAC,QAAQ,CAAC,IAAI,QAAQ,CAAC,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC;QAC/C,CAAC,CAAC,GAAG,GAAG,QAAQ,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,GAAG,CAAC,uBAAuB,CAAC,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,EAAE,CAAC;QAC3F,CAAC,CAAC,UAAU,MAAM,CAAC,IAAI,CAAC,EAAE,CAAC;IAC/B,OAAO,GAAG,cAAc,IAAI,MAAM,EAAE,CAAC;AACvC,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,cAAc,CAClC,OAA8B;IAE9B,4EAA4E;IAC5E,qFAAqF;IACrF,6DAA6D;IAC7D,IACE,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,OAAO,KAAK,WAAW,IAAI,OAAO,KAAK,MAAM,CAAC,EAC9F,CAAC;QACD,MAAM,IAAI,KAAK,CACb,gBAAgB,OAAO,CAAC,MAAM,yGAAyG,CACxI,CAAC;IACJ,CAAC;IACD,iFAAiF;IACjF,mFAAmF;IACnF,mFAAmF;IACnF,IAAI,OAAO,CAAC,KAAK,IAAI,sBAAsB,CAAC,IAAI,CAAC,OAAO,CAAC,KAAK,CAAC,EAAE,CAAC;QAChE,MAAM,IAAI,iBAAiB,CACzB,kFAAkF,OAAO,CAAC,KAAK,GAAG,CACnG,CAAC;IACJ,CAAC;IACD,MAAM,UAAU,GAAG,OAAO,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC;IAC3C,MAAM,EAAE,QAAQ,EAAE,OAAO,EAAE,GAAG,MAAM,QAAQ,CAAC,OAAO,CAAC,GAAG,EAAE,OAAO,CAAC,MAAM,CAAC,CAAC;IAC1E,MAAM,UAAU,GACd,OAAO,KAAK,MAAM;QAChB,CAAC,CAAC,6EAA6E;YAC7E,iEAAiE;YACjE,iBAAiB,CAAC,QAA8C,CAAC;QACnE,CAAC,CAAC,QAAQ,CAAC;IACf,MAAM,KAAK,GAAG,aAAa,CAAC,UAAU,CAAC,CAAC;IACxC,sBAAsB,CAAC,KAAK,CAAC,CAAC;IAE9B,0FAA0F;IAC1F,oFAAoF;IACpF,kFAAkF;IAClF,IAAI,UAA8B,CAAC;IACnC,IAAI,OAAO,CAAC,KAAK,EAAE,CAAC;QAClB,MAAM,EAAE,SAAS,EAAE,GAAG,MAAM,MAAM,CAAC,iBAAiB,CAAC,CAAC;QACtD,6EAA6E;QAC7E,kFAAkF;QAClF,MAAM,SAAS,GAAG,OAAO,CAAC,OAAO,CAAC,SAAS,IAAI,OAAO,CAAC,GAAG,EAAE,EAAE,OAAO,CAAC,KAAK,CAAC,CAAC;QAC7E,UAAU,GAAG,SAAS,CAAC,MAAM,QAAQ,CAAC,SAAS,EAAE,OAAO,CAAC,CAAC,CAAC;IAC7D,CAAC;IAED,4EAA4E;IAC5E,2EAA2E;IAC3E,+EAA+E;IAC/E,yEAAyE;IACzE,kDAAkD;IAClD,MAAM,SAAS,GAAG,OAAO,CAAC,UAAU,EAAE,MAAM,CAAC,CAAC,CAAC,OAAO,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC,YAAY,CAAC,CAAC;IACnF,MAAM,EAAE,QAAQ,EAAE,QAAQ,EAAE,GAAG,MAAM,iBAAiB,CAAC,SAAS,EAAE;QAChE,gBAAgB,EAAE,OAAO,CAAC,gBAAgB;QAC1C,SAAS,EAAE,OAAO,CAAC,SAAS;KAC7B,CAAC,CAAC;IAEH,iFAAiF;IACjF,+CAA+C;IAC/C,MAAM,UAAU,GAAG,sBAAsB,CAAC,KAAK,EAAE,OAAO,CAAC,UAAU,CAAC,CAAC;IACrE,MAAM,IAAI,GAAgB;QACxB,SAAS,EAAE,OAAO,CAAC,SAAS;QAC5B,SAAS,EAAE,OAAO,CAAC,SAAS;QAC5B,SAAS,EAAE,OAAO,CAAC,SAAS;QAC5B,QAAQ,EAAE,OAAO,CAAC,QAAQ;QAC1B,QAAQ,EAAE,OAAO,CAAC,QAAQ;QAC1B,QAAQ,EAAE,OAAO,CAAC,QAAQ;QAC1B,cAAc,EAAE,OAAO,CAAC,cAAc;QACtC,KAAK,EAAE,UAAU;QACjB,OAAO,EAAE,OAAO,CAAC,OAAO;QACxB,SAAS,EAAE,OAAO,CAAC,SAAS;QAC5B,SAAS,EAAE,OAAO,CAAC,SAAS;QAC5B,UAAU;QACV,IAAI,EAAE,OAAO,CAAC,IAAI;QAClB,eAAe,EAAE,OAAO,CAAC,eAAe;KACzC,CAAC;IACF,4EAA4E;IAC5E,oFAAoF;IACpF,kCAAkC;IAClC,iBAAiB,CAAC,QAAQ,EAAE,IAAI,EAAE,QAAQ,EAAE,OAAO,CAAC,UAAU,CAAC,CAAC;IAChE,MAAM,gBAAgB,GAAG,uBAAuB,CAAC,QAAQ,EAAE,QAAQ,EAAE,OAAO,CAAC,OAAO,CAAC,CAAC;IACtF,MAAM,KAAK,GAAG,aAAa,CAAC,KAAK,EAAE;QACjC,UAAU;QACV,UAAU,EAAE,OAAO,CAAC,UAAU,IAAI,QAAQ;QAC1C,IAAI;QACJ,UAAU;QACV,UAAU,EAAE,QAAQ;QACpB,gBAAgB;QAChB,QAAQ;KACT,CAAC,CAAC;IAEH,IAAI,OAAO,CAAC,WAAW,KAAK,IAAI,EAAE,CAAC;QACjC,MAAM,OAAO,GAAG,kBAAkB,CAChC,QAAQ,EACR,KAAK,EACL,IAAI,EACJ,QAAQ,EACR,QAAQ,EACR,UAAU,EACV,UAAU,CACX,CAAC;QACF,IAAI,OAAO,KAAK,SAAS,EAAE,CAAC;YAC1B,KAAK,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,UAAU,CAAC,OAAO,CAAC,UAAU,EAAE,oBAAoB,CAAC,EAAE,OAAO,EAAE,OAAO,EAAE,CAAC,CAAC;QAC/F,CAAC;IACH,CAAC;IAED,MAAM,OAAO,GAAkC,EAAE,CAAC;IAClD,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;QACzB,MAAM,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;QACrD,MAAM,SAAS,CAAC,IAAI,CAAC,IAAI,EAAE,IAAI,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC;QAClD,OAAO,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,IAAI,CAAC,IAAI,EAAE,KAAK,EAAE,MAAM,CAAC,UAAU,CAAC,IAAI,CAAC,OAAO,EAAE,OAAO,CAAC,EAAE,CAAC,CAAC;IACrF,CAAC;IAED,OAAO;QACL,UAAU;QACV,KAAK,EAAE,OAAO,CAAC,MAAM,CAAC,CAAC,GAAG,EAAE,IAAI,EAAE,EAAE,CAAC,GAAG,GAAG,IAAI,CAAC,KAAK,EAAE,CAAC,CAAC;QACzD,KAAK,EAAE,OAAO;KACf,CAAC;AACJ,CAAC"}
|
|
1
|
+
{"version":3,"file":"pipeline.js","sourceRoot":"","sources":["../src/pipeline.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"reserved-names.d.ts","sourceRoot":"","sources":["../src/reserved-names.ts"],"names":[],"mappings":"AAYA,6FAA6F;AAC7F,eAAO,MAAM,YAAY,UA0BxB,CAAC;
|
|
1
|
+
{"version":3,"file":"reserved-names.d.ts","sourceRoot":"","sources":["../src/reserved-names.ts"],"names":[],"mappings":"AAYA,6FAA6F;AAC7F,eAAO,MAAM,YAAY,UA0BxB,CAAC;AAkFF;;;6EAG6E;AAC7E,wBAAgB,mBAAmB,IAAI,GAAG,CAAC,MAAM,CAAC,CAUjD"}
|
package/lib/reserved-names.js
CHANGED
|
@@ -59,6 +59,7 @@ const SATELLITE_NAMES = [
|
|
|
59
59
|
// the runtime's free identifiers with a scope walk and fails when this list falls
|
|
60
60
|
// behind. `undefined` is here because `export type undefined` would not even parse.
|
|
61
61
|
const GLOBAL_NAMES = [
|
|
62
|
+
'AbortController',
|
|
62
63
|
'AbortSignal',
|
|
63
64
|
'Array',
|
|
64
65
|
'ArrayBuffer',
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"reserved-names.js","sourceRoot":"","sources":["../src/reserved-names.ts"],"names":[],"mappings":"AAAA,+EAA+E;AAC/E,oFAAoF;AACpF,oFAAoF;AACpF,8EAA8E;AAC9E,oFAAoF;AACpF,iFAAiF;AACjF,mFAAmF;AACnF,mFAAmF;AACnF,sDAAsD;AAEtD,OAAO,EAAE,sBAAsB,EAAE,MAAM,iCAAiC,CAAC;AAEzE,6FAA6F;AAC7F,MAAM,CAAC,MAAM,YAAY,GAAG;IAC1B,QAAQ;IACR,YAAY;IACZ,KAAK;IACL,aAAa;IACb,eAAe;IACf,cAAc;IACd,cAAc;IACd,YAAY;IACZ,UAAU;IACV,cAAc;IACd,WAAW;IACX,KAAK;IACL,MAAM;IACN,gBAAgB;IAChB,cAAc;IACd,gBAAgB;IAChB,YAAY;IACZ,YAAY;IACZ,qBAAqB;IACrB,iBAAiB;IACjB,QAAQ;IACR,UAAU;IACV,gBAAgB;IAChB,eAAe;IACf,gBAAgB;CACjB,CAAC;AAEF,gFAAgF;AAChF,mFAAmF;AACnF,8BAA8B;AAC9B,MAAM,eAAe,GAAG;IACtB,GAAG;IACH,MAAM;IACN,cAAc;IACd,UAAU;IACV,OAAO;IACP,cAAc;IACd,QAAQ;IACR,gBAAgB;IAChB,YAAY;CACb,CAAC;AAEF,uFAAuF;AACvF,uFAAuF;AACvF,mFAAmF;AACnF,uFAAuF;AACvF,mFAAmF;AACnF,uFAAuF;AACvF,kFAAkF;AAClF,oFAAoF;AACpF,MAAM,YAAY,GAAG;IACnB,aAAa;IACb,OAAO;IACP,aAAa;IACb,iBAAiB;IACjB,gBAAgB;IAChB,eAAe;IACf,MAAM;IACN,UAAU;IACV,SAAS;IACT,cAAc;IACd,MAAM;IACN,OAAO;IACP,SAAS;IACT,UAAU;IACV,SAAS;IACT,aAAa;IACb,MAAM;IACN,KAAK;IACL,MAAM;IACN,aAAa;IACb,QAAQ;IACR,QAAQ;IACR,MAAM;IACN,SAAS;IACT,SAAS;IACT,gBAAgB;IAChB,QAAQ;IACR,QAAQ;IACR,iBAAiB;IACjB,SAAS;IACT,aAAa;IACb,UAAU;IACV,KAAK;IACL,QAAQ;IACR,QAAQ;IACR,aAAa;IACb,aAAa;IACb,WAAW;IACX,YAAY;IACZ,KAAK;IACL,iBAAiB;IACjB,MAAM;IACN,cAAc;IACd,QAAQ;IACR,oBAAoB;IACpB,UAAU;IACV,oBAAoB;IACpB,OAAO;IACP,YAAY;IACZ,YAAY;IACZ,WAAW;CACZ,CAAC;AAEF,IAAI,MAA+B,CAAC;AAEpC;;;6EAG6E;AAC7E,MAAM,UAAU,mBAAmB;IACjC,IAAI,MAAM,KAAK,SAAS,EAAE,CAAC;QACzB,MAAM,GAAG,IAAI,GAAG,CAAC;YACf,GAAG,YAAY;YACf,GAAG,eAAe;YAClB,GAAG,YAAY;YACf,GAAG,sBAAsB;SAC1B,CAAC,CAAC;IACL,CAAC;IACD,OAAO,MAAM,CAAC;AAChB,CAAC"}
|
|
1
|
+
{"version":3,"file":"reserved-names.js","sourceRoot":"","sources":["../src/reserved-names.ts"],"names":[],"mappings":"AAAA,+EAA+E;AAC/E,oFAAoF;AACpF,oFAAoF;AACpF,8EAA8E;AAC9E,oFAAoF;AACpF,iFAAiF;AACjF,mFAAmF;AACnF,mFAAmF;AACnF,sDAAsD;AAEtD,OAAO,EAAE,sBAAsB,EAAE,MAAM,iCAAiC,CAAC;AAEzE,6FAA6F;AAC7F,MAAM,CAAC,MAAM,YAAY,GAAG;IAC1B,QAAQ;IACR,YAAY;IACZ,KAAK;IACL,aAAa;IACb,eAAe;IACf,cAAc;IACd,cAAc;IACd,YAAY;IACZ,UAAU;IACV,cAAc;IACd,WAAW;IACX,KAAK;IACL,MAAM;IACN,gBAAgB;IAChB,cAAc;IACd,gBAAgB;IAChB,YAAY;IACZ,YAAY;IACZ,qBAAqB;IACrB,iBAAiB;IACjB,QAAQ;IACR,UAAU;IACV,gBAAgB;IAChB,eAAe;IACf,gBAAgB;CACjB,CAAC;AAEF,gFAAgF;AAChF,mFAAmF;AACnF,8BAA8B;AAC9B,MAAM,eAAe,GAAG;IACtB,GAAG;IACH,MAAM;IACN,cAAc;IACd,UAAU;IACV,OAAO;IACP,cAAc;IACd,QAAQ;IACR,gBAAgB;IAChB,YAAY;CACb,CAAC;AAEF,uFAAuF;AACvF,uFAAuF;AACvF,mFAAmF;AACnF,uFAAuF;AACvF,mFAAmF;AACnF,uFAAuF;AACvF,kFAAkF;AAClF,oFAAoF;AACpF,MAAM,YAAY,GAAG;IACnB,iBAAiB;IACjB,aAAa;IACb,OAAO;IACP,aAAa;IACb,iBAAiB;IACjB,gBAAgB;IAChB,eAAe;IACf,MAAM;IACN,UAAU;IACV,SAAS;IACT,cAAc;IACd,MAAM;IACN,OAAO;IACP,SAAS;IACT,UAAU;IACV,SAAS;IACT,aAAa;IACb,MAAM;IACN,KAAK;IACL,MAAM;IACN,aAAa;IACb,QAAQ;IACR,QAAQ;IACR,MAAM;IACN,SAAS;IACT,SAAS;IACT,gBAAgB;IAChB,QAAQ;IACR,QAAQ;IACR,iBAAiB;IACjB,SAAS;IACT,aAAa;IACb,UAAU;IACV,KAAK;IACL,QAAQ;IACR,QAAQ;IACR,aAAa;IACb,aAAa;IACb,WAAW;IACX,YAAY;IACZ,KAAK;IACL,iBAAiB;IACjB,MAAM;IACN,cAAc;IACd,QAAQ;IACR,oBAAoB;IACpB,UAAU;IACV,oBAAoB;IACpB,OAAO;IACP,YAAY;IACZ,YAAY;IACZ,WAAW;CACZ,CAAC;AAEF,IAAI,MAA+B,CAAC;AAEpC;;;6EAG6E;AAC7E,MAAM,UAAU,mBAAmB;IACjC,IAAI,MAAM,KAAK,SAAS,EAAE,CAAC;QACzB,MAAM,GAAG,IAAI,GAAG,CAAC;YACf,GAAG,YAAY;YACf,GAAG,eAAe;YAClB,GAAG,YAAY;YACf,GAAG,sBAAsB;SAC1B,CAAC,CAAC;IACL,CAAC;IACD,OAAO,MAAM,CAAC;AAChB,CAAC"}
|
|
@@ -47,12 +47,19 @@ export type ApiErrorLike = globalThis.Error & {
|
|
|
47
47
|
statusText: string;
|
|
48
48
|
body: unknown;
|
|
49
49
|
};
|
|
50
|
-
|
|
50
|
+
export type SettledCall = {
|
|
51
|
+
response?: Response;
|
|
52
|
+
error?: unknown;
|
|
53
|
+
attempts: number;
|
|
54
|
+
durationMs: number;
|
|
55
|
+
};
|
|
56
|
+
/** One interceptor: any subset of the four hooks. */
|
|
51
57
|
export type Middleware<Op extends OperationContext = OperationContext> = {
|
|
52
58
|
onRequest?: (ctx: RequestContext<Op>) => void | Promise<void>;
|
|
53
59
|
onResponse?: (response: Response, ctx: RequestContext<Op>) => Response | void | Promise<Response | void>;
|
|
54
60
|
/** Throw mode only: may map/replace the error. */
|
|
55
61
|
onError?: (error: ApiErrorLike, ctx: RequestContext<Op>) => globalThis.Error | Promise<globalThis.Error>;
|
|
62
|
+
onSettled?: (ctx: RequestContext<Op>, call: SettledCall) => void | Promise<void>;
|
|
56
63
|
};
|
|
57
64
|
/**
|
|
58
65
|
* The spec-independent subset of a client's `ClientConfig` a publisher may bake in
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"runtime-contract.d.ts","sourceRoot":"","sources":["../src/runtime-contract.ts"],"names":[],"mappings":"AAKA,qFAAqF;AACrF,MAAM,MAAM,aAAa,GAAG,OAAO,GAAG,aAAa,CAAC;AAEpD;;;;;;;;GAQG;AACH,MAAM,MAAM,gBAAgB,CAC1B,EAAE,SAAS,MAAM,GAAG,MAAM,EAC1B,IAAI,SAAS,MAAM,GAAG,MAAM,EAC5B,GAAG,SAAS,MAAM,GAAG,MAAM,IACzB;IAAE,EAAE,EAAE,EAAE,CAAC;IAAC,IAAI,EAAE,IAAI,CAAC;IAAC,IAAI,EAAE,GAAG,EAAE,CAAA;CAAE,CAAC;AAExC,yEAAyE;AACzE,MAAM,MAAM,cAAc,CAAC,EAAE,SAAS,gBAAgB,GAAG,gBAAgB,IAAI;IAC3E,GAAG,EAAE,MAAM,CAAC;IACZ,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAChC,IAAI,CAAC,EAAE,OAAO,CAAC;IACf,SAAS,EAAE,EAAE,CAAC;CACf,CAAC;AAEF,iGAAiG;AACjG,MAAM,MAAM,YAAY,CAAC,EAAE,SAAS,gBAAgB,GAAG,gBAAgB,IAAI;IACzE,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,EAAE,cAAc,CAAC,EAAE,CAAC,CAAC;IAC5B,QAAQ,CAAC,EAAE,QAAQ,CAAC;IACpB,KAAK,CAAC,EAAE,OAAO,CAAC;CACjB,CAAC;AAEF,6FAA6F;AAC7F,MAAM,MAAM,WAAW,CAAC,EAAE,SAAS,gBAAgB,GAAG,gBAAgB,IAAI;IACxE,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,aAAa,CAAC,EAAE,aAAa,CAAC;IAC9B,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,OAAO,CAAC,EAAE,CAAC,GAAG,EAAE,YAAY,CAAC,EAAE,CAAC,KAAK,OAAO,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC;CACjE,CAAC;AAEF;;;GAGG;AACH,MAAM,MAAM,YAAY,GAAG,UAAU,CAAC,KAAK,GAAG;IAC5C,GAAG,EAAE,MAAM,CAAC;IACZ,MAAM,EAAE,MAAM,CAAC;IACf,UAAU,EAAE,MAAM,CAAC;IACnB,IAAI,EAAE,OAAO,CAAC;CACf,CAAC;AAEF,
|
|
1
|
+
{"version":3,"file":"runtime-contract.d.ts","sourceRoot":"","sources":["../src/runtime-contract.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"runtime-contract.js","sourceRoot":"","sources":["../src/runtime-contract.ts"],"names":[],"mappings":"AAAA,sFAAsF;AACtF,iFAAiF;AACjF,oFAAoF;AACpF,iFAAiF;
|
|
1
|
+
{"version":3,"file":"runtime-contract.js","sourceRoot":"","sources":["../src/runtime-contract.ts"],"names":[],"mappings":"AAAA,sFAAsF;AACtF,iFAAiF;AACjF,oFAAoF;AACpF,iFAAiF;AAqGjF;;;;;GAKG;AACH,MAAM,UAAU,iBAAiB,CAAC,KAAkB;IAClD,OAAO,KAAK,CAAC;AACf,CAAC"}
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
export declare const GO_RUNTIME_SOURCE = "// Package client \u2014 the embedded runtime for generated Go SDKs. Hand-authored\n// once and stitched into every generated client (see\n// scripts/generate-runtime-sources.mjs), semantically in lockstep with the\n// TypeScript runtime: auth OR-alternatives, a retry loop with Retry-After and\n// full-jitter backoff, per-attempt timeouts, idempotency keys, and middleware\n// hooks. Standard library only \u2014 a generated Go SDK has zero dependencies.\npackage client\n\nimport (\n\t\"bytes\"\n\t\"context\"\n\t\"encoding/base64\"\n\t\"encoding/json\"\n\t\"errors\"\n\t\"fmt\"\n\t\"io\"\n\t\"math/rand\"\n\t\"mime/multipart\"\n\t\"net/http\"\n\t\"net/url\"\n\t\"strconv\"\n\t\"strings\"\n\t\"time\"\n)\n\n// APIError is returned for a non-2xx response, carrying the decoded error body.\ntype APIError struct {\n\tURL string\n\tStatus int\n\tStatusText string\n\tBody any\n}\n\nfunc (e *APIError) Error() string {\n\treturn fmt.Sprintf(\"request failed with status %d\", e.Status)\n}\n\n// TimeoutError is returned when a request attempt exceeds the configured\n// timeout \u2014 carrying the context a log line needs.\ntype TimeoutError struct {\n\tOperationID string\n\tTimeout time.Duration\n\tAttempt int\n}\n\nfunc (e *TimeoutError) Error() string {\n\treturn fmt.Sprintf(\"request %q timed out after %s (attempt %d)\", e.OperationID, e.Timeout, e.Attempt)\n}\n\n// SecuritySpec mirrors the descriptor table's security entries.\ntype SecuritySpec struct {\n\tScheme string\n\tKind string // \"bearer\" | \"basic\" | \"apiKey\"\n\tName string // header/query/cookie name for apiKey\n\tIn string // \"header\" | \"query\" | \"cookie\"\n}\n\n// Auth holds the client credentials; zero value = anonymous.\ntype Auth struct {\n\tBearer func() string\n\tBasic *BasicAuth\n\tAPIKey map[string]func() string\n}\n\ntype BasicAuth struct {\n\tUsername string\n\tPassword string\n}\n\n// RetryConfig mirrors the TypeScript runtime's retry policy knobs.\ntype RetryConfig struct {\n\tRetries int\n\tRetryDelay time.Duration // base; default 1s\n\tRetryStrategy string // \"\" (exponential) | \"fixed\"\n\tNoJitter bool\n\t// RetryOn fully replaces the default predicate when set.\n\tRetryOn func(attempt int, resp *http.Response, err error) bool\n}\n\n// Middleware hooks run around every request (OnRequest before serialization order\n// is N/A in Go \u2014 bodies are values; OnResponse runs in reverse registration order).\ntype Middleware struct {\n\tOnRequest func(req *http.Request)\n\tOnResponse func(resp *http.Response)\n}\n\n// Date is an RFC 3339 full-date \u2014 a calendar date with no time component. Fields\n// typed `date` under `dateType: Date` use it because encoding/json speaks only\n// RFC 3339 date-time for time.Time, which a bare \"2006-01-02\" fails to satisfy.\ntype Date struct {\n\ttime.Time\n}\n\nconst dateLayout = \"2006-01-02\"\n\n// UnmarshalJSON parses a \"2006-01-02\" string; an empty string leaves the zero value.\nfunc (d *Date) UnmarshalJSON(data []byte) error {\n\tvar raw string\n\tif err := json.Unmarshal(data, &raw); err != nil {\n\t\treturn err\n\t}\n\tif raw == \"\" {\n\t\treturn nil\n\t}\n\tparsed, err := time.Parse(dateLayout, raw)\n\tif err != nil {\n\t\treturn err\n\t}\n\td.Time = parsed\n\treturn nil\n}\n\n// MarshalJSON writes the date back without a time component.\nfunc (d Date) MarshalJSON() ([]byte, error) {\n\treturn json.Marshal(d.Format(dateLayout))\n}\n\n// Config is the per-client configuration shared by every operation method.\ntype Config struct {\n\tServerURL string\n\tHTTPClient *http.Client\n\tHeaders map[string]string\n\tTimeout time.Duration\n\tRetry RetryConfig\n\tMiddleware []Middleware\n\tIdempotencyKey func() string\n\tAuth Auth\n}\n\nfunc resolveToken(provider func() string) string {\n\tif provider == nil {\n\t\treturn \"\"\n\t}\n\treturn provider()\n}\n\nfunc schemeConfigured(spec SecuritySpec, auth Auth) bool {\n\tswitch spec.Kind {\n\tcase \"apiKey\":\n\t\t_, ok := auth.APIKey[spec.Scheme]\n\t\treturn ok\n\tcase \"bearer\":\n\t\treturn auth.Bearer != nil\n\tdefault:\n\t\treturn auth.Basic != nil\n\t}\n}\n\n// resolveAuth applies the first fully-configured OR-alternative; when none is,\n// the first alternative's configured schemes are still sent (the server rejects\n// the request \u2014 same behavior as the TypeScript runtime).\nfunc resolveAuth(security [][]SecuritySpec, auth Auth) (map[string]string, url.Values) {\n\theaders := map[string]string{}\n\tquery := url.Values{}\n\tif len(security) == 0 {\n\t\treturn headers, query\n\t}\n\talternative := security[0]\n\tfor _, candidate := range security {\n\t\tall := true\n\t\tfor _, spec := range candidate {\n\t\t\tif !schemeConfigured(spec, auth) {\n\t\t\t\tall = false\n\t\t\t\tbreak\n\t\t\t}\n\t\t}\n\t\tif all {\n\t\t\talternative = candidate\n\t\t\tbreak\n\t\t}\n\t}\n\tvar cookies []string\n\tfor _, spec := range alternative {\n\t\tswitch spec.Kind {\n\t\tcase \"apiKey\":\n\t\t\tprovider, ok := auth.APIKey[spec.Scheme]\n\t\t\tif !ok {\n\t\t\t\tcontinue\n\t\t\t}\n\t\t\tvalue := resolveToken(provider)\n\t\t\tswitch spec.In {\n\t\t\tcase \"query\":\n\t\t\t\tquery.Set(spec.Name, value)\n\t\t\tcase \"cookie\":\n\t\t\t\tcookies = append(cookies, spec.Name+\"=\"+url.QueryEscape(value))\n\t\t\tdefault:\n\t\t\t\theaders[spec.Name] = value\n\t\t\t}\n\t\tcase \"bearer\":\n\t\t\tif auth.Bearer != nil {\n\t\t\t\theaders[\"Authorization\"] = \"Bearer \" + resolveToken(auth.Bearer)\n\t\t\t}\n\t\tdefault:\n\t\t\tif auth.Basic != nil {\n\t\t\t\ttoken := base64.StdEncoding.EncodeToString([]byte(auth.Basic.Username + \":\" + auth.Basic.Password))\n\t\t\t\theaders[\"Authorization\"] = \"Basic \" + token\n\t\t\t}\n\t\t}\n\t}\n\tif len(cookies) > 0 {\n\t\theaders[\"Cookie\"] = strings.Join(cookies, \"; \")\n\t}\n\treturn headers, query\n}\n\n// buildURL substitutes {param} path placeholders with percent-encoded values.\nfunc buildURL(serverURL, path string, pathParams map[string]string) string {\n\tfilled := path\n\tfor name, value := range pathParams {\n\t\tfilled = strings.ReplaceAll(filled, \"{\"+name+\"}\", url.PathEscape(value))\n\t}\n\treturn strings.TrimRight(serverURL, \"/\") + filled\n}\n\nvar transientStatus = map[int]bool{408: true, 429: true, 500: true, 502: true, 503: true, 504: true}\n\nfunc defaultRetryOn(method string, headers map[string]string, resp *http.Response, err error) bool {\n\tsafe := false\n\tswitch strings.ToUpper(method) {\n\tcase \"GET\", \"HEAD\", \"PUT\", \"DELETE\", \"OPTIONS\":\n\t\tsafe = true\n\t}\n\tif _, ok := headers[\"Idempotency-Key\"]; ok {\n\t\tsafe = true\n\t}\n\tif !safe {\n\t\treturn false\n\t}\n\tif err != nil {\n\t\treturn true\n\t}\n\treturn resp != nil && transientStatus[resp.StatusCode]\n}\n\nfunc retryDelay(retry RetryConfig, attempt int, retryAfter string) time.Duration {\n\tif retryAfter != \"\" {\n\t\tif seconds, err := strconv.ParseFloat(retryAfter, 64); err == nil {\n\t\t\treturn time.Duration(seconds * float64(time.Second))\n\t\t}\n\t}\n\tbase := retry.RetryDelay\n\tif base == 0 {\n\t\tbase = time.Second\n\t}\n\traw := base\n\tif retry.RetryStrategy != \"fixed\" {\n\t\traw = base * time.Duration(1<<(attempt-1))\n\t}\n\tif retry.NoJitter {\n\t\treturn raw\n\t}\n\treturn time.Duration(rand.Int63n(int64(raw) + 1))\n}\n\ntype requestSpec struct {\n\tOperationID string\n\tMethod string\n\tURL string\n\tHeaders map[string]string\n\tQuery url.Values\n\tBody io.Reader\n\t// Stream sends Body as is: no buffering, one attempt, the caller's Content-Type.\n\tStream bool\n\tContentType string\n\tTimeout time.Duration\n\tRetry *RetryConfig\n\tIdempotencyKey string\n\t// bodyBytes is retained so retries can replay the body.\n\tbodyBytes []byte\n}\n\n// send is the request core: header merge, idempotency keys, the retry loop\n// (fresh timeout budget per attempt), and the middleware onion.\nfunc send(ctx context.Context, config *Config, spec requestSpec) (*http.Response, error) {\n\tretry := config.Retry\n\tif spec.Retry != nil {\n\t\tretry = *spec.Retry\n\t}\n\ttimeout := config.Timeout\n\tif spec.Timeout != 0 {\n\t\ttimeout = spec.Timeout\n\t}\n\theaders := map[string]string{}\n\tfor key, value := range config.Headers {\n\t\theaders[key] = value\n\t}\n\tfor key, value := range spec.Headers {\n\t\theaders[key] = value\n\t}\n\tmethod := strings.ToUpper(spec.Method)\n\tif (method == \"POST\" || method == \"PATCH\") && headers[\"Idempotency-Key\"] == \"\" {\n\t\tif spec.IdempotencyKey != \"\" {\n\t\t\theaders[\"Idempotency-Key\"] = spec.IdempotencyKey\n\t\t} else if config.IdempotencyKey != nil {\n\t\t\theaders[\"Idempotency-Key\"] = config.IdempotencyKey()\n\t\t}\n\t}\n\thttpClient := config.HTTPClient\n\tif httpClient == nil {\n\t\thttpClient = http.DefaultClient\n\t}\n\tif spec.Body != nil && !spec.Stream {\n\t\tpayload, err := io.ReadAll(spec.Body)\n\t\tif err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t\tspec.bodyBytes = payload\n\t}\n\tfullURL := spec.URL\n\tif len(spec.Query) > 0 {\n\t\tseparator := \"?\"\n\t\tif strings.Contains(fullURL, \"?\") {\n\t\t\tseparator = \"&\"\n\t\t}\n\t\tfullURL += separator + spec.Query.Encode()\n\t}\n\tmaxAttempts := 1 + retry.Retries\n\tif spec.Stream {\n\t\t// The first attempt consumes the reader, so there is nothing to replay.\n\t\tmaxAttempts = 1\n\t}\n\tfor attempt := 1; ; attempt++ {\n\t\tattemptCtx := ctx\n\t\tvar cancel context.CancelFunc\n\t\tif timeout > 0 {\n\t\t\tattemptCtx, cancel = context.WithTimeout(ctx, timeout)\n\t\t}\n\t\tvar bodyReader io.Reader\n\t\tswitch {\n\t\tcase spec.Stream:\n\t\t\tbodyReader = spec.Body\n\t\tcase spec.bodyBytes != nil:\n\t\t\tbodyReader = bytes.NewReader(spec.bodyBytes)\n\t\t}\n\t\treq, err := http.NewRequestWithContext(attemptCtx, method, fullURL, bodyReader)\n\t\tif err != nil {\n\t\t\tif cancel != nil {\n\t\t\t\tcancel()\n\t\t\t}\n\t\t\treturn nil, err\n\t\t}\n\t\tfor key, value := range headers {\n\t\t\treq.Header.Set(key, value)\n\t\t}\n\t\tif spec.ContentType != \"\" && bodyReader != nil && req.Header.Get(\"Content-Type\") == \"\" {\n\t\t\treq.Header.Set(\"Content-Type\", spec.ContentType)\n\t\t}\n\t\tfor _, mw := range config.Middleware {\n\t\t\tif mw.OnRequest != nil {\n\t\t\t\tmw.OnRequest(req)\n\t\t\t}\n\t\t}\n\t\tresp, err := httpClient.Do(req)\n\t\tshouldRetry := retry.RetryOn\n\t\tretryable := false\n\t\tif shouldRetry != nil {\n\t\t\tretryable = shouldRetry(attempt, resp, err)\n\t\t} else {\n\t\t\tretryable = defaultRetryOn(method, headers, resp, err)\n\t\t}\n\t\tif err != nil {\n\t\t\tif cancel != nil {\n\t\t\t\tcancel()\n\t\t\t}\n\t\t\ttimedOut := errors.Is(err, context.DeadlineExceeded) && ctx.Err() == nil\n\t\t\tif attempt < maxAttempts && retryable {\n\t\t\t\ttime.Sleep(retryDelay(retry, attempt, \"\"))\n\t\t\t\tcontinue\n\t\t\t}\n\t\t\tif timedOut {\n\t\t\t\treturn nil, &TimeoutError{OperationID: spec.OperationID, Timeout: timeout, Attempt: attempt}\n\t\t\t}\n\t\t\treturn nil, err\n\t\t}\n\t\tfor i := len(config.Middleware) - 1; i >= 0; i-- {\n\t\t\tif config.Middleware[i].OnResponse != nil {\n\t\t\t\tconfig.Middleware[i].OnResponse(resp)\n\t\t\t}\n\t\t}\n\t\tif resp.StatusCode >= 400 && attempt < maxAttempts && retryable {\n\t\t\tafter := resp.Header.Get(\"Retry-After\")\n\t\t\tio.Copy(io.Discard, resp.Body)\n\t\t\tresp.Body.Close()\n\t\t\tif cancel != nil {\n\t\t\t\tcancel()\n\t\t\t}\n\t\t\ttime.Sleep(retryDelay(retry, attempt, after))\n\t\t\tcontinue\n\t\t}\n\t\t// The response body outlives this call; tie the attempt context's lifetime to it.\n\t\tif cancel != nil {\n\t\t\tresp.Body = &cancelOnClose{ReadCloser: resp.Body, cancel: cancel}\n\t\t}\n\t\treturn resp, nil\n\t}\n}\n\ntype cancelOnClose struct {\n\tio.ReadCloser\n\tcancel context.CancelFunc\n}\n\nfunc (c *cancelOnClose) Close() error {\n\tc.cancel()\n\treturn c.ReadCloser.Close()\n}\n\n// decodeJSON decodes a response body into target; a nil target drains and closes.\nfunc decodeJSON(resp *http.Response, target any) error {\n\tdefer resp.Body.Close()\n\tif target == nil {\n\t\t_, err := io.Copy(io.Discard, resp.Body)\n\t\treturn err\n\t}\n\treturn json.NewDecoder(resp.Body).Decode(target)\n}\n\n// headerString returns the named response header, or nil when absent.\nfunc headerString(header http.Header, name string) *string {\n\tvalue := header.Get(name)\n\tif value == \"\" {\n\t\treturn nil\n\t}\n\treturn &value\n}\n\n// headerInt64 parses the named header as an integer; nil when absent or unparsable.\nfunc headerInt64(header http.Header, name string) *int64 {\n\traw := strings.TrimSpace(header.Get(name))\n\tif raw == \"\" {\n\t\treturn nil\n\t}\n\tvalue, err := strconv.ParseInt(raw, 10, 64)\n\tif err != nil {\n\t\treturn nil\n\t}\n\treturn &value\n}\n\n// headerFloat64 parses the named header as a number; nil when absent or unparsable.\nfunc headerFloat64(header http.Header, name string) *float64 {\n\traw := strings.TrimSpace(header.Get(name))\n\tif raw == \"\" {\n\t\treturn nil\n\t}\n\tvalue, err := strconv.ParseFloat(raw, 64)\n\tif err != nil {\n\t\treturn nil\n\t}\n\treturn &value\n}\n\n// headerBool parses a `true`/`false` header; nil when absent or anything else.\nfunc headerBool(header http.Header, name string) *bool {\n\traw := strings.ToLower(strings.TrimSpace(header.Get(name)))\n\tif raw != \"true\" && raw != \"false\" {\n\t\treturn nil\n\t}\n\tvalue := raw == \"true\"\n\treturn &value\n}\n\n// apiErrorFrom builds the structured error for a non-2xx response.\nfunc apiErrorFrom(resp *http.Response, requestURL string) error {\n\tdefer resp.Body.Close()\n\tvar body any\n\tdata, _ := io.ReadAll(resp.Body)\n\tif len(data) > 0 {\n\t\tif err := json.Unmarshal(data, &body); err != nil {\n\t\t\tbody = string(data)\n\t\t}\n\t}\n\treturn &APIError{URL: requestURL, Status: resp.StatusCode, StatusText: resp.Status, Body: body}\n}\n\n// \u2500\u2500\u2500 Pagination \u2500\u2500\u2500\n\n// PaginationSpec mirrors the descriptor table's pagination entries.\ntype PaginationSpec struct {\n\tStyle string\n\tParam string\n\tNextCursor string\n\tHasMore string\n\tLimitParam string\n\tItems string\n}\n\n// resolvePointer walks an RFC 6901 JSON pointer over decoded JSON; nil on any miss.\nfunc resolvePointer(data any, pointer string) any {\n\tif pointer == \"\" {\n\t\treturn data\n\t}\n\tif !strings.HasPrefix(pointer, \"/\") {\n\t\treturn nil\n\t}\n\tcurrent := data\n\tfor _, token := range strings.Split(pointer[1:], \"/\") {\n\t\tkey := strings.ReplaceAll(strings.ReplaceAll(token, \"~1\", \"/\"), \"~0\", \"~\")\n\t\tswitch typed := current.(type) {\n\t\tcase map[string]any:\n\t\t\tcurrent = typed[key]\n\t\tcase []any:\n\t\t\tindex, err := strconv.Atoi(key)\n\t\t\tif err != nil || index < 0 || index >= len(typed) {\n\t\t\t\treturn nil\n\t\t\t}\n\t\t\tcurrent = typed[index]\n\t\tdefault:\n\t\t\treturn nil\n\t\t}\n\t\tif current == nil {\n\t\t\treturn nil\n\t\t}\n\t}\n\treturn current\n}\n\n// reencode converts decoded JSON (maps/slices) into a typed value via a JSON round-trip.\nfunc reencode(raw any, target any) error {\n\tdata, err := json.Marshal(raw)\n\tif err != nil {\n\t\treturn err\n\t}\n\treturn json.Unmarshal(data, target)\n}\n\ntype pageCall func(params url.Values) (any, *http.Response, error)\n\n// iterPages yields raw page JSON per the pagination spec \u2014 the same stop\n// conditions and infinite-loop guards as the TypeScript runtime. The returned\n// function is a range-over-func iterator (Go 1.23+) and plainly callable before that.\nfunc iterPages(call pageCall, spec PaginationSpec, base url.Values) func(yield func(any, error) bool) {\n\treturn func(yield func(any, error) bool) {\n\t\tswitch spec.Style {\n\t\tcase \"cursor\":\n\t\t\tvar cursor any\n\t\t\tif values, ok := base[spec.Param]; ok && len(values) > 0 {\n\t\t\t\tcursor = values[0]\n\t\t\t}\n\t\t\tfor {\n\t\t\t\tparams := cloneValues(base)\n\t\t\t\tif cursor != nil {\n\t\t\t\t\tparams.Set(spec.Param, fmt.Sprint(cursor))\n\t\t\t\t}\n\t\t\t\tpage, _, err := call(params)\n\t\t\t\tif err != nil {\n\t\t\t\t\tyield(nil, err)\n\t\t\t\t\treturn\n\t\t\t\t}\n\t\t\t\tif !yield(page, nil) {\n\t\t\t\t\treturn\n\t\t\t\t}\n\t\t\t\tif spec.HasMore != \"\" {\n\t\t\t\t\tif more, ok := resolvePointer(page, spec.HasMore).(bool); ok && !more {\n\t\t\t\t\t\treturn\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tnext := resolvePointer(page, spec.NextCursor)\n\t\t\t\tif next == nil || next == \"\" {\n\t\t\t\t\treturn\n\t\t\t\t}\n\t\t\t\tswitch next.(type) {\n\t\t\t\tcase string, float64:\n\t\t\t\tdefault:\n\t\t\t\t\tyield(nil, fmt.Errorf(\"pagination cursor at %s is not a string or number\", spec.NextCursor))\n\t\t\t\t\treturn\n\t\t\t\t}\n\t\t\t\tif cursor != nil && fmt.Sprint(next) == fmt.Sprint(cursor) {\n\t\t\t\t\tyield(nil, errors.New(\"pagination did not advance: the operation returned the same cursor twice\"))\n\t\t\t\t\treturn\n\t\t\t\t}\n\t\t\t\tcursor = next\n\t\t\t}\n\t\tcase \"link\":\n\t\t\tparams := cloneValues(base)\n\t\t\tprevious := \"\"\n\t\t\tfor {\n\t\t\t\tpage, resp, err := call(params)\n\t\t\t\tif err != nil {\n\t\t\t\t\tyield(nil, err)\n\t\t\t\t\treturn\n\t\t\t\t}\n\t\t\t\tif !yield(page, nil) {\n\t\t\t\t\treturn\n\t\t\t\t}\n\t\t\t\ttarget := linkNext(resp.Header.Get(\"Link\"))\n\t\t\t\tif target == \"\" {\n\t\t\t\t\treturn\n\t\t\t\t}\n\t\t\t\tpageURL := \"\"\n\t\t\t\tif resp.Request != nil && resp.Request.URL != nil {\n\t\t\t\t\tpageURL = resp.Request.URL.String()\n\t\t\t\t}\n\t\t\t\tbaseURL, err := url.Parse(pageURL)\n\t\t\t\tif err != nil || pageURL == \"\" {\n\t\t\t\t\tbaseURL, _ = url.Parse(\"http://relative.invalid\")\n\t\t\t\t}\n\t\t\t\ttargetURL, err := baseURL.Parse(target)\n\t\t\t\tif err != nil {\n\t\t\t\t\tyield(nil, err)\n\t\t\t\t\treturn\n\t\t\t\t}\n\t\t\t\tnext := targetURL.String()\n\t\t\t\tif next == previous || next == pageURL {\n\t\t\t\t\tyield(nil, errors.New(`pagination did not advance: the Link rel=\"next\" target repeats`))\n\t\t\t\t\treturn\n\t\t\t\t}\n\t\t\t\tprevious = next\n\t\t\t\tparams = cloneValues(base)\n\t\t\t\tfor key, values := range targetURL.Query() {\n\t\t\t\t\tfor _, value := range values {\n\t\t\t\t\t\tparams.Add(key, value)\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\tdefault: // offset / page\n\t\t\tposition := 0\n\t\t\tif spec.Style == \"page\" {\n\t\t\t\tposition = 1\n\t\t\t}\n\t\t\tif values, ok := base[spec.Param]; ok && len(values) > 0 && values[0] != \"\" {\n\t\t\t\tif parsed, err := strconv.Atoi(values[0]); err == nil {\n\t\t\t\t\tposition = parsed\n\t\t\t\t}\n\t\t\t}\n\t\t\tpreviousItems := \"\"\n\t\t\tfor {\n\t\t\t\tparams := cloneValues(base)\n\t\t\t\tparams.Set(spec.Param, strconv.Itoa(position))\n\t\t\t\tpage, _, err := call(params)\n\t\t\t\tif err != nil {\n\t\t\t\t\tyield(nil, err)\n\t\t\t\t\treturn\n\t\t\t\t}\n\t\t\t\titems, _ := resolvePointer(page, spec.Items).([]any)\n\t\t\t\tserialized := \"\"\n\t\t\t\tif items != nil {\n\t\t\t\t\tserialized = fmt.Sprint(items)\n\t\t\t\t\tif serialized == previousItems {\n\t\t\t\t\t\tyield(nil, errors.New(\"pagination did not advance: the operation returned the same page twice\"))\n\t\t\t\t\t\treturn\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tif !yield(page, nil) {\n\t\t\t\t\treturn\n\t\t\t\t}\n\t\t\t\tif len(items) == 0 {\n\t\t\t\t\treturn\n\t\t\t\t}\n\t\t\t\tpreviousItems = serialized\n\t\t\t\tif spec.Style == \"page\" {\n\t\t\t\t\tposition++\n\t\t\t\t} else {\n\t\t\t\t\tposition += len(items)\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n}\n\nfunc cloneValues(values url.Values) url.Values {\n\tout := url.Values{}\n\tfor key, entries := range values {\n\t\tfor _, entry := range entries {\n\t\t\tout.Add(key, entry)\n\t\t}\n\t}\n\treturn out\n}\n\nfunc linkNext(header string) string {\n\tif header == \"\" {\n\t\treturn \"\"\n\t}\n\tfor _, entry := range strings.Split(header, \",\") {\n\t\tparts := strings.Split(entry, \";\")\n\t\tif len(parts) < 2 {\n\t\t\tcontinue\n\t\t}\n\t\ttarget := strings.TrimSpace(parts[0])\n\t\tif !strings.HasPrefix(target, \"<\") || !strings.HasSuffix(target, \">\") {\n\t\t\tcontinue\n\t\t}\n\t\tfor _, param := range parts[1:] {\n\t\t\ttrimmed := strings.TrimSpace(param)\n\t\t\tif strings.HasPrefix(trimmed, \"rel=\") {\n\t\t\t\trel := strings.Trim(strings.TrimPrefix(trimmed, \"rel=\"), `\"`)\n\t\t\t\tfor _, kind := range strings.Fields(rel) {\n\t\t\t\t\tif kind == \"next\" {\n\t\t\t\t\t\treturn strings.Trim(target, \"<>\")\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\treturn \"\"\n}\n\n// \u2500\u2500\u2500 Server-Sent Events \u2500\u2500\u2500\n\n// ServerSentEvent is one decoded event; Data is the raw text (or parsed JSON\n// for operations that declare a JSON event stream).\ntype ServerSentEvent struct {\n\tEvent string\n\tData any\n\tID string\n\tRetry int\n}\n\nfunc parseSSEFrame(raw string, jsonData bool) (ServerSentEvent, bool, error) {\n\tevent := ServerSentEvent{Retry: -1}\n\tsawField := false\n\tvar dataLines []string\n\tnormalized := strings.ReplaceAll(strings.ReplaceAll(raw, \"\\r\\n\", \"\\n\"), \"\\r\", \"\\n\")\n\tfor _, line := range strings.Split(normalized, \"\\n\") {\n\t\tif line == \"\" || strings.HasPrefix(line, \":\") {\n\t\t\tcontinue\n\t\t}\n\t\tfield, value, _ := strings.Cut(line, \":\")\n\t\tvalue = strings.TrimPrefix(value, \" \")\n\t\tsawField = true\n\t\tswitch field {\n\t\tcase \"event\":\n\t\t\tevent.Event = value\n\t\tcase \"data\":\n\t\t\tdataLines = append(dataLines, value)\n\t\tcase \"id\":\n\t\t\tevent.ID = value\n\t\tcase \"retry\":\n\t\t\tif parsed, err := strconv.Atoi(value); err == nil && parsed >= 0 && value != \"\" {\n\t\t\t\tevent.Retry = parsed\n\t\t\t}\n\t\t}\n\t}\n\tif !sawField {\n\t\treturn event, false, nil\n\t}\n\ttext := strings.Join(dataLines, \"\\n\")\n\tevent.Data = text\n\tif jsonData && text != \"\" {\n\t\tvar parsed any\n\t\tif err := json.Unmarshal([]byte(text), &parsed); err != nil {\n\t\t\treturn event, false, err\n\t\t}\n\t\tevent.Data = parsed\n\t}\n\treturn event, true, nil\n}\n\n// iterSSE streams events, reconnecting on dropped connections with Last-Event-ID\n// (a fresh open call = fresh auth); a 4xx/5xx or a bad JSON payload is definitive.\nfunc iterSSE(open func(extraHeaders map[string]string) (*http.Response, error), jsonData bool) func(yield func(ServerSentEvent, error) bool) {\n\treturn func(yield func(ServerSentEvent, error) bool) {\n\t\tlastEventID := \"\"\n\t\tserverRetry := -1\n\t\tfailures := 0\n\t\tfor {\n\t\t\theaders := map[string]string{\"Accept\": \"text/event-stream\"}\n\t\t\tif lastEventID != \"\" {\n\t\t\t\theaders[\"Last-Event-ID\"] = lastEventID\n\t\t\t}\n\t\t\tresp, err := open(headers)\n\t\t\tif err == nil && resp.StatusCode >= 400 {\n\t\t\t\tyield(ServerSentEvent{}, apiErrorFrom(resp, \"\"))\n\t\t\t\treturn\n\t\t\t}\n\t\t\tif err == nil {\n\t\t\t\tfailures = 0\n\t\t\t\tbuffer := \"\"\n\t\t\t\tchunk := make([]byte, 4096)\n\t\t\t\tclean := false\n\t\t\t\tfor {\n\t\t\t\t\tn, readErr := resp.Body.Read(chunk)\n\t\t\t\t\tbuffer += string(chunk[:n])\n\t\t\t\t\tfor {\n\t\t\t\t\t\tframe, rest, found := strings.Cut(buffer, \"\\n\\n\")\n\t\t\t\t\t\tif !found {\n\t\t\t\t\t\t\tbreak\n\t\t\t\t\t\t}\n\t\t\t\t\t\tbuffer = rest\n\t\t\t\t\t\tevent, ok, parseErr := parseSSEFrame(frame, jsonData)\n\t\t\t\t\t\tif parseErr != nil {\n\t\t\t\t\t\t\tresp.Body.Close()\n\t\t\t\t\t\t\tyield(ServerSentEvent{}, parseErr)\n\t\t\t\t\t\t\treturn\n\t\t\t\t\t\t}\n\t\t\t\t\t\tif ok {\n\t\t\t\t\t\t\tif event.ID != \"\" {\n\t\t\t\t\t\t\t\tlastEventID = event.ID\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tif event.Retry >= 0 {\n\t\t\t\t\t\t\t\tserverRetry = event.Retry\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tif !yield(event, nil) {\n\t\t\t\t\t\t\t\tresp.Body.Close()\n\t\t\t\t\t\t\t\treturn\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\tif readErr == io.EOF {\n\t\t\t\t\t\tclean = true\n\t\t\t\t\t\tbreak\n\t\t\t\t\t}\n\t\t\t\t\tif readErr != nil {\n\t\t\t\t\t\tbreak\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tresp.Body.Close()\n\t\t\t\tif clean {\n\t\t\t\t\tif strings.TrimSpace(buffer) != \"\" {\n\t\t\t\t\t\tif event, ok, parseErr := parseSSEFrame(buffer, jsonData); parseErr == nil && ok {\n\t\t\t\t\t\t\tyield(event, nil)\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\treturn\n\t\t\t\t}\n\t\t\t}\n\t\t\tfailures++\n\t\t\tbase := time.Second\n\t\t\tif serverRetry >= 0 {\n\t\t\t\tbase = time.Duration(serverRetry) * time.Millisecond\n\t\t\t}\n\t\t\tdelay := base * time.Duration(1<<(failures-1))\n\t\t\tif delay > 30*time.Second {\n\t\t\t\tdelay = 30 * time.Second\n\t\t\t}\n\t\t\ttime.Sleep(time.Duration(rand.Int63n(int64(delay) + 1)))\n\t\t}\n\t}\n}\n\n// \u2500\u2500\u2500 Multipart \u2500\u2500\u2500\n\n// toMultipart splits a typed body into a multipart/form-data payload: []byte\n// values upload as file parts, everything else as form fields (nested values\n// JSON-encoded) \u2014 mirroring the TypeScript runtime's FormData serialization.\nfunc toMultipart(body any) (string, io.Reader, error) {\n\tvar wire map[string]any\n\tif err := reencode(body, &wire); err != nil {\n\t\treturn \"\", nil, err\n\t}\n\tbuffer := &bytes.Buffer{}\n\twriter := multipart.NewWriter(buffer)\n\tfor key, value := range wire {\n\t\tswitch typed := value.(type) {\n\t\tcase string:\n\t\t\tif err := writer.WriteField(key, typed); err != nil {\n\t\t\t\treturn \"\", nil, err\n\t\t\t}\n\t\tcase float64, bool:\n\t\t\tif err := writer.WriteField(key, fmt.Sprint(typed)); err != nil {\n\t\t\t\treturn \"\", nil, err\n\t\t\t}\n\t\tdefault:\n\t\t\tencoded, err := json.Marshal(typed)\n\t\t\tif err != nil {\n\t\t\t\treturn \"\", nil, err\n\t\t\t}\n\t\t\tif err := writer.WriteField(key, string(encoded)); err != nil {\n\t\t\t\treturn \"\", nil, err\n\t\t\t}\n\t\t}\n\t}\n\tif err := writer.Close(); err != nil {\n\t\treturn \"\", nil, err\n\t}\n\treturn writer.FormDataContentType(), buffer, nil\n}\n\n// multipartBody prepares the body of an untyped multipart operation: an io.Reader is\n// streamed and a []byte or string sent as is, all under the caller's Content-Type (the\n// boundary is theirs to set); any other value goes through toMultipart.\nfunc multipartBody(body any) (string, io.Reader, bool, error) {\n\tif reader, stream, raw := rawBody(body); raw {\n\t\treturn \"\", reader, stream, nil\n\t}\n\tcontentType, reader, err := toMultipart(body)\n\treturn contentType, reader, false, err\n}\n\n// binaryBody prepares the body of a binary operation: an io.Reader is streamed, a\n// []byte or string sent as is, and any other value JSON-marshalled.\nfunc binaryBody(body any) (io.Reader, bool, error) {\n\tif reader, stream, raw := rawBody(body); raw {\n\t\treturn reader, stream, nil\n\t}\n\tpayload, err := json.Marshal(body)\n\treturn bytes.NewReader(payload), false, err\n}\n\n// rawBody recognizes a body that needs no encoding: an io.Reader streams through in one\n// attempt, a []byte or a string is replayable bytes.\nfunc rawBody(body any) (io.Reader, bool, bool) {\n\tswitch typed := body.(type) {\n\tcase io.Reader:\n\t\treturn typed, true, true\n\tcase []byte:\n\t\treturn bytes.NewReader(typed), false, true\n\tcase string:\n\t\treturn strings.NewReader(typed), false, true\n\t}\n\treturn nil, false, false\n}\n";
|
|
1
|
+
export declare const GO_RUNTIME_SOURCE = "// Package client \u2014 the embedded runtime for generated Go SDKs. Hand-authored\n// once and stitched into every generated client (see\n// scripts/generate-runtime-sources.mjs), semantically in lockstep with the\n// TypeScript runtime: auth OR-alternatives, a retry loop with Retry-After and\n// full-jitter backoff, per-attempt timeouts, idempotency keys, and middleware\n// hooks. Standard library only \u2014 a generated Go SDK has zero dependencies.\npackage client\n\nimport (\n\t\"bytes\"\n\t\"context\"\n\t\"encoding/base64\"\n\t\"encoding/json\"\n\t\"errors\"\n\t\"fmt\"\n\t\"io\"\n\t\"math/rand\"\n\t\"mime/multipart\"\n\t\"net/http\"\n\t\"net/url\"\n\t\"strconv\"\n\t\"strings\"\n\t\"time\"\n)\n\n// APIError is returned for a non-2xx response, carrying the decoded error body.\ntype APIError struct {\n\tURL string\n\tStatus int\n\tStatusText string\n\tBody any\n}\n\nfunc (e *APIError) Error() string {\n\treturn fmt.Sprintf(\"request failed with status %d\", e.Status)\n}\n\n// TimeoutError is returned when a request attempt exceeds the configured\n// timeout \u2014 carrying the context a log line needs.\ntype TimeoutError struct {\n\tOperationID string\n\tTimeout time.Duration\n\tAttempt int\n}\n\nfunc (e *TimeoutError) Error() string {\n\treturn fmt.Sprintf(\"request %q timed out after %s (attempt %d)\", e.OperationID, e.Timeout, e.Attempt)\n}\n\n// SecuritySpec mirrors the descriptor table's security entries.\ntype SecuritySpec struct {\n\tScheme string\n\tKind string // \"bearer\" | \"basic\" | \"apiKey\"\n\tName string // header/query/cookie name for apiKey\n\tIn string // \"header\" | \"query\" | \"cookie\"\n}\n\n// Auth holds the client credentials; zero value = anonymous.\ntype Auth struct {\n\tBearer func() string\n\tBasic *BasicAuth\n\tAPIKey map[string]func() string\n}\n\ntype BasicAuth struct {\n\tUsername string\n\tPassword string\n}\n\n// RetryConfig mirrors the TypeScript runtime's retry policy knobs.\ntype RetryConfig struct {\n\tRetries int\n\tRetryDelay time.Duration // base; default 1s\n\tRetryStrategy string // \"\" (exponential) | \"fixed\"\n\tNoJitter bool\n\t// RetryOn fully replaces the default predicate when set.\n\tRetryOn func(attempt int, resp *http.Response, err error) bool\n}\n\n// Middleware hooks run around every request (OnRequest before serialization order\n// is N/A in Go \u2014 bodies are values; OnResponse runs in reverse registration order).\ntype Middleware struct {\n\tOnRequest func(req *http.Request)\n\tOnResponse func(resp *http.Response)\n}\n\n// Date is an RFC 3339 full-date \u2014 a calendar date with no time component. Fields\n// typed `date` under `dateType: Date` use it because encoding/json speaks only\n// RFC 3339 date-time for time.Time, which a bare \"2006-01-02\" fails to satisfy.\ntype Date struct {\n\ttime.Time\n}\n\nconst dateLayout = \"2006-01-02\"\n\n// UnmarshalJSON parses a \"2006-01-02\" string; an empty string leaves the zero value.\nfunc (d *Date) UnmarshalJSON(data []byte) error {\n\tvar raw string\n\tif err := json.Unmarshal(data, &raw); err != nil {\n\t\treturn err\n\t}\n\tif raw == \"\" {\n\t\treturn nil\n\t}\n\tparsed, err := time.Parse(dateLayout, raw)\n\tif err != nil {\n\t\treturn err\n\t}\n\td.Time = parsed\n\treturn nil\n}\n\n// MarshalJSON writes the date back without a time component.\nfunc (d Date) MarshalJSON() ([]byte, error) {\n\treturn json.Marshal(d.Format(dateLayout))\n}\n\n// Config is the per-client configuration shared by every operation method.\ntype Config struct {\n\tServerURL string\n\tHTTPClient *http.Client\n\tHeaders map[string]string\n\tTimeout time.Duration\n\tRetry RetryConfig\n\tMiddleware []Middleware\n\tIdempotencyKey func() string\n\tAuth Auth\n}\n\nfunc resolveToken(provider func() string) string {\n\tif provider == nil {\n\t\treturn \"\"\n\t}\n\treturn provider()\n}\n\nfunc schemeConfigured(spec SecuritySpec, auth Auth) bool {\n\tswitch spec.Kind {\n\tcase \"apiKey\":\n\t\t_, ok := auth.APIKey[spec.Scheme]\n\t\treturn ok\n\tcase \"bearer\":\n\t\treturn auth.Bearer != nil\n\tdefault:\n\t\treturn auth.Basic != nil\n\t}\n}\n\n// resolveAuth applies the first fully-configured OR-alternative; when none is,\n// the first alternative's configured schemes are still sent (the server rejects\n// the request \u2014 same behavior as the TypeScript runtime).\nfunc resolveAuth(security [][]SecuritySpec, auth Auth) (map[string]string, url.Values) {\n\theaders := map[string]string{}\n\tquery := url.Values{}\n\tif len(security) == 0 {\n\t\treturn headers, query\n\t}\n\talternative := security[0]\n\tfor _, candidate := range security {\n\t\tall := true\n\t\tfor _, spec := range candidate {\n\t\t\tif !schemeConfigured(spec, auth) {\n\t\t\t\tall = false\n\t\t\t\tbreak\n\t\t\t}\n\t\t}\n\t\tif all {\n\t\t\talternative = candidate\n\t\t\tbreak\n\t\t}\n\t}\n\tvar cookies []string\n\tfor _, spec := range alternative {\n\t\tswitch spec.Kind {\n\t\tcase \"apiKey\":\n\t\t\tprovider, ok := auth.APIKey[spec.Scheme]\n\t\t\tif !ok {\n\t\t\t\tcontinue\n\t\t\t}\n\t\t\tvalue := resolveToken(provider)\n\t\t\tswitch spec.In {\n\t\t\tcase \"query\":\n\t\t\t\tquery.Set(spec.Name, value)\n\t\t\tcase \"cookie\":\n\t\t\t\tcookies = append(cookies, spec.Name+\"=\"+url.QueryEscape(value))\n\t\t\tdefault:\n\t\t\t\theaders[spec.Name] = value\n\t\t\t}\n\t\tcase \"bearer\":\n\t\t\tif auth.Bearer != nil {\n\t\t\t\theaders[\"Authorization\"] = \"Bearer \" + resolveToken(auth.Bearer)\n\t\t\t}\n\t\tdefault:\n\t\t\tif auth.Basic != nil {\n\t\t\t\ttoken := base64.StdEncoding.EncodeToString([]byte(auth.Basic.Username + \":\" + auth.Basic.Password))\n\t\t\t\theaders[\"Authorization\"] = \"Basic \" + token\n\t\t\t}\n\t\t}\n\t}\n\tif len(cookies) > 0 {\n\t\theaders[\"Cookie\"] = strings.Join(cookies, \"; \")\n\t}\n\treturn headers, query\n}\n\n// buildURL substitutes {param} path placeholders with percent-encoded values.\nfunc buildURL(serverURL, path string, pathParams map[string]string) string {\n\tfilled := path\n\tfor name, value := range pathParams {\n\t\tfilled = strings.ReplaceAll(filled, \"{\"+name+\"}\", url.PathEscape(value))\n\t}\n\treturn strings.TrimRight(serverURL, \"/\") + filled\n}\n\nvar transientStatus = map[int]bool{408: true, 429: true, 500: true, 502: true, 503: true, 504: true}\n\nfunc defaultRetryOn(method string, headers map[string]string, resp *http.Response, err error) bool {\n\tsafe := false\n\tswitch strings.ToUpper(method) {\n\tcase \"GET\", \"HEAD\", \"PUT\", \"DELETE\", \"OPTIONS\":\n\t\tsafe = true\n\t}\n\tif _, ok := headers[\"Idempotency-Key\"]; ok {\n\t\tsafe = true\n\t}\n\tif !safe {\n\t\treturn false\n\t}\n\tif err != nil {\n\t\treturn true\n\t}\n\treturn resp != nil && transientStatus[resp.StatusCode]\n}\n\nfunc retryDelay(retry RetryConfig, attempt int, retryAfter string) time.Duration {\n\tif retryAfter != \"\" {\n\t\tif seconds, err := strconv.ParseFloat(retryAfter, 64); err == nil {\n\t\t\treturn time.Duration(seconds * float64(time.Second))\n\t\t}\n\t}\n\tbase := retry.RetryDelay\n\tif base == 0 {\n\t\tbase = time.Second\n\t}\n\traw := base\n\tif retry.RetryStrategy != \"fixed\" {\n\t\traw = base * time.Duration(1<<(attempt-1))\n\t}\n\tif retry.NoJitter {\n\t\treturn raw\n\t}\n\treturn time.Duration(rand.Int63n(int64(raw) + 1))\n}\n\ntype requestSpec struct {\n\tOperationID string\n\tMethod string\n\tURL string\n\tHeaders map[string]string\n\tQuery url.Values\n\tBody io.Reader\n\t// Stream sends Body as is: no buffering, one attempt, the caller's Content-Type.\n\tStream bool\n\tContentType string\n\tTimeout time.Duration\n\tRetry *RetryConfig\n\tIdempotencyKey string\n\t// bodyBytes is retained so retries can replay the body.\n\tbodyBytes []byte\n}\n\n// send is the request core: header merge, idempotency keys, the retry loop\n// (fresh timeout budget per attempt), and the middleware onion.\nfunc send(ctx context.Context, config *Config, spec requestSpec) (*http.Response, error) {\n\tretry := config.Retry\n\tif spec.Retry != nil {\n\t\tretry = *spec.Retry\n\t}\n\ttimeout := config.Timeout\n\tif spec.Timeout != 0 {\n\t\ttimeout = spec.Timeout\n\t}\n\theaders := map[string]string{}\n\tfor key, value := range config.Headers {\n\t\theaders[key] = value\n\t}\n\tfor key, value := range spec.Headers {\n\t\theaders[key] = value\n\t}\n\tmethod := strings.ToUpper(spec.Method)\n\tif (method == \"POST\" || method == \"PATCH\") && headers[\"Idempotency-Key\"] == \"\" {\n\t\tif spec.IdempotencyKey != \"\" {\n\t\t\theaders[\"Idempotency-Key\"] = spec.IdempotencyKey\n\t\t} else if config.IdempotencyKey != nil {\n\t\t\theaders[\"Idempotency-Key\"] = config.IdempotencyKey()\n\t\t}\n\t}\n\thttpClient := config.HTTPClient\n\tif httpClient == nil {\n\t\thttpClient = http.DefaultClient\n\t}\n\tif spec.Body != nil && !spec.Stream {\n\t\tpayload, err := io.ReadAll(spec.Body)\n\t\tif err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t\tspec.bodyBytes = payload\n\t}\n\tfullURL := spec.URL\n\tif len(spec.Query) > 0 {\n\t\tseparator := \"?\"\n\t\tif strings.Contains(fullURL, \"?\") {\n\t\t\tseparator = \"&\"\n\t\t}\n\t\tfullURL += separator + spec.Query.Encode()\n\t}\n\tmaxAttempts := 1 + retry.Retries\n\tif spec.Stream {\n\t\t// The first attempt consumes the reader, so there is nothing to replay.\n\t\tmaxAttempts = 1\n\t}\n\tfor attempt := 1; ; attempt++ {\n\t\tattemptCtx := ctx\n\t\tvar cancel context.CancelFunc\n\t\tif timeout > 0 {\n\t\t\tattemptCtx, cancel = context.WithTimeout(ctx, timeout)\n\t\t}\n\t\tvar bodyReader io.Reader\n\t\tswitch {\n\t\tcase spec.Stream:\n\t\t\tbodyReader = spec.Body\n\t\tcase spec.bodyBytes != nil:\n\t\t\tbodyReader = bytes.NewReader(spec.bodyBytes)\n\t\t}\n\t\treq, err := http.NewRequestWithContext(attemptCtx, method, fullURL, bodyReader)\n\t\tif err != nil {\n\t\t\tif cancel != nil {\n\t\t\t\tcancel()\n\t\t\t}\n\t\t\treturn nil, err\n\t\t}\n\t\tfor key, value := range headers {\n\t\t\treq.Header.Set(key, value)\n\t\t}\n\t\tif spec.ContentType != \"\" && bodyReader != nil && req.Header.Get(\"Content-Type\") == \"\" {\n\t\t\treq.Header.Set(\"Content-Type\", spec.ContentType)\n\t\t}\n\t\tfor _, mw := range config.Middleware {\n\t\t\tif mw.OnRequest != nil {\n\t\t\t\tmw.OnRequest(req)\n\t\t\t}\n\t\t}\n\t\tresp, err := httpClient.Do(req)\n\t\tshouldRetry := retry.RetryOn\n\t\tretryable := false\n\t\tif shouldRetry != nil {\n\t\t\tretryable = shouldRetry(attempt, resp, err)\n\t\t} else {\n\t\t\tretryable = defaultRetryOn(method, headers, resp, err)\n\t\t}\n\t\tif err != nil {\n\t\t\tif cancel != nil {\n\t\t\t\tcancel()\n\t\t\t}\n\t\t\ttimedOut := errors.Is(err, context.DeadlineExceeded) && ctx.Err() == nil\n\t\t\tif attempt < maxAttempts && retryable {\n\t\t\t\ttime.Sleep(retryDelay(retry, attempt, \"\"))\n\t\t\t\tcontinue\n\t\t\t}\n\t\t\tif timedOut {\n\t\t\t\treturn nil, &TimeoutError{OperationID: spec.OperationID, Timeout: timeout, Attempt: attempt}\n\t\t\t}\n\t\t\treturn nil, err\n\t\t}\n\t\tfor i := len(config.Middleware) - 1; i >= 0; i-- {\n\t\t\tif config.Middleware[i].OnResponse != nil {\n\t\t\t\tconfig.Middleware[i].OnResponse(resp)\n\t\t\t}\n\t\t}\n\t\tif resp.StatusCode >= 400 && attempt < maxAttempts && retryable {\n\t\t\tafter := resp.Header.Get(\"Retry-After\")\n\t\t\tio.Copy(io.Discard, resp.Body)\n\t\t\tresp.Body.Close()\n\t\t\tif cancel != nil {\n\t\t\t\tcancel()\n\t\t\t}\n\t\t\ttime.Sleep(retryDelay(retry, attempt, after))\n\t\t\tcontinue\n\t\t}\n\t\t// The response body outlives this call; tie the attempt context's lifetime to it.\n\t\tif cancel != nil {\n\t\t\tresp.Body = &cancelOnClose{ReadCloser: resp.Body, cancel: cancel}\n\t\t}\n\t\treturn resp, nil\n\t}\n}\n\ntype cancelOnClose struct {\n\tio.ReadCloser\n\tcancel context.CancelFunc\n}\n\nfunc (c *cancelOnClose) Close() error {\n\tc.cancel()\n\treturn c.ReadCloser.Close()\n}\n\n// decodeJSON decodes a response body into target; a nil target drains and closes.\nfunc decodeJSON(resp *http.Response, target any) error {\n\tdefer resp.Body.Close()\n\tif target == nil {\n\t\t_, err := io.Copy(io.Discard, resp.Body)\n\t\treturn err\n\t}\n\treturn json.NewDecoder(resp.Body).Decode(target)\n}\n\n// headerString returns the named response header, or nil when absent.\nfunc headerString(header http.Header, name string) *string {\n\tvalue := header.Get(name)\n\tif value == \"\" {\n\t\treturn nil\n\t}\n\treturn &value\n}\n\n// headerInt64 parses the named header as an integer; nil when absent or unparsable.\nfunc headerInt64(header http.Header, name string) *int64 {\n\traw := strings.TrimSpace(header.Get(name))\n\tif raw == \"\" {\n\t\treturn nil\n\t}\n\tvalue, err := strconv.ParseInt(raw, 10, 64)\n\tif err != nil {\n\t\treturn nil\n\t}\n\treturn &value\n}\n\n// headerFloat64 parses the named header as a number; nil when absent or unparsable.\nfunc headerFloat64(header http.Header, name string) *float64 {\n\traw := strings.TrimSpace(header.Get(name))\n\tif raw == \"\" {\n\t\treturn nil\n\t}\n\tvalue, err := strconv.ParseFloat(raw, 64)\n\tif err != nil {\n\t\treturn nil\n\t}\n\treturn &value\n}\n\n// headerBool parses a `true`/`false` header; nil when absent or anything else.\nfunc headerBool(header http.Header, name string) *bool {\n\traw := strings.ToLower(strings.TrimSpace(header.Get(name)))\n\tif raw != \"true\" && raw != \"false\" {\n\t\treturn nil\n\t}\n\tvalue := raw == \"true\"\n\treturn &value\n}\n\n// apiErrorFrom builds the structured error for a non-2xx response.\nfunc apiErrorFrom(resp *http.Response, requestURL string) error {\n\tdefer resp.Body.Close()\n\tvar body any\n\tdata, _ := io.ReadAll(resp.Body)\n\tif len(data) > 0 {\n\t\tif err := json.Unmarshal(data, &body); err != nil {\n\t\t\tbody = string(data)\n\t\t}\n\t}\n\treturn &APIError{URL: requestURL, Status: resp.StatusCode, StatusText: resp.Status, Body: body}\n}\n\n// \u2500\u2500\u2500 Pagination \u2500\u2500\u2500\n\n// PaginationSpec mirrors the descriptor table's pagination entries.\ntype PaginationSpec struct {\n\tStyle string\n\tParam string\n\tNextCursor string\n\tHasMore string\n\tNextLink string\n\tLimitParam string\n\tItems string\n}\n\n// resolvePointer walks an RFC 6901 JSON pointer over decoded JSON; nil on any miss.\nfunc resolvePointer(data any, pointer string) any {\n\tif pointer == \"\" {\n\t\treturn data\n\t}\n\tif !strings.HasPrefix(pointer, \"/\") {\n\t\treturn nil\n\t}\n\tcurrent := data\n\tfor _, token := range strings.Split(pointer[1:], \"/\") {\n\t\tkey := strings.ReplaceAll(strings.ReplaceAll(token, \"~1\", \"/\"), \"~0\", \"~\")\n\t\tswitch typed := current.(type) {\n\t\tcase map[string]any:\n\t\t\tcurrent = typed[key]\n\t\tcase []any:\n\t\t\tindex, err := strconv.Atoi(key)\n\t\t\tif err != nil || index < 0 || index >= len(typed) {\n\t\t\t\treturn nil\n\t\t\t}\n\t\t\tcurrent = typed[index]\n\t\tdefault:\n\t\t\treturn nil\n\t\t}\n\t\tif current == nil {\n\t\t\treturn nil\n\t\t}\n\t}\n\treturn current\n}\n\n// reencode converts decoded JSON (maps/slices) into a typed value via a JSON round-trip.\nfunc reencode(raw any, target any) error {\n\tdata, err := json.Marshal(raw)\n\tif err != nil {\n\t\treturn err\n\t}\n\treturn json.Unmarshal(data, target)\n}\n\ntype pageCall func(params url.Values) (any, *http.Response, error)\n\n// iterPages yields raw page JSON per the pagination spec \u2014 the same stop\n// conditions and infinite-loop guards as the TypeScript runtime. The returned\n// function is a range-over-func iterator (Go 1.23+) and plainly callable before that.\nfunc iterPages(call pageCall, spec PaginationSpec, base url.Values) func(yield func(any, error) bool) {\n\treturn func(yield func(any, error) bool) {\n\t\tswitch spec.Style {\n\t\tcase \"cursor\":\n\t\t\tvar cursor any\n\t\t\tif values, ok := base[spec.Param]; ok && len(values) > 0 {\n\t\t\t\tcursor = values[0]\n\t\t\t}\n\t\t\tfor {\n\t\t\t\tparams := cloneValues(base)\n\t\t\t\tif cursor != nil {\n\t\t\t\t\tparams.Set(spec.Param, fmt.Sprint(cursor))\n\t\t\t\t}\n\t\t\t\tpage, _, err := call(params)\n\t\t\t\tif err != nil {\n\t\t\t\t\tyield(nil, err)\n\t\t\t\t\treturn\n\t\t\t\t}\n\t\t\t\tif !yield(page, nil) {\n\t\t\t\t\treturn\n\t\t\t\t}\n\t\t\t\tif spec.HasMore != \"\" {\n\t\t\t\t\tif more, ok := resolvePointer(page, spec.HasMore).(bool); ok && !more {\n\t\t\t\t\t\treturn\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tnext := resolvePointer(page, spec.NextCursor)\n\t\t\t\tif next == nil || next == \"\" {\n\t\t\t\t\treturn\n\t\t\t\t}\n\t\t\t\tswitch next.(type) {\n\t\t\t\tcase string, float64:\n\t\t\t\tdefault:\n\t\t\t\t\tyield(nil, fmt.Errorf(\"pagination cursor at %s is not a string or number\", spec.NextCursor))\n\t\t\t\t\treturn\n\t\t\t\t}\n\t\t\t\tif cursor != nil && fmt.Sprint(next) == fmt.Sprint(cursor) {\n\t\t\t\t\tyield(nil, errors.New(\"pagination did not advance: the operation returned the same cursor twice\"))\n\t\t\t\t\treturn\n\t\t\t\t}\n\t\t\t\tcursor = next\n\t\t\t}\n\t\tcase \"link\", \"body-link\":\n\t\t\tparams := cloneValues(base)\n\t\t\tprevious := \"\"\n\t\t\tfor {\n\t\t\t\tpage, resp, err := call(params)\n\t\t\t\tif err != nil {\n\t\t\t\t\tyield(nil, err)\n\t\t\t\t\treturn\n\t\t\t\t}\n\t\t\t\tif !yield(page, nil) {\n\t\t\t\t\treturn\n\t\t\t\t}\n\t\t\t\tvar target string\n\t\t\t\tif spec.Style == \"link\" {\n\t\t\t\t\ttarget = linkNext(resp.Header.Get(\"Link\"))\n\t\t\t\t} else {\n\t\t\t\t\tvalue := resolvePointer(page, spec.NextLink)\n\t\t\t\t\tlink, isString := value.(string)\n\t\t\t\t\tif value != nil && !isString {\n\t\t\t\t\t\tyield(nil, fmt.Errorf(\"pagination link at %s is not a string\", spec.NextLink))\n\t\t\t\t\t\treturn\n\t\t\t\t\t}\n\t\t\t\t\ttarget = link\n\t\t\t\t}\n\t\t\t\tif target == \"\" {\n\t\t\t\t\treturn\n\t\t\t\t}\n\t\t\t\tpageURL := \"\"\n\t\t\t\tif resp.Request != nil && resp.Request.URL != nil {\n\t\t\t\t\tpageURL = resp.Request.URL.String()\n\t\t\t\t}\n\t\t\t\tbaseURL, err := url.Parse(pageURL)\n\t\t\t\tif err != nil || pageURL == \"\" {\n\t\t\t\t\tbaseURL, _ = url.Parse(\"http://relative.invalid\")\n\t\t\t\t}\n\t\t\t\ttargetURL, err := baseURL.Parse(target)\n\t\t\t\tif err != nil {\n\t\t\t\t\tyield(nil, err)\n\t\t\t\t\treturn\n\t\t\t\t}\n\t\t\t\tnext := targetURL.String()\n\t\t\t\tif next == previous || next == pageURL {\n\t\t\t\t\tyield(nil, errors.New(`pagination did not advance: the Link rel=\"next\" target repeats`))\n\t\t\t\t\treturn\n\t\t\t\t}\n\t\t\t\tprevious = next\n\t\t\t\tparams = cloneValues(base)\n\t\t\t\tfor key, values := range targetURL.Query() {\n\t\t\t\t\tparams[key] = values\n\t\t\t\t}\n\t\t\t}\n\t\tdefault: // offset / page\n\t\t\tposition := 0\n\t\t\tif spec.Style == \"page\" {\n\t\t\t\tposition = 1\n\t\t\t}\n\t\t\tif values, ok := base[spec.Param]; ok && len(values) > 0 && values[0] != \"\" {\n\t\t\t\tif parsed, err := strconv.Atoi(values[0]); err == nil {\n\t\t\t\t\tposition = parsed\n\t\t\t\t}\n\t\t\t}\n\t\t\tpreviousItems := \"\"\n\t\t\tfor {\n\t\t\t\tparams := cloneValues(base)\n\t\t\t\tparams.Set(spec.Param, strconv.Itoa(position))\n\t\t\t\tpage, _, err := call(params)\n\t\t\t\tif err != nil {\n\t\t\t\t\tyield(nil, err)\n\t\t\t\t\treturn\n\t\t\t\t}\n\t\t\t\titems, _ := resolvePointer(page, spec.Items).([]any)\n\t\t\t\tserialized := \"\"\n\t\t\t\tif items != nil {\n\t\t\t\t\tserialized = fmt.Sprint(items)\n\t\t\t\t\tif serialized == previousItems {\n\t\t\t\t\t\tyield(nil, errors.New(\"pagination did not advance: the operation returned the same page twice\"))\n\t\t\t\t\t\treturn\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tif !yield(page, nil) {\n\t\t\t\t\treturn\n\t\t\t\t}\n\t\t\t\tif len(items) == 0 {\n\t\t\t\t\treturn\n\t\t\t\t}\n\t\t\t\tpreviousItems = serialized\n\t\t\t\tif spec.Style == \"page\" {\n\t\t\t\t\tposition++\n\t\t\t\t} else {\n\t\t\t\t\tposition += len(items)\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n}\n\nfunc cloneValues(values url.Values) url.Values {\n\tout := url.Values{}\n\tfor key, entries := range values {\n\t\tfor _, entry := range entries {\n\t\t\tout.Add(key, entry)\n\t\t}\n\t}\n\treturn out\n}\n\nfunc linkNext(header string) string {\n\tif header == \"\" {\n\t\treturn \"\"\n\t}\n\tfor _, entry := range strings.Split(header, \",\") {\n\t\tparts := strings.Split(entry, \";\")\n\t\tif len(parts) < 2 {\n\t\t\tcontinue\n\t\t}\n\t\ttarget := strings.TrimSpace(parts[0])\n\t\tif !strings.HasPrefix(target, \"<\") || !strings.HasSuffix(target, \">\") {\n\t\t\tcontinue\n\t\t}\n\t\tfor _, param := range parts[1:] {\n\t\t\ttrimmed := strings.TrimSpace(param)\n\t\t\tif strings.HasPrefix(trimmed, \"rel=\") {\n\t\t\t\trel := strings.Trim(strings.TrimPrefix(trimmed, \"rel=\"), `\"`)\n\t\t\t\tfor _, kind := range strings.Fields(rel) {\n\t\t\t\t\tif kind == \"next\" {\n\t\t\t\t\t\treturn strings.Trim(target, \"<>\")\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\treturn \"\"\n}\n\n// \u2500\u2500\u2500 Server-Sent Events \u2500\u2500\u2500\n\n// ServerSentEvent is one decoded event; Data is the raw text (or parsed JSON\n// for operations that declare a JSON event stream).\ntype ServerSentEvent struct {\n\tEvent string\n\tData any\n\tID string\n\tRetry int\n}\n\nfunc parseSSEFrame(raw string, jsonData bool) (ServerSentEvent, bool, error) {\n\tevent := ServerSentEvent{Retry: -1}\n\tsawField := false\n\tvar dataLines []string\n\tnormalized := strings.ReplaceAll(strings.ReplaceAll(raw, \"\\r\\n\", \"\\n\"), \"\\r\", \"\\n\")\n\tfor _, line := range strings.Split(normalized, \"\\n\") {\n\t\tif line == \"\" || strings.HasPrefix(line, \":\") {\n\t\t\tcontinue\n\t\t}\n\t\tfield, value, _ := strings.Cut(line, \":\")\n\t\tvalue = strings.TrimPrefix(value, \" \")\n\t\tsawField = true\n\t\tswitch field {\n\t\tcase \"event\":\n\t\t\tevent.Event = value\n\t\tcase \"data\":\n\t\t\tdataLines = append(dataLines, value)\n\t\tcase \"id\":\n\t\t\tevent.ID = value\n\t\tcase \"retry\":\n\t\t\tif parsed, err := strconv.Atoi(value); err == nil && parsed >= 0 && value != \"\" {\n\t\t\t\tevent.Retry = parsed\n\t\t\t}\n\t\t}\n\t}\n\tif !sawField {\n\t\treturn event, false, nil\n\t}\n\ttext := strings.Join(dataLines, \"\\n\")\n\tevent.Data = text\n\tif jsonData && text != \"\" {\n\t\tvar parsed any\n\t\tif err := json.Unmarshal([]byte(text), &parsed); err != nil {\n\t\t\treturn event, false, err\n\t\t}\n\t\tevent.Data = parsed\n\t}\n\treturn event, true, nil\n}\n\n// iterSSE streams events, reconnecting on dropped connections with Last-Event-ID\n// (a fresh open call = fresh auth); a 4xx/5xx or a bad JSON payload is definitive.\nfunc iterSSE(open func(extraHeaders map[string]string) (*http.Response, error), jsonData bool) func(yield func(ServerSentEvent, error) bool) {\n\treturn func(yield func(ServerSentEvent, error) bool) {\n\t\tlastEventID := \"\"\n\t\tserverRetry := -1\n\t\tfailures := 0\n\t\tfor {\n\t\t\theaders := map[string]string{\"Accept\": \"text/event-stream\"}\n\t\t\tif lastEventID != \"\" {\n\t\t\t\theaders[\"Last-Event-ID\"] = lastEventID\n\t\t\t}\n\t\t\tresp, err := open(headers)\n\t\t\tif err == nil && resp.StatusCode >= 400 {\n\t\t\t\tyield(ServerSentEvent{}, apiErrorFrom(resp, \"\"))\n\t\t\t\treturn\n\t\t\t}\n\t\t\tif err == nil {\n\t\t\t\tfailures = 0\n\t\t\t\tbuffer := \"\"\n\t\t\t\tchunk := make([]byte, 4096)\n\t\t\t\tclean := false\n\t\t\t\tfor {\n\t\t\t\t\tn, readErr := resp.Body.Read(chunk)\n\t\t\t\t\tbuffer += string(chunk[:n])\n\t\t\t\t\tfor {\n\t\t\t\t\t\tframe, rest, found := strings.Cut(buffer, \"\\n\\n\")\n\t\t\t\t\t\tif !found {\n\t\t\t\t\t\t\tbreak\n\t\t\t\t\t\t}\n\t\t\t\t\t\tbuffer = rest\n\t\t\t\t\t\tevent, ok, parseErr := parseSSEFrame(frame, jsonData)\n\t\t\t\t\t\tif parseErr != nil {\n\t\t\t\t\t\t\tresp.Body.Close()\n\t\t\t\t\t\t\tyield(ServerSentEvent{}, parseErr)\n\t\t\t\t\t\t\treturn\n\t\t\t\t\t\t}\n\t\t\t\t\t\tif ok {\n\t\t\t\t\t\t\tif event.ID != \"\" {\n\t\t\t\t\t\t\t\tlastEventID = event.ID\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tif event.Retry >= 0 {\n\t\t\t\t\t\t\t\tserverRetry = event.Retry\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tif !yield(event, nil) {\n\t\t\t\t\t\t\t\tresp.Body.Close()\n\t\t\t\t\t\t\t\treturn\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\tif readErr == io.EOF {\n\t\t\t\t\t\tclean = true\n\t\t\t\t\t\tbreak\n\t\t\t\t\t}\n\t\t\t\t\tif readErr != nil {\n\t\t\t\t\t\tbreak\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tresp.Body.Close()\n\t\t\t\tif clean {\n\t\t\t\t\tif strings.TrimSpace(buffer) != \"\" {\n\t\t\t\t\t\tif event, ok, parseErr := parseSSEFrame(buffer, jsonData); parseErr == nil && ok {\n\t\t\t\t\t\t\tyield(event, nil)\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\treturn\n\t\t\t\t}\n\t\t\t}\n\t\t\tfailures++\n\t\t\tbase := time.Second\n\t\t\tif serverRetry >= 0 {\n\t\t\t\tbase = time.Duration(serverRetry) * time.Millisecond\n\t\t\t}\n\t\t\tdelay := base * time.Duration(1<<(failures-1))\n\t\t\tif delay > 30*time.Second {\n\t\t\t\tdelay = 30 * time.Second\n\t\t\t}\n\t\t\ttime.Sleep(time.Duration(rand.Int63n(int64(delay) + 1)))\n\t\t}\n\t}\n}\n\n// \u2500\u2500\u2500 Multipart \u2500\u2500\u2500\n\n// toMultipart splits a typed body into a multipart/form-data payload: []byte\n// values upload as file parts, everything else as form fields (nested values\n// JSON-encoded) \u2014 mirroring the TypeScript runtime's FormData serialization.\nfunc toMultipart(body any) (string, io.Reader, error) {\n\tvar wire map[string]any\n\tif err := reencode(body, &wire); err != nil {\n\t\treturn \"\", nil, err\n\t}\n\tbuffer := &bytes.Buffer{}\n\twriter := multipart.NewWriter(buffer)\n\tfor key, value := range wire {\n\t\tswitch typed := value.(type) {\n\t\tcase string:\n\t\t\tif err := writer.WriteField(key, typed); err != nil {\n\t\t\t\treturn \"\", nil, err\n\t\t\t}\n\t\tcase float64, bool:\n\t\t\tif err := writer.WriteField(key, fmt.Sprint(typed)); err != nil {\n\t\t\t\treturn \"\", nil, err\n\t\t\t}\n\t\tdefault:\n\t\t\tencoded, err := json.Marshal(typed)\n\t\t\tif err != nil {\n\t\t\t\treturn \"\", nil, err\n\t\t\t}\n\t\t\tif err := writer.WriteField(key, string(encoded)); err != nil {\n\t\t\t\treturn \"\", nil, err\n\t\t\t}\n\t\t}\n\t}\n\tif err := writer.Close(); err != nil {\n\t\treturn \"\", nil, err\n\t}\n\treturn writer.FormDataContentType(), buffer, nil\n}\n\n// multipartBody prepares the body of an untyped multipart operation: an io.Reader is\n// streamed and a []byte or string sent as is, all under the caller's Content-Type (the\n// boundary is theirs to set); any other value goes through toMultipart.\nfunc multipartBody(body any) (string, io.Reader, bool, error) {\n\tif reader, stream, raw := rawBody(body); raw {\n\t\treturn \"\", reader, stream, nil\n\t}\n\tcontentType, reader, err := toMultipart(body)\n\treturn contentType, reader, false, err\n}\n\n// binaryBody prepares the body of a binary operation: an io.Reader is streamed, a\n// []byte or string sent as is, and any other value JSON-marshalled.\nfunc binaryBody(body any) (io.Reader, bool, error) {\n\tif reader, stream, raw := rawBody(body); raw {\n\t\treturn reader, stream, nil\n\t}\n\tpayload, err := json.Marshal(body)\n\treturn bytes.NewReader(payload), false, err\n}\n\n// rawBody recognizes a body that needs no encoding: an io.Reader streams through in one\n// attempt, a []byte or a string is replayable bytes.\nfunc rawBody(body any) (io.Reader, bool, bool) {\n\tswitch typed := body.(type) {\n\tcase io.Reader:\n\t\treturn typed, true, true\n\tcase []byte:\n\t\treturn bytes.NewReader(typed), false, true\n\tcase string:\n\t\treturn strings.NewReader(typed), false, true\n\t}\n\treturn nil, false, false\n}\n";
|
|
2
2
|
//# sourceMappingURL=go.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"go.d.ts","sourceRoot":"","sources":["../../src/runtime-sources/go.ts"],"names":[],"mappings":"AACA,eAAO,MAAM,iBAAiB
|
|
1
|
+
{"version":3,"file":"go.d.ts","sourceRoot":"","sources":["../../src/runtime-sources/go.ts"],"names":[],"mappings":"AACA,eAAO,MAAM,iBAAiB,4y1BACw20B,CAAC"}
|
|
@@ -1,3 +1,3 @@
|
|
|
1
1
|
// GENERATED by scripts/generate-runtime-sources.mjs — do not edit. Regenerated on install (`prepare`); manually: `npm run prepare -w @redocly/client-generator`.
|
|
2
|
-
export const GO_RUNTIME_SOURCE = '// Package client — the embedded runtime for generated Go SDKs. Hand-authored\n// once and stitched into every generated client (see\n// scripts/generate-runtime-sources.mjs), semantically in lockstep with the\n// TypeScript runtime: auth OR-alternatives, a retry loop with Retry-After and\n// full-jitter backoff, per-attempt timeouts, idempotency keys, and middleware\n// hooks. Standard library only — a generated Go SDK has zero dependencies.\npackage client\n\nimport (\n\t"bytes"\n\t"context"\n\t"encoding/base64"\n\t"encoding/json"\n\t"errors"\n\t"fmt"\n\t"io"\n\t"math/rand"\n\t"mime/multipart"\n\t"net/http"\n\t"net/url"\n\t"strconv"\n\t"strings"\n\t"time"\n)\n\n// APIError is returned for a non-2xx response, carrying the decoded error body.\ntype APIError struct {\n\tURL string\n\tStatus int\n\tStatusText string\n\tBody any\n}\n\nfunc (e *APIError) Error() string {\n\treturn fmt.Sprintf("request failed with status %d", e.Status)\n}\n\n// TimeoutError is returned when a request attempt exceeds the configured\n// timeout — carrying the context a log line needs.\ntype TimeoutError struct {\n\tOperationID string\n\tTimeout time.Duration\n\tAttempt int\n}\n\nfunc (e *TimeoutError) Error() string {\n\treturn fmt.Sprintf("request %q timed out after %s (attempt %d)", e.OperationID, e.Timeout, e.Attempt)\n}\n\n// SecuritySpec mirrors the descriptor table\'s security entries.\ntype SecuritySpec struct {\n\tScheme string\n\tKind string // "bearer" | "basic" | "apiKey"\n\tName string // header/query/cookie name for apiKey\n\tIn string // "header" | "query" | "cookie"\n}\n\n// Auth holds the client credentials; zero value = anonymous.\ntype Auth struct {\n\tBearer func() string\n\tBasic *BasicAuth\n\tAPIKey map[string]func() string\n}\n\ntype BasicAuth struct {\n\tUsername string\n\tPassword string\n}\n\n// RetryConfig mirrors the TypeScript runtime\'s retry policy knobs.\ntype RetryConfig struct {\n\tRetries int\n\tRetryDelay time.Duration // base; default 1s\n\tRetryStrategy string // "" (exponential) | "fixed"\n\tNoJitter bool\n\t// RetryOn fully replaces the default predicate when set.\n\tRetryOn func(attempt int, resp *http.Response, err error) bool\n}\n\n// Middleware hooks run around every request (OnRequest before serialization order\n// is N/A in Go — bodies are values; OnResponse runs in reverse registration order).\ntype Middleware struct {\n\tOnRequest func(req *http.Request)\n\tOnResponse func(resp *http.Response)\n}\n\n// Date is an RFC 3339 full-date — a calendar date with no time component. Fields\n// typed `date` under `dateType: Date` use it because encoding/json speaks only\n// RFC 3339 date-time for time.Time, which a bare "2006-01-02" fails to satisfy.\ntype Date struct {\n\ttime.Time\n}\n\nconst dateLayout = "2006-01-02"\n\n// UnmarshalJSON parses a "2006-01-02" string; an empty string leaves the zero value.\nfunc (d *Date) UnmarshalJSON(data []byte) error {\n\tvar raw string\n\tif err := json.Unmarshal(data, &raw); err != nil {\n\t\treturn err\n\t}\n\tif raw == "" {\n\t\treturn nil\n\t}\n\tparsed, err := time.Parse(dateLayout, raw)\n\tif err != nil {\n\t\treturn err\n\t}\n\td.Time = parsed\n\treturn nil\n}\n\n// MarshalJSON writes the date back without a time component.\nfunc (d Date) MarshalJSON() ([]byte, error) {\n\treturn json.Marshal(d.Format(dateLayout))\n}\n\n// Config is the per-client configuration shared by every operation method.\ntype Config struct {\n\tServerURL string\n\tHTTPClient *http.Client\n\tHeaders map[string]string\n\tTimeout time.Duration\n\tRetry RetryConfig\n\tMiddleware []Middleware\n\tIdempotencyKey func() string\n\tAuth Auth\n}\n\nfunc resolveToken(provider func() string) string {\n\tif provider == nil {\n\t\treturn ""\n\t}\n\treturn provider()\n}\n\nfunc schemeConfigured(spec SecuritySpec, auth Auth) bool {\n\tswitch spec.Kind {\n\tcase "apiKey":\n\t\t_, ok := auth.APIKey[spec.Scheme]\n\t\treturn ok\n\tcase "bearer":\n\t\treturn auth.Bearer != nil\n\tdefault:\n\t\treturn auth.Basic != nil\n\t}\n}\n\n// resolveAuth applies the first fully-configured OR-alternative; when none is,\n// the first alternative\'s configured schemes are still sent (the server rejects\n// the request — same behavior as the TypeScript runtime).\nfunc resolveAuth(security [][]SecuritySpec, auth Auth) (map[string]string, url.Values) {\n\theaders := map[string]string{}\n\tquery := url.Values{}\n\tif len(security) == 0 {\n\t\treturn headers, query\n\t}\n\talternative := security[0]\n\tfor _, candidate := range security {\n\t\tall := true\n\t\tfor _, spec := range candidate {\n\t\t\tif !schemeConfigured(spec, auth) {\n\t\t\t\tall = false\n\t\t\t\tbreak\n\t\t\t}\n\t\t}\n\t\tif all {\n\t\t\talternative = candidate\n\t\t\tbreak\n\t\t}\n\t}\n\tvar cookies []string\n\tfor _, spec := range alternative {\n\t\tswitch spec.Kind {\n\t\tcase "apiKey":\n\t\t\tprovider, ok := auth.APIKey[spec.Scheme]\n\t\t\tif !ok {\n\t\t\t\tcontinue\n\t\t\t}\n\t\t\tvalue := resolveToken(provider)\n\t\t\tswitch spec.In {\n\t\t\tcase "query":\n\t\t\t\tquery.Set(spec.Name, value)\n\t\t\tcase "cookie":\n\t\t\t\tcookies = append(cookies, spec.Name+"="+url.QueryEscape(value))\n\t\t\tdefault:\n\t\t\t\theaders[spec.Name] = value\n\t\t\t}\n\t\tcase "bearer":\n\t\t\tif auth.Bearer != nil {\n\t\t\t\theaders["Authorization"] = "Bearer " + resolveToken(auth.Bearer)\n\t\t\t}\n\t\tdefault:\n\t\t\tif auth.Basic != nil {\n\t\t\t\ttoken := base64.StdEncoding.EncodeToString([]byte(auth.Basic.Username + ":" + auth.Basic.Password))\n\t\t\t\theaders["Authorization"] = "Basic " + token\n\t\t\t}\n\t\t}\n\t}\n\tif len(cookies) > 0 {\n\t\theaders["Cookie"] = strings.Join(cookies, "; ")\n\t}\n\treturn headers, query\n}\n\n// buildURL substitutes {param} path placeholders with percent-encoded values.\nfunc buildURL(serverURL, path string, pathParams map[string]string) string {\n\tfilled := path\n\tfor name, value := range pathParams {\n\t\tfilled = strings.ReplaceAll(filled, "{"+name+"}", url.PathEscape(value))\n\t}\n\treturn strings.TrimRight(serverURL, "/") + filled\n}\n\nvar transientStatus = map[int]bool{408: true, 429: true, 500: true, 502: true, 503: true, 504: true}\n\nfunc defaultRetryOn(method string, headers map[string]string, resp *http.Response, err error) bool {\n\tsafe := false\n\tswitch strings.ToUpper(method) {\n\tcase "GET", "HEAD", "PUT", "DELETE", "OPTIONS":\n\t\tsafe = true\n\t}\n\tif _, ok := headers["Idempotency-Key"]; ok {\n\t\tsafe = true\n\t}\n\tif !safe {\n\t\treturn false\n\t}\n\tif err != nil {\n\t\treturn true\n\t}\n\treturn resp != nil && transientStatus[resp.StatusCode]\n}\n\nfunc retryDelay(retry RetryConfig, attempt int, retryAfter string) time.Duration {\n\tif retryAfter != "" {\n\t\tif seconds, err := strconv.ParseFloat(retryAfter, 64); err == nil {\n\t\t\treturn time.Duration(seconds * float64(time.Second))\n\t\t}\n\t}\n\tbase := retry.RetryDelay\n\tif base == 0 {\n\t\tbase = time.Second\n\t}\n\traw := base\n\tif retry.RetryStrategy != "fixed" {\n\t\traw = base * time.Duration(1<<(attempt-1))\n\t}\n\tif retry.NoJitter {\n\t\treturn raw\n\t}\n\treturn time.Duration(rand.Int63n(int64(raw) + 1))\n}\n\ntype requestSpec struct {\n\tOperationID string\n\tMethod string\n\tURL string\n\tHeaders map[string]string\n\tQuery url.Values\n\tBody io.Reader\n\t// Stream sends Body as is: no buffering, one attempt, the caller\'s Content-Type.\n\tStream bool\n\tContentType string\n\tTimeout time.Duration\n\tRetry *RetryConfig\n\tIdempotencyKey string\n\t// bodyBytes is retained so retries can replay the body.\n\tbodyBytes []byte\n}\n\n// send is the request core: header merge, idempotency keys, the retry loop\n// (fresh timeout budget per attempt), and the middleware onion.\nfunc send(ctx context.Context, config *Config, spec requestSpec) (*http.Response, error) {\n\tretry := config.Retry\n\tif spec.Retry != nil {\n\t\tretry = *spec.Retry\n\t}\n\ttimeout := config.Timeout\n\tif spec.Timeout != 0 {\n\t\ttimeout = spec.Timeout\n\t}\n\theaders := map[string]string{}\n\tfor key, value := range config.Headers {\n\t\theaders[key] = value\n\t}\n\tfor key, value := range spec.Headers {\n\t\theaders[key] = value\n\t}\n\tmethod := strings.ToUpper(spec.Method)\n\tif (method == "POST" || method == "PATCH") && headers["Idempotency-Key"] == "" {\n\t\tif spec.IdempotencyKey != "" {\n\t\t\theaders["Idempotency-Key"] = spec.IdempotencyKey\n\t\t} else if config.IdempotencyKey != nil {\n\t\t\theaders["Idempotency-Key"] = config.IdempotencyKey()\n\t\t}\n\t}\n\thttpClient := config.HTTPClient\n\tif httpClient == nil {\n\t\thttpClient = http.DefaultClient\n\t}\n\tif spec.Body != nil && !spec.Stream {\n\t\tpayload, err := io.ReadAll(spec.Body)\n\t\tif err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t\tspec.bodyBytes = payload\n\t}\n\tfullURL := spec.URL\n\tif len(spec.Query) > 0 {\n\t\tseparator := "?"\n\t\tif strings.Contains(fullURL, "?") {\n\t\t\tseparator = "&"\n\t\t}\n\t\tfullURL += separator + spec.Query.Encode()\n\t}\n\tmaxAttempts := 1 + retry.Retries\n\tif spec.Stream {\n\t\t// The first attempt consumes the reader, so there is nothing to replay.\n\t\tmaxAttempts = 1\n\t}\n\tfor attempt := 1; ; attempt++ {\n\t\tattemptCtx := ctx\n\t\tvar cancel context.CancelFunc\n\t\tif timeout > 0 {\n\t\t\tattemptCtx, cancel = context.WithTimeout(ctx, timeout)\n\t\t}\n\t\tvar bodyReader io.Reader\n\t\tswitch {\n\t\tcase spec.Stream:\n\t\t\tbodyReader = spec.Body\n\t\tcase spec.bodyBytes != nil:\n\t\t\tbodyReader = bytes.NewReader(spec.bodyBytes)\n\t\t}\n\t\treq, err := http.NewRequestWithContext(attemptCtx, method, fullURL, bodyReader)\n\t\tif err != nil {\n\t\t\tif cancel != nil {\n\t\t\t\tcancel()\n\t\t\t}\n\t\t\treturn nil, err\n\t\t}\n\t\tfor key, value := range headers {\n\t\t\treq.Header.Set(key, value)\n\t\t}\n\t\tif spec.ContentType != "" && bodyReader != nil && req.Header.Get("Content-Type") == "" {\n\t\t\treq.Header.Set("Content-Type", spec.ContentType)\n\t\t}\n\t\tfor _, mw := range config.Middleware {\n\t\t\tif mw.OnRequest != nil {\n\t\t\t\tmw.OnRequest(req)\n\t\t\t}\n\t\t}\n\t\tresp, err := httpClient.Do(req)\n\t\tshouldRetry := retry.RetryOn\n\t\tretryable := false\n\t\tif shouldRetry != nil {\n\t\t\tretryable = shouldRetry(attempt, resp, err)\n\t\t} else {\n\t\t\tretryable = defaultRetryOn(method, headers, resp, err)\n\t\t}\n\t\tif err != nil {\n\t\t\tif cancel != nil {\n\t\t\t\tcancel()\n\t\t\t}\n\t\t\ttimedOut := errors.Is(err, context.DeadlineExceeded) && ctx.Err() == nil\n\t\t\tif attempt < maxAttempts && retryable {\n\t\t\t\ttime.Sleep(retryDelay(retry, attempt, ""))\n\t\t\t\tcontinue\n\t\t\t}\n\t\t\tif timedOut {\n\t\t\t\treturn nil, &TimeoutError{OperationID: spec.OperationID, Timeout: timeout, Attempt: attempt}\n\t\t\t}\n\t\t\treturn nil, err\n\t\t}\n\t\tfor i := len(config.Middleware) - 1; i >= 0; i-- {\n\t\t\tif config.Middleware[i].OnResponse != nil {\n\t\t\t\tconfig.Middleware[i].OnResponse(resp)\n\t\t\t}\n\t\t}\n\t\tif resp.StatusCode >= 400 && attempt < maxAttempts && retryable {\n\t\t\tafter := resp.Header.Get("Retry-After")\n\t\t\tio.Copy(io.Discard, resp.Body)\n\t\t\tresp.Body.Close()\n\t\t\tif cancel != nil {\n\t\t\t\tcancel()\n\t\t\t}\n\t\t\ttime.Sleep(retryDelay(retry, attempt, after))\n\t\t\tcontinue\n\t\t}\n\t\t// The response body outlives this call; tie the attempt context\'s lifetime to it.\n\t\tif cancel != nil {\n\t\t\tresp.Body = &cancelOnClose{ReadCloser: resp.Body, cancel: cancel}\n\t\t}\n\t\treturn resp, nil\n\t}\n}\n\ntype cancelOnClose struct {\n\tio.ReadCloser\n\tcancel context.CancelFunc\n}\n\nfunc (c *cancelOnClose) Close() error {\n\tc.cancel()\n\treturn c.ReadCloser.Close()\n}\n\n// decodeJSON decodes a response body into target; a nil target drains and closes.\nfunc decodeJSON(resp *http.Response, target any) error {\n\tdefer resp.Body.Close()\n\tif target == nil {\n\t\t_, err := io.Copy(io.Discard, resp.Body)\n\t\treturn err\n\t}\n\treturn json.NewDecoder(resp.Body).Decode(target)\n}\n\n// headerString returns the named response header, or nil when absent.\nfunc headerString(header http.Header, name string) *string {\n\tvalue := header.Get(name)\n\tif value == "" {\n\t\treturn nil\n\t}\n\treturn &value\n}\n\n// headerInt64 parses the named header as an integer; nil when absent or unparsable.\nfunc headerInt64(header http.Header, name string) *int64 {\n\traw := strings.TrimSpace(header.Get(name))\n\tif raw == "" {\n\t\treturn nil\n\t}\n\tvalue, err := strconv.ParseInt(raw, 10, 64)\n\tif err != nil {\n\t\treturn nil\n\t}\n\treturn &value\n}\n\n// headerFloat64 parses the named header as a number; nil when absent or unparsable.\nfunc headerFloat64(header http.Header, name string) *float64 {\n\traw := strings.TrimSpace(header.Get(name))\n\tif raw == "" {\n\t\treturn nil\n\t}\n\tvalue, err := strconv.ParseFloat(raw, 64)\n\tif err != nil {\n\t\treturn nil\n\t}\n\treturn &value\n}\n\n// headerBool parses a `true`/`false` header; nil when absent or anything else.\nfunc headerBool(header http.Header, name string) *bool {\n\traw := strings.ToLower(strings.TrimSpace(header.Get(name)))\n\tif raw != "true" && raw != "false" {\n\t\treturn nil\n\t}\n\tvalue := raw == "true"\n\treturn &value\n}\n\n// apiErrorFrom builds the structured error for a non-2xx response.\nfunc apiErrorFrom(resp *http.Response, requestURL string) error {\n\tdefer resp.Body.Close()\n\tvar body any\n\tdata, _ := io.ReadAll(resp.Body)\n\tif len(data) > 0 {\n\t\tif err := json.Unmarshal(data, &body); err != nil {\n\t\t\tbody = string(data)\n\t\t}\n\t}\n\treturn &APIError{URL: requestURL, Status: resp.StatusCode, StatusText: resp.Status, Body: body}\n}\n\n// ─── Pagination ───\n\n// PaginationSpec mirrors the descriptor table\'s pagination entries.\ntype PaginationSpec struct {\n\tStyle string\n\tParam string\n\tNextCursor string\n\tHasMore string\n\tLimitParam string\n\tItems string\n}\n\n// resolvePointer walks an RFC 6901 JSON pointer over decoded JSON; nil on any miss.\nfunc resolvePointer(data any, pointer string) any {\n\tif pointer == "" {\n\t\treturn data\n\t}\n\tif !strings.HasPrefix(pointer, "/") {\n\t\treturn nil\n\t}\n\tcurrent := data\n\tfor _, token := range strings.Split(pointer[1:], "/") {\n\t\tkey := strings.ReplaceAll(strings.ReplaceAll(token, "~1", "/"), "~0", "~")\n\t\tswitch typed := current.(type) {\n\t\tcase map[string]any:\n\t\t\tcurrent = typed[key]\n\t\tcase []any:\n\t\t\tindex, err := strconv.Atoi(key)\n\t\t\tif err != nil || index < 0 || index >= len(typed) {\n\t\t\t\treturn nil\n\t\t\t}\n\t\t\tcurrent = typed[index]\n\t\tdefault:\n\t\t\treturn nil\n\t\t}\n\t\tif current == nil {\n\t\t\treturn nil\n\t\t}\n\t}\n\treturn current\n}\n\n// reencode converts decoded JSON (maps/slices) into a typed value via a JSON round-trip.\nfunc reencode(raw any, target any) error {\n\tdata, err := json.Marshal(raw)\n\tif err != nil {\n\t\treturn err\n\t}\n\treturn json.Unmarshal(data, target)\n}\n\ntype pageCall func(params url.Values) (any, *http.Response, error)\n\n// iterPages yields raw page JSON per the pagination spec — the same stop\n// conditions and infinite-loop guards as the TypeScript runtime. The returned\n// function is a range-over-func iterator (Go 1.23+) and plainly callable before that.\nfunc iterPages(call pageCall, spec PaginationSpec, base url.Values) func(yield func(any, error) bool) {\n\treturn func(yield func(any, error) bool) {\n\t\tswitch spec.Style {\n\t\tcase "cursor":\n\t\t\tvar cursor any\n\t\t\tif values, ok := base[spec.Param]; ok && len(values) > 0 {\n\t\t\t\tcursor = values[0]\n\t\t\t}\n\t\t\tfor {\n\t\t\t\tparams := cloneValues(base)\n\t\t\t\tif cursor != nil {\n\t\t\t\t\tparams.Set(spec.Param, fmt.Sprint(cursor))\n\t\t\t\t}\n\t\t\t\tpage, _, err := call(params)\n\t\t\t\tif err != nil {\n\t\t\t\t\tyield(nil, err)\n\t\t\t\t\treturn\n\t\t\t\t}\n\t\t\t\tif !yield(page, nil) {\n\t\t\t\t\treturn\n\t\t\t\t}\n\t\t\t\tif spec.HasMore != "" {\n\t\t\t\t\tif more, ok := resolvePointer(page, spec.HasMore).(bool); ok && !more {\n\t\t\t\t\t\treturn\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tnext := resolvePointer(page, spec.NextCursor)\n\t\t\t\tif next == nil || next == "" {\n\t\t\t\t\treturn\n\t\t\t\t}\n\t\t\t\tswitch next.(type) {\n\t\t\t\tcase string, float64:\n\t\t\t\tdefault:\n\t\t\t\t\tyield(nil, fmt.Errorf("pagination cursor at %s is not a string or number", spec.NextCursor))\n\t\t\t\t\treturn\n\t\t\t\t}\n\t\t\t\tif cursor != nil && fmt.Sprint(next) == fmt.Sprint(cursor) {\n\t\t\t\t\tyield(nil, errors.New("pagination did not advance: the operation returned the same cursor twice"))\n\t\t\t\t\treturn\n\t\t\t\t}\n\t\t\t\tcursor = next\n\t\t\t}\n\t\tcase "link":\n\t\t\tparams := cloneValues(base)\n\t\t\tprevious := ""\n\t\t\tfor {\n\t\t\t\tpage, resp, err := call(params)\n\t\t\t\tif err != nil {\n\t\t\t\t\tyield(nil, err)\n\t\t\t\t\treturn\n\t\t\t\t}\n\t\t\t\tif !yield(page, nil) {\n\t\t\t\t\treturn\n\t\t\t\t}\n\t\t\t\ttarget := linkNext(resp.Header.Get("Link"))\n\t\t\t\tif target == "" {\n\t\t\t\t\treturn\n\t\t\t\t}\n\t\t\t\tpageURL := ""\n\t\t\t\tif resp.Request != nil && resp.Request.URL != nil {\n\t\t\t\t\tpageURL = resp.Request.URL.String()\n\t\t\t\t}\n\t\t\t\tbaseURL, err := url.Parse(pageURL)\n\t\t\t\tif err != nil || pageURL == "" {\n\t\t\t\t\tbaseURL, _ = url.Parse("http://relative.invalid")\n\t\t\t\t}\n\t\t\t\ttargetURL, err := baseURL.Parse(target)\n\t\t\t\tif err != nil {\n\t\t\t\t\tyield(nil, err)\n\t\t\t\t\treturn\n\t\t\t\t}\n\t\t\t\tnext := targetURL.String()\n\t\t\t\tif next == previous || next == pageURL {\n\t\t\t\t\tyield(nil, errors.New(`pagination did not advance: the Link rel="next" target repeats`))\n\t\t\t\t\treturn\n\t\t\t\t}\n\t\t\t\tprevious = next\n\t\t\t\tparams = cloneValues(base)\n\t\t\t\tfor key, values := range targetURL.Query() {\n\t\t\t\t\tfor _, value := range values {\n\t\t\t\t\t\tparams.Add(key, value)\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\tdefault: // offset / page\n\t\t\tposition := 0\n\t\t\tif spec.Style == "page" {\n\t\t\t\tposition = 1\n\t\t\t}\n\t\t\tif values, ok := base[spec.Param]; ok && len(values) > 0 && values[0] != "" {\n\t\t\t\tif parsed, err := strconv.Atoi(values[0]); err == nil {\n\t\t\t\t\tposition = parsed\n\t\t\t\t}\n\t\t\t}\n\t\t\tpreviousItems := ""\n\t\t\tfor {\n\t\t\t\tparams := cloneValues(base)\n\t\t\t\tparams.Set(spec.Param, strconv.Itoa(position))\n\t\t\t\tpage, _, err := call(params)\n\t\t\t\tif err != nil {\n\t\t\t\t\tyield(nil, err)\n\t\t\t\t\treturn\n\t\t\t\t}\n\t\t\t\titems, _ := resolvePointer(page, spec.Items).([]any)\n\t\t\t\tserialized := ""\n\t\t\t\tif items != nil {\n\t\t\t\t\tserialized = fmt.Sprint(items)\n\t\t\t\t\tif serialized == previousItems {\n\t\t\t\t\t\tyield(nil, errors.New("pagination did not advance: the operation returned the same page twice"))\n\t\t\t\t\t\treturn\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tif !yield(page, nil) {\n\t\t\t\t\treturn\n\t\t\t\t}\n\t\t\t\tif len(items) == 0 {\n\t\t\t\t\treturn\n\t\t\t\t}\n\t\t\t\tpreviousItems = serialized\n\t\t\t\tif spec.Style == "page" {\n\t\t\t\t\tposition++\n\t\t\t\t} else {\n\t\t\t\t\tposition += len(items)\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n}\n\nfunc cloneValues(values url.Values) url.Values {\n\tout := url.Values{}\n\tfor key, entries := range values {\n\t\tfor _, entry := range entries {\n\t\t\tout.Add(key, entry)\n\t\t}\n\t}\n\treturn out\n}\n\nfunc linkNext(header string) string {\n\tif header == "" {\n\t\treturn ""\n\t}\n\tfor _, entry := range strings.Split(header, ",") {\n\t\tparts := strings.Split(entry, ";")\n\t\tif len(parts) < 2 {\n\t\t\tcontinue\n\t\t}\n\t\ttarget := strings.TrimSpace(parts[0])\n\t\tif !strings.HasPrefix(target, "<") || !strings.HasSuffix(target, ">") {\n\t\t\tcontinue\n\t\t}\n\t\tfor _, param := range parts[1:] {\n\t\t\ttrimmed := strings.TrimSpace(param)\n\t\t\tif strings.HasPrefix(trimmed, "rel=") {\n\t\t\t\trel := strings.Trim(strings.TrimPrefix(trimmed, "rel="), `"`)\n\t\t\t\tfor _, kind := range strings.Fields(rel) {\n\t\t\t\t\tif kind == "next" {\n\t\t\t\t\t\treturn strings.Trim(target, "<>")\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\treturn ""\n}\n\n// ─── Server-Sent Events ───\n\n// ServerSentEvent is one decoded event; Data is the raw text (or parsed JSON\n// for operations that declare a JSON event stream).\ntype ServerSentEvent struct {\n\tEvent string\n\tData any\n\tID string\n\tRetry int\n}\n\nfunc parseSSEFrame(raw string, jsonData bool) (ServerSentEvent, bool, error) {\n\tevent := ServerSentEvent{Retry: -1}\n\tsawField := false\n\tvar dataLines []string\n\tnormalized := strings.ReplaceAll(strings.ReplaceAll(raw, "\\r\\n", "\\n"), "\\r", "\\n")\n\tfor _, line := range strings.Split(normalized, "\\n") {\n\t\tif line == "" || strings.HasPrefix(line, ":") {\n\t\t\tcontinue\n\t\t}\n\t\tfield, value, _ := strings.Cut(line, ":")\n\t\tvalue = strings.TrimPrefix(value, " ")\n\t\tsawField = true\n\t\tswitch field {\n\t\tcase "event":\n\t\t\tevent.Event = value\n\t\tcase "data":\n\t\t\tdataLines = append(dataLines, value)\n\t\tcase "id":\n\t\t\tevent.ID = value\n\t\tcase "retry":\n\t\t\tif parsed, err := strconv.Atoi(value); err == nil && parsed >= 0 && value != "" {\n\t\t\t\tevent.Retry = parsed\n\t\t\t}\n\t\t}\n\t}\n\tif !sawField {\n\t\treturn event, false, nil\n\t}\n\ttext := strings.Join(dataLines, "\\n")\n\tevent.Data = text\n\tif jsonData && text != "" {\n\t\tvar parsed any\n\t\tif err := json.Unmarshal([]byte(text), &parsed); err != nil {\n\t\t\treturn event, false, err\n\t\t}\n\t\tevent.Data = parsed\n\t}\n\treturn event, true, nil\n}\n\n// iterSSE streams events, reconnecting on dropped connections with Last-Event-ID\n// (a fresh open call = fresh auth); a 4xx/5xx or a bad JSON payload is definitive.\nfunc iterSSE(open func(extraHeaders map[string]string) (*http.Response, error), jsonData bool) func(yield func(ServerSentEvent, error) bool) {\n\treturn func(yield func(ServerSentEvent, error) bool) {\n\t\tlastEventID := ""\n\t\tserverRetry := -1\n\t\tfailures := 0\n\t\tfor {\n\t\t\theaders := map[string]string{"Accept": "text/event-stream"}\n\t\t\tif lastEventID != "" {\n\t\t\t\theaders["Last-Event-ID"] = lastEventID\n\t\t\t}\n\t\t\tresp, err := open(headers)\n\t\t\tif err == nil && resp.StatusCode >= 400 {\n\t\t\t\tyield(ServerSentEvent{}, apiErrorFrom(resp, ""))\n\t\t\t\treturn\n\t\t\t}\n\t\t\tif err == nil {\n\t\t\t\tfailures = 0\n\t\t\t\tbuffer := ""\n\t\t\t\tchunk := make([]byte, 4096)\n\t\t\t\tclean := false\n\t\t\t\tfor {\n\t\t\t\t\tn, readErr := resp.Body.Read(chunk)\n\t\t\t\t\tbuffer += string(chunk[:n])\n\t\t\t\t\tfor {\n\t\t\t\t\t\tframe, rest, found := strings.Cut(buffer, "\\n\\n")\n\t\t\t\t\t\tif !found {\n\t\t\t\t\t\t\tbreak\n\t\t\t\t\t\t}\n\t\t\t\t\t\tbuffer = rest\n\t\t\t\t\t\tevent, ok, parseErr := parseSSEFrame(frame, jsonData)\n\t\t\t\t\t\tif parseErr != nil {\n\t\t\t\t\t\t\tresp.Body.Close()\n\t\t\t\t\t\t\tyield(ServerSentEvent{}, parseErr)\n\t\t\t\t\t\t\treturn\n\t\t\t\t\t\t}\n\t\t\t\t\t\tif ok {\n\t\t\t\t\t\t\tif event.ID != "" {\n\t\t\t\t\t\t\t\tlastEventID = event.ID\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tif event.Retry >= 0 {\n\t\t\t\t\t\t\t\tserverRetry = event.Retry\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tif !yield(event, nil) {\n\t\t\t\t\t\t\t\tresp.Body.Close()\n\t\t\t\t\t\t\t\treturn\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\tif readErr == io.EOF {\n\t\t\t\t\t\tclean = true\n\t\t\t\t\t\tbreak\n\t\t\t\t\t}\n\t\t\t\t\tif readErr != nil {\n\t\t\t\t\t\tbreak\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tresp.Body.Close()\n\t\t\t\tif clean {\n\t\t\t\t\tif strings.TrimSpace(buffer) != "" {\n\t\t\t\t\t\tif event, ok, parseErr := parseSSEFrame(buffer, jsonData); parseErr == nil && ok {\n\t\t\t\t\t\t\tyield(event, nil)\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\treturn\n\t\t\t\t}\n\t\t\t}\n\t\t\tfailures++\n\t\t\tbase := time.Second\n\t\t\tif serverRetry >= 0 {\n\t\t\t\tbase = time.Duration(serverRetry) * time.Millisecond\n\t\t\t}\n\t\t\tdelay := base * time.Duration(1<<(failures-1))\n\t\t\tif delay > 30*time.Second {\n\t\t\t\tdelay = 30 * time.Second\n\t\t\t}\n\t\t\ttime.Sleep(time.Duration(rand.Int63n(int64(delay) + 1)))\n\t\t}\n\t}\n}\n\n// ─── Multipart ───\n\n// toMultipart splits a typed body into a multipart/form-data payload: []byte\n// values upload as file parts, everything else as form fields (nested values\n// JSON-encoded) — mirroring the TypeScript runtime\'s FormData serialization.\nfunc toMultipart(body any) (string, io.Reader, error) {\n\tvar wire map[string]any\n\tif err := reencode(body, &wire); err != nil {\n\t\treturn "", nil, err\n\t}\n\tbuffer := &bytes.Buffer{}\n\twriter := multipart.NewWriter(buffer)\n\tfor key, value := range wire {\n\t\tswitch typed := value.(type) {\n\t\tcase string:\n\t\t\tif err := writer.WriteField(key, typed); err != nil {\n\t\t\t\treturn "", nil, err\n\t\t\t}\n\t\tcase float64, bool:\n\t\t\tif err := writer.WriteField(key, fmt.Sprint(typed)); err != nil {\n\t\t\t\treturn "", nil, err\n\t\t\t}\n\t\tdefault:\n\t\t\tencoded, err := json.Marshal(typed)\n\t\t\tif err != nil {\n\t\t\t\treturn "", nil, err\n\t\t\t}\n\t\t\tif err := writer.WriteField(key, string(encoded)); err != nil {\n\t\t\t\treturn "", nil, err\n\t\t\t}\n\t\t}\n\t}\n\tif err := writer.Close(); err != nil {\n\t\treturn "", nil, err\n\t}\n\treturn writer.FormDataContentType(), buffer, nil\n}\n\n// multipartBody prepares the body of an untyped multipart operation: an io.Reader is\n// streamed and a []byte or string sent as is, all under the caller\'s Content-Type (the\n// boundary is theirs to set); any other value goes through toMultipart.\nfunc multipartBody(body any) (string, io.Reader, bool, error) {\n\tif reader, stream, raw := rawBody(body); raw {\n\t\treturn "", reader, stream, nil\n\t}\n\tcontentType, reader, err := toMultipart(body)\n\treturn contentType, reader, false, err\n}\n\n// binaryBody prepares the body of a binary operation: an io.Reader is streamed, a\n// []byte or string sent as is, and any other value JSON-marshalled.\nfunc binaryBody(body any) (io.Reader, bool, error) {\n\tif reader, stream, raw := rawBody(body); raw {\n\t\treturn reader, stream, nil\n\t}\n\tpayload, err := json.Marshal(body)\n\treturn bytes.NewReader(payload), false, err\n}\n\n// rawBody recognizes a body that needs no encoding: an io.Reader streams through in one\n// attempt, a []byte or a string is replayable bytes.\nfunc rawBody(body any) (io.Reader, bool, bool) {\n\tswitch typed := body.(type) {\n\tcase io.Reader:\n\t\treturn typed, true, true\n\tcase []byte:\n\t\treturn bytes.NewReader(typed), false, true\n\tcase string:\n\t\treturn strings.NewReader(typed), false, true\n\t}\n\treturn nil, false, false\n}\n';
|
|
2
|
+
export const GO_RUNTIME_SOURCE = '// Package client — the embedded runtime for generated Go SDKs. Hand-authored\n// once and stitched into every generated client (see\n// scripts/generate-runtime-sources.mjs), semantically in lockstep with the\n// TypeScript runtime: auth OR-alternatives, a retry loop with Retry-After and\n// full-jitter backoff, per-attempt timeouts, idempotency keys, and middleware\n// hooks. Standard library only — a generated Go SDK has zero dependencies.\npackage client\n\nimport (\n\t"bytes"\n\t"context"\n\t"encoding/base64"\n\t"encoding/json"\n\t"errors"\n\t"fmt"\n\t"io"\n\t"math/rand"\n\t"mime/multipart"\n\t"net/http"\n\t"net/url"\n\t"strconv"\n\t"strings"\n\t"time"\n)\n\n// APIError is returned for a non-2xx response, carrying the decoded error body.\ntype APIError struct {\n\tURL string\n\tStatus int\n\tStatusText string\n\tBody any\n}\n\nfunc (e *APIError) Error() string {\n\treturn fmt.Sprintf("request failed with status %d", e.Status)\n}\n\n// TimeoutError is returned when a request attempt exceeds the configured\n// timeout — carrying the context a log line needs.\ntype TimeoutError struct {\n\tOperationID string\n\tTimeout time.Duration\n\tAttempt int\n}\n\nfunc (e *TimeoutError) Error() string {\n\treturn fmt.Sprintf("request %q timed out after %s (attempt %d)", e.OperationID, e.Timeout, e.Attempt)\n}\n\n// SecuritySpec mirrors the descriptor table\'s security entries.\ntype SecuritySpec struct {\n\tScheme string\n\tKind string // "bearer" | "basic" | "apiKey"\n\tName string // header/query/cookie name for apiKey\n\tIn string // "header" | "query" | "cookie"\n}\n\n// Auth holds the client credentials; zero value = anonymous.\ntype Auth struct {\n\tBearer func() string\n\tBasic *BasicAuth\n\tAPIKey map[string]func() string\n}\n\ntype BasicAuth struct {\n\tUsername string\n\tPassword string\n}\n\n// RetryConfig mirrors the TypeScript runtime\'s retry policy knobs.\ntype RetryConfig struct {\n\tRetries int\n\tRetryDelay time.Duration // base; default 1s\n\tRetryStrategy string // "" (exponential) | "fixed"\n\tNoJitter bool\n\t// RetryOn fully replaces the default predicate when set.\n\tRetryOn func(attempt int, resp *http.Response, err error) bool\n}\n\n// Middleware hooks run around every request (OnRequest before serialization order\n// is N/A in Go — bodies are values; OnResponse runs in reverse registration order).\ntype Middleware struct {\n\tOnRequest func(req *http.Request)\n\tOnResponse func(resp *http.Response)\n}\n\n// Date is an RFC 3339 full-date — a calendar date with no time component. Fields\n// typed `date` under `dateType: Date` use it because encoding/json speaks only\n// RFC 3339 date-time for time.Time, which a bare "2006-01-02" fails to satisfy.\ntype Date struct {\n\ttime.Time\n}\n\nconst dateLayout = "2006-01-02"\n\n// UnmarshalJSON parses a "2006-01-02" string; an empty string leaves the zero value.\nfunc (d *Date) UnmarshalJSON(data []byte) error {\n\tvar raw string\n\tif err := json.Unmarshal(data, &raw); err != nil {\n\t\treturn err\n\t}\n\tif raw == "" {\n\t\treturn nil\n\t}\n\tparsed, err := time.Parse(dateLayout, raw)\n\tif err != nil {\n\t\treturn err\n\t}\n\td.Time = parsed\n\treturn nil\n}\n\n// MarshalJSON writes the date back without a time component.\nfunc (d Date) MarshalJSON() ([]byte, error) {\n\treturn json.Marshal(d.Format(dateLayout))\n}\n\n// Config is the per-client configuration shared by every operation method.\ntype Config struct {\n\tServerURL string\n\tHTTPClient *http.Client\n\tHeaders map[string]string\n\tTimeout time.Duration\n\tRetry RetryConfig\n\tMiddleware []Middleware\n\tIdempotencyKey func() string\n\tAuth Auth\n}\n\nfunc resolveToken(provider func() string) string {\n\tif provider == nil {\n\t\treturn ""\n\t}\n\treturn provider()\n}\n\nfunc schemeConfigured(spec SecuritySpec, auth Auth) bool {\n\tswitch spec.Kind {\n\tcase "apiKey":\n\t\t_, ok := auth.APIKey[spec.Scheme]\n\t\treturn ok\n\tcase "bearer":\n\t\treturn auth.Bearer != nil\n\tdefault:\n\t\treturn auth.Basic != nil\n\t}\n}\n\n// resolveAuth applies the first fully-configured OR-alternative; when none is,\n// the first alternative\'s configured schemes are still sent (the server rejects\n// the request — same behavior as the TypeScript runtime).\nfunc resolveAuth(security [][]SecuritySpec, auth Auth) (map[string]string, url.Values) {\n\theaders := map[string]string{}\n\tquery := url.Values{}\n\tif len(security) == 0 {\n\t\treturn headers, query\n\t}\n\talternative := security[0]\n\tfor _, candidate := range security {\n\t\tall := true\n\t\tfor _, spec := range candidate {\n\t\t\tif !schemeConfigured(spec, auth) {\n\t\t\t\tall = false\n\t\t\t\tbreak\n\t\t\t}\n\t\t}\n\t\tif all {\n\t\t\talternative = candidate\n\t\t\tbreak\n\t\t}\n\t}\n\tvar cookies []string\n\tfor _, spec := range alternative {\n\t\tswitch spec.Kind {\n\t\tcase "apiKey":\n\t\t\tprovider, ok := auth.APIKey[spec.Scheme]\n\t\t\tif !ok {\n\t\t\t\tcontinue\n\t\t\t}\n\t\t\tvalue := resolveToken(provider)\n\t\t\tswitch spec.In {\n\t\t\tcase "query":\n\t\t\t\tquery.Set(spec.Name, value)\n\t\t\tcase "cookie":\n\t\t\t\tcookies = append(cookies, spec.Name+"="+url.QueryEscape(value))\n\t\t\tdefault:\n\t\t\t\theaders[spec.Name] = value\n\t\t\t}\n\t\tcase "bearer":\n\t\t\tif auth.Bearer != nil {\n\t\t\t\theaders["Authorization"] = "Bearer " + resolveToken(auth.Bearer)\n\t\t\t}\n\t\tdefault:\n\t\t\tif auth.Basic != nil {\n\t\t\t\ttoken := base64.StdEncoding.EncodeToString([]byte(auth.Basic.Username + ":" + auth.Basic.Password))\n\t\t\t\theaders["Authorization"] = "Basic " + token\n\t\t\t}\n\t\t}\n\t}\n\tif len(cookies) > 0 {\n\t\theaders["Cookie"] = strings.Join(cookies, "; ")\n\t}\n\treturn headers, query\n}\n\n// buildURL substitutes {param} path placeholders with percent-encoded values.\nfunc buildURL(serverURL, path string, pathParams map[string]string) string {\n\tfilled := path\n\tfor name, value := range pathParams {\n\t\tfilled = strings.ReplaceAll(filled, "{"+name+"}", url.PathEscape(value))\n\t}\n\treturn strings.TrimRight(serverURL, "/") + filled\n}\n\nvar transientStatus = map[int]bool{408: true, 429: true, 500: true, 502: true, 503: true, 504: true}\n\nfunc defaultRetryOn(method string, headers map[string]string, resp *http.Response, err error) bool {\n\tsafe := false\n\tswitch strings.ToUpper(method) {\n\tcase "GET", "HEAD", "PUT", "DELETE", "OPTIONS":\n\t\tsafe = true\n\t}\n\tif _, ok := headers["Idempotency-Key"]; ok {\n\t\tsafe = true\n\t}\n\tif !safe {\n\t\treturn false\n\t}\n\tif err != nil {\n\t\treturn true\n\t}\n\treturn resp != nil && transientStatus[resp.StatusCode]\n}\n\nfunc retryDelay(retry RetryConfig, attempt int, retryAfter string) time.Duration {\n\tif retryAfter != "" {\n\t\tif seconds, err := strconv.ParseFloat(retryAfter, 64); err == nil {\n\t\t\treturn time.Duration(seconds * float64(time.Second))\n\t\t}\n\t}\n\tbase := retry.RetryDelay\n\tif base == 0 {\n\t\tbase = time.Second\n\t}\n\traw := base\n\tif retry.RetryStrategy != "fixed" {\n\t\traw = base * time.Duration(1<<(attempt-1))\n\t}\n\tif retry.NoJitter {\n\t\treturn raw\n\t}\n\treturn time.Duration(rand.Int63n(int64(raw) + 1))\n}\n\ntype requestSpec struct {\n\tOperationID string\n\tMethod string\n\tURL string\n\tHeaders map[string]string\n\tQuery url.Values\n\tBody io.Reader\n\t// Stream sends Body as is: no buffering, one attempt, the caller\'s Content-Type.\n\tStream bool\n\tContentType string\n\tTimeout time.Duration\n\tRetry *RetryConfig\n\tIdempotencyKey string\n\t// bodyBytes is retained so retries can replay the body.\n\tbodyBytes []byte\n}\n\n// send is the request core: header merge, idempotency keys, the retry loop\n// (fresh timeout budget per attempt), and the middleware onion.\nfunc send(ctx context.Context, config *Config, spec requestSpec) (*http.Response, error) {\n\tretry := config.Retry\n\tif spec.Retry != nil {\n\t\tretry = *spec.Retry\n\t}\n\ttimeout := config.Timeout\n\tif spec.Timeout != 0 {\n\t\ttimeout = spec.Timeout\n\t}\n\theaders := map[string]string{}\n\tfor key, value := range config.Headers {\n\t\theaders[key] = value\n\t}\n\tfor key, value := range spec.Headers {\n\t\theaders[key] = value\n\t}\n\tmethod := strings.ToUpper(spec.Method)\n\tif (method == "POST" || method == "PATCH") && headers["Idempotency-Key"] == "" {\n\t\tif spec.IdempotencyKey != "" {\n\t\t\theaders["Idempotency-Key"] = spec.IdempotencyKey\n\t\t} else if config.IdempotencyKey != nil {\n\t\t\theaders["Idempotency-Key"] = config.IdempotencyKey()\n\t\t}\n\t}\n\thttpClient := config.HTTPClient\n\tif httpClient == nil {\n\t\thttpClient = http.DefaultClient\n\t}\n\tif spec.Body != nil && !spec.Stream {\n\t\tpayload, err := io.ReadAll(spec.Body)\n\t\tif err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t\tspec.bodyBytes = payload\n\t}\n\tfullURL := spec.URL\n\tif len(spec.Query) > 0 {\n\t\tseparator := "?"\n\t\tif strings.Contains(fullURL, "?") {\n\t\t\tseparator = "&"\n\t\t}\n\t\tfullURL += separator + spec.Query.Encode()\n\t}\n\tmaxAttempts := 1 + retry.Retries\n\tif spec.Stream {\n\t\t// The first attempt consumes the reader, so there is nothing to replay.\n\t\tmaxAttempts = 1\n\t}\n\tfor attempt := 1; ; attempt++ {\n\t\tattemptCtx := ctx\n\t\tvar cancel context.CancelFunc\n\t\tif timeout > 0 {\n\t\t\tattemptCtx, cancel = context.WithTimeout(ctx, timeout)\n\t\t}\n\t\tvar bodyReader io.Reader\n\t\tswitch {\n\t\tcase spec.Stream:\n\t\t\tbodyReader = spec.Body\n\t\tcase spec.bodyBytes != nil:\n\t\t\tbodyReader = bytes.NewReader(spec.bodyBytes)\n\t\t}\n\t\treq, err := http.NewRequestWithContext(attemptCtx, method, fullURL, bodyReader)\n\t\tif err != nil {\n\t\t\tif cancel != nil {\n\t\t\t\tcancel()\n\t\t\t}\n\t\t\treturn nil, err\n\t\t}\n\t\tfor key, value := range headers {\n\t\t\treq.Header.Set(key, value)\n\t\t}\n\t\tif spec.ContentType != "" && bodyReader != nil && req.Header.Get("Content-Type") == "" {\n\t\t\treq.Header.Set("Content-Type", spec.ContentType)\n\t\t}\n\t\tfor _, mw := range config.Middleware {\n\t\t\tif mw.OnRequest != nil {\n\t\t\t\tmw.OnRequest(req)\n\t\t\t}\n\t\t}\n\t\tresp, err := httpClient.Do(req)\n\t\tshouldRetry := retry.RetryOn\n\t\tretryable := false\n\t\tif shouldRetry != nil {\n\t\t\tretryable = shouldRetry(attempt, resp, err)\n\t\t} else {\n\t\t\tretryable = defaultRetryOn(method, headers, resp, err)\n\t\t}\n\t\tif err != nil {\n\t\t\tif cancel != nil {\n\t\t\t\tcancel()\n\t\t\t}\n\t\t\ttimedOut := errors.Is(err, context.DeadlineExceeded) && ctx.Err() == nil\n\t\t\tif attempt < maxAttempts && retryable {\n\t\t\t\ttime.Sleep(retryDelay(retry, attempt, ""))\n\t\t\t\tcontinue\n\t\t\t}\n\t\t\tif timedOut {\n\t\t\t\treturn nil, &TimeoutError{OperationID: spec.OperationID, Timeout: timeout, Attempt: attempt}\n\t\t\t}\n\t\t\treturn nil, err\n\t\t}\n\t\tfor i := len(config.Middleware) - 1; i >= 0; i-- {\n\t\t\tif config.Middleware[i].OnResponse != nil {\n\t\t\t\tconfig.Middleware[i].OnResponse(resp)\n\t\t\t}\n\t\t}\n\t\tif resp.StatusCode >= 400 && attempt < maxAttempts && retryable {\n\t\t\tafter := resp.Header.Get("Retry-After")\n\t\t\tio.Copy(io.Discard, resp.Body)\n\t\t\tresp.Body.Close()\n\t\t\tif cancel != nil {\n\t\t\t\tcancel()\n\t\t\t}\n\t\t\ttime.Sleep(retryDelay(retry, attempt, after))\n\t\t\tcontinue\n\t\t}\n\t\t// The response body outlives this call; tie the attempt context\'s lifetime to it.\n\t\tif cancel != nil {\n\t\t\tresp.Body = &cancelOnClose{ReadCloser: resp.Body, cancel: cancel}\n\t\t}\n\t\treturn resp, nil\n\t}\n}\n\ntype cancelOnClose struct {\n\tio.ReadCloser\n\tcancel context.CancelFunc\n}\n\nfunc (c *cancelOnClose) Close() error {\n\tc.cancel()\n\treturn c.ReadCloser.Close()\n}\n\n// decodeJSON decodes a response body into target; a nil target drains and closes.\nfunc decodeJSON(resp *http.Response, target any) error {\n\tdefer resp.Body.Close()\n\tif target == nil {\n\t\t_, err := io.Copy(io.Discard, resp.Body)\n\t\treturn err\n\t}\n\treturn json.NewDecoder(resp.Body).Decode(target)\n}\n\n// headerString returns the named response header, or nil when absent.\nfunc headerString(header http.Header, name string) *string {\n\tvalue := header.Get(name)\n\tif value == "" {\n\t\treturn nil\n\t}\n\treturn &value\n}\n\n// headerInt64 parses the named header as an integer; nil when absent or unparsable.\nfunc headerInt64(header http.Header, name string) *int64 {\n\traw := strings.TrimSpace(header.Get(name))\n\tif raw == "" {\n\t\treturn nil\n\t}\n\tvalue, err := strconv.ParseInt(raw, 10, 64)\n\tif err != nil {\n\t\treturn nil\n\t}\n\treturn &value\n}\n\n// headerFloat64 parses the named header as a number; nil when absent or unparsable.\nfunc headerFloat64(header http.Header, name string) *float64 {\n\traw := strings.TrimSpace(header.Get(name))\n\tif raw == "" {\n\t\treturn nil\n\t}\n\tvalue, err := strconv.ParseFloat(raw, 64)\n\tif err != nil {\n\t\treturn nil\n\t}\n\treturn &value\n}\n\n// headerBool parses a `true`/`false` header; nil when absent or anything else.\nfunc headerBool(header http.Header, name string) *bool {\n\traw := strings.ToLower(strings.TrimSpace(header.Get(name)))\n\tif raw != "true" && raw != "false" {\n\t\treturn nil\n\t}\n\tvalue := raw == "true"\n\treturn &value\n}\n\n// apiErrorFrom builds the structured error for a non-2xx response.\nfunc apiErrorFrom(resp *http.Response, requestURL string) error {\n\tdefer resp.Body.Close()\n\tvar body any\n\tdata, _ := io.ReadAll(resp.Body)\n\tif len(data) > 0 {\n\t\tif err := json.Unmarshal(data, &body); err != nil {\n\t\t\tbody = string(data)\n\t\t}\n\t}\n\treturn &APIError{URL: requestURL, Status: resp.StatusCode, StatusText: resp.Status, Body: body}\n}\n\n// ─── Pagination ───\n\n// PaginationSpec mirrors the descriptor table\'s pagination entries.\ntype PaginationSpec struct {\n\tStyle string\n\tParam string\n\tNextCursor string\n\tHasMore string\n\tNextLink string\n\tLimitParam string\n\tItems string\n}\n\n// resolvePointer walks an RFC 6901 JSON pointer over decoded JSON; nil on any miss.\nfunc resolvePointer(data any, pointer string) any {\n\tif pointer == "" {\n\t\treturn data\n\t}\n\tif !strings.HasPrefix(pointer, "/") {\n\t\treturn nil\n\t}\n\tcurrent := data\n\tfor _, token := range strings.Split(pointer[1:], "/") {\n\t\tkey := strings.ReplaceAll(strings.ReplaceAll(token, "~1", "/"), "~0", "~")\n\t\tswitch typed := current.(type) {\n\t\tcase map[string]any:\n\t\t\tcurrent = typed[key]\n\t\tcase []any:\n\t\t\tindex, err := strconv.Atoi(key)\n\t\t\tif err != nil || index < 0 || index >= len(typed) {\n\t\t\t\treturn nil\n\t\t\t}\n\t\t\tcurrent = typed[index]\n\t\tdefault:\n\t\t\treturn nil\n\t\t}\n\t\tif current == nil {\n\t\t\treturn nil\n\t\t}\n\t}\n\treturn current\n}\n\n// reencode converts decoded JSON (maps/slices) into a typed value via a JSON round-trip.\nfunc reencode(raw any, target any) error {\n\tdata, err := json.Marshal(raw)\n\tif err != nil {\n\t\treturn err\n\t}\n\treturn json.Unmarshal(data, target)\n}\n\ntype pageCall func(params url.Values) (any, *http.Response, error)\n\n// iterPages yields raw page JSON per the pagination spec — the same stop\n// conditions and infinite-loop guards as the TypeScript runtime. The returned\n// function is a range-over-func iterator (Go 1.23+) and plainly callable before that.\nfunc iterPages(call pageCall, spec PaginationSpec, base url.Values) func(yield func(any, error) bool) {\n\treturn func(yield func(any, error) bool) {\n\t\tswitch spec.Style {\n\t\tcase "cursor":\n\t\t\tvar cursor any\n\t\t\tif values, ok := base[spec.Param]; ok && len(values) > 0 {\n\t\t\t\tcursor = values[0]\n\t\t\t}\n\t\t\tfor {\n\t\t\t\tparams := cloneValues(base)\n\t\t\t\tif cursor != nil {\n\t\t\t\t\tparams.Set(spec.Param, fmt.Sprint(cursor))\n\t\t\t\t}\n\t\t\t\tpage, _, err := call(params)\n\t\t\t\tif err != nil {\n\t\t\t\t\tyield(nil, err)\n\t\t\t\t\treturn\n\t\t\t\t}\n\t\t\t\tif !yield(page, nil) {\n\t\t\t\t\treturn\n\t\t\t\t}\n\t\t\t\tif spec.HasMore != "" {\n\t\t\t\t\tif more, ok := resolvePointer(page, spec.HasMore).(bool); ok && !more {\n\t\t\t\t\t\treturn\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tnext := resolvePointer(page, spec.NextCursor)\n\t\t\t\tif next == nil || next == "" {\n\t\t\t\t\treturn\n\t\t\t\t}\n\t\t\t\tswitch next.(type) {\n\t\t\t\tcase string, float64:\n\t\t\t\tdefault:\n\t\t\t\t\tyield(nil, fmt.Errorf("pagination cursor at %s is not a string or number", spec.NextCursor))\n\t\t\t\t\treturn\n\t\t\t\t}\n\t\t\t\tif cursor != nil && fmt.Sprint(next) == fmt.Sprint(cursor) {\n\t\t\t\t\tyield(nil, errors.New("pagination did not advance: the operation returned the same cursor twice"))\n\t\t\t\t\treturn\n\t\t\t\t}\n\t\t\t\tcursor = next\n\t\t\t}\n\t\tcase "link", "body-link":\n\t\t\tparams := cloneValues(base)\n\t\t\tprevious := ""\n\t\t\tfor {\n\t\t\t\tpage, resp, err := call(params)\n\t\t\t\tif err != nil {\n\t\t\t\t\tyield(nil, err)\n\t\t\t\t\treturn\n\t\t\t\t}\n\t\t\t\tif !yield(page, nil) {\n\t\t\t\t\treturn\n\t\t\t\t}\n\t\t\t\tvar target string\n\t\t\t\tif spec.Style == "link" {\n\t\t\t\t\ttarget = linkNext(resp.Header.Get("Link"))\n\t\t\t\t} else {\n\t\t\t\t\tvalue := resolvePointer(page, spec.NextLink)\n\t\t\t\t\tlink, isString := value.(string)\n\t\t\t\t\tif value != nil && !isString {\n\t\t\t\t\t\tyield(nil, fmt.Errorf("pagination link at %s is not a string", spec.NextLink))\n\t\t\t\t\t\treturn\n\t\t\t\t\t}\n\t\t\t\t\ttarget = link\n\t\t\t\t}\n\t\t\t\tif target == "" {\n\t\t\t\t\treturn\n\t\t\t\t}\n\t\t\t\tpageURL := ""\n\t\t\t\tif resp.Request != nil && resp.Request.URL != nil {\n\t\t\t\t\tpageURL = resp.Request.URL.String()\n\t\t\t\t}\n\t\t\t\tbaseURL, err := url.Parse(pageURL)\n\t\t\t\tif err != nil || pageURL == "" {\n\t\t\t\t\tbaseURL, _ = url.Parse("http://relative.invalid")\n\t\t\t\t}\n\t\t\t\ttargetURL, err := baseURL.Parse(target)\n\t\t\t\tif err != nil {\n\t\t\t\t\tyield(nil, err)\n\t\t\t\t\treturn\n\t\t\t\t}\n\t\t\t\tnext := targetURL.String()\n\t\t\t\tif next == previous || next == pageURL {\n\t\t\t\t\tyield(nil, errors.New(`pagination did not advance: the Link rel="next" target repeats`))\n\t\t\t\t\treturn\n\t\t\t\t}\n\t\t\t\tprevious = next\n\t\t\t\tparams = cloneValues(base)\n\t\t\t\tfor key, values := range targetURL.Query() {\n\t\t\t\t\tparams[key] = values\n\t\t\t\t}\n\t\t\t}\n\t\tdefault: // offset / page\n\t\t\tposition := 0\n\t\t\tif spec.Style == "page" {\n\t\t\t\tposition = 1\n\t\t\t}\n\t\t\tif values, ok := base[spec.Param]; ok && len(values) > 0 && values[0] != "" {\n\t\t\t\tif parsed, err := strconv.Atoi(values[0]); err == nil {\n\t\t\t\t\tposition = parsed\n\t\t\t\t}\n\t\t\t}\n\t\t\tpreviousItems := ""\n\t\t\tfor {\n\t\t\t\tparams := cloneValues(base)\n\t\t\t\tparams.Set(spec.Param, strconv.Itoa(position))\n\t\t\t\tpage, _, err := call(params)\n\t\t\t\tif err != nil {\n\t\t\t\t\tyield(nil, err)\n\t\t\t\t\treturn\n\t\t\t\t}\n\t\t\t\titems, _ := resolvePointer(page, spec.Items).([]any)\n\t\t\t\tserialized := ""\n\t\t\t\tif items != nil {\n\t\t\t\t\tserialized = fmt.Sprint(items)\n\t\t\t\t\tif serialized == previousItems {\n\t\t\t\t\t\tyield(nil, errors.New("pagination did not advance: the operation returned the same page twice"))\n\t\t\t\t\t\treturn\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tif !yield(page, nil) {\n\t\t\t\t\treturn\n\t\t\t\t}\n\t\t\t\tif len(items) == 0 {\n\t\t\t\t\treturn\n\t\t\t\t}\n\t\t\t\tpreviousItems = serialized\n\t\t\t\tif spec.Style == "page" {\n\t\t\t\t\tposition++\n\t\t\t\t} else {\n\t\t\t\t\tposition += len(items)\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n}\n\nfunc cloneValues(values url.Values) url.Values {\n\tout := url.Values{}\n\tfor key, entries := range values {\n\t\tfor _, entry := range entries {\n\t\t\tout.Add(key, entry)\n\t\t}\n\t}\n\treturn out\n}\n\nfunc linkNext(header string) string {\n\tif header == "" {\n\t\treturn ""\n\t}\n\tfor _, entry := range strings.Split(header, ",") {\n\t\tparts := strings.Split(entry, ";")\n\t\tif len(parts) < 2 {\n\t\t\tcontinue\n\t\t}\n\t\ttarget := strings.TrimSpace(parts[0])\n\t\tif !strings.HasPrefix(target, "<") || !strings.HasSuffix(target, ">") {\n\t\t\tcontinue\n\t\t}\n\t\tfor _, param := range parts[1:] {\n\t\t\ttrimmed := strings.TrimSpace(param)\n\t\t\tif strings.HasPrefix(trimmed, "rel=") {\n\t\t\t\trel := strings.Trim(strings.TrimPrefix(trimmed, "rel="), `"`)\n\t\t\t\tfor _, kind := range strings.Fields(rel) {\n\t\t\t\t\tif kind == "next" {\n\t\t\t\t\t\treturn strings.Trim(target, "<>")\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\treturn ""\n}\n\n// ─── Server-Sent Events ───\n\n// ServerSentEvent is one decoded event; Data is the raw text (or parsed JSON\n// for operations that declare a JSON event stream).\ntype ServerSentEvent struct {\n\tEvent string\n\tData any\n\tID string\n\tRetry int\n}\n\nfunc parseSSEFrame(raw string, jsonData bool) (ServerSentEvent, bool, error) {\n\tevent := ServerSentEvent{Retry: -1}\n\tsawField := false\n\tvar dataLines []string\n\tnormalized := strings.ReplaceAll(strings.ReplaceAll(raw, "\\r\\n", "\\n"), "\\r", "\\n")\n\tfor _, line := range strings.Split(normalized, "\\n") {\n\t\tif line == "" || strings.HasPrefix(line, ":") {\n\t\t\tcontinue\n\t\t}\n\t\tfield, value, _ := strings.Cut(line, ":")\n\t\tvalue = strings.TrimPrefix(value, " ")\n\t\tsawField = true\n\t\tswitch field {\n\t\tcase "event":\n\t\t\tevent.Event = value\n\t\tcase "data":\n\t\t\tdataLines = append(dataLines, value)\n\t\tcase "id":\n\t\t\tevent.ID = value\n\t\tcase "retry":\n\t\t\tif parsed, err := strconv.Atoi(value); err == nil && parsed >= 0 && value != "" {\n\t\t\t\tevent.Retry = parsed\n\t\t\t}\n\t\t}\n\t}\n\tif !sawField {\n\t\treturn event, false, nil\n\t}\n\ttext := strings.Join(dataLines, "\\n")\n\tevent.Data = text\n\tif jsonData && text != "" {\n\t\tvar parsed any\n\t\tif err := json.Unmarshal([]byte(text), &parsed); err != nil {\n\t\t\treturn event, false, err\n\t\t}\n\t\tevent.Data = parsed\n\t}\n\treturn event, true, nil\n}\n\n// iterSSE streams events, reconnecting on dropped connections with Last-Event-ID\n// (a fresh open call = fresh auth); a 4xx/5xx or a bad JSON payload is definitive.\nfunc iterSSE(open func(extraHeaders map[string]string) (*http.Response, error), jsonData bool) func(yield func(ServerSentEvent, error) bool) {\n\treturn func(yield func(ServerSentEvent, error) bool) {\n\t\tlastEventID := ""\n\t\tserverRetry := -1\n\t\tfailures := 0\n\t\tfor {\n\t\t\theaders := map[string]string{"Accept": "text/event-stream"}\n\t\t\tif lastEventID != "" {\n\t\t\t\theaders["Last-Event-ID"] = lastEventID\n\t\t\t}\n\t\t\tresp, err := open(headers)\n\t\t\tif err == nil && resp.StatusCode >= 400 {\n\t\t\t\tyield(ServerSentEvent{}, apiErrorFrom(resp, ""))\n\t\t\t\treturn\n\t\t\t}\n\t\t\tif err == nil {\n\t\t\t\tfailures = 0\n\t\t\t\tbuffer := ""\n\t\t\t\tchunk := make([]byte, 4096)\n\t\t\t\tclean := false\n\t\t\t\tfor {\n\t\t\t\t\tn, readErr := resp.Body.Read(chunk)\n\t\t\t\t\tbuffer += string(chunk[:n])\n\t\t\t\t\tfor {\n\t\t\t\t\t\tframe, rest, found := strings.Cut(buffer, "\\n\\n")\n\t\t\t\t\t\tif !found {\n\t\t\t\t\t\t\tbreak\n\t\t\t\t\t\t}\n\t\t\t\t\t\tbuffer = rest\n\t\t\t\t\t\tevent, ok, parseErr := parseSSEFrame(frame, jsonData)\n\t\t\t\t\t\tif parseErr != nil {\n\t\t\t\t\t\t\tresp.Body.Close()\n\t\t\t\t\t\t\tyield(ServerSentEvent{}, parseErr)\n\t\t\t\t\t\t\treturn\n\t\t\t\t\t\t}\n\t\t\t\t\t\tif ok {\n\t\t\t\t\t\t\tif event.ID != "" {\n\t\t\t\t\t\t\t\tlastEventID = event.ID\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tif event.Retry >= 0 {\n\t\t\t\t\t\t\t\tserverRetry = event.Retry\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tif !yield(event, nil) {\n\t\t\t\t\t\t\t\tresp.Body.Close()\n\t\t\t\t\t\t\t\treturn\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\tif readErr == io.EOF {\n\t\t\t\t\t\tclean = true\n\t\t\t\t\t\tbreak\n\t\t\t\t\t}\n\t\t\t\t\tif readErr != nil {\n\t\t\t\t\t\tbreak\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tresp.Body.Close()\n\t\t\t\tif clean {\n\t\t\t\t\tif strings.TrimSpace(buffer) != "" {\n\t\t\t\t\t\tif event, ok, parseErr := parseSSEFrame(buffer, jsonData); parseErr == nil && ok {\n\t\t\t\t\t\t\tyield(event, nil)\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\treturn\n\t\t\t\t}\n\t\t\t}\n\t\t\tfailures++\n\t\t\tbase := time.Second\n\t\t\tif serverRetry >= 0 {\n\t\t\t\tbase = time.Duration(serverRetry) * time.Millisecond\n\t\t\t}\n\t\t\tdelay := base * time.Duration(1<<(failures-1))\n\t\t\tif delay > 30*time.Second {\n\t\t\t\tdelay = 30 * time.Second\n\t\t\t}\n\t\t\ttime.Sleep(time.Duration(rand.Int63n(int64(delay) + 1)))\n\t\t}\n\t}\n}\n\n// ─── Multipart ───\n\n// toMultipart splits a typed body into a multipart/form-data payload: []byte\n// values upload as file parts, everything else as form fields (nested values\n// JSON-encoded) — mirroring the TypeScript runtime\'s FormData serialization.\nfunc toMultipart(body any) (string, io.Reader, error) {\n\tvar wire map[string]any\n\tif err := reencode(body, &wire); err != nil {\n\t\treturn "", nil, err\n\t}\n\tbuffer := &bytes.Buffer{}\n\twriter := multipart.NewWriter(buffer)\n\tfor key, value := range wire {\n\t\tswitch typed := value.(type) {\n\t\tcase string:\n\t\t\tif err := writer.WriteField(key, typed); err != nil {\n\t\t\t\treturn "", nil, err\n\t\t\t}\n\t\tcase float64, bool:\n\t\t\tif err := writer.WriteField(key, fmt.Sprint(typed)); err != nil {\n\t\t\t\treturn "", nil, err\n\t\t\t}\n\t\tdefault:\n\t\t\tencoded, err := json.Marshal(typed)\n\t\t\tif err != nil {\n\t\t\t\treturn "", nil, err\n\t\t\t}\n\t\t\tif err := writer.WriteField(key, string(encoded)); err != nil {\n\t\t\t\treturn "", nil, err\n\t\t\t}\n\t\t}\n\t}\n\tif err := writer.Close(); err != nil {\n\t\treturn "", nil, err\n\t}\n\treturn writer.FormDataContentType(), buffer, nil\n}\n\n// multipartBody prepares the body of an untyped multipart operation: an io.Reader is\n// streamed and a []byte or string sent as is, all under the caller\'s Content-Type (the\n// boundary is theirs to set); any other value goes through toMultipart.\nfunc multipartBody(body any) (string, io.Reader, bool, error) {\n\tif reader, stream, raw := rawBody(body); raw {\n\t\treturn "", reader, stream, nil\n\t}\n\tcontentType, reader, err := toMultipart(body)\n\treturn contentType, reader, false, err\n}\n\n// binaryBody prepares the body of a binary operation: an io.Reader is streamed, a\n// []byte or string sent as is, and any other value JSON-marshalled.\nfunc binaryBody(body any) (io.Reader, bool, error) {\n\tif reader, stream, raw := rawBody(body); raw {\n\t\treturn reader, stream, nil\n\t}\n\tpayload, err := json.Marshal(body)\n\treturn bytes.NewReader(payload), false, err\n}\n\n// rawBody recognizes a body that needs no encoding: an io.Reader streams through in one\n// attempt, a []byte or a string is replayable bytes.\nfunc rawBody(body any) (io.Reader, bool, bool) {\n\tswitch typed := body.(type) {\n\tcase io.Reader:\n\t\treturn typed, true, true\n\tcase []byte:\n\t\treturn bytes.NewReader(typed), false, true\n\tcase string:\n\t\treturn strings.NewReader(typed), false, true\n\t}\n\treturn nil, false, false\n}\n';
|
|
3
3
|
//# sourceMappingURL=go.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"go.js","sourceRoot":"","sources":["../../src/runtime-sources/go.ts"],"names":[],"mappings":"AAAA,iKAAiK;AACjK,MAAM,CAAC,MAAM,iBAAiB,GAC5B,
|
|
1
|
+
{"version":3,"file":"go.js","sourceRoot":"","sources":["../../src/runtime-sources/go.ts"],"names":[],"mappings":"AAAA,iKAAiK;AACjK,MAAM,CAAC,MAAM,iBAAiB,GAC5B,o40BAAo40B,CAAC"}
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
export declare const PHP_RUNTIME_SOURCE = "<?php\n\n// @redocly/client-generator PHP runtime \u2014 embedded into generated clients.\n// PHP >= 8.1, zero Composer dependencies; HTTP over the curl extension.\n// The generated file re-declares the namespace; the embed strips this header.\n\ndeclare(strict_types=1);\n\nnamespace RedoclyClientRuntime;\n\n/** A response with status >= 400, decoded body attached. */\nfinal class ApiError extends \\RuntimeException\n{\n public function __construct(\n public readonly string $url,\n public readonly int $status,\n public readonly string $reason,\n public readonly mixed $body,\n ) {\n parent::__construct(\"HTTP {$status} {$reason} for {$url}\");\n }\n}\n\n/** Every attempt timed out or failed to connect. */\nfinal class TimeoutError extends \\RuntimeException\n{\n public function __construct(\n public readonly string $url,\n public readonly ?float $timeout,\n public readonly int $attempts,\n ) {\n $seconds = $timeout === null ? 'the configured timeout' : \"{$timeout}s\";\n parent::__construct(\"Request to {$url} timed out after {$seconds} ({$attempts} attempt(s))\");\n }\n}\n\n/** One parsed `text/event-stream` frame. */\n/** A `<op>WithHeaders()` result: the decoded body plus coerced declared headers. */\nfinal class Envelope\n{\n public function __construct(\n public readonly mixed $data,\n public readonly array $headers,\n public readonly int $status,\n ) {\n }\n}\n\n/** Coerce declared response headers per `[name, key, type]` specs; absent/unparsable omitted. */\nfunction readEnvelopeHeaders(array $response, array $specs): array\n{\n $headers = [];\n foreach ($specs as [$name, $key, $type]) {\n $raw = $response['headers'][$name] ?? null;\n if ($raw === null) {\n continue;\n }\n if ($type === 'integer' || $type === 'number') {\n if (is_numeric($raw)) {\n $headers[$key] = $type === 'integer' ? (int) $raw : (float) $raw;\n }\n } elseif ($type === 'boolean') {\n $lower = strtolower(trim($raw));\n if ($lower === 'true' || $lower === 'false') {\n $headers[$key] = $lower === 'true';\n }\n } else {\n $headers[$key] = $raw;\n }\n }\n return $headers;\n}\n\nfinal class ServerSentEvent\n{\n public function __construct(\n public readonly string $event,\n public readonly mixed $data,\n public readonly ?string $id = null,\n public readonly ?int $retry = null,\n ) {\n }\n}\n\n/**\n * Per-instance configuration.\n * `auth`: `['bearer' => string|callable, 'basic' => ['username' => ..., 'password' => ...], 'apiKey' => [scheme => string|callable]]`.\n * `retry`: `['attempts' => int, 'delay' => float, 'strategy' => 'exponential'|'fixed', 'retryOn' => callable]`.\n * `middleware`: callables `fn(array $request, callable $next): array` around each attempt.\n */\nfinal class Config\n{\n public function __construct(\n public string $serverUrl = '',\n public array $auth = [],\n public ?float $timeout = null,\n public array $retry = [],\n public array $middleware = [],\n public string $clientHeader = 'redocly-client-generator',\n ) {\n }\n}\n\n/** Resolve a literal-or-callable credential to its string value. */\nfunction resolveToken(mixed $provider): string\n{\n return is_callable($provider) ? (string) $provider() : (string) $provider;\n}\n\n/**\n * Apply the first fully-configured security alternative. `$security` is an OR-list\n * of AND-sets of specs: `['kind' => 'bearer'|'basic'|'apiKey', 'scheme' => ..., 'name' => ?, 'in' => ?]`.\n * Returns `[headers, query, cookies]`.\n */\nfunction resolveAuth(array $security, array $auth): array\n{\n foreach ($security as $andSet) {\n $headers = [];\n $query = [];\n $cookies = [];\n $satisfied = true;\n foreach ($andSet as $spec) {\n if ($spec['kind'] === 'bearer' && isset($auth['bearer'])) {\n $headers['Authorization'] = 'Bearer ' . resolveToken($auth['bearer']);\n } elseif ($spec['kind'] === 'basic' && isset($auth['basic'])) {\n $headers['Authorization'] =\n 'Basic ' . base64_encode($auth['basic']['username'] . ':' . $auth['basic']['password']);\n } elseif ($spec['kind'] === 'apiKey' && isset($auth['apiKey'][$spec['scheme']])) {\n $value = resolveToken($auth['apiKey'][$spec['scheme']]);\n if ($spec['in'] === 'query') {\n $query[$spec['name']] = $value;\n } elseif ($spec['in'] === 'cookie') {\n $cookies[] = $spec['name'] . '=' . rawurlencode($value);\n } else {\n $headers[$spec['name']] = $value;\n }\n } else {\n $satisfied = false;\n break;\n }\n }\n if ($satisfied) {\n return [$headers, $query, $cookies];\n }\n }\n return [[], [], []];\n}\n\n/** Substitute `{param}` templates with encoded values and prefix the server URL. */\nfunction buildUrl(string $serverUrl, string $path, array $pathParams): string\n{\n foreach ($pathParams as $name => $value) {\n $path = str_replace('{' . $name . '}', rawurlencode((string) $value), $path);\n }\n return rtrim($serverUrl, '/') . $path;\n}\n\n/** The default retry predicate: 5xx, 429, and transport timeouts/connect failures. */\nfunction defaultRetryOn(array $context): bool\n{\n if (($context['timedOut'] ?? false) === true) {\n return true;\n }\n $status = $context['status'] ?? 0;\n return $status >= 500 || $status === 429;\n}\n\n/** Delay before the next attempt: `Retry-After` wins; otherwise jittered (fixed|exponential) backoff. */\nfunction retryDelay(int $attempt, array $retry, ?string $retryAfter): float\n{\n if ($retryAfter !== null && ctype_digit($retryAfter)) {\n return (float) $retryAfter;\n }\n $base = (float) ($retry['delay'] ?? 1.0);\n $strategy = $retry['strategy'] ?? 'exponential';\n $delay = $strategy === 'fixed' ? $base : $base * (2 ** ($attempt - 1));\n return $delay * (0.5 + mt_rand() / mt_getrandmax() / 2);\n}\n\n/** Append query params in form style: list values repeat the key (`tag=a&tag=b`). */\nfunction appendQuery(string $url, array $query): string\n{\n $pairs = [];\n foreach ($query as $name => $value) {\n foreach (is_array($value) ? $value : [$value] as $single) {\n $encoded = is_bool($single) ? ($single ? 'true' : 'false') : (string) $single;\n $pairs[] = rawurlencode($name) . '=' . rawurlencode($encoded);\n }\n }\n if ($pairs === []) {\n return $url;\n }\n return $url . (str_contains($url, '?') ? '&' : '?') . implode('&', $pairs);\n}\n\n/** One raw curl exchange. Returns `['status', 'reason', 'headers', 'body', 'url', 'timedOut']`. */\nfunction rawSend(Config $config, array $request): array\n{\n $url = appendQuery($request['url'], $request['query'] ?? []);\n $handle = curl_init($url);\n $headerLines = [];\n foreach ($request['headers'] ?? [] as $name => $value) {\n $headerLines[] = $name . ': ' . $value;\n }\n $responseHeaders = [];\n curl_setopt_array($handle, [\n CURLOPT_CUSTOMREQUEST => $request['method'],\n CURLOPT_RETURNTRANSFER => true,\n CURLOPT_HTTPHEADER => $headerLines,\n CURLOPT_HEADERFUNCTION => function ($ch, string $line) use (&$responseHeaders): int {\n $parts = explode(':', $line, 2);\n if (count($parts) === 2) {\n $responseHeaders[strtolower(trim($parts[0]))] = trim($parts[1]);\n }\n return strlen($line);\n },\n ]);\n $body = $request['body'] ?? null;\n if (is_resource($body)) {\n curl_setopt_array($handle, [CURLOPT_UPLOAD => true, CURLOPT_INFILE => $body]);\n // php://input and wrappers without stream_stat report seekable but fstat() fails (with a\n // warning for the wrappers): those go chunked.\n $stat = @fstat($body);\n if (stream_get_meta_data($body)['seekable'] && $stat !== false) {\n curl_setopt($handle, CURLOPT_INFILESIZE, $stat['size'] - ftell($body));\n }\n } elseif ($body !== null) {\n curl_setopt($handle, CURLOPT_POSTFIELDS, $body);\n }\n if ($config->timeout !== null) {\n curl_setopt($handle, CURLOPT_TIMEOUT_MS, (int) round($config->timeout * 1000));\n }\n $body = curl_exec($handle);\n $errno = curl_errno($handle);\n $status = (int) curl_getinfo($handle, CURLINFO_RESPONSE_CODE);\n $effectiveUrl = (string) curl_getinfo($handle, CURLINFO_EFFECTIVE_URL);\n if ($errno !== 0) {\n $timedOut = $errno === CURLE_OPERATION_TIMEDOUT || $errno === CURLE_COULDNT_CONNECT;\n return [\n 'status' => 0,\n 'reason' => curl_strerror($errno) ?? 'transport error',\n 'headers' => [],\n 'body' => '',\n 'url' => $effectiveUrl,\n 'timedOut' => $timedOut,\n ];\n }\n return [\n 'status' => $status,\n 'reason' => '',\n 'headers' => $responseHeaders,\n 'body' => is_string($body) ? $body : '',\n 'url' => $effectiveUrl,\n 'timedOut' => false,\n ];\n}\n\n/**\n * Send with retries and middleware. `$request` carries `operationId`, `method`, `url`,\n * `headers`, `query`, and optional `body`/`contentType`/`idempotencyKey`.\n * Returns the raw response array; callers map status >= 400 to `ApiError`.\n */\nfunction send(Config $config, array $request): array\n{\n $headers = $request['headers'] ?? [];\n $headers['X-Redocly-Client'] = $config->clientHeader;\n $callerContentType = in_array('content-type', array_map('strtolower', array_keys($headers)), true);\n if (($request['contentType'] ?? null) !== null && !$callerContentType) {\n $headers['Content-Type'] = $request['contentType'];\n }\n if (($request['idempotencyKey'] ?? null) !== null) {\n $headers['Idempotency-Key'] = $request['idempotencyKey'];\n }\n $request['headers'] = $headers;\n\n $handler = fn (array $req): array => rawSend($config, $req);\n foreach (array_reverse($config->middleware) as $middleware) {\n $next = $handler;\n $handler = fn (array $req): array => $middleware($req, $next);\n }\n\n // The first attempt consumes a stream resource, so there is nothing to replay.\n $attempts = is_resource($request['body'] ?? null) ? 1 : max(1, (int) ($config->retry['attempts'] ?? 3));\n $retryOn = $config->retry['retryOn'] ?? __NAMESPACE__ . '\\\\defaultRetryOn';\n $response = null;\n for ($attempt = 1; $attempt <= $attempts; $attempt++) {\n $response = $handler($request);\n $context = [\n 'status' => $response['status'],\n 'timedOut' => $response['timedOut'],\n 'attempt' => $attempt,\n 'operationId' => $request['operationId'] ?? '',\n ];\n if ($attempt === $attempts || !$retryOn($context)) {\n break;\n }\n $seconds = retryDelay($attempt, $config->retry, $response['headers']['retry-after'] ?? null);\n usleep((int) round($seconds * 1_000_000));\n }\n if ($response['timedOut']) {\n throw new TimeoutError($response['url'], $config->timeout, $attempts);\n }\n if ($response['status'] === 0) {\n throw new \\RuntimeException(\"Request to {$response['url']} failed: {$response['reason']}\");\n }\n return $response;\n}\n\n/** Decoded JSON body (assoc arrays), or null for empty bodies. */\nfunction decodeJson(array $response): mixed\n{\n if ($response['body'] === '') {\n return null;\n }\n return json_decode($response['body'], true);\n}\n\n/** `ApiError` from a non-2xx response. */\nfunction apiErrorFrom(array $response): ApiError\n{\n return new ApiError($response['url'], $response['status'], $response['reason'], decodeJson($response));\n}\n\n/** Walk an RFC 6901 JSON pointer over decoded JSON; null on any miss. */\nfunction resolvePointer(mixed $data, string $pointer): mixed\n{\n if ($pointer === '') {\n return $data;\n }\n foreach (explode('/', substr($pointer, 1)) as $token) {\n $key = str_replace(['~1', '~0'], ['/', '~'], $token);\n if (!is_array($data) || !array_key_exists($key, $data)) {\n return null;\n }\n $data = $data[$key];\n }\n return $data;\n}\n\n/** The `rel=\"next\"` target of a `Link` header, or null. */\nfunction linkNext(?string $header): ?string\n{\n if ($header === null) {\n return null;\n }\n foreach (explode(',', $header) as $part) {\n if (preg_match('/<([^>]+)>\\s*;[^,]*rel=\"?next\"?/', trim($part), $match) === 1) {\n return $match[1];\n }\n }\n return null;\n}\n\n/**\n * Auto-pagination: `$call(array $params): [mixed rawPage, array $response]`, `$spec` is the\n * normalized rule (`style`, `param`, `nextCursor`, `hasMore`, `items`), `$base` the caller's\n * query params. Yields raw decoded pages; generated wrappers hydrate them into models.\n */\nfunction iterPages(callable $call, array $spec, array $base): \\Generator\n{\n $params = $base;\n $style = $spec['style'];\n $seenCursors = [];\n $seenLinks = [];\n $offset = null;\n $page = null;\n while (true) {\n [$raw, $response] = $call($params);\n yield $raw;\n if ($style === 'cursor') {\n $next = resolvePointer($raw, $spec['nextCursor'] ?? '');\n if (isset($spec['hasMore']) && resolvePointer($raw, $spec['hasMore']) !== true) {\n return;\n }\n if (!is_string($next) || $next === '' || isset($seenCursors[$next])) {\n return;\n }\n $seenCursors[$next] = true;\n $params[$spec['param']] = $next;\n } elseif ($style === 'link') {\n $target = linkNext($response['headers']['link'] ?? null);\n if ($target === null || isset($seenLinks[$target])) {\n return;\n }\n $seenLinks[$target] = true;\n $parsed = parse_url($target);\n $linkParams = [];\n parse_str($parsed['query'] ?? '', $linkParams);\n $params = array_merge($params, $linkParams);\n } else {\n $items = resolvePointer($raw, $spec['items'] ?? '');\n $count = is_array($items) ? count($items) : 0;\n if ($count === 0) {\n return;\n }\n if ($style === 'offset') {\n $offset = ($offset ?? (int) ($base[$spec['param']] ?? 0)) + $count;\n $params[$spec['param']] = $offset;\n } else {\n $page = ($page ?? (int) ($base[$spec['param']] ?? 1)) + 1;\n $params[$spec['param']] = $page;\n }\n }\n }\n}\n\n/** Parse one SSE frame; returns `[?ServerSentEvent, ?string lastEventId, ?int retryMs]`. */\nfunction parseSseFrame(string $frame, bool $jsonData): array\n{\n $event = 'message';\n $dataLines = [];\n $id = null;\n $retry = null;\n foreach (explode(\"\\n\", str_replace(\"\\r\\n\", \"\\n\", $frame)) as $line) {\n if ($line === '' || str_starts_with($line, ':')) {\n continue;\n }\n $colon = strpos($line, ':');\n $field = $colon === false ? $line : substr($line, 0, $colon);\n $value = $colon === false ? '' : ltrim(substr($line, $colon + 1), ' ');\n if ($field === 'event') {\n $event = $value;\n } elseif ($field === 'data') {\n $dataLines[] = $value;\n } elseif ($field === 'id') {\n $id = $value;\n } elseif ($field === 'retry' && ctype_digit($value)) {\n $retry = (int) $value;\n }\n }\n if ($dataLines === [] && $id === null && $retry === null) {\n return [null, null, $retry];\n }\n $data = implode(\"\\n\", $dataLines);\n $decoded = $jsonData && $data !== '' ? json_decode($data, true) : $data;\n return [new ServerSentEvent($event, $decoded, $id, $retry), $id, $retry];\n}\n\n/**\n * Stream server-sent events. `$open(array $extraHeaders): \\CurlHandle` returns a configured\n * (not yet executed) handle; this pump drives it with curl_multi, yields parsed frames, and\n * reconnects with `Last-Event-ID` on transient failures (4xx is definitive; backoff <= 30s).\n */\nfunction iterSse(callable $open, bool $jsonData): \\Generator\n{\n $lastEventId = null;\n $retryMs = 3000;\n while (true) {\n $extra = ['Accept' => 'text/event-stream'];\n if ($lastEventId !== null) {\n $extra['Last-Event-ID'] = $lastEventId;\n }\n $handle = $open($extra);\n $buffer = '';\n curl_setopt($handle, CURLOPT_WRITEFUNCTION, function ($ch, string $chunk) use (&$buffer): int {\n $buffer .= $chunk;\n return strlen($chunk);\n });\n $multi = curl_multi_init();\n curl_multi_add_handle($multi, $handle);\n do {\n curl_multi_exec($multi, $running);\n if ($running > 0) {\n curl_multi_select($multi, 0.1);\n }\n while (($split = strpos($buffer, \"\\n\\n\")) !== false || ($split = strpos($buffer, \"\\r\\n\\r\\n\")) !== false) {\n $frameLength = $buffer[$split] === \"\\r\" ? 4 : 2;\n $frame = substr($buffer, 0, $split);\n $buffer = substr($buffer, $split + $frameLength);\n [$event, $id, $retry] = parseSseFrame($frame, $jsonData);\n if ($id !== null) {\n $lastEventId = $id;\n }\n if ($retry !== null) {\n $retryMs = min($retry, 30000);\n }\n if ($event !== null) {\n yield $event;\n }\n }\n } while ($running > 0);\n $status = (int) curl_getinfo($handle, CURLINFO_RESPONSE_CODE);\n $url = (string) curl_getinfo($handle, CURLINFO_EFFECTIVE_URL);\n curl_multi_remove_handle($multi, $handle);\n curl_multi_close($multi);\n if ($status >= 400 && $status < 500) {\n throw new ApiError($url, $status, '', $buffer);\n }\n // A clean 200 end-of-stream is done; anything else reconnects with Last-Event-ID.\n if ($status === 200) {\n return;\n }\n usleep($retryMs * 1000);\n }\n}\n\n/** Encode an assoc body as `multipart/form-data`; nested values are JSON parts. Returns `[contentType, body]`. */\nfunction toMultipart(array $body): array\n{\n $boundary = 'redocly-' . bin2hex(random_bytes(12));\n $parts = '';\n foreach ($body as $name => $value) {\n $parts .= \"--{$boundary}\\r\\n\";\n if (is_array($value)) {\n $parts .= \"Content-Disposition: form-data; name=\\\"{$name}\\\"\\r\\n\";\n $parts .= \"Content-Type: application/json\\r\\n\\r\\n\";\n $parts .= json_encode($value) . \"\\r\\n\";\n } else {\n $parts .= \"Content-Disposition: form-data; name=\\\"{$name}\\\"\\r\\n\\r\\n\";\n $parts .= (is_bool($value) ? ($value ? 'true' : 'false') : (string) $value) . \"\\r\\n\";\n }\n }\n $parts .= \"--{$boundary}--\\r\\n\";\n return ['multipart/form-data; boundary=' . $boundary, $parts];\n}\n\n/**\n * The body of an untyped multipart operation: a stream resource or a string passes through\n * under the caller's Content-Type (the boundary is theirs to set); an array is encoded.\n * Returns `[contentType, body]`.\n */\nfunction multipartBody(mixed $body): array\n{\n return is_array($body) ? toMultipart($body) : [null, $body];\n}\n\n/** The body of an octet-stream operation: a stream resource or a string passes through; anything else is JSON. */\nfunction binaryBody(mixed $body): mixed\n{\n return is_resource($body) || is_string($body) ? $body : json_encode($body);\n}\n";
|
|
1
|
+
export declare const PHP_RUNTIME_SOURCE = "<?php\n\n// @redocly/client-generator PHP runtime \u2014 embedded into generated clients.\n// PHP >= 8.1, zero Composer dependencies; HTTP over the curl extension.\n// The generated file re-declares the namespace; the embed strips this header.\n\ndeclare(strict_types=1);\n\nnamespace RedoclyClientRuntime;\n\n/** A response with status >= 400, decoded body attached. */\nfinal class ApiError extends \\RuntimeException\n{\n public function __construct(\n public readonly string $url,\n public readonly int $status,\n public readonly string $reason,\n public readonly mixed $body,\n ) {\n parent::__construct(\"HTTP {$status} {$reason} for {$url}\");\n }\n}\n\n/** Every attempt timed out or failed to connect. */\nfinal class TimeoutError extends \\RuntimeException\n{\n public function __construct(\n public readonly string $url,\n public readonly ?float $timeout,\n public readonly int $attempts,\n ) {\n $seconds = $timeout === null ? 'the configured timeout' : \"{$timeout}s\";\n parent::__construct(\"Request to {$url} timed out after {$seconds} ({$attempts} attempt(s))\");\n }\n}\n\n/** One parsed `text/event-stream` frame. */\n/** A `<op>WithHeaders()` result: the decoded body plus coerced declared headers. */\nfinal class Envelope\n{\n public function __construct(\n public readonly mixed $data,\n public readonly array $headers,\n public readonly int $status,\n ) {\n }\n}\n\n/** Coerce declared response headers per `[name, key, type]` specs; absent/unparsable omitted. */\nfunction readEnvelopeHeaders(array $response, array $specs): array\n{\n $headers = [];\n foreach ($specs as [$name, $key, $type]) {\n $raw = $response['headers'][$name] ?? null;\n if ($raw === null) {\n continue;\n }\n if ($type === 'integer' || $type === 'number') {\n if (is_numeric($raw)) {\n $headers[$key] = $type === 'integer' ? (int) $raw : (float) $raw;\n }\n } elseif ($type === 'boolean') {\n $lower = strtolower(trim($raw));\n if ($lower === 'true' || $lower === 'false') {\n $headers[$key] = $lower === 'true';\n }\n } else {\n $headers[$key] = $raw;\n }\n }\n return $headers;\n}\n\nfinal class ServerSentEvent\n{\n public function __construct(\n public readonly string $event,\n public readonly mixed $data,\n public readonly ?string $id = null,\n public readonly ?int $retry = null,\n ) {\n }\n}\n\n/**\n * Per-instance configuration.\n * `auth`: `['bearer' => string|callable, 'basic' => ['username' => ..., 'password' => ...], 'apiKey' => [scheme => string|callable]]`.\n * `retry`: `['attempts' => int, 'delay' => float, 'strategy' => 'exponential'|'fixed', 'retryOn' => callable]`.\n * `middleware`: callables `fn(array $request, callable $next): array` around each attempt.\n */\nfinal class Config\n{\n public function __construct(\n public string $serverUrl = '',\n public array $auth = [],\n public ?float $timeout = null,\n public array $retry = [],\n public array $middleware = [],\n public string $clientHeader = 'redocly-client-generator',\n ) {\n }\n}\n\n/** Resolve a literal-or-callable credential to its string value. */\nfunction resolveToken(mixed $provider): string\n{\n return is_callable($provider) ? (string) $provider() : (string) $provider;\n}\n\n/**\n * Apply the first fully-configured security alternative. `$security` is an OR-list\n * of AND-sets of specs: `['kind' => 'bearer'|'basic'|'apiKey', 'scheme' => ..., 'name' => ?, 'in' => ?]`.\n * Returns `[headers, query, cookies]`.\n */\nfunction resolveAuth(array $security, array $auth): array\n{\n foreach ($security as $andSet) {\n $headers = [];\n $query = [];\n $cookies = [];\n $satisfied = true;\n foreach ($andSet as $spec) {\n if ($spec['kind'] === 'bearer' && isset($auth['bearer'])) {\n $headers['Authorization'] = 'Bearer ' . resolveToken($auth['bearer']);\n } elseif ($spec['kind'] === 'basic' && isset($auth['basic'])) {\n $headers['Authorization'] =\n 'Basic ' . base64_encode($auth['basic']['username'] . ':' . $auth['basic']['password']);\n } elseif ($spec['kind'] === 'apiKey' && isset($auth['apiKey'][$spec['scheme']])) {\n $value = resolveToken($auth['apiKey'][$spec['scheme']]);\n if ($spec['in'] === 'query') {\n $query[$spec['name']] = $value;\n } elseif ($spec['in'] === 'cookie') {\n $cookies[] = $spec['name'] . '=' . rawurlencode($value);\n } else {\n $headers[$spec['name']] = $value;\n }\n } else {\n $satisfied = false;\n break;\n }\n }\n if ($satisfied) {\n return [$headers, $query, $cookies];\n }\n }\n return [[], [], []];\n}\n\n/** Substitute `{param}` templates with encoded values and prefix the server URL. */\nfunction buildUrl(string $serverUrl, string $path, array $pathParams): string\n{\n foreach ($pathParams as $name => $value) {\n $path = str_replace('{' . $name . '}', rawurlencode((string) $value), $path);\n }\n return rtrim($serverUrl, '/') . $path;\n}\n\n/** The default retry predicate: 5xx, 429, and transport timeouts/connect failures. */\nfunction defaultRetryOn(array $context): bool\n{\n if (($context['timedOut'] ?? false) === true) {\n return true;\n }\n $status = $context['status'] ?? 0;\n return $status >= 500 || $status === 429;\n}\n\n/** Delay before the next attempt: `Retry-After` wins; otherwise jittered (fixed|exponential) backoff. */\nfunction retryDelay(int $attempt, array $retry, ?string $retryAfter): float\n{\n if ($retryAfter !== null && ctype_digit($retryAfter)) {\n return (float) $retryAfter;\n }\n $base = (float) ($retry['delay'] ?? 1.0);\n $strategy = $retry['strategy'] ?? 'exponential';\n $delay = $strategy === 'fixed' ? $base : $base * (2 ** ($attempt - 1));\n return $delay * (0.5 + mt_rand() / mt_getrandmax() / 2);\n}\n\n/** Append query params in form style: list values repeat the key (`tag=a&tag=b`). */\nfunction appendQuery(string $url, array $query): string\n{\n $pairs = [];\n foreach ($query as $name => $value) {\n foreach (is_array($value) ? $value : [$value] as $single) {\n $encoded = is_bool($single) ? ($single ? 'true' : 'false') : (string) $single;\n $pairs[] = rawurlencode($name) . '=' . rawurlencode($encoded);\n }\n }\n if ($pairs === []) {\n return $url;\n }\n return $url . (str_contains($url, '?') ? '&' : '?') . implode('&', $pairs);\n}\n\n/** One raw curl exchange. Returns `['status', 'reason', 'headers', 'body', 'url', 'timedOut']`. */\nfunction rawSend(Config $config, array $request): array\n{\n $url = appendQuery($request['url'], $request['query'] ?? []);\n $handle = curl_init($url);\n $headerLines = [];\n foreach ($request['headers'] ?? [] as $name => $value) {\n $headerLines[] = $name . ': ' . $value;\n }\n $responseHeaders = [];\n curl_setopt_array($handle, [\n CURLOPT_CUSTOMREQUEST => $request['method'],\n CURLOPT_RETURNTRANSFER => true,\n CURLOPT_HTTPHEADER => $headerLines,\n CURLOPT_HEADERFUNCTION => function ($ch, string $line) use (&$responseHeaders): int {\n $parts = explode(':', $line, 2);\n if (count($parts) === 2) {\n $responseHeaders[strtolower(trim($parts[0]))] = trim($parts[1]);\n }\n return strlen($line);\n },\n ]);\n $body = $request['body'] ?? null;\n if (is_resource($body)) {\n curl_setopt_array($handle, [CURLOPT_UPLOAD => true, CURLOPT_INFILE => $body]);\n // php://input and wrappers without stream_stat report seekable but fstat() fails (with a\n // warning for the wrappers): those go chunked.\n $stat = @fstat($body);\n if (stream_get_meta_data($body)['seekable'] && $stat !== false) {\n curl_setopt($handle, CURLOPT_INFILESIZE, $stat['size'] - ftell($body));\n }\n } elseif ($body !== null) {\n curl_setopt($handle, CURLOPT_POSTFIELDS, $body);\n }\n if ($config->timeout !== null) {\n curl_setopt($handle, CURLOPT_TIMEOUT_MS, (int) round($config->timeout * 1000));\n }\n $body = curl_exec($handle);\n $errno = curl_errno($handle);\n $status = (int) curl_getinfo($handle, CURLINFO_RESPONSE_CODE);\n $effectiveUrl = (string) curl_getinfo($handle, CURLINFO_EFFECTIVE_URL);\n if ($errno !== 0) {\n $timedOut = $errno === CURLE_OPERATION_TIMEDOUT || $errno === CURLE_COULDNT_CONNECT;\n return [\n 'status' => 0,\n 'reason' => curl_strerror($errno) ?? 'transport error',\n 'headers' => [],\n 'body' => '',\n 'url' => $effectiveUrl,\n 'timedOut' => $timedOut,\n ];\n }\n return [\n 'status' => $status,\n 'reason' => '',\n 'headers' => $responseHeaders,\n 'body' => is_string($body) ? $body : '',\n 'url' => $effectiveUrl,\n 'timedOut' => false,\n ];\n}\n\n/**\n * Send with retries and middleware. `$request` carries `operationId`, `method`, `url`,\n * `headers`, `query`, and optional `body`/`contentType`/`idempotencyKey`.\n * Returns the raw response array; callers map status >= 400 to `ApiError`.\n */\nfunction send(Config $config, array $request): array\n{\n $headers = $request['headers'] ?? [];\n $headers['X-Redocly-Client'] = $config->clientHeader;\n $callerContentType = in_array('content-type', array_map('strtolower', array_keys($headers)), true);\n if (($request['contentType'] ?? null) !== null && !$callerContentType) {\n $headers['Content-Type'] = $request['contentType'];\n }\n if (($request['idempotencyKey'] ?? null) !== null) {\n $headers['Idempotency-Key'] = $request['idempotencyKey'];\n }\n $request['headers'] = $headers;\n\n $handler = fn (array $req): array => rawSend($config, $req);\n foreach (array_reverse($config->middleware) as $middleware) {\n $next = $handler;\n $handler = fn (array $req): array => $middleware($req, $next);\n }\n\n // The first attempt consumes a stream resource, so there is nothing to replay.\n $attempts = is_resource($request['body'] ?? null) ? 1 : max(1, (int) ($config->retry['attempts'] ?? 3));\n $retryOn = $config->retry['retryOn'] ?? __NAMESPACE__ . '\\\\defaultRetryOn';\n $response = null;\n for ($attempt = 1; $attempt <= $attempts; $attempt++) {\n $response = $handler($request);\n $context = [\n 'status' => $response['status'],\n 'timedOut' => $response['timedOut'],\n 'attempt' => $attempt,\n 'operationId' => $request['operationId'] ?? '',\n ];\n if ($attempt === $attempts || !$retryOn($context)) {\n break;\n }\n $seconds = retryDelay($attempt, $config->retry, $response['headers']['retry-after'] ?? null);\n usleep((int) round($seconds * 1_000_000));\n }\n if ($response['timedOut']) {\n throw new TimeoutError($response['url'], $config->timeout, $attempts);\n }\n if ($response['status'] === 0) {\n throw new \\RuntimeException(\"Request to {$response['url']} failed: {$response['reason']}\");\n }\n return $response;\n}\n\n/** Decoded JSON body (assoc arrays), or null for empty bodies. */\nfunction decodeJson(array $response): mixed\n{\n if ($response['body'] === '') {\n return null;\n }\n return json_decode($response['body'], true);\n}\n\n/** `ApiError` from a non-2xx response. */\nfunction apiErrorFrom(array $response): ApiError\n{\n return new ApiError($response['url'], $response['status'], $response['reason'], decodeJson($response));\n}\n\n/** Walk an RFC 6901 JSON pointer over decoded JSON; null on any miss. */\nfunction resolvePointer(mixed $data, string $pointer): mixed\n{\n if ($pointer === '') {\n return $data;\n }\n foreach (explode('/', substr($pointer, 1)) as $token) {\n $key = str_replace(['~1', '~0'], ['/', '~'], $token);\n if (!is_array($data) || !array_key_exists($key, $data)) {\n return null;\n }\n $data = $data[$key];\n }\n return $data;\n}\n\n/** The `rel=\"next\"` target of a `Link` header, or null. */\nfunction linkNext(?string $header): ?string\n{\n if ($header === null) {\n return null;\n }\n foreach (explode(',', $header) as $part) {\n if (preg_match('/<([^>]+)>\\s*;[^,]*rel=\"?next\"?/', trim($part), $match) === 1) {\n return $match[1];\n }\n }\n return null;\n}\n\n/**\n * Auto-pagination: `$call(array $params): [mixed rawPage, array $response]`, `$spec` is the\n * normalized rule (`style`, `param`, `nextCursor`, `hasMore`, `nextLink`, `items`), `$base`\n * the caller's query params. Yields raw decoded pages; generated wrappers hydrate them into models.\n */\nfunction iterPages(callable $call, array $spec, array $base): \\Generator\n{\n $params = $base;\n $style = $spec['style'];\n $seenCursors = [];\n $seenLinks = [];\n $offset = null;\n $page = null;\n while (true) {\n [$raw, $response] = $call($params);\n yield $raw;\n if ($style === 'cursor') {\n $next = resolvePointer($raw, $spec['nextCursor'] ?? '');\n if (isset($spec['hasMore']) && resolvePointer($raw, $spec['hasMore']) !== true) {\n return;\n }\n if (!is_string($next) || $next === '' || isset($seenCursors[$next])) {\n return;\n }\n $seenCursors[$next] = true;\n $params[$spec['param']] = $next;\n } elseif ($style === 'link' || $style === 'body-link') {\n $target = $style === 'body-link'\n ? resolvePointer($raw, $spec['nextLink'])\n : linkNext($response['headers']['link'] ?? null);\n if (!is_string($target) || $target === '' || isset($seenLinks[$target])) {\n return;\n }\n $seenLinks[$target] = true;\n $parsed = parse_url($target);\n $linkParams = [];\n parse_str($parsed['query'] ?? '', $linkParams);\n $params = array_merge($params, $linkParams);\n } else {\n $items = resolvePointer($raw, $spec['items'] ?? '');\n $count = is_array($items) ? count($items) : 0;\n if ($count === 0) {\n return;\n }\n if ($style === 'offset') {\n $offset = ($offset ?? (int) ($base[$spec['param']] ?? 0)) + $count;\n $params[$spec['param']] = $offset;\n } else {\n $page = ($page ?? (int) ($base[$spec['param']] ?? 1)) + 1;\n $params[$spec['param']] = $page;\n }\n }\n }\n}\n\n/** Parse one SSE frame; returns `[?ServerSentEvent, ?string lastEventId, ?int retryMs]`. */\nfunction parseSseFrame(string $frame, bool $jsonData): array\n{\n $event = 'message';\n $dataLines = [];\n $id = null;\n $retry = null;\n foreach (explode(\"\\n\", str_replace(\"\\r\\n\", \"\\n\", $frame)) as $line) {\n if ($line === '' || str_starts_with($line, ':')) {\n continue;\n }\n $colon = strpos($line, ':');\n $field = $colon === false ? $line : substr($line, 0, $colon);\n $value = $colon === false ? '' : ltrim(substr($line, $colon + 1), ' ');\n if ($field === 'event') {\n $event = $value;\n } elseif ($field === 'data') {\n $dataLines[] = $value;\n } elseif ($field === 'id') {\n $id = $value;\n } elseif ($field === 'retry' && ctype_digit($value)) {\n $retry = (int) $value;\n }\n }\n if ($dataLines === [] && $id === null && $retry === null) {\n return [null, null, $retry];\n }\n $data = implode(\"\\n\", $dataLines);\n $decoded = $jsonData && $data !== '' ? json_decode($data, true) : $data;\n return [new ServerSentEvent($event, $decoded, $id, $retry), $id, $retry];\n}\n\n/**\n * Stream server-sent events. `$open(array $extraHeaders): \\CurlHandle` returns a configured\n * (not yet executed) handle; this pump drives it with curl_multi, yields parsed frames, and\n * reconnects with `Last-Event-ID` on transient failures (4xx is definitive; backoff <= 30s).\n */\nfunction iterSse(callable $open, bool $jsonData): \\Generator\n{\n $lastEventId = null;\n $retryMs = 3000;\n while (true) {\n $extra = ['Accept' => 'text/event-stream'];\n if ($lastEventId !== null) {\n $extra['Last-Event-ID'] = $lastEventId;\n }\n $handle = $open($extra);\n $buffer = '';\n curl_setopt($handle, CURLOPT_WRITEFUNCTION, function ($ch, string $chunk) use (&$buffer): int {\n $buffer .= $chunk;\n return strlen($chunk);\n });\n $multi = curl_multi_init();\n curl_multi_add_handle($multi, $handle);\n do {\n curl_multi_exec($multi, $running);\n if ($running > 0) {\n curl_multi_select($multi, 0.1);\n }\n while (($split = strpos($buffer, \"\\n\\n\")) !== false || ($split = strpos($buffer, \"\\r\\n\\r\\n\")) !== false) {\n $frameLength = $buffer[$split] === \"\\r\" ? 4 : 2;\n $frame = substr($buffer, 0, $split);\n $buffer = substr($buffer, $split + $frameLength);\n [$event, $id, $retry] = parseSseFrame($frame, $jsonData);\n if ($id !== null) {\n $lastEventId = $id;\n }\n if ($retry !== null) {\n $retryMs = min($retry, 30000);\n }\n if ($event !== null) {\n yield $event;\n }\n }\n } while ($running > 0);\n $status = (int) curl_getinfo($handle, CURLINFO_RESPONSE_CODE);\n $url = (string) curl_getinfo($handle, CURLINFO_EFFECTIVE_URL);\n curl_multi_remove_handle($multi, $handle);\n curl_multi_close($multi);\n if ($status >= 400 && $status < 500) {\n throw new ApiError($url, $status, '', $buffer);\n }\n // A clean 200 end-of-stream is done; anything else reconnects with Last-Event-ID.\n if ($status === 200) {\n return;\n }\n usleep($retryMs * 1000);\n }\n}\n\n/** Encode an assoc body as `multipart/form-data`; nested values are JSON parts. Returns `[contentType, body]`. */\nfunction toMultipart(array $body): array\n{\n $boundary = 'redocly-' . bin2hex(random_bytes(12));\n $parts = '';\n foreach ($body as $name => $value) {\n $parts .= \"--{$boundary}\\r\\n\";\n if (is_array($value)) {\n $parts .= \"Content-Disposition: form-data; name=\\\"{$name}\\\"\\r\\n\";\n $parts .= \"Content-Type: application/json\\r\\n\\r\\n\";\n $parts .= json_encode($value) . \"\\r\\n\";\n } else {\n $parts .= \"Content-Disposition: form-data; name=\\\"{$name}\\\"\\r\\n\\r\\n\";\n $parts .= (is_bool($value) ? ($value ? 'true' : 'false') : (string) $value) . \"\\r\\n\";\n }\n }\n $parts .= \"--{$boundary}--\\r\\n\";\n return ['multipart/form-data; boundary=' . $boundary, $parts];\n}\n\n/**\n * The body of an untyped multipart operation: a stream resource or a string passes through\n * under the caller's Content-Type (the boundary is theirs to set); an array is encoded.\n * Returns `[contentType, body]`.\n */\nfunction multipartBody(mixed $body): array\n{\n return is_array($body) ? toMultipart($body) : [null, $body];\n}\n\n/** The body of an octet-stream operation: a stream resource or a string passes through; anything else is JSON. */\nfunction binaryBody(mixed $body): mixed\n{\n return is_resource($body) || is_string($body) ? $body : json_encode($body);\n}\n";
|
|
2
2
|
//# sourceMappingURL=php.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"php.d.ts","sourceRoot":"","sources":["../../src/runtime-sources/php.ts"],"names":[],"mappings":"AACA,eAAO,MAAM,kBAAkB,
|
|
1
|
+
{"version":3,"file":"php.d.ts","sourceRoot":"","sources":["../../src/runtime-sources/php.ts"],"names":[],"mappings":"AACA,eAAO,MAAM,kBAAkB,o9nBAC+6nB,CAAC"}
|