@warlock.js/core 5.27.0 → 5.28.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.
Files changed (58) hide show
  1. package/CHANGELOG.md +11 -0
  2. package/esm/cli/commands/openapi-generator.action.mjs +1 -1
  3. package/esm/cli/commands/openapi-generator.action.mjs.map +1 -1
  4. package/esm/cli/commands/postman-generator.action.mjs +47 -0
  5. package/esm/cli/commands/postman-generator.action.mjs.map +1 -0
  6. package/esm/cli/commands/postman-generator.command.mjs +43 -0
  7. package/esm/cli/commands/postman-generator.command.mjs.map +1 -0
  8. package/esm/cli/framework-cli-commands.mjs +2 -0
  9. package/esm/cli/framework-cli-commands.mjs.map +1 -1
  10. package/esm/http/middleware/inject-request-context.d.mts.map +1 -1
  11. package/esm/http/middleware/inject-request-context.mjs +29 -3
  12. package/esm/http/middleware/inject-request-context.mjs.map +1 -1
  13. package/esm/http/request.d.mts +2 -2
  14. package/esm/http/request.d.mts.map +1 -1
  15. package/esm/index.d.mts +5 -2
  16. package/esm/index.mjs +4 -2
  17. package/esm/openapi/development-openapi-provider.d.mts +12 -1
  18. package/esm/openapi/development-openapi-provider.d.mts.map +1 -1
  19. package/esm/openapi/development-openapi-provider.mjs +15 -1
  20. package/esm/openapi/development-openapi-provider.mjs.map +1 -1
  21. package/esm/openapi/index.d.mts +5 -2
  22. package/esm/openapi/index.mjs +3 -1
  23. package/esm/openapi/postman/build-request-body.mjs +86 -0
  24. package/esm/openapi/postman/build-request-body.mjs.map +1 -0
  25. package/esm/openapi/postman/build-request-url.mjs +85 -0
  26. package/esm/openapi/postman/build-request-url.mjs.map +1 -0
  27. package/esm/openapi/postman/build-saved-responses.mjs +60 -0
  28. package/esm/openapi/postman/build-saved-responses.mjs.map +1 -0
  29. package/esm/openapi/postman/example-from-schema.d.mts +17 -0
  30. package/esm/openapi/postman/example-from-schema.d.mts.map +1 -0
  31. package/esm/openapi/postman/example-from-schema.mjs +92 -0
  32. package/esm/openapi/postman/example-from-schema.mjs.map +1 -0
  33. package/esm/openapi/postman/http-status-text.mjs +31 -0
  34. package/esm/openapi/postman/http-status-text.mjs.map +1 -0
  35. package/esm/openapi/postman/index.d.mts +3 -0
  36. package/esm/openapi/postman/openapi-to-postman-collection.d.mts +22 -0
  37. package/esm/openapi/postman/openapi-to-postman-collection.d.mts.map +1 -0
  38. package/esm/openapi/postman/openapi-to-postman-collection.mjs +109 -0
  39. package/esm/openapi/postman/openapi-to-postman-collection.mjs.map +1 -0
  40. package/esm/openapi/postman/postman-types.d.mts +119 -0
  41. package/esm/openapi/postman/postman-types.d.mts.map +1 -0
  42. package/esm/openapi/postman/resolve-operation-auth.mjs +51 -0
  43. package/esm/openapi/postman/resolve-operation-auth.mjs.map +1 -0
  44. package/esm/openapi/postman/schema-refs.d.mts +7 -0
  45. package/esm/openapi/postman/schema-refs.d.mts.map +1 -0
  46. package/esm/openapi/postman/schema-refs.mjs +41 -0
  47. package/esm/openapi/postman/schema-refs.mjs.map +1 -0
  48. package/esm/openapi/postman/uuid-v5.mjs +29 -0
  49. package/esm/openapi/postman/uuid-v5.mjs.map +1 -0
  50. package/esm/resource/resource.d.mts.map +1 -1
  51. package/esm/resource/resource.mjs +2 -4
  52. package/esm/resource/resource.mjs.map +1 -1
  53. package/esm/restful/restful.d.mts +5 -5
  54. package/esm/restful/restful.d.mts.map +1 -1
  55. package/llms-full.txt +29 -1
  56. package/llms.txt +1 -1
  57. package/package.json +12 -12
  58. package/skills/generate-openapi/SKILL.md +29 -1
