@sdk-it/spec 0.25.0 → 0.26.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 (50) hide show
  1. package/dist/index.d.ts +3 -0
  2. package/dist/index.d.ts.map +1 -1
  3. package/dist/index.js +3 -0
  4. package/dist/index.js.map +2 -2
  5. package/dist/lib/create-operation.d.ts +28 -0
  6. package/dist/lib/create-operation.d.ts.map +1 -0
  7. package/dist/lib/create-operation.js +62 -0
  8. package/dist/lib/create-operation.js.map +7 -0
  9. package/dist/lib/for-each-operation.d.ts.map +1 -1
  10. package/dist/lib/for-each-operation.js +0 -3
  11. package/dist/lib/for-each-operation.js.map +2 -2
  12. package/dist/lib/guess/guess-resource.d.ts +7 -0
  13. package/dist/lib/guess/guess-resource.d.ts.map +1 -0
  14. package/dist/lib/guess/guess-resource.js +76 -0
  15. package/dist/lib/guess/guess-resource.js.map +7 -0
  16. package/dist/lib/metadata.test.js +359 -0
  17. package/dist/lib/metadata.test.js.map +7 -0
  18. package/dist/lib/operation.d.ts +1 -32
  19. package/dist/lib/operation.d.ts.map +1 -1
  20. package/dist/lib/operation.js +32 -312
  21. package/dist/lib/operation.js.map +2 -2
  22. package/dist/lib/options.d.ts +42 -1
  23. package/dist/lib/options.d.ts.map +1 -1
  24. package/dist/lib/options.js +23 -8
  25. package/dist/lib/options.js.map +2 -2
  26. package/dist/lib/pagination/guess-pagination.d.ts +50 -0
  27. package/dist/lib/pagination/guess-pagination.d.ts.map +1 -0
  28. package/dist/lib/pagination/guess-pagination.js +222 -0
  29. package/dist/lib/pagination/guess-pagination.js.map +7 -0
  30. package/dist/lib/pagination/pagination.d.ts +2 -49
  31. package/dist/lib/pagination/pagination.d.ts.map +1 -1
  32. package/dist/lib/pagination/pagination.js +43 -209
  33. package/dist/lib/pagination/pagination.js.map +2 -2
  34. package/dist/lib/pagination/pagination.test.js +2 -1
  35. package/dist/lib/pagination/pagination.test.js.map +2 -2
  36. package/dist/lib/sidebar.d.ts +4 -23
  37. package/dist/lib/sidebar.d.ts.map +1 -1
  38. package/dist/lib/sidebar.js +22 -65
  39. package/dist/lib/sidebar.js.map +3 -3
  40. package/dist/lib/tune-request-body.d.ts +5 -0
  41. package/dist/lib/tune-request-body.d.ts.map +1 -0
  42. package/dist/lib/tune-request-body.js +88 -0
  43. package/dist/lib/tune-request-body.js.map +7 -0
  44. package/dist/lib/tune-response.d.ts +5 -0
  45. package/dist/lib/tune-response.d.ts.map +1 -0
  46. package/dist/lib/tune-response.js +102 -0
  47. package/dist/lib/tune-response.js.map +7 -0
  48. package/dist/lib/types.d.ts +8 -3
  49. package/dist/lib/types.d.ts.map +1 -1
  50. package/package.json +2 -2