@@ -0,0 +1,86 @@
1
+ import { isRecord, primaryType, resolveSchema } from "./schema-refs.mjs";
2
+ import { exampleFromSchema } from "./example-from-schema.mjs";
3
+
4
+ //#region ../core/src/openapi/postman/build-request-body.ts
5
+ const MULTIPART = "multipart/form-data";
6
+ const URL_ENCODED = "application/x-www-form-urlencoded";
7
+ function isJsonContentType(contentType) {
8
+ return contentType === "application/json" || contentType.endsWith("+json");
9
+ }
10
+ function stringifyValue(value) {
11
+ if (typeof value === "string") return value;
12
+ return isRecord(value) || Array.isArray(value) ? JSON.stringify(value) : String(value);
13
+ }
14
+ function isFileSchema(schema, components) {
15
+ const resolved = resolveSchema(schema, components);
16
+ if (resolved.format === "binary" || typeof resolved.contentMediaType === "string") return true;
17
+ return primaryType(resolved) === "array" && isRecord(resolved.items) ? isFileSchema(resolved.items, components) : false;
18
+ }
19
+ function formFields(schema, components) {
20
+ const resolved = resolveSchema(schema, components);
21
+ const properties = isRecord(resolved.properties) ? resolved.properties : {};
22
+ return Object.entries(properties).flatMap(([key, property]) => {
23
+ if (!isRecord(property)) return [];
24
+ const description = typeof property.description === "string" ? { description: property.description } : {};
25
+ if (isFileSchema(property, components)) return [{
26
+ key,
27
+ type: "file",
28
+ src: [],
29
+ ...description
30
+ }];
31
+ return [{
32
+ key,
33
+ value: stringifyValue(exampleFromSchema(property, components)),
34
+ type: "text",
35
+ ...description
36
+ }];
37
+ });
38
+ }
39
+ function pickContentType(contentTypes) {
40
+ return contentTypes.find(isJsonContentType) ?? contentTypes.find((contentType) => contentType === MULTIPART) ?? contentTypes.find((contentType) => contentType === URL_ENCODED) ?? contentTypes[0];
41
+ }
42
+ /**
43
+ * The Postman body of an operation's request body: JSON becomes a raw JSON example, multipart
44
+ * becomes `formdata` (binary properties as file rows), url-encoded becomes `urlencoded`.
45
+ *
46
+ * @returns `undefined` when the operation has no usable body.
47
+ */
48
+ function buildRequestBody(requestBody, components) {
49
+ if (!requestBody) return;
50
+ const contentType = pickContentType(Object.keys(requestBody.content));
51
+ const schema = contentType !== void 0 ? requestBody.content[contentType]?.schema : void 0;
52
+ if (contentType === void 0 || schema === void 0) return;
53
+ if (contentType === MULTIPART) return { body: {
54
+ mode: "formdata",
55
+ formdata: formFields(schema, components)
56
+ } };
57
+ if (contentType === URL_ENCODED) return { body: {
58
+ mode: "urlencoded",
59
+ urlencoded: formFields(schema, components).flatMap((field) => field.type === "text" ? [{
60
+ key: field.key,
61
+ value: field.value,
62
+ type: "text"
63
+ }] : [])
64
+ } };
65
+ const example = exampleFromSchema(schema, components);
66
+ if (isJsonContentType(contentType)) return {
67
+ contentType,
68
+ body: {
69
+ mode: "raw",
70
+ raw: JSON.stringify(example, null, 2),
71
+ options: { raw: { language: "json" } }
72
+ }
73
+ };
74
+ return {
75
+ contentType,
76
+ body: {
77
+ mode: "raw",
78
+ raw: typeof example === "string" ? example : "",
79
+ options: { raw: { language: "text" } }
80
+ }
81
+ };
82
+ }
83
+
84
+ //#endregion
85
+ export { buildRequestBody };
86
+ //# sourceMappingURL=build-request-body.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"build-request-body.mjs","names":[],"sources":["../../../../../../../../core/src/openapi/postman/build-request-body.ts"],"sourcesContent":["import type { OpenApiRequestBody, OpenApiSchema } from \"../types\";\nimport { exampleFromSchema } from \"./example-from-schema\";\nimport type { PostmanBody, PostmanFormParam } from \"./postman-types\";\nimport { isRecord, primaryType, resolveSchema, type SchemaComponents } from \"./schema-refs\";\n\nexport type RequestBodyParts = {\n body: PostmanBody;\n /** Set when the request needs an explicit `Content-Type` header; Postman adds the form ones itself. */\n contentType?: string;\n};\n\nconst MULTIPART = \"multipart/form-data\";\nconst URL_ENCODED = \"application/x-www-form-urlencoded\";\n\nfunction isJsonContentType(contentType: string): boolean {\n return contentType === \"application/json\" || contentType.endsWith(\"+json\");\n}\n\nfunction stringifyValue(value: unknown): string {\n if (typeof value === \"string\") {\n return value;\n }\n\n return isRecord(value) || Array.isArray(value) ? JSON.stringify(value) : String(value);\n}\n\nfunction isFileSchema(schema: OpenApiSchema, components: SchemaComponents): boolean {\n const resolved = resolveSchema(schema, components);\n\n if (resolved.format === \"binary\" || typeof resolved.contentMediaType === \"string\") {\n return true;\n }\n\n return primaryType(resolved) === \"array\" && isRecord(resolved.items)\n ? isFileSchema(resolved.items, components)\n : false;\n}\n\nfunction formFields(schema: OpenApiSchema, components: SchemaComponents): PostmanFormParam[] {\n const resolved = resolveSchema(schema, components);\n const properties = isRecord(resolved.properties) ? resolved.properties : {};\n\n return Object.entries(properties).flatMap(([key, property]): PostmanFormParam[] => {\n if (!isRecord(property)) {\n return [];\n }\n\n const description = typeof property.description === \"string\" ? { description: property.description } : {};\n\n if (isFileSchema(property, components)) {\n return [{ key, type: \"file\", src: [], ...description }];\n }\n\n return [{ key, value: stringifyValue(exampleFromSchema(property, components)), type: \"text\", ...description }];\n });\n}\n\nfunction pickContentType(contentTypes: string[]): string | undefined {\n return (\n contentTypes.find(isJsonContentType) ??\n contentTypes.find((contentType) => contentType === MULTIPART) ??\n contentTypes.find((contentType) => contentType === URL_ENCODED) ??\n contentTypes[0]\n );\n}\n\n/**\n * The Postman body of an operation's request body: JSON becomes a raw JSON example, multipart\n * becomes `formdata` (binary properties as file rows), url-encoded becomes `urlencoded`.\n *\n * @returns `undefined` when the operation has no usable body.\n */\nexport function buildRequestBody(\n requestBody: OpenApiRequestBody | undefined,\n components: SchemaComponents,\n): RequestBodyParts | undefined {\n if (!requestBody) {\n return undefined;\n }\n\n const contentType = pickContentType(Object.keys(requestBody.content));\n const schema = contentType !== undefined ? requestBody.content[contentType]?.schema : undefined;\n\n if (contentType === undefined || schema === undefined) {\n return undefined;\n }\n\n if (contentType === MULTIPART) {\n return { body: { mode: \"formdata\", formdata: formFields(schema, components) } };\n }\n\n if (contentType === URL_ENCODED) {\n const urlencoded = formFields(schema, components).flatMap((field) =>\n field.type === \"text\" ? [{ key: field.key, value: field.value, type: \"text\" as const }] : [],\n );\n\n return { body: { mode: \"urlencoded\", urlencoded } };\n }\n\n const example = exampleFromSchema(schema, components);\n\n if (isJsonContentType(contentType)) {\n return {\n contentType,\n body: {\n mode: \"raw\",\n raw: JSON.stringify(example, null, 2),\n options: { raw: { language: \"json\" } },\n },\n };\n }\n\n return {\n contentType,\n body: {\n mode: \"raw\",\n raw: typeof example === \"string\" ? example : \"\",\n options: { raw: { language: \"text\" } },\n },\n };\n}\n"],"mappings":";;;;AAWA,MAAM,YAAY;AAClB,MAAM,cAAc;AAEpB,SAAS,kBAAkB,aAA8B;CACvD,OAAO,gBAAgB,sBAAsB,YAAY,SAAS,OAAO;AAC3E;AAEA,SAAS,eAAe,OAAwB;CAC9C,IAAI,OAAO,UAAU,UACnB,OAAO;CAGT,OAAO,SAAS,KAAK,KAAK,MAAM,QAAQ,KAAK,IAAI,KAAK,UAAU,KAAK,IAAI,OAAO,KAAK;AACvF;AAEA,SAAS,aAAa,QAAuB,YAAuC;CAClF,MAAM,WAAW,cAAc,QAAQ,UAAU;CAEjD,IAAI,SAAS,WAAW,YAAY,OAAO,SAAS,qBAAqB,UACvE,OAAO;CAGT,OAAO,YAAY,QAAQ,MAAM,WAAW,SAAS,SAAS,KAAK,IAC/D,aAAa,SAAS,OAAO,UAAU,IACvC;AACN;AAEA,SAAS,WAAW,QAAuB,YAAkD;CAC3F,MAAM,WAAW,cAAc,QAAQ,UAAU;CACjD,MAAM,aAAa,SAAS,SAAS,UAAU,IAAI,SAAS,aAAa,CAAC;CAE1E,OAAO,OAAO,QAAQ,UAAU,CAAC,CAAC,SAAS,CAAC,KAAK,cAAkC;EACjF,IAAI,CAAC,SAAS,QAAQ,GACpB,OAAO,CAAC;EAGV,MAAM,cAAc,OAAO,SAAS,gBAAgB,WAAW,EAAE,aAAa,SAAS,YAAY,IAAI,CAAC;EAExG,IAAI,aAAa,UAAU,UAAU,GACnC,OAAO,CAAC;GAAE;GAAK,MAAM;GAAQ,KAAK,CAAC;GAAG,GAAG;EAAY,CAAC;EAGxD,OAAO,CAAC;GAAE;GAAK,OAAO,eAAe,kBAAkB,UAAU,UAAU,CAAC;GAAG,MAAM;GAAQ,GAAG;EAAY,CAAC;CAC/G,CAAC;AACH;AAEA,SAAS,gBAAgB,cAA4C;CACnE,OACE,aAAa,KAAK,iBAAiB,KACnC,aAAa,MAAM,gBAAgB,gBAAgB,SAAS,KAC5D,aAAa,MAAM,gBAAgB,gBAAgB,WAAW,KAC9D,aAAa;AAEjB;;;;;;;AAQA,SAAgB,iBACd,aACA,YAC8B;CAC9B,IAAI,CAAC,aACH;CAGF,MAAM,cAAc,gBAAgB,OAAO,KAAK,YAAY,OAAO,CAAC;CACpE,MAAM,SAAS,gBAAgB,SAAY,YAAY,QAAQ,YAAY,EAAE,SAAS;CAEtF,IAAI,gBAAgB,UAAa,WAAW,QAC1C;CAGF,IAAI,gBAAgB,WAClB,OAAO,EAAE,MAAM;EAAE,MAAM;EAAY,UAAU,WAAW,QAAQ,UAAU;CAAE,EAAE;CAGhF,IAAI,gBAAgB,aAKlB,OAAO,EAAE,MAAM;EAAE,MAAM;EAAc,YAJlB,WAAW,QAAQ,UAAU,CAAC,CAAC,SAAS,UACzD,MAAM,SAAS,SAAS,CAAC;GAAE,KAAK,MAAM;GAAK,OAAO,MAAM;GAAO,MAAM;EAAgB,CAAC,IAAI,CAAC,CAG/C;CAAE,EAAE;CAGpD,MAAM,UAAU,kBAAkB,QAAQ,UAAU;CAEpD,IAAI,kBAAkB,WAAW,GAC/B,OAAO;EACL;EACA,MAAM;GACJ,MAAM;GACN,KAAK,KAAK,UAAU,SAAS,MAAM,CAAC;GACpC,SAAS,EAAE,KAAK,EAAE,UAAU,OAAO,EAAE;EACvC;CACF;CAGF,OAAO;EACL;EACA,MAAM;GACJ,MAAM;GACN,KAAK,OAAO,YAAY,WAAW,UAAU;GAC7C,SAAS,EAAE,KAAK,EAAE,UAAU,OAAO,EAAE;EACvC;CACF;AACF"}
@@ -0,0 +1,85 @@
1
+ import { isRecord, resolveSchema } from "./schema-refs.mjs";
2
+
3
+ //#region ../core/src/openapi/postman/build-request-url.ts
4
+ /** The Postman variable every request URL starts with. */
5
+ const BASE_URL_HOST = "{{baseUrl}}";
6
+ const PATH_TEMPLATE_PARAM = /\{([^}]+)\}/g;
7
+ function stringifyValue(value) {
8
+ if (typeof value === "string") return value;
9
+ return isRecord(value) || Array.isArray(value) ? JSON.stringify(value) : String(value);
10
+ }
11
+ /**
12
+ * Value a parameter starts with in Postman: its declared `example`, `default`, `const` or
13
+ * first `enum` value, otherwise empty so the caller fills it in.
14
+ */
15
+ function parameterValue(schema, components) {
16
+ const resolved = resolveSchema(schema, components);
17
+ for (const key of [
18
+ "example",
19
+ "default",
20
+ "const"
21
+ ]) if (key in resolved) return stringifyValue(resolved[key]);
22
+ if (Array.isArray(resolved.enum) && resolved.enum.length > 0) return stringifyValue(resolved.enum[0]);
23
+ return "";
24
+ }
25
+ function withDescription(row, parameter) {
26
+ return parameter.description ? {
27
+ ...row,
28
+ description: parameter.description
29
+ } : row;
30
+ }
31
+ function queryRows(parameter, components) {
32
+ const disabled = parameter.required === true ? {} : { disabled: true };
33
+ const schema = resolveSchema(parameter.schema, components);
34
+ if (parameter.style === "deepObject" && isRecord(schema.properties)) return Object.entries(schema.properties).map(([property, propertySchema]) => ({
35
+ key: `${parameter.name}[${property}]`,
36
+ value: isRecord(propertySchema) ? parameterValue(propertySchema, components) : "",
37
+ ...disabled
38
+ }));
39
+ return [{
40
+ key: parameter.name,
41
+ value: parameterValue(parameter.schema, components),
42
+ ...parameter.description ? { description: parameter.description } : {},
43
+ ...disabled
44
+ }];
45
+ }
46
+ /**
47
+ * Header rows for the `header` parameters of an operation. Optional ones start disabled.
48
+ */
49
+ function buildHeaderParameters(parameters, components) {
50
+ return parameters.filter((parameter) => parameter.in === "header").map((parameter) => withDescription({
51
+ key: parameter.name,
52
+ value: parameterValue(parameter.schema, components),
53
+ ...parameter.required === true ? {} : { disabled: true }
54
+ }, parameter));
55
+ }
56
+ /**
57
+ * The Postman URL of an operation: `{id}` templates become `:id` path variables, query
58
+ * parameters become rows (optional ones disabled, so `raw` carries only the enabled ones).
59
+ */
60
+ function buildRequestUrl(path, parameters, components) {
61
+ const segments = path.split("/").filter((segment) => segment.length > 0).map((segment) => segment.replace(PATH_TEMPLATE_PARAM, ":$1"));
62
+ const variables = [...path.matchAll(PATH_TEMPLATE_PARAM)].flatMap((match) => {
63
+ const name = match[1];
64
+ if (name === void 0) return [];
65
+ const description = parameters.find((parameter) => parameter.in === "path" && parameter.name === name)?.description;
66
+ return [{
67
+ key: name,
68
+ value: "",
69
+ ...description ? { description } : {}
70
+ }];
71
+ });
72
+ const query = parameters.filter((parameter) => parameter.in === "query").flatMap((parameter) => queryRows(parameter, components));
73
+ const search = query.filter((row) => row.disabled !== true).map((row) => `${row.key}=${row.value}`).join("&");
74
+ return {
75
+ raw: `${BASE_URL_HOST}/${segments.join("/")}${search ? `?${search}` : ""}`,
76
+ host: [BASE_URL_HOST],
77
+ path: segments,
78
+ ...variables.length > 0 ? { variable: variables } : {},
79
+ ...query.length > 0 ? { query } : {}
80
+ };
81
+ }
82
+
83
+ //#endregion
84
+ export { buildHeaderParameters, buildRequestUrl };
85
+ //# sourceMappingURL=build-request-url.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"build-request-url.mjs","names":[],"sources":["../../../../../../../../core/src/openapi/postman/build-request-url.ts"],"sourcesContent":["import type { OpenApiParameter, OpenApiSchema } from \"../types\";\nimport { isRecord, resolveSchema, type SchemaComponents } from \"./schema-refs\";\nimport type { PostmanHeader, PostmanQueryParam, PostmanUrl, PostmanVariable } from \"./postman-types\";\n\n/** The Postman variable every request URL starts with. */\nexport const BASE_URL_HOST = \"{{baseUrl}}\";\n\nconst PATH_TEMPLATE_PARAM = /\\{([^}]+)\\}/g;\n\nfunction stringifyValue(value: unknown): string {\n if (typeof value === \"string\") {\n return value;\n }\n\n return isRecord(value) || Array.isArray(value) ? JSON.stringify(value) : String(value);\n}\n\n/**\n * Value a parameter starts with in Postman: its declared `example`, `default`, `const` or\n * first `enum` value, otherwise empty so the caller fills it in.\n */\nfunction parameterValue(schema: OpenApiSchema, components: SchemaComponents): string {\n const resolved = resolveSchema(schema, components);\n\n for (const key of [\"example\", \"default\", \"const\"]) {\n if (key in resolved) {\n return stringifyValue(resolved[key]);\n }\n }\n\n if (Array.isArray(resolved.enum) && resolved.enum.length > 0) {\n return stringifyValue(resolved.enum[0]);\n }\n\n return \"\";\n}\n\nfunction withDescription<T extends object>(row: T, parameter: OpenApiParameter): T & { description?: string } {\n return parameter.description ? { ...row, description: parameter.description } : row;\n}\n\nfunction queryRows(parameter: OpenApiParameter, components: SchemaComponents): PostmanQueryParam[] {\n const disabled = parameter.required === true ? {} : { disabled: true as const };\n const schema = resolveSchema(parameter.schema, components);\n\n if (parameter.style === \"deepObject\" && isRecord(schema.properties)) {\n return Object.entries(schema.properties).map(([property, propertySchema]) => ({\n key: `${parameter.name}[${property}]`,\n value: isRecord(propertySchema) ? parameterValue(propertySchema, components) : \"\",\n ...disabled,\n }));\n }\n\n return [\n {\n key: parameter.name,\n value: parameterValue(parameter.schema, components),\n ...(parameter.description ? { description: parameter.description } : {}),\n ...disabled,\n },\n ];\n}\n\n/**\n * Header rows for the `header` parameters of an operation. Optional ones start disabled.\n */\nexport function buildHeaderParameters(\n parameters: readonly OpenApiParameter[],\n components: SchemaComponents,\n): PostmanHeader[] {\n return parameters\n .filter((parameter) => parameter.in === \"header\")\n .map((parameter) =>\n withDescription(\n {\n key: parameter.name,\n value: parameterValue(parameter.schema, components),\n ...(parameter.required === true ? {} : { disabled: true as const }),\n },\n parameter,\n ),\n );\n}\n\n/**\n * The Postman URL of an operation: `{id}` templates become `:id` path variables, query\n * parameters become rows (optional ones disabled, so `raw` carries only the enabled ones).\n */\nexport function buildRequestUrl(\n path: string,\n parameters: readonly OpenApiParameter[],\n components: SchemaComponents,\n): PostmanUrl {\n const segments = path\n .split(\"/\")\n .filter((segment) => segment.length > 0)\n .map((segment) => segment.replace(PATH_TEMPLATE_PARAM, \":$1\"));\n\n const variables: PostmanVariable[] = [...path.matchAll(PATH_TEMPLATE_PARAM)].flatMap((match) => {\n const name = match[1];\n\n if (name === undefined) {\n return [];\n }\n\n const description = parameters.find((parameter) => parameter.in === \"path\" && parameter.name === name)\n ?.description;\n\n return [{ key: name, value: \"\", ...(description ? { description } : {}) }];\n });\n\n const query = parameters\n .filter((parameter) => parameter.in === \"query\")\n .flatMap((parameter) => queryRows(parameter, components));\n\n const search = query\n .filter((row) => row.disabled !== true)\n .map((row) => `${row.key}=${row.value}`)\n .join(\"&\");\n\n return {\n raw: `${BASE_URL_HOST}/${segments.join(\"/\")}${search ? `?${search}` : \"\"}`,\n host: [BASE_URL_HOST],\n path: segments,\n ...(variables.length > 0 ? { variable: variables } : {}),\n ...(query.length > 0 ? { query } : {}),\n };\n}\n"],"mappings":"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"}
@@ -0,0 +1,60 @@
1
+ import { exampleFromSchema } from "./example-from-schema.mjs";
2
+ import { httpStatusText } from "./http-status-text.mjs";
3
+
4
+ //#region ../core/src/openapi/postman/build-saved-responses.ts
5
+ function previewLanguage(contentType) {
6
+ if (contentType === "application/json" || contentType.endsWith("+json")) return "json";
7
+ return contentType === "text/html" ? "html" : "text";
8
+ }
9
+ function stringExample(example) {
10
+ return typeof example === "string" ? example : "";
11
+ }
12
+ function responseBody(content, components) {
13
+ const contentTypes = Object.keys(content);
14
+ const contentType = contentTypes.find((type) => previewLanguage(type) === "json") ?? contentTypes[0];
15
+ const schema = contentType !== void 0 ? content[contentType]?.schema : void 0;
16
+ if (contentType === void 0 || schema === void 0) return {
17
+ body: "",
18
+ header: [],
19
+ language: "text"
20
+ };
21
+ const language = previewLanguage(contentType);
22
+ const example = exampleFromSchema(schema, components);
23
+ return {
24
+ body: language === "json" ? JSON.stringify(example, null, 2) : stringExample(example),
25
+ header: [{
26
+ key: "Content-Type",
27
+ value: contentType,
28
+ type: "text"
29
+ }],
30
+ language
31
+ };
32
+ }
33
+ /**
34
+ * One saved Postman response per declared numeric status, with an example body from the
35
+ * response schema. `default` and range keys (`2XX`) have no single status code and are skipped.
36
+ */
37
+ function buildSavedResponses(responses, originalRequest, components) {
38
+ return Object.entries(responses).flatMap(([status, response]) => {
39
+ if (!/^\d{3}$/.test(status)) return [];
40
+ const code = Number(status);
41
+ const { body, header, language } = response.content ? responseBody(response.content, components) : {
42
+ body: "",
43
+ header: [],
44
+ language: "text"
45
+ };
46
+ return [{
47
+ name: `${status} ${response.description}`,
48
+ originalRequest,
49
+ status: httpStatusText(code, response.description),
50
+ code,
51
+ _postman_previewlanguage: language,
52
+ header,
53
+ body
54
+ }];
55
+ });
56
+ }
57
+
58
+ //#endregion
59
+ export { buildSavedResponses };
60
+ //# sourceMappingURL=build-saved-responses.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"build-saved-responses.mjs","names":[],"sources":["../../../../../../../../core/src/openapi/postman/build-saved-responses.ts"],"sourcesContent":["import type { OpenApiOperation } from \"../types\";\nimport { exampleFromSchema } from \"./example-from-schema\";\nimport { httpStatusText } from \"./http-status-text\";\nimport type { PostmanHeader, PostmanOriginalRequest, PostmanResponse } from \"./postman-types\";\nimport type { SchemaComponents } from \"./schema-refs\";\n\ntype PreviewLanguage = PostmanResponse[\"_postman_previewlanguage\"];\n\nfunction previewLanguage(contentType: string): PreviewLanguage {\n if (contentType === \"application/json\" || contentType.endsWith(\"+json\")) {\n return \"json\";\n }\n\n return contentType === \"text/html\" ? \"html\" : \"text\";\n}\n\nfunction stringExample(example: unknown): string {\n return typeof example === \"string\" ? example : \"\";\n}\n\nfunction responseBody(\n content: NonNullable<OpenApiOperation[\"responses\"][string][\"content\"]>,\n components: SchemaComponents,\n): { body: string; header: PostmanHeader[]; language: PreviewLanguage } {\n const contentTypes = Object.keys(content);\n const contentType = contentTypes.find((type) => previewLanguage(type) === \"json\") ?? contentTypes[0];\n const schema = contentType !== undefined ? content[contentType]?.schema : undefined;\n\n if (contentType === undefined || schema === undefined) {\n return { body: \"\", header: [], language: \"text\" };\n }\n\n const language = previewLanguage(contentType);\n const example = exampleFromSchema(schema, components);\n const body = language === \"json\" ? JSON.stringify(example, null, 2) : stringExample(example);\n\n return { body, header: [{ key: \"Content-Type\", value: contentType, type: \"text\" }], language };\n}\n\n/**\n * One saved Postman response per declared numeric status, with an example body from the\n * response schema. `default` and range keys (`2XX`) have no single status code and are skipped.\n */\nexport function buildSavedResponses(\n responses: OpenApiOperation[\"responses\"],\n originalRequest: PostmanOriginalRequest,\n components: SchemaComponents,\n): PostmanResponse[] {\n return Object.entries(responses).flatMap(([status, response]): PostmanResponse[] => {\n if (!/^\\d{3}$/.test(status)) {\n return [];\n }\n\n const code = Number(status);\n const { body, header, language } = response.content\n ? responseBody(response.content, components)\n : { body: \"\", header: [], language: \"text\" as const };\n\n return [\n {\n name: `${status} ${response.description}`,\n originalRequest,\n status: httpStatusText(code, response.description),\n code,\n _postman_previewlanguage: language,\n header,\n body,\n },\n ];\n });\n}\n"],"mappings":";;;;AAQA,SAAS,gBAAgB,aAAsC;CAC7D,IAAI,gBAAgB,sBAAsB,YAAY,SAAS,OAAO,GACpE,OAAO;CAGT,OAAO,gBAAgB,cAAc,SAAS;AAChD;AAEA,SAAS,cAAc,SAA0B;CAC/C,OAAO,OAAO,YAAY,WAAW,UAAU;AACjD;AAEA,SAAS,aACP,SACA,YACsE;CACtE,MAAM,eAAe,OAAO,KAAK,OAAO;CACxC,MAAM,cAAc,aAAa,MAAM,SAAS,gBAAgB,IAAI,MAAM,MAAM,KAAK,aAAa;CAClG,MAAM,SAAS,gBAAgB,SAAY,QAAQ,YAAY,EAAE,SAAS;CAE1E,IAAI,gBAAgB,UAAa,WAAW,QAC1C,OAAO;EAAE,MAAM;EAAI,QAAQ,CAAC;EAAG,UAAU;CAAO;CAGlD,MAAM,WAAW,gBAAgB,WAAW;CAC5C,MAAM,UAAU,kBAAkB,QAAQ,UAAU;CAGpD,OAAO;EAAE,MAFI,aAAa,SAAS,KAAK,UAAU,SAAS,MAAM,CAAC,IAAI,cAAc,OAAO;EAE5E,QAAQ,CAAC;GAAE,KAAK;GAAgB,OAAO;GAAa,MAAM;EAAO,CAAC;EAAG;CAAS;AAC/F;;;;;AAMA,SAAgB,oBACd,WACA,iBACA,YACmB;CACnB,OAAO,OAAO,QAAQ,SAAS,CAAC,CAAC,SAAS,CAAC,QAAQ,cAAiC;EAClF,IAAI,CAAC,UAAU,KAAK,MAAM,GACxB,OAAO,CAAC;EAGV,MAAM,OAAO,OAAO,MAAM;EAC1B,MAAM,EAAE,MAAM,QAAQ,aAAa,SAAS,UACxC,aAAa,SAAS,SAAS,UAAU,IACzC;GAAE,MAAM;GAAI,QAAQ,CAAC;GAAG,UAAU;EAAgB;EAEtD,OAAO,CACL;GACE,MAAM,GAAG,OAAO,GAAG,SAAS;GAC5B;GACA,QAAQ,eAAe,MAAM,SAAS,WAAW;GACjD;GACA,0BAA0B;GAC1B;GACA;EACF,CACF;CACF,CAAC;AACH"}
@@ -0,0 +1,17 @@
1
+ import { OpenApiSchema } from "../types.mjs";
2
+ import { SchemaComponents } from "./schema-refs.mjs";
3
+
4
+ //#region ../core/src/openapi/postman/example-from-schema.d.ts
5
+ /**
6
+ * A deterministic example value for a JSON Schema.
7
+ *
8
+ * Explicit `example`, `const`, `default`, `enum[0]` and `examples[0]` win, in that order;
9
+ * otherwise a type sample is produced (format-aware strings, `0`, `false`, one array item,
10
+ * every object property). `$ref`s resolve against `components`; a cyclic reference is cut
11
+ * (the property is omitted, an array of it is empty). A nullable union yields its non-null
12
+ * branch. A schema with no usable type is `null`.
13
+ */
14
+ declare function exampleFromSchema(schema: OpenApiSchema, components?: SchemaComponents): unknown;
15
+ //#endregion
16
+ export { exampleFromSchema };
17
+ //# sourceMappingURL=example-from-schema.d.mts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"example-from-schema.d.mts","names":[],"sources":["../../../../../../../../core/src/openapi/postman/example-from-schema.ts"],"mappings":";;;;;;AAgJA;;;;;;;iBAAgB,iBAAA,CAAkB,MAAA,EAAQ,aAAA,EAAe,UAAA,GAAa,gBAAgB"}
@@ -0,0 +1,92 @@
1
+ import { isRecord, primaryType, refName, resolveSchema } from "./schema-refs.mjs";
2
+
3
+ //#region ../core/src/openapi/postman/example-from-schema.ts
4
+ const STRING_FORMAT_EXAMPLES = {
5
+ email: "user@example.com",
6
+ "date-time": "2024-01-01T00:00:00.000Z",
7
+ date: "2024-01-01",
8
+ time: "00:00:00",
9
+ uri: "https://example.com",
10
+ url: "https://example.com",
11
+ iri: "https://example.com",
12
+ uuid: "00000000-0000-4000-8000-000000000000",
13
+ hostname: "example.com",
14
+ ipv4: "127.0.0.1",
15
+ ipv6: "::1"
16
+ };
17
+ function numberExample(schema) {
18
+ if (typeof schema.minimum === "number" && schema.minimum > 0) return schema.minimum;
19
+ if (typeof schema.maximum === "number" && schema.maximum < 0) return schema.maximum;
20
+ return 0;
21
+ }
22
+ function stringExample(schema) {
23
+ const format = typeof schema.format === "string" ? schema.format : void 0;
24
+ return (format !== void 0 ? STRING_FORMAT_EXAMPLES[format] : void 0) ?? "string";
25
+ }
26
+ function isNullBranch(branch, components) {
27
+ return isRecord(branch) && primaryType(resolveSchema(branch, components)) === "null";
28
+ }
29
+ function mergeExamples(parts) {
30
+ const objects = parts.filter(isRecord);
31
+ if (objects.length === parts.length) return Object.assign({}, ...objects);
32
+ return parts[parts.length - 1] ?? null;
33
+ }
34
+ /**
35
+ * `undefined` marks a `$ref` cycle: the caller omits the property, or yields an empty array.
36
+ */
37
+ function generate(schema, components, stack) {
38
+ if (!isRecord(schema)) return null;
39
+ const name = refName(schema);
40
+ if (name !== void 0) {
41
+ const target = components?.[name];
42
+ if (stack.includes(name)) return;
43
+ return target ? generate(target, components, [...stack, name]) : null;
44
+ }
45
+ if ("example" in schema) return schema.example;
46
+ if ("const" in schema) return schema.const;
47
+ if ("default" in schema) return schema.default;
48
+ if (Array.isArray(schema.enum) && schema.enum.length > 0) return schema.enum[0];
49
+ if (Array.isArray(schema.examples) && schema.examples.length > 0) return schema.examples[0];
50
+ for (const key of ["oneOf", "anyOf"]) {
51
+ const branches = schema[key];
52
+ if (Array.isArray(branches) && branches.length > 0) return generate(branches.find((candidate) => !isNullBranch(candidate, components)) ?? branches[0], components, stack);
53
+ }
54
+ if (Array.isArray(schema.allOf) && schema.allOf.length > 0) return mergeExamples(schema.allOf.map((part) => generate(part, components, stack)));
55
+ switch (primaryType(schema)) {
56
+ case "string": return stringExample(schema);
57
+ case "number":
58
+ case "integer": return numberExample(schema);
59
+ case "boolean": return false;
60
+ case "array": {
61
+ const item = generate(schema.items, components, stack);
62
+ return item === void 0 ? [] : [item];
63
+ }
64
+ case "object": {
65
+ const result = {};
66
+ const properties = isRecord(schema.properties) ? schema.properties : {};
67
+ for (const [key, property] of Object.entries(properties)) {
68
+ const value = generate(property, components, stack);
69
+ if (value !== void 0) result[key] = value;
70
+ }
71
+ return result;
72
+ }
73
+ default: return null;
74
+ }
75
+ }
76
+ /**
77
+ * A deterministic example value for a JSON Schema.
78
+ *
79
+ * Explicit `example`, `const`, `default`, `enum[0]` and `examples[0]` win, in that order;
80
+ * otherwise a type sample is produced (format-aware strings, `0`, `false`, one array item,
81
+ * every object property). `$ref`s resolve against `components`; a cyclic reference is cut
82
+ * (the property is omitted, an array of it is empty). A nullable union yields its non-null
83
+ * branch. A schema with no usable type is `null`.
84
+ */
85
+ function exampleFromSchema(schema, components) {
86
+ const value = generate(schema, components, []);
87
+ return value === void 0 ? null : value;
88
+ }
89
+
90
+ //#endregion
91
+ export { exampleFromSchema };
92
+ //# sourceMappingURL=example-from-schema.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"example-from-schema.mjs","names":[],"sources":["../../../../../../../../core/src/openapi/postman/example-from-schema.ts"],"sourcesContent":["import type { OpenApiSchema } from \"../types\";\nimport { isRecord, primaryType, refName, resolveSchema, type SchemaComponents } from \"./schema-refs\";\n\nconst STRING_FORMAT_EXAMPLES: Record<string, string> = {\n email: \"user@example.com\",\n \"date-time\": \"2024-01-01T00:00:00.000Z\",\n date: \"2024-01-01\",\n time: \"00:00:00\",\n uri: \"https://example.com\",\n url: \"https://example.com\",\n iri: \"https://example.com\",\n uuid: \"00000000-0000-4000-8000-000000000000\",\n hostname: \"example.com\",\n ipv4: \"127.0.0.1\",\n ipv6: \"::1\",\n};\n\nfunction numberExample(schema: OpenApiSchema): number {\n if (typeof schema.minimum === \"number\" && schema.minimum > 0) {\n return schema.minimum;\n }\n\n if (typeof schema.maximum === \"number\" && schema.maximum < 0) {\n return schema.maximum;\n }\n\n return 0;\n}\n\nfunction stringExample(schema: OpenApiSchema): string {\n const format = typeof schema.format === \"string\" ? schema.format : undefined;\n\n return (format !== undefined ? STRING_FORMAT_EXAMPLES[format] : undefined) ?? \"string\";\n}\n\nfunction isNullBranch(branch: unknown, components: SchemaComponents): boolean {\n return isRecord(branch) && primaryType(resolveSchema(branch, components)) === \"null\";\n}\n\nfunction mergeExamples(parts: unknown[]): unknown {\n const objects = parts.filter(isRecord);\n\n if (objects.length === parts.length) {\n return Object.assign({}, ...objects);\n }\n\n return parts[parts.length - 1] ?? null;\n}\n\n/**\n * `undefined` marks a `$ref` cycle: the caller omits the property, or yields an empty array.\n */\nfunction generate(schema: unknown, components: SchemaComponents, stack: readonly string[]): unknown {\n if (!isRecord(schema)) {\n return null;\n }\n\n const name = refName(schema);\n\n if (name !== undefined) {\n const target = components?.[name];\n\n if (stack.includes(name)) {\n return undefined;\n }\n\n return target ? generate(target, components, [...stack, name]) : null;\n }\n\n if (\"example\" in schema) {\n return schema.example;\n }\n\n if (\"const\" in schema) {\n return schema.const;\n }\n\n if (\"default\" in schema) {\n return schema.default;\n }\n\n if (Array.isArray(schema.enum) && schema.enum.length > 0) {\n return schema.enum[0];\n }\n\n if (Array.isArray(schema.examples) && schema.examples.length > 0) {\n return schema.examples[0];\n }\n\n for (const key of [\"oneOf\", \"anyOf\"] as const) {\n const branches = schema[key];\n\n if (Array.isArray(branches) && branches.length > 0) {\n const branch = branches.find((candidate) => !isNullBranch(candidate, components)) ?? branches[0];\n\n return generate(branch, components, stack);\n }\n }\n\n if (Array.isArray(schema.allOf) && schema.allOf.length > 0) {\n return mergeExamples(schema.allOf.map((part) => generate(part, components, stack)));\n }\n\n switch (primaryType(schema)) {\n case \"string\":\n return stringExample(schema);\n case \"number\":\n case \"integer\":\n return numberExample(schema);\n case \"boolean\":\n return false;\n case \"array\": {\n const item = generate(schema.items, components, stack);\n\n return item === undefined ? [] : [item];\n }\n case \"object\": {\n const result: Record<string, unknown> = {};\n const properties = isRecord(schema.properties) ? schema.properties : {};\n\n for (const [key, property] of Object.entries(properties)) {\n const value = generate(property, components, stack);\n\n if (value !== undefined) {\n result[key] = value;\n }\n }\n\n return result;\n }\n default:\n return null;\n }\n}\n\n/**\n * A deterministic example value for a JSON Schema.\n *\n * Explicit `example`, `const`, `default`, `enum[0]` and `examples[0]` win, in that order;\n * otherwise a type sample is produced (format-aware strings, `0`, `false`, one array item,\n * every object property). `$ref`s resolve against `components`; a cyclic reference is cut\n * (the property is omitted, an array of it is empty). A nullable union yields its non-null\n * branch. A schema with no usable type is `null`.\n */\nexport function exampleFromSchema(schema: OpenApiSchema, components?: SchemaComponents): unknown {\n const value = generate(schema, components, []);\n\n return value === undefined ? null : value;\n}\n"],"mappings":"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"}
@@ -0,0 +1,31 @@
1
+ //#region ../core/src/openapi/postman/http-status-text.ts
2
+ const STATUS_TEXT = {
3
+ 200: "OK",
4
+ 201: "Created",
5
+ 202: "Accepted",
6
+ 204: "No Content",
7
+ 301: "Moved Permanently",
8
+ 302: "Found",
9
+ 304: "Not Modified",
10
+ 400: "Bad Request",
11
+ 401: "Unauthorized",
12
+ 403: "Forbidden",
13
+ 404: "Not Found",
14
+ 405: "Method Not Allowed",
15
+ 409: "Conflict",
16
+ 410: "Gone",
17
+ 422: "Unprocessable Entity",
18
+ 429: "Too Many Requests",
19
+ 500: "Internal Server Error",
20
+ 503: "Service Unavailable"
21
+ };
22
+ /**
23
+ * The HTTP reason phrase of a status code, or `fallback` for one that is not listed.
24
+ */
25
+ function httpStatusText(code, fallback) {
26
+ return STATUS_TEXT[code] ?? fallback;
27
+ }
28
+
29
+ //#endregion
30
+ export { httpStatusText };
31
+ //# sourceMappingURL=http-status-text.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"http-status-text.mjs","names":[],"sources":["../../../../../../../../core/src/openapi/postman/http-status-text.ts"],"sourcesContent":["const STATUS_TEXT: Record<number, string> = {\n 200: \"OK\",\n 201: \"Created\",\n 202: \"Accepted\",\n 204: \"No Content\",\n 301: \"Moved Permanently\",\n 302: \"Found\",\n 304: \"Not Modified\",\n 400: \"Bad Request\",\n 401: \"Unauthorized\",\n 403: \"Forbidden\",\n 404: \"Not Found\",\n 405: \"Method Not Allowed\",\n 409: \"Conflict\",\n 410: \"Gone\",\n 422: \"Unprocessable Entity\",\n 429: \"Too Many Requests\",\n 500: \"Internal Server Error\",\n 503: \"Service Unavailable\",\n};\n\n/**\n * The HTTP reason phrase of a status code, or `fallback` for one that is not listed.\n */\nexport function httpStatusText(code: number, fallback: string): string {\n return STATUS_TEXT[code] ?? fallback;\n}\n"],"mappings":";AAAA,MAAM,cAAsC;CAC1C,KAAK;CACL,KAAK;CACL,KAAK;CACL,KAAK;CACL,KAAK;CACL,KAAK;CACL,KAAK;CACL,KAAK;CACL,KAAK;CACL,KAAK;CACL,KAAK;CACL,KAAK;CACL,KAAK;CACL,KAAK;CACL,KAAK;CACL,KAAK;CACL,KAAK;CACL,KAAK;AACP;;;;AAKA,SAAgB,eAAe,MAAc,UAA0B;CACrE,OAAO,YAAY,SAAS;AAC9B"}
@@ -0,0 +1,3 @@
1
+ import { PostmanAuth, PostmanAuthEntry, PostmanBody, PostmanCollection, PostmanCollectionOptions, PostmanFolder, PostmanFormParam, PostmanHeader, PostmanItem, PostmanOriginalRequest, PostmanQueryParam, PostmanRequest, PostmanRequestItem, PostmanResponse, PostmanUrl, PostmanVariable } from "./postman-types.mjs";
2
+ import { exampleFromSchema } from "./example-from-schema.mjs";
3
+ import { DEFAULT_POSTMAN_BASE_URL, POSTMAN_COLLECTION_SCHEMA, openApiToPostmanCollection } from "./openapi-to-postman-collection.mjs";
@@ -0,0 +1,22 @@
1
+ import { PostmanCollection, PostmanCollectionOptions } from "./postman-types.mjs";
2
+ import { OpenApiDocument } from "../types.mjs";
3
+
4
+ //#region ../core/src/openapi/postman/openapi-to-postman-collection.d.ts
5
+ /** `info.schema` of every collection this converter produces. */
6
+ declare const POSTMAN_COLLECTION_SCHEMA = "https://schema.getpostman.com/json/collection/v2.1.0/collection.json";
7
+ /** `{{baseUrl}}` when neither the options nor the document name a server. */
8
+ declare const DEFAULT_POSTMAN_BASE_URL = "http://localhost:3000";
9
+ /**
10
+ * Convert an OpenAPI document into a Postman Collection v2.1.0 object.
11
+ *
12
+ * Pure and deterministic (the collection id is a UUIDv5 of the title), derived only from the
13
+ * document so the collection can never disagree with the OpenAPI output. Each tag becomes a
14
+ * folder in order of first appearance and untagged operations stay at the root; each
15
+ * operation becomes a request with example bodies generated from its schemas and a saved
16
+ * response per declared status. `{{baseUrl}}` and `{{token}}` are collection variables; a
17
+ * bearer scheme becomes collection-level bearer auth and public operations opt out of it.
18
+ */
19
+ declare function openApiToPostmanCollection(document: OpenApiDocument, options?: PostmanCollectionOptions): PostmanCollection;
20
+ //#endregion
21
+ export { DEFAULT_POSTMAN_BASE_URL, POSTMAN_COLLECTION_SCHEMA, openApiToPostmanCollection };
22
+ //# sourceMappingURL=openapi-to-postman-collection.d.mts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"openapi-to-postman-collection.d.mts","names":[],"sources":["../../../../../../../../core/src/openapi/postman/openapi-to-postman-collection.ts"],"mappings":";;;;;cAgBa,yBAAA;AAAb;AAAA,cAGa,wBAAA;;;AAHyB;AAGtC;;;;AAAqC;AAqDrC;;iBAAgB,0BAAA,CACd,QAAA,EAAU,eAAA,EACV,OAAA,GAAS,wBAAA,GACR,iBAAA"}
@@ -0,0 +1,109 @@
1
+ import { buildRequestBody } from "./build-request-body.mjs";
2
+ import { buildHeaderParameters, buildRequestUrl } from "./build-request-url.mjs";
3
+ import { buildSavedResponses } from "./build-saved-responses.mjs";
4
+ import { collectionBearerAuth, hasBearerScheme, resolveOperationAuth } from "./resolve-operation-auth.mjs";
5
+ import { uuidV5 } from "./uuid-v5.mjs";
6
+
7
+ //#region ../core/src/openapi/postman/openapi-to-postman-collection.ts
8
+ /** `info.schema` of every collection this converter produces. */
9
+ const POSTMAN_COLLECTION_SCHEMA = "https://schema.getpostman.com/json/collection/v2.1.0/collection.json";
10
+ /** `{{baseUrl}}` when neither the options nor the document name a server. */
11
+ const DEFAULT_POSTMAN_BASE_URL = "http://localhost:3000";
12
+ const OPERATION_METHODS = [
13
+ "get",
14
+ "put",
15
+ "post",
16
+ "delete",
17
+ "options",
18
+ "head",
19
+ "patch",
20
+ "trace"
21
+ ];
22
+ function buildRequestItem(path, method, operation, document) {
23
+ const components = document.components?.schemas;
24
+ const parameters = operation.parameters ?? [];
25
+ const body = buildRequestBody(operation.requestBody, components);
26
+ const { auth, note } = resolveOperationAuth(operation, document.components);
27
+ const description = [operation.description, note].filter((line) => Boolean(line)).join("\n\n");
28
+ const header = [...body?.contentType ? [{
29
+ key: "Content-Type",
30
+ value: body.contentType,
31
+ type: "text"
32
+ }] : [], ...buildHeaderParameters(parameters, components)];
33
+ const originalRequest = {
34
+ method: method.toUpperCase(),
35
+ header,
36
+ ...body ? { body: body.body } : {},
37
+ url: buildRequestUrl(path, parameters, components)
38
+ };
39
+ return {
40
+ name: operation.summary ?? operation.operationId,
41
+ request: {
42
+ ...originalRequest,
43
+ ...auth ? { auth } : {},
44
+ ...description ? { description } : {}
45
+ },
46
+ response: buildSavedResponses(operation.responses, originalRequest, components)
47
+ };
48
+ }
49
+ function normalizeBaseUrl(baseUrl) {
50
+ return baseUrl.replace(/\/+$/, "");
51
+ }
52
+ /**
53
+ * Convert an OpenAPI document into a Postman Collection v2.1.0 object.
54
+ *
55
+ * Pure and deterministic (the collection id is a UUIDv5 of the title), derived only from the
56
+ * document so the collection can never disagree with the OpenAPI output. Each tag becomes a
57
+ * folder in order of first appearance and untagged operations stay at the root; each
58
+ * operation becomes a request with example bodies generated from its schemas and a saved
59
+ * response per declared status. `{{baseUrl}}` and `{{token}}` are collection variables; a
60
+ * bearer scheme becomes collection-level bearer auth and public operations opt out of it.
61
+ */
62
+ function openApiToPostmanCollection(document, options = {}) {
63
+ const name = options.title ?? document.info.title;
64
+ const baseUrl = normalizeBaseUrl(options.baseUrl ?? document.servers?.[0]?.url ?? "http://localhost:3000");
65
+ const root = [];
66
+ const folders = /* @__PURE__ */ new Map();
67
+ for (const [path, pathItem] of Object.entries(document.paths)) for (const [method, operation] of Object.entries(pathItem)) {
68
+ if (!OPERATION_METHODS.includes(method)) continue;
69
+ const item = buildRequestItem(path, method, operation, document);
70
+ const tag = operation.tags?.[0];
71
+ if (tag === void 0) {
72
+ root.push(item);
73
+ continue;
74
+ }
75
+ let folder = folders.get(tag);
76
+ if (!folder) {
77
+ folder = {
78
+ name: tag,
79
+ item: []
80
+ };
81
+ folders.set(tag, folder);
82
+ root.push(folder);
83
+ }
84
+ folder.item.push(item);
85
+ }
86
+ return {
87
+ info: {
88
+ _postman_id: uuidV5(name),
89
+ name,
90
+ ...document.info.description ? { description: document.info.description } : {},
91
+ schema: POSTMAN_COLLECTION_SCHEMA
92
+ },
93
+ item: root,
94
+ ...hasBearerScheme(document.components) ? { auth: collectionBearerAuth() } : {},
95
+ variable: [{
96
+ key: "baseUrl",
97
+ value: baseUrl,
98
+ type: "string"
99
+ }, {
100
+ key: "token",
101
+ value: "",
102
+ type: "string"
103
+ }]
104
+ };
105
+ }
106
+
107
+ //#endregion
108
+ export { DEFAULT_POSTMAN_BASE_URL, POSTMAN_COLLECTION_SCHEMA, openApiToPostmanCollection };
109
+ //# sourceMappingURL=openapi-to-postman-collection.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"openapi-to-postman-collection.mjs","names":[],"sources":["../../../../../../../../core/src/openapi/postman/openapi-to-postman-collection.ts"],"sourcesContent":["import type { OpenApiDocument, OpenApiOperation } from \"../types\";\nimport { buildRequestBody } from \"./build-request-body\";\nimport { buildHeaderParameters, buildRequestUrl } from \"./build-request-url\";\nimport { buildSavedResponses } from \"./build-saved-responses\";\nimport type {\n PostmanCollection,\n PostmanCollectionOptions,\n PostmanFolder,\n PostmanHeader,\n PostmanItem,\n PostmanRequestItem,\n} from \"./postman-types\";\nimport { collectionBearerAuth, hasBearerScheme, resolveOperationAuth } from \"./resolve-operation-auth\";\nimport { uuidV5 } from \"./uuid-v5\";\n\n/** `info.schema` of every collection this converter produces. */\nexport const POSTMAN_COLLECTION_SCHEMA = \"https://schema.getpostman.com/json/collection/v2.1.0/collection.json\";\n\n/** `{{baseUrl}}` when neither the options nor the document name a server. */\nexport const DEFAULT_POSTMAN_BASE_URL = \"http://localhost:3000\";\n\nconst OPERATION_METHODS = [\"get\", \"put\", \"post\", \"delete\", \"options\", \"head\", \"patch\", \"trace\"];\n\nfunction buildRequestItem(\n path: string,\n method: string,\n operation: OpenApiOperation,\n document: OpenApiDocument,\n): PostmanRequestItem {\n const components = document.components?.schemas;\n const parameters = operation.parameters ?? [];\n const body = buildRequestBody(operation.requestBody, components);\n const { auth, note } = resolveOperationAuth(operation, document.components);\n const description = [operation.description, note].filter((line): line is string => Boolean(line)).join(\"\\n\\n\");\n\n const header: PostmanHeader[] = [\n ...(body?.contentType ? [{ key: \"Content-Type\", value: body.contentType, type: \"text\" as const }] : []),\n ...buildHeaderParameters(parameters, components),\n ];\n\n const originalRequest = {\n method: method.toUpperCase(),\n header,\n ...(body ? { body: body.body } : {}),\n url: buildRequestUrl(path, parameters, components),\n };\n\n return {\n name: operation.summary ?? operation.operationId,\n request: {\n ...originalRequest,\n ...(auth ? { auth } : {}),\n ...(description ? { description } : {}),\n },\n response: buildSavedResponses(operation.responses, originalRequest, components),\n };\n}\n\nfunction normalizeBaseUrl(baseUrl: string): string {\n return baseUrl.replace(/\\/+$/, \"\");\n}\n\n/**\n * Convert an OpenAPI document into a Postman Collection v2.1.0 object.\n *\n * Pure and deterministic (the collection id is a UUIDv5 of the title), derived only from the\n * document so the collection can never disagree with the OpenAPI output. Each tag becomes a\n * folder in order of first appearance and untagged operations stay at the root; each\n * operation becomes a request with example bodies generated from its schemas and a saved\n * response per declared status. `{{baseUrl}}` and `{{token}}` are collection variables; a\n * bearer scheme becomes collection-level bearer auth and public operations opt out of it.\n */\nexport function openApiToPostmanCollection(\n document: OpenApiDocument,\n options: PostmanCollectionOptions = {},\n): PostmanCollection {\n const name = options.title ?? document.info.title;\n const baseUrl = normalizeBaseUrl(options.baseUrl ?? document.servers?.[0]?.url ?? DEFAULT_POSTMAN_BASE_URL);\n const root: PostmanItem[] = [];\n const folders = new Map<string, PostmanFolder>();\n\n for (const [path, pathItem] of Object.entries(document.paths)) {\n for (const [method, operation] of Object.entries(pathItem)) {\n if (!OPERATION_METHODS.includes(method)) {\n continue;\n }\n\n const item = buildRequestItem(path, method, operation, document);\n const tag = operation.tags?.[0];\n\n if (tag === undefined) {\n root.push(item);\n\n continue;\n }\n\n let folder = folders.get(tag);\n\n if (!folder) {\n folder = { name: tag, item: [] };\n folders.set(tag, folder);\n root.push(folder);\n }\n\n folder.item.push(item);\n }\n }\n\n return {\n info: {\n _postman_id: uuidV5(name),\n name,\n ...(document.info.description ? { description: document.info.description } : {}),\n schema: POSTMAN_COLLECTION_SCHEMA,\n },\n item: root,\n ...(hasBearerScheme(document.components) ? { auth: collectionBearerAuth() } : {}),\n variable: [\n { key: \"baseUrl\", value: baseUrl, type: \"string\" },\n { key: \"token\", value: \"\", type: \"string\" },\n ],\n };\n}\n"],"mappings":";;;;;;;;AAgBA,MAAa,4BAA4B;;AAGzC,MAAa,2BAA2B;AAExC,MAAM,oBAAoB;CAAC;CAAO;CAAO;CAAQ;CAAU;CAAW;CAAQ;CAAS;AAAO;AAE9F,SAAS,iBACP,MACA,QACA,WACA,UACoB;CACpB,MAAM,aAAa,SAAS,YAAY;CACxC,MAAM,aAAa,UAAU,cAAc,CAAC;CAC5C,MAAM,OAAO,iBAAiB,UAAU,aAAa,UAAU;CAC/D,MAAM,EAAE,MAAM,SAAS,qBAAqB,WAAW,SAAS,UAAU;CAC1E,MAAM,cAAc,CAAC,UAAU,aAAa,IAAI,CAAC,CAAC,QAAQ,SAAyB,QAAQ,IAAI,CAAC,CAAC,CAAC,KAAK,MAAM;CAE7G,MAAM,SAA0B,CAC9B,GAAI,MAAM,cAAc,CAAC;EAAE,KAAK;EAAgB,OAAO,KAAK;EAAa,MAAM;CAAgB,CAAC,IAAI,CAAC,GACrG,GAAG,sBAAsB,YAAY,UAAU,CACjD;CAEA,MAAM,kBAAkB;EACtB,QAAQ,OAAO,YAAY;EAC3B;EACA,GAAI,OAAO,EAAE,MAAM,KAAK,KAAK,IAAI,CAAC;EAClC,KAAK,gBAAgB,MAAM,YAAY,UAAU;CACnD;CAEA,OAAO;EACL,MAAM,UAAU,WAAW,UAAU;EACrC,SAAS;GACP,GAAG;GACH,GAAI,OAAO,EAAE,KAAK,IAAI,CAAC;GACvB,GAAI,cAAc,EAAE,YAAY,IAAI,CAAC;EACvC;EACA,UAAU,oBAAoB,UAAU,WAAW,iBAAiB,UAAU;CAChF;AACF;AAEA,SAAS,iBAAiB,SAAyB;CACjD,OAAO,QAAQ,QAAQ,QAAQ,EAAE;AACnC;;;;;;;;;;;AAYA,SAAgB,2BACd,UACA,UAAoC,CAAC,GAClB;CACnB,MAAM,OAAO,QAAQ,SAAS,SAAS,KAAK;CAC5C,MAAM,UAAU,iBAAiB,QAAQ,WAAW,SAAS,UAAU,EAAE,EAAE,8BAA+B;CAC1G,MAAM,OAAsB,CAAC;CAC7B,MAAM,0BAAU,IAAI,IAA2B;CAE/C,KAAK,MAAM,CAAC,MAAM,aAAa,OAAO,QAAQ,SAAS,KAAK,GAC1D,KAAK,MAAM,CAAC,QAAQ,cAAc,OAAO,QAAQ,QAAQ,GAAG;EAC1D,IAAI,CAAC,kBAAkB,SAAS,MAAM,GACpC;EAGF,MAAM,OAAO,iBAAiB,MAAM,QAAQ,WAAW,QAAQ;EAC/D,MAAM,MAAM,UAAU,OAAO;EAE7B,IAAI,QAAQ,QAAW;GACrB,KAAK,KAAK,IAAI;GAEd;EACF;EAEA,IAAI,SAAS,QAAQ,IAAI,GAAG;EAE5B,IAAI,CAAC,QAAQ;GACX,SAAS;IAAE,MAAM;IAAK,MAAM,CAAC;GAAE;GAC/B,QAAQ,IAAI,KAAK,MAAM;GACvB,KAAK,KAAK,MAAM;EAClB;EAEA,OAAO,KAAK,KAAK,IAAI;CACvB;CAGF,OAAO;EACL,MAAM;GACJ,aAAa,OAAO,IAAI;GACxB;GACA,GAAI,SAAS,KAAK,cAAc,EAAE,aAAa,SAAS,KAAK,YAAY,IAAI,CAAC;GAC9E,QAAQ;EACV;EACA,MAAM;EACN,GAAI,gBAAgB,SAAS,UAAU,IAAI,EAAE,MAAM,qBAAqB,EAAE,IAAI,CAAC;EAC/E,UAAU,CACR;GAAE,KAAK;GAAW,OAAO;GAAS,MAAM;EAAS,GACjD;GAAE,KAAK;GAAS,OAAO;GAAI,MAAM;EAAS,CAC5C;CACF;AACF"}