@@ -0,0 +1,50 @@
1
+ import type { SchemaObject } from 'openapi3-ts/oas31';
2
+ import type { TunedOperationObject } from '../types.js';
3
+ interface PaginationResultBase {
4
+ type: 'offset' | 'page' | 'cursor' | 'none';
5
+ }
6
+ export interface OffsetPaginationResult extends PaginationResultBase {
7
+ type: 'offset';
8
+ offsetParamName: string;
9
+ offsetKeyword: string;
10
+ limitParamName: string;
11
+ limitKeyword: string;
12
+ }
13
+ export interface PagePaginationResult extends PaginationResultBase {
14
+ type: 'page';
15
+ pageNumberParamName: string;
16
+ pageNumberKeyword: string;
17
+ pageSizeParamName: string;
18
+ pageSizeKeyword: string;
19
+ }
20
+ export interface CursorPaginationResult extends PaginationResultBase {
21
+ type: 'cursor';
22
+ cursorParamName: string;
23
+ cursorKeyword: string;
24
+ limitParamName: string;
25
+ limitKeyword: string;
26
+ }
27
+ export interface NoPaginationResult extends PaginationResultBase {
28
+ type: 'none';
29
+ reason: string;
30
+ }
31
+ export type PaginationGuess = ((OffsetPaginationResult | PagePaginationResult | CursorPaginationResult) & {
32
+ items: string;
33
+ hasMore: string;
34
+ }) | NoPaginationResult;
35
+ export declare const OFFSET_PARAM_REGEXES: RegExp[];
36
+ export declare const GENERIC_LIMIT_PARAM_REGEXES: RegExp[];
37
+ export declare const PAGE_NUMBER_REGEXES: RegExp[];
38
+ export declare const PAGE_SIZE_REGEXES: RegExp[];
39
+ export declare const CURSOR_REGEXES: RegExp[];
40
+ export declare const CURSOR_LIMIT_REGEXES: RegExp[];
41
+ /**
42
+ * Guesses the pagination strategy of an OpenAPI operation based on its query parameters.
43
+ * It checks for offset, page-based, and cursor-based pagination in that order.
44
+ *
45
+ * @param operation The OpenAPI operation object.
46
+ * @returns A PaginationGuess object indicating the detected type and relevant parameters.
47
+ */
48
+ export declare function guessPagination(operation: TunedOperationObject, body?: SchemaObject, response?: SchemaObject): PaginationGuess;
49
+ export {};
50
+ //# sourceMappingURL=guess-pagination.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"guess-pagination.d.ts","sourceRoot":"","sources":["../../../src/lib/pagination/guess-pagination.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAEV,YAAY,EAEb,MAAM,mBAAmB,CAAC;AAK3B,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,aAAa,CAAC;AAGxD,UAAU,oBAAoB;IAC5B,IAAI,EAAE,QAAQ,GAAG,MAAM,GAAG,QAAQ,GAAG,MAAM,CAAC;CAC7C;AAED,MAAM,WAAW,sBAAuB,SAAQ,oBAAoB;IAClE,IAAI,EAAE,QAAQ,CAAC;IACf,eAAe,EAAE,MAAM,CAAC;IACxB,aAAa,EAAE,MAAM,CAAC;IACtB,cAAc,EAAE,MAAM,CAAC;IACvB,YAAY,EAAE,MAAM,CAAC;CACtB;AAED,MAAM,WAAW,oBAAqB,SAAQ,oBAAoB;IAChE,IAAI,EAAE,MAAM,CAAC;IACb,mBAAmB,EAAE,MAAM,CAAC;IAC5B,iBAAiB,EAAE,MAAM,CAAC;IAC1B,iBAAiB,EAAE,MAAM,CAAC;IAC1B,eAAe,EAAE,MAAM,CAAC;CACzB;AAED,MAAM,WAAW,sBAAuB,SAAQ,oBAAoB;IAClE,IAAI,EAAE,QAAQ,CAAC;IACf,eAAe,EAAE,MAAM,CAAC;IACxB,aAAa,EAAE,MAAM,CAAC;IACtB,cAAc,EAAE,MAAM,CAAC;IACvB,YAAY,EAAE,MAAM,CAAC;CACtB;AAED,MAAM,WAAW,kBAAmB,SAAQ,oBAAoB;IAC9D,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,MAAM,CAAC;CAChB;AAED,MAAM,MAAM,eAAe,GACvB,CAAC,CACG,sBAAsB,GACtB,oBAAoB,GACpB,sBAAsB,CACzB,GAAG;IAAE,KAAK,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,MAAM,CAAA;CAAE,CAAC,GACvC,kBAAkB,CAAC;AAIvB,eAAO,MAAM,oBAAoB,EAAE,MAAM,EAKxC,CAAC;AAEF,eAAO,MAAM,2BAA2B,EAAE,MAAM,EAU/C,CAAC;AAEF,eAAO,MAAM,mBAAmB,EAAE,MAAM,EAMvC,CAAC;AAGF,eAAO,MAAM,iBAAiB,EAAE,MAAM,EAUrC,CAAC;AAGF,eAAO,MAAM,cAAc,EAAE,MAAM,EAWlC,CAAC;AAGF,eAAO,MAAM,oBAAoB,EAAE,MAAM,EAUxC,CAAC;AA4IF;;;;;;GAMG;AACH,wBAAgB,eAAe,CAC7B,SAAS,EAAE,oBAAoB,EAC/B,IAAI,CAAC,EAAE,YAAY,EACnB,QAAQ,CAAC,EAAE,YAAY,GACtB,eAAe,CAqCjB"}
@@ -0,0 +1,222 @@
1
+ import { isRef } from "@sdk-it/core/ref.js";
2
+ import { isEmpty } from "@sdk-it/core/utils.js";
3
+ import { getHasMoreName, getItemsName } from "./pagination-result.js";
4
+ const OFFSET_PARAM_REGEXES = [
5
+ /\boffset\b/i,
6
+ /\bskip\b/i,
7
+ /\bstart(?:ing_at|_index)?\b/i,
8
+ // e.g., start, starting_at, start_index
9
+ /\bfrom\b/i
10
+ ];
11
+ const GENERIC_LIMIT_PARAM_REGEXES = [
12
+ /\blimit\b/i,
13
+ /\bcount\b/i,
14
+ /\b(?:page_?)?size\b/i,
15
+ // e.g., size, page_size, pagesize
16
+ /\bmax_results\b/i,
17
+ /\bnum_results\b/i,
18
+ /\bshow\b/i,
19
+ // Can sometimes mean limit
20
+ /\bper_?page\b/i,
21
+ // e.g., per_page, perpage
22
+ /\bper-page\b/i,
23
+ /\btake\b/i
24
+ ];
25
+ const PAGE_NUMBER_REGEXES = [
26
+ // /^(currentPage)?page$/i, // Exact match for "page"
27
+ // /^currentPage$/i, // Exact match for "currentPage"
28
+ /^p$/i,
29
+ // Exact match for "p" (common shorthand)
30
+ // /\bpage_?(?:number|no|num|idx|index)\b/i, // e.g., page_number, pageNumber, page_num, page_idx
31
+ /^(current)?_?page(_?)(?:number|no|num|idx|index)?\b/i
32
+ ];
33
+ const PAGE_SIZE_REGEXES = [
34
+ /\bpage_?size\b/i,
35
+ // e.g., page_size, pagesize
36
+ /^size$/i,
37
+ // Exact "size"
38
+ // /\bsize\b/i, // Broader "size" - can be ambiguous, prefer more specific ones first
39
+ /\blimit\b/i,
40
+ // Limit is often used for page size
41
+ /\bcount\b/i,
42
+ // Count can also be used for page size
43
+ /\bper_?page\b/i,
44
+ // e.g., per_page, perpage
45
+ /\bper-page\b/i,
46
+ /\bnum_?(?:items|records|results)\b/i,
47
+ // e.g., num_items, numitems
48
+ /\bresults_?per_?page\b/i
49
+ ];
50
+ const CURSOR_REGEXES = [
51
+ /\bmarker\b/i,
52
+ /\bcursor\b/i,
53
+ /\bafter(?:_?cursor)?\b/i,
54
+ // e.g., after, after_cursor
55
+ /\bbefore(?:_?cursor)?\b/i,
56
+ // e.g., before, before_cursor
57
+ /\b(next|prev|previous)_?(?:page_?)?token\b/i,
58
+ // e.g., next_page_token, nextPageToken, prev_token
59
+ /\b(next|prev|previous)_?cursor\b/i,
60
+ // e.g., next_cursor, previousCursor
61
+ /\bcontinuation(?:_?token)?\b/i,
62
+ // e.g., continuation, continuation_token
63
+ /\bpage(?:_?(token|id))?\b/i,
64
+ // e.g., after, after_cursor
65
+ /\bstart_?(?:key|cursor|token|after)\b/i
66
+ // e.g., start_key, startCursor, startToken, startAfter
67
+ ];
68
+ const CURSOR_LIMIT_REGEXES = [
69
+ /\blimit\b/i,
70
+ /\bcount\b/i,
71
+ /\bsize\b/i,
72
+ // General size
73
+ /\bfirst\b/i,
74
+ // Common in Relay-style cursor pagination (forward pagination)
75
+ /\blast\b/i,
76
+ // Common in Relay-style cursor pagination (backward pagination)
77
+ /\bpage_?size\b/i,
78
+ // Sometimes page_size is used with cursors
79
+ /\bnum_?(?:items|records|results)\b/i,
80
+ // e.g., num_items
81
+ /\bmax_?items\b/i,
82
+ /\btake\b/i
83
+ ];
84
+ function findParamAndKeyword(queryParams, regexes, excludeParamName) {
85
+ for (const param of queryParams) {
86
+ if (param.name === excludeParamName) {
87
+ continue;
88
+ }
89
+ for (const regex of regexes) {
90
+ const match = param.name.match(regex);
91
+ if (match) {
92
+ return { param, keyword: match[0] };
93
+ }
94
+ }
95
+ }
96
+ return null;
97
+ }
98
+ function coearceParameters(parameters) {
99
+ const cleanedParameters = [];
100
+ for (const param of parameters) {
101
+ if (!param.schema) {
102
+ continue;
103
+ }
104
+ if (isRef(param.schema)) {
105
+ continue;
106
+ }
107
+ if (!param.schema.type) {
108
+ continue;
109
+ }
110
+ if (param.schema) {
111
+ cleanedParameters.push({
112
+ ...param,
113
+ schema: {
114
+ ...param.schema,
115
+ type: Array.isArray(param.schema.type) ? param.schema.type : [param.schema.type]
116
+ }
117
+ });
118
+ }
119
+ }
120
+ return cleanedParameters;
121
+ }
122
+ function isOffsetPagination(operation, parameters) {
123
+ const params = coearceParameters(parameters).filter(
124
+ (it) => it.schema.type.includes("integer") || it.schema.type.includes("number")
125
+ );
126
+ const offsetMatch = findParamAndKeyword(params, OFFSET_PARAM_REGEXES);
127
+ if (!offsetMatch) return null;
128
+ const limitMatch = findParamAndKeyword(
129
+ params,
130
+ GENERIC_LIMIT_PARAM_REGEXES,
131
+ offsetMatch.param.name
132
+ );
133
+ if (!limitMatch) return null;
134
+ return {
135
+ type: "offset",
136
+ offsetParamName: offsetMatch.param.name,
137
+ offsetKeyword: offsetMatch.keyword,
138
+ limitParamName: limitMatch.param.name,
139
+ limitKeyword: limitMatch.keyword
140
+ };
141
+ }
142
+ function isPagePagination(operation, parameters) {
143
+ const params = coearceParameters(parameters).filter(
144
+ (it) => it.schema.type.includes("integer") || it.schema.type.includes("number")
145
+ );
146
+ if (params.length < 2) return null;
147
+ const pageNoMatch = findParamAndKeyword(params, PAGE_NUMBER_REGEXES);
148
+ if (!pageNoMatch) return null;
149
+ const pageSizeMatch = findParamAndKeyword(
150
+ params,
151
+ PAGE_SIZE_REGEXES,
152
+ pageNoMatch.param.name
153
+ );
154
+ if (!pageSizeMatch) return null;
155
+ return {
156
+ type: "page",
157
+ pageNumberParamName: pageNoMatch.param.name,
158
+ pageNumberKeyword: pageNoMatch.keyword,
159
+ pageSizeParamName: pageSizeMatch.param.name,
160
+ pageSizeKeyword: pageSizeMatch.keyword
161
+ };
162
+ }
163
+ function isCursorPagination(operation, parameters = []) {
164
+ const queryParams = parameters;
165
+ if (queryParams.length < 2) return null;
166
+ const cursorMatch = findParamAndKeyword(queryParams, CURSOR_REGEXES);
167
+ if (!cursorMatch) return null;
168
+ const limitMatch = findParamAndKeyword(
169
+ queryParams,
170
+ CURSOR_LIMIT_REGEXES,
171
+ cursorMatch.param.name
172
+ );
173
+ if (!limitMatch) return null;
174
+ return {
175
+ type: "cursor",
176
+ cursorParamName: cursorMatch.param.name,
177
+ cursorKeyword: cursorMatch.keyword,
178
+ limitParamName: limitMatch.param.name,
179
+ limitKeyword: limitMatch.keyword
180
+ };
181
+ }
182
+ function guessPagination(operation, body, response) {
183
+ const bodyParameters = body && body.properties ? Object.entries(body.properties).map(([it, schema]) => ({
184
+ name: it,
185
+ schema
186
+ })) : [];
187
+ const parameters = operation.parameters;
188
+ if (isEmpty(operation.parameters) && isEmpty(bodyParameters)) {
189
+ return { type: "none", reason: "no parameters" };
190
+ }
191
+ if (!response) {
192
+ return { type: "none", reason: "no response" };
193
+ }
194
+ if (!response.properties) {
195
+ return { type: "none", reason: "empty response" };
196
+ }
197
+ const properties = response.properties;
198
+ const itemsKey = getItemsName(properties);
199
+ if (!itemsKey) {
200
+ return { type: "none", reason: "no items key" };
201
+ }
202
+ const hasMoreKey = getHasMoreName(excludeKey(properties, itemsKey));
203
+ if (!hasMoreKey) {
204
+ return { type: "none", reason: "no hasMore key" };
205
+ }
206
+ const pagination = isOffsetPagination(operation, [...parameters, ...bodyParameters]) || isPagePagination(operation, [...parameters, ...bodyParameters]) || isCursorPagination(operation, [...parameters, ...bodyParameters]);
207
+ return pagination ? { ...pagination, items: itemsKey, hasMore: hasMoreKey } : { type: "none", reason: "no pagination" };
208
+ }
209
+ function excludeKey(obj, key) {
210
+ const { [key]: _, ...rest } = obj;
211
+ return rest;
212
+ }
213
+ export {
214
+ CURSOR_LIMIT_REGEXES,
215
+ CURSOR_REGEXES,
216
+ GENERIC_LIMIT_PARAM_REGEXES,
217
+ OFFSET_PARAM_REGEXES,
218
+ PAGE_NUMBER_REGEXES,
219
+ PAGE_SIZE_REGEXES,
220
+ guessPagination
221
+ };
222
+ //# sourceMappingURL=guess-pagination.js.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../../src/lib/pagination/guess-pagination.ts"],
4
+ "sourcesContent": ["import type {\n ReferenceObject,\n SchemaObject,\n SchemasObject,\n} from 'openapi3-ts/oas31';\n\nimport { isRef } from '@sdk-it/core/ref.js';\nimport { isEmpty } from '@sdk-it/core/utils.js';\n\nimport type { TunedOperationObject } from '../types.js';\nimport { getHasMoreName, getItemsName } from './pagination-result.js';\n\ninterface PaginationResultBase {\n type: 'offset' | 'page' | 'cursor' | 'none';\n}\n\nexport interface OffsetPaginationResult extends PaginationResultBase {\n type: 'offset';\n offsetParamName: string;\n offsetKeyword: string; // The actual part of param name that matched\n limitParamName: string;\n limitKeyword: string; // The actual part of param name that matched\n}\n\nexport interface PagePaginationResult extends PaginationResultBase {\n type: 'page';\n pageNumberParamName: string;\n pageNumberKeyword: string;\n pageSizeParamName: string;\n pageSizeKeyword: string;\n}\n\nexport interface CursorPaginationResult extends PaginationResultBase {\n type: 'cursor';\n cursorParamName: string;\n cursorKeyword: string;\n limitParamName: string;\n limitKeyword: string;\n}\n\nexport interface NoPaginationResult extends PaginationResultBase {\n type: 'none';\n reason: string;\n}\n\nexport type PaginationGuess =\n | ((\n | OffsetPaginationResult\n | PagePaginationResult\n | CursorPaginationResult\n ) & { items: string; hasMore: string })\n | NoPaginationResult;\n\n// --- Keyword Regex Definitions ---\n\nexport const OFFSET_PARAM_REGEXES: RegExp[] = [\n /\\boffset\\b/i,\n /\\bskip\\b/i,\n /\\bstart(?:ing_at|_index)?\\b/i, // e.g., start, starting_at, start_index\n /\\bfrom\\b/i,\n];\n\nexport const GENERIC_LIMIT_PARAM_REGEXES: RegExp[] = [\n /\\blimit\\b/i,\n /\\bcount\\b/i,\n /\\b(?:page_?)?size\\b/i, // e.g., size, page_size, pagesize\n /\\bmax_results\\b/i,\n /\\bnum_results\\b/i,\n /\\bshow\\b/i, // Can sometimes mean limit\n /\\bper_?page\\b/i, // e.g., per_page, perpage\n /\\bper-page\\b/i,\n /\\btake\\b/i,\n];\n\nexport const PAGE_NUMBER_REGEXES: RegExp[] = [\n // /^(currentPage)?page$/i, // Exact match for \"page\"\n // /^currentPage$/i, // Exact match for \"currentPage\"\n /^p$/i, // Exact match for \"p\" (common shorthand)\n // /\\bpage_?(?:number|no|num|idx|index)\\b/i, // e.g., page_number, pageNumber, page_num, page_idx\n /^(current)?_?page(_?)(?:number|no|num|idx|index)?\\b/i,\n];\n\n// Regexes for parameters indicating page size (when used with page number)\nexport const PAGE_SIZE_REGEXES: RegExp[] = [\n /\\bpage_?size\\b/i, // e.g., page_size, pagesize\n /^size$/i, // Exact \"size\"\n // /\\bsize\\b/i, // Broader \"size\" - can be ambiguous, prefer more specific ones first\n /\\blimit\\b/i, // Limit is often used for page size\n /\\bcount\\b/i, // Count can also be used for page size\n /\\bper_?page\\b/i, // e.g., per_page, perpage\n /\\bper-page\\b/i,\n /\\bnum_?(?:items|records|results)\\b/i, // e.g., num_items, numitems\n /\\bresults_?per_?page\\b/i,\n];\n\n// Regexes for parameters indicating a cursor\nexport const CURSOR_REGEXES: RegExp[] = [\n /\\bmarker\\b/i,\n /\\bcursor\\b/i,\n /\\bafter(?:_?cursor)?\\b/i, // e.g., after, after_cursor\n /\\bbefore(?:_?cursor)?\\b/i, // e.g., before, before_cursor\n /\\b(next|prev|previous)_?(?:page_?)?token\\b/i, // e.g., next_page_token, nextPageToken, prev_token\n /\\b(next|prev|previous)_?cursor\\b/i, // e.g., next_cursor, previousCursor\n /\\bcontinuation(?:_?token)?\\b/i, // e.g., continuation, continuation_token\n /\\bpage(?:_?(token|id))?\\b/i, // e.g., after, after_cursor\n\n /\\bstart_?(?:key|cursor|token|after)\\b/i, // e.g., start_key, startCursor, startToken, startAfter\n];\n\n// Regexes for parameters indicating a limit when used with cursors\nexport const CURSOR_LIMIT_REGEXES: RegExp[] = [\n /\\blimit\\b/i,\n /\\bcount\\b/i,\n /\\bsize\\b/i, // General size\n /\\bfirst\\b/i, // Common in Relay-style cursor pagination (forward pagination)\n /\\blast\\b/i, // Common in Relay-style cursor pagination (backward pagination)\n /\\bpage_?size\\b/i, // Sometimes page_size is used with cursors\n /\\bnum_?(?:items|records|results)\\b/i, // e.g., num_items\n /\\bmax_?items\\b/i,\n /\\btake\\b/i,\n];\n\n// --- Helper Function ---\nfunction findParamAndKeyword(\n queryParams: { name: string }[],\n regexes: RegExp[],\n excludeParamName?: string,\n) {\n for (const param of queryParams) {\n if (param.name === excludeParamName) {\n continue;\n }\n for (const regex of regexes) {\n const match = param.name.match(regex);\n if (match) {\n return { param, keyword: match[0] }; // match[0] is the actual matched substring\n }\n }\n }\n return null;\n}\n\nfunction coearceParameters(\n parameters: { name: string; schema?: SchemaObject | ReferenceObject }[],\n) {\n const cleanedParameters: {\n name: string;\n schema: Omit<SchemaObject, 'type'> & {\n type: string[]; // Ensure type is always an array\n };\n }[] = [];\n for (const param of parameters) {\n if (!param.schema) {\n continue;\n }\n if (isRef(param.schema)) {\n continue;\n }\n if (!param.schema.type) {\n continue;\n }\n if (param.schema) {\n cleanedParameters.push({\n ...param,\n schema: {\n ...param.schema,\n type: Array.isArray(param.schema.type)\n ? param.schema.type\n : [param.schema.type],\n },\n });\n }\n }\n return cleanedParameters;\n}\n\nfunction isOffsetPagination(\n operation: TunedOperationObject,\n parameters: { name: string; schema?: SchemaObject | ReferenceObject }[],\n): OffsetPaginationResult | null {\n const params = coearceParameters(parameters).filter(\n (it) =>\n it.schema.type.includes('integer') || it.schema.type.includes('number'),\n );\n const offsetMatch = findParamAndKeyword(params, OFFSET_PARAM_REGEXES);\n\n if (!offsetMatch) return null;\n\n const limitMatch = findParamAndKeyword(\n params,\n GENERIC_LIMIT_PARAM_REGEXES,\n offsetMatch.param.name,\n );\n if (!limitMatch) return null;\n\n return {\n type: 'offset',\n offsetParamName: offsetMatch.param.name,\n offsetKeyword: offsetMatch.keyword,\n limitParamName: limitMatch.param.name,\n limitKeyword: limitMatch.keyword,\n };\n}\n\nfunction isPagePagination(\n operation: TunedOperationObject,\n parameters: { name: string; schema?: SchemaObject | ReferenceObject }[],\n): PagePaginationResult | null {\n const params = coearceParameters(parameters).filter(\n (it) =>\n it.schema.type.includes('integer') || it.schema.type.includes('number'),\n );\n\n if (params.length < 2) return null;\n\n const pageNoMatch = findParamAndKeyword(params, PAGE_NUMBER_REGEXES);\n if (!pageNoMatch) return null;\n\n const pageSizeMatch = findParamAndKeyword(\n params,\n PAGE_SIZE_REGEXES,\n pageNoMatch.param.name,\n );\n if (!pageSizeMatch) return null;\n\n return {\n type: 'page',\n pageNumberParamName: pageNoMatch.param.name,\n pageNumberKeyword: pageNoMatch.keyword,\n pageSizeParamName: pageSizeMatch.param.name,\n pageSizeKeyword: pageSizeMatch.keyword,\n };\n}\n\nfunction isCursorPagination(\n operation: TunedOperationObject,\n parameters: { name: string; schema?: SchemaObject | ReferenceObject }[] = [],\n): CursorPaginationResult | null {\n const queryParams = parameters;\n if (queryParams.length < 2) return null; // Need at least a cursor and a limit-like param\n\n const cursorMatch = findParamAndKeyword(queryParams, CURSOR_REGEXES);\n if (!cursorMatch) return null;\n\n const limitMatch = findParamAndKeyword(\n queryParams,\n CURSOR_LIMIT_REGEXES,\n cursorMatch.param.name,\n );\n if (!limitMatch) return null;\n\n return {\n type: 'cursor',\n cursorParamName: cursorMatch.param.name,\n cursorKeyword: cursorMatch.keyword,\n limitParamName: limitMatch.param.name,\n limitKeyword: limitMatch.keyword,\n };\n}\n\n/**\n * Guesses the pagination strategy of an OpenAPI operation based on its query parameters.\n * It checks for offset, page-based, and cursor-based pagination in that order.\n *\n * @param operation The OpenAPI operation object.\n * @returns A PaginationGuess object indicating the detected type and relevant parameters.\n */\nexport function guessPagination(\n operation: TunedOperationObject,\n body?: SchemaObject,\n response?: SchemaObject,\n): PaginationGuess {\n const bodyParameters =\n body && body.properties\n ? Object.entries(body.properties).map(([it, schema]) => ({\n name: it,\n schema,\n }))\n : [];\n const parameters = operation.parameters;\n\n if (isEmpty(operation.parameters) && isEmpty(bodyParameters)) {\n return { type: 'none', reason: 'no parameters' };\n }\n if (!response) {\n return { type: 'none', reason: 'no response' };\n }\n if (!response.properties) {\n return { type: 'none', reason: 'empty response' };\n }\n const properties = response.properties as SchemasObject;\n\n const itemsKey = getItemsName(properties);\n if (!itemsKey) {\n return { type: 'none', reason: 'no items key' };\n }\n const hasMoreKey = getHasMoreName(excludeKey(properties, itemsKey));\n\n if (!hasMoreKey) {\n return { type: 'none', reason: 'no hasMore key' };\n }\n const pagination =\n isOffsetPagination(operation, [...parameters, ...bodyParameters]) ||\n isPagePagination(operation, [...parameters, ...bodyParameters]) ||\n isCursorPagination(operation, [...parameters, ...bodyParameters]);\n return pagination\n ? { ...pagination, items: itemsKey, hasMore: hasMoreKey }\n : { type: 'none', reason: 'no pagination' };\n}\n\nfunction excludeKey<T extends Record<string, any>>(\n obj: T,\n key: string,\n): Omit<T, typeof key> {\n const { [key]: _, ...rest } = obj;\n return rest;\n}\n"],
5
+ "mappings": "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",
6
+ "names": []
7
+ }
@@ -1,50 +1,3 @@
1
- import type { SchemaObject } from 'openapi3-ts/oas31';
2
- import type { TunedOperationObject } from '../types.js';
3
- interface PaginationResultBase {
4
- type: 'offset' | 'page' | 'cursor' | 'none';
5
- }
6
- export interface OffsetPaginationResult extends PaginationResultBase {
7
- type: 'offset';
8
- offsetParamName: string;
9
- offsetKeyword: string;
10
- limitParamName: string;
11
- limitKeyword: string;
12
- }
13
- export interface PagePaginationResult extends PaginationResultBase {
14
- type: 'page';
15
- pageNumberParamName: string;
16
- pageNumberKeyword: string;
17
- pageSizeParamName: string;
18
- pageSizeKeyword: string;
19
- }
20
- export interface CursorPaginationResult extends PaginationResultBase {
21
- type: 'cursor';
22
- cursorParamName: string;
23
- cursorKeyword: string;
24
- limitParamName: string;
25
- limitKeyword: string;
26
- }
27
- export interface NoPaginationResult extends PaginationResultBase {
28
- type: 'none';
29
- reason: string;
30
- }
31
- export type PaginationGuess = ((OffsetPaginationResult | PagePaginationResult | CursorPaginationResult) & {
32
- items: string;
33
- hasMore: string;
34
- }) | NoPaginationResult;
35
- export declare const OFFSET_PARAM_REGEXES: RegExp[];
36
- export declare const GENERIC_LIMIT_PARAM_REGEXES: RegExp[];
37
- export declare const PAGE_NUMBER_REGEXES: RegExp[];
38
- export declare const PAGE_SIZE_REGEXES: RegExp[];
39
- export declare const CURSOR_REGEXES: RegExp[];
40
- export declare const CURSOR_LIMIT_REGEXES: RegExp[];
41
- /**
42
- * Guesses the pagination strategy of an OpenAPI operation based on its query parameters.
43
- * It checks for offset, page-based, and cursor-based pagination in that order.
44
- *
45
- * @param operation The OpenAPI operation object.
46
- * @returns A PaginationGuess object indicating the detected type and relevant parameters.
47
- */
48
- export declare function guessPagination(operation: TunedOperationObject, body?: SchemaObject, response?: SchemaObject): PaginationGuess;
49
- export {};
1
+ import type { OurOpenAPIObject, TunedOperationObject } from '../types.js';
2
+ export declare function toPagination(spec: OurOpenAPIObject, tunedOperation: TunedOperationObject): any;
50
3
  //# sourceMappingURL=pagination.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"pagination.d.ts","sourceRoot":"","sources":["../../../src/lib/pagination/pagination.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAEV,YAAY,EAEb,MAAM,mBAAmB,CAAC;AAK3B,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,aAAa,CAAC;AAGxD,UAAU,oBAAoB;IAC5B,IAAI,EAAE,QAAQ,GAAG,MAAM,GAAG,QAAQ,GAAG,MAAM,CAAC;CAC7C;AAED,MAAM,WAAW,sBAAuB,SAAQ,oBAAoB;IAClE,IAAI,EAAE,QAAQ,CAAC;IACf,eAAe,EAAE,MAAM,CAAC;IACxB,aAAa,EAAE,MAAM,CAAC;IACtB,cAAc,EAAE,MAAM,CAAC;IACvB,YAAY,EAAE,MAAM,CAAC;CACtB;AAED,MAAM,WAAW,oBAAqB,SAAQ,oBAAoB;IAChE,IAAI,EAAE,MAAM,CAAC;IACb,mBAAmB,EAAE,MAAM,CAAC;IAC5B,iBAAiB,EAAE,MAAM,CAAC;IAC1B,iBAAiB,EAAE,MAAM,CAAC;IAC1B,eAAe,EAAE,MAAM,CAAC;CACzB;AAED,MAAM,WAAW,sBAAuB,SAAQ,oBAAoB;IAClE,IAAI,EAAE,QAAQ,CAAC;IACf,eAAe,EAAE,MAAM,CAAC;IACxB,aAAa,EAAE,MAAM,CAAC;IACtB,cAAc,EAAE,MAAM,CAAC;IACvB,YAAY,EAAE,MAAM,CAAC;CACtB;AAED,MAAM,WAAW,kBAAmB,SAAQ,oBAAoB;IAC9D,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,MAAM,CAAC;CAChB;AAED,MAAM,MAAM,eAAe,GACvB,CAAC,CACG,sBAAsB,GACtB,oBAAoB,GACpB,sBAAsB,CACzB,GAAG;IAAE,KAAK,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,MAAM,CAAA;CAAE,CAAC,GACvC,kBAAkB,CAAC;AAIvB,eAAO,MAAM,oBAAoB,EAAE,MAAM,EAKxC,CAAC;AAEF,eAAO,MAAM,2BAA2B,EAAE,MAAM,EAU/C,CAAC;AAEF,eAAO,MAAM,mBAAmB,EAAE,MAAM,EAMvC,CAAC;AAGF,eAAO,MAAM,iBAAiB,EAAE,MAAM,EAUrC,CAAC;AAGF,eAAO,MAAM,cAAc,EAAE,MAAM,EAWlC,CAAC;AAGF,eAAO,MAAM,oBAAoB,EAAE,MAAM,EAUxC,CAAC;AA4IF;;;;;;GAMG;AACH,wBAAgB,eAAe,CAC7B,SAAS,EAAE,oBAAoB,EAC/B,IAAI,CAAC,EAAE,YAAY,EACnB,QAAQ,CAAC,EAAE,YAAY,GACtB,eAAe,CAqCjB"}
1
+ {"version":3,"file":"pagination.d.ts","sourceRoot":"","sources":["../../../src/lib/pagination/pagination.ts"],"names":[],"mappings":"AAQA,OAAO,KAAK,EAAE,gBAAgB,EAAE,oBAAoB,EAAE,MAAM,aAAa,CAAC;AAG1E,wBAAgB,YAAY,CAC1B,IAAI,EAAE,gBAAgB,EACtB,cAAc,EAAE,oBAAoB,OAyBrC"}
@@ -1,222 +1,56 @@
1
- import { isRef } from "@sdk-it/core/ref.js";
2
- import { isEmpty } from "@sdk-it/core/utils.js";
3
- import { getHasMoreName, getItemsName } from "./pagination-result.js";
4
- const OFFSET_PARAM_REGEXES = [
5
- /\boffset\b/i,
6
- /\bskip\b/i,
7
- /\bstart(?:ing_at|_index)?\b/i,
8
- // e.g., start, starting_at, start_index
9
- /\bfrom\b/i
10
- ];
11
- const GENERIC_LIMIT_PARAM_REGEXES = [
12
- /\blimit\b/i,
13
- /\bcount\b/i,
14
- /\b(?:page_?)?size\b/i,
15
- // e.g., size, page_size, pagesize
16
- /\bmax_results\b/i,
17
- /\bnum_results\b/i,
18
- /\bshow\b/i,
19
- // Can sometimes mean limit
20
- /\bper_?page\b/i,
21
- // e.g., per_page, perpage
22
- /\bper-page\b/i,
23
- /\btake\b/i
24
- ];
25
- const PAGE_NUMBER_REGEXES = [
26
- // /^(currentPage)?page$/i, // Exact match for "page"
27
- // /^currentPage$/i, // Exact match for "currentPage"
28
- /^p$/i,
29
- // Exact match for "p" (common shorthand)
30
- // /\bpage_?(?:number|no|num|idx|index)\b/i, // e.g., page_number, pageNumber, page_num, page_idx
31
- /^(current)?_?page(_?)(?:number|no|num|idx|index)?\b/i
32
- ];
33
- const PAGE_SIZE_REGEXES = [
34
- /\bpage_?size\b/i,
35
- // e.g., page_size, pagesize
36
- /^size$/i,
37
- // Exact "size"
38
- // /\bsize\b/i, // Broader "size" - can be ambiguous, prefer more specific ones first
39
- /\blimit\b/i,
40
- // Limit is often used for page size
41
- /\bcount\b/i,
42
- // Count can also be used for page size
43
- /\bper_?page\b/i,
44
- // e.g., per_page, perpage
45
- /\bper-page\b/i,
46
- /\bnum_?(?:items|records|results)\b/i,
47
- // e.g., num_items, numitems
48
- /\bresults_?per_?page\b/i
49
- ];
50
- const CURSOR_REGEXES = [
51
- /\bmarker\b/i,
52
- /\bcursor\b/i,
53
- /\bafter(?:_?cursor)?\b/i,
54
- // e.g., after, after_cursor
55
- /\bbefore(?:_?cursor)?\b/i,
56
- // e.g., before, before_cursor
57
- /\b(next|prev|previous)_?(?:page_?)?token\b/i,
58
- // e.g., next_page_token, nextPageToken, prev_token
59
- /\b(next|prev|previous)_?cursor\b/i,
60
- // e.g., next_cursor, previousCursor
61
- /\bcontinuation(?:_?token)?\b/i,
62
- // e.g., continuation, continuation_token
63
- /\bpage(?:_?(token|id))?\b/i,
64
- // e.g., after, after_cursor
65
- /\bstart_?(?:key|cursor|token|after)\b/i
66
- // e.g., start_key, startCursor, startToken, startAfter
67
- ];
68
- const CURSOR_LIMIT_REGEXES = [
69
- /\blimit\b/i,
70
- /\bcount\b/i,
71
- /\bsize\b/i,
72
- // General size
73
- /\bfirst\b/i,
74
- // Common in Relay-style cursor pagination (forward pagination)
75
- /\blast\b/i,
76
- // Common in Relay-style cursor pagination (backward pagination)
77
- /\bpage_?size\b/i,
78
- // Sometimes page_size is used with cursors
79
- /\bnum_?(?:items|records|results)\b/i,
80
- // e.g., num_items
81
- /\bmax_?items\b/i,
82
- /\btake\b/i
83
- ];
84
- function findParamAndKeyword(queryParams, regexes, excludeParamName) {
85
- for (const param of queryParams) {
86
- if (param.name === excludeParamName) {
87
- continue;
88
- }
89
- for (const regex of regexes) {
90
- const match = param.name.match(regex);
91
- if (match) {
92
- return { param, keyword: match[0] };
93
- }
94
- }
95
- }
96
- return null;
97
- }
98
- function coearceParameters(parameters) {
99
- const cleanedParameters = [];
100
- for (const param of parameters) {
101
- if (!param.schema) {
102
- continue;
103
- }
104
- if (isRef(param.schema)) {
105
- continue;
106
- }
107
- if (!param.schema.type) {
108
- continue;
109
- }
110
- if (param.schema) {
111
- cleanedParameters.push({
112
- ...param,
113
- schema: {
114
- ...param.schema,
115
- type: Array.isArray(param.schema.type) ? param.schema.type : [param.schema.type]
116
- }
117
- });
118
- }
1
+ import { followRef, isRef } from "@sdk-it/core/ref.js";
2
+ import { guessPagination } from "./guess-pagination.js";
3
+ function toPagination(spec, tunedOperation) {
4
+ if (tunedOperation["x-pagination"]) {
5
+ return tunedOperation["x-pagination"];
119
6
  }
120
- return cleanedParameters;
121
- }
122
- function isOffsetPagination(operation, parameters) {
123
- const params = coearceParameters(parameters).filter(
124
- (it) => it.schema.type.includes("integer") || it.schema.type.includes("number")
125
- );
126
- const offsetMatch = findParamAndKeyword(params, OFFSET_PARAM_REGEXES);
127
- if (!offsetMatch) return null;
128
- const limitMatch = findParamAndKeyword(
129
- params,
130
- GENERIC_LIMIT_PARAM_REGEXES,
131
- offsetMatch.param.name
132
- );
133
- if (!limitMatch) return null;
134
- return {
135
- type: "offset",
136
- offsetParamName: offsetMatch.param.name,
137
- offsetKeyword: offsetMatch.keyword,
138
- limitParamName: limitMatch.param.name,
139
- limitKeyword: limitMatch.keyword
140
- };
141
- }
142
- function isPagePagination(operation, parameters) {
143
- const params = coearceParameters(parameters).filter(
144
- (it) => it.schema.type.includes("integer") || it.schema.type.includes("number")
7
+ const schema = getResponseContentSchema(
8
+ spec,
9
+ tunedOperation.responses["200"],
10
+ "application/json"
145
11
  );
146
- if (params.length < 2) return null;
147
- const pageNoMatch = findParamAndKeyword(params, PAGE_NUMBER_REGEXES);
148
- if (!pageNoMatch) return null;
149
- const pageSizeMatch = findParamAndKeyword(
150
- params,
151
- PAGE_SIZE_REGEXES,
152
- pageNoMatch.param.name
153
- );
154
- if (!pageSizeMatch) return null;
155
- return {
156
- type: "page",
157
- pageNumberParamName: pageNoMatch.param.name,
158
- pageNumberKeyword: pageNoMatch.keyword,
159
- pageSizeParamName: pageSizeMatch.param.name,
160
- pageSizeKeyword: pageSizeMatch.keyword
161
- };
162
- }
163
- function isCursorPagination(operation, parameters = []) {
164
- const queryParams = parameters;
165
- if (queryParams.length < 2) return null;
166
- const cursorMatch = findParamAndKeyword(queryParams, CURSOR_REGEXES);
167
- if (!cursorMatch) return null;
168
- const limitMatch = findParamAndKeyword(
169
- queryParams,
170
- CURSOR_LIMIT_REGEXES,
171
- cursorMatch.param.name
172
- );
173
- if (!limitMatch) return null;
174
- return {
175
- type: "cursor",
176
- cursorParamName: cursorMatch.param.name,
177
- cursorKeyword: cursorMatch.keyword,
178
- limitParamName: limitMatch.param.name,
179
- limitKeyword: limitMatch.keyword
180
- };
181
- }
182
- function guessPagination(operation, body, response) {
183
- const bodyParameters = body && body.properties ? Object.entries(body.properties).map(([it, schema]) => ({
184
- name: it,
12
+ const pagination = guessPagination(
13
+ tunedOperation,
14
+ tunedOperation.requestBody ? getRequestContentSchema(
15
+ spec,
16
+ tunedOperation.requestBody,
17
+ "application/json"
18
+ ) : void 0,
185
19
  schema
186
- })) : [];
187
- const parameters = operation.parameters;
188
- if (isEmpty(operation.parameters) && isEmpty(bodyParameters)) {
189
- return { type: "none", reason: "no parameters" };
20
+ );
21
+ if (pagination && pagination.type !== "none" && schema) {
22
+ return pagination;
190
23
  }
24
+ return void 0;
25
+ }
26
+ function getResponseContentSchema(spec, response, type) {
191
27
  if (!response) {
192
- return { type: "none", reason: "no response" };
28
+ return void 0;
193
29
  }
194
- if (!response.properties) {
195
- return { type: "none", reason: "empty response" };
30
+ const content = response.content;
31
+ if (!content) {
32
+ return void 0;
196
33
  }
197
- const properties = response.properties;
198
- const itemsKey = getItemsName(properties);
199
- if (!itemsKey) {
200
- return { type: "none", reason: "no items key" };
201
- }
202
- const hasMoreKey = getHasMoreName(excludeKey(properties, itemsKey));
203
- if (!hasMoreKey) {
204
- return { type: "none", reason: "no hasMore key" };
34
+ for (const contentType in content) {
35
+ if (contentType.toLowerCase() === type.toLowerCase()) {
36
+ return isRef(content[contentType].schema) ? followRef(spec, content[contentType].schema.$ref) : content[contentType].schema;
37
+ }
205
38
  }
206
- const pagination = isOffsetPagination(operation, [...parameters, ...bodyParameters]) || isPagePagination(operation, [...parameters, ...bodyParameters]) || isCursorPagination(operation, [...parameters, ...bodyParameters]);
207
- return pagination ? { ...pagination, items: itemsKey, hasMore: hasMoreKey } : { type: "none", reason: "no pagination" };
39
+ return void 0;
208
40
  }
209
- function excludeKey(obj, key) {
210
- const { [key]: _, ...rest } = obj;
211
- return rest;
41
+ function getRequestContentSchema(spec, requestBody, type) {
42
+ const content = requestBody.content;
43
+ if (!content) {
44
+ return void 0;
45
+ }
46
+ for (const contentType in content) {
47
+ if (contentType.toLowerCase() === type.toLowerCase()) {
48
+ return isRef(content[contentType].schema) ? followRef(spec, content[contentType].schema.$ref) : content[contentType].schema;
49
+ }
50
+ }
51
+ return void 0;
212
52
  }
213
53
  export {
214
- CURSOR_LIMIT_REGEXES,
215
- CURSOR_REGEXES,
216
- GENERIC_LIMIT_PARAM_REGEXES,
217
- OFFSET_PARAM_REGEXES,
218
- PAGE_NUMBER_REGEXES,
219
- PAGE_SIZE_REGEXES,
220
- guessPagination
54
+ toPagination
221
55
  };
222
56
  //# sourceMappingURL=pagination.js.map