@sdk-it/spec 0.31.0 → 0.31.2

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.
@@ -1,7 +0,0 @@
1
- {
2
- "version": 3,
3
- "sources": ["../../src/lib/find-polymorphic-varients.test.ts"],
4
- "sourcesContent": ["import { merge } from 'lodash-es';\nimport assert from 'node:assert';\nimport { describe, it } from 'node:test';\nimport type { OpenAPIObject, SchemaObject } from 'openapi3-ts/oas31';\n\nimport {\n type Varient,\n findPolymorphicVarients,\n findVarients,\n} from './find-polymorphic-varients.ts';\nimport { toIR } from './ir.ts';\nimport type { IR } from './types.ts';\n\nfunction createSpec(openapi?: Partial<OpenAPIObject>): IR {\n return toIR(\n {\n spec: merge(\n {\n openapi: '3.1.0',\n info: {\n title: 'Test API',\n version: '1.0.0',\n },\n components: {\n schemas: {},\n securitySchemes: {},\n },\n paths: {},\n },\n openapi,\n ),\n },\n true,\n );\n}\ndescribe('findVarients', () => {\n describe('strings', () => {\n it('names string type as text', () => {\n const spec = createSpec();\n const result = findVarients(spec, [{ type: 'string' }]);\n\n assert.deepStrictEqual(result, [\n {\n name: 'text',\n position: 0,\n type: 'string',\n },\n ] satisfies Varient[]);\n });\n it('names string based on format', () => {\n const spec = createSpec();\n const result = findVarients(spec, [\n {\n type: 'string',\n format: 'date-time',\n },\n { type: 'string' },\n ]);\n\n assert.deepStrictEqual(result, [\n {\n name: 'dateTime',\n position: 0,\n priority: 90,\n type: 'string',\n },\n {\n name: 'text',\n position: 1,\n type: 'string',\n },\n ] satisfies Varient[]);\n });\n\n it('names string based on const value', () => {\n const spec = createSpec();\n const result = findVarients(spec, [\n { type: 'string', const: 'active' },\n { type: 'string', const: '' },\n ]);\n\n assert.deepStrictEqual(result, [\n {\n name: 'active',\n position: 0,\n priority: 100,\n type: 'string',\n },\n {\n name: 'empty',\n position: 1,\n priority: 99,\n type: 'string',\n },\n ] satisfies Varient[]);\n });\n\n it.skip('names string based on enum values', () => {\n const spec = createSpec();\n const result = findVarients(spec, [\n { type: 'string', enum: ['pending', 'completed', ''] },\n ]);\n\n assert.deepStrictEqual(result, [\n {\n name: 'pending',\n position: 0,\n priority: 80,\n type: 'string',\n },\n {\n name: 'completed',\n position: 0,\n priority: 79,\n type: 'string',\n },\n {\n name: 'empty',\n position: 0,\n priority: 78,\n type: 'string',\n },\n ] satisfies Varient[]);\n });\n\n it.skip('prioritizes const first', () => {\n const spec = createSpec();\n const result = findVarients(spec, [\n { type: 'string', format: 'email' },\n { type: 'string', const: 'fixed' },\n { type: 'string', enum: ['option1', 'option2'] },\n { type: 'string' },\n ]);\n\n assert.deepStrictEqual(result, [\n {\n name: 'fixed',\n position: 1,\n priority: 99,\n type: 'string',\n },\n {\n name: 'email',\n position: 0,\n priority: 90,\n type: 'string',\n },\n {\n name: 'option1',\n position: 2,\n priority: 78,\n type: 'string',\n },\n {\n name: 'option2',\n position: 2,\n priority: 77,\n type: 'string',\n },\n {\n name: 'text',\n position: 3,\n type: 'string',\n },\n ] satisfies Varient[]);\n });\n\n it('handles format priority over enum', () => {\n const spec = createSpec();\n const result = findVarients(spec, [\n { type: 'string', format: 'email', enum: ['user@example.com'] },\n ]);\n\n assert.deepStrictEqual(result, [\n {\n name: 'email',\n position: 0,\n priority: 90,\n type: 'string',\n },\n ] satisfies Varient[]);\n });\n\n it('handles const priority over enum', () => {\n const spec = createSpec();\n const result = findVarients(spec, [\n { type: 'string', const: 'fixed', enum: ['option1', 'option2'] },\n ]);\n\n assert.deepStrictEqual(result, [\n {\n name: 'fixed',\n position: 0,\n priority: 100,\n type: 'string',\n },\n ] satisfies Varient[]);\n });\n\n it('handles complex format names with camelCase conversion', () => {\n const spec = createSpec();\n const result = findVarients(spec, [\n { type: 'string', format: 'date-time' },\n { type: 'string', format: 'iso-8601' },\n { type: 'string', format: 'binary' },\n ]);\n\n assert.deepStrictEqual(result, [\n {\n name: 'dateTime',\n position: 0,\n priority: 90,\n type: 'string',\n },\n {\n name: 'iso8601',\n position: 1,\n priority: 89,\n type: 'string',\n },\n {\n name: 'binary',\n position: 2,\n priority: 88,\n type: 'string',\n },\n ] satisfies Varient[]);\n });\n });\n\n describe('numbers', () => {\n it('names number type as number', () => {\n const spec = createSpec();\n const result = findVarients(spec, [{ type: 'number' }]);\n\n assert.deepStrictEqual(result, [\n {\n name: 'number',\n position: 0,\n type: 'number',\n },\n ] satisfies Varient[]);\n });\n\n it('names integer type as integer', () => {\n const spec = createSpec();\n const result = findVarients(spec, [{ type: 'integer' }]);\n\n assert.deepStrictEqual(result, [\n {\n name: 'number',\n position: 0,\n type: 'number',\n },\n ] satisfies Varient[]);\n });\n\n it('names number based on format', () => {\n const spec = createSpec();\n const result = findVarients(spec, [\n {\n type: 'number',\n format: 'float',\n },\n {\n type: 'number',\n format: 'double',\n },\n {\n type: 'integer',\n format: 'int64',\n },\n { type: 'number' },\n ]);\n\n assert.deepStrictEqual(result, [\n {\n name: 'float',\n position: 0,\n priority: 90,\n type: 'number',\n },\n {\n name: 'double',\n position: 1,\n priority: 89,\n type: 'number',\n },\n {\n name: 'integer',\n position: 2,\n priority: 87,\n type: 'number',\n },\n {\n name: 'number',\n position: 3,\n type: 'number',\n },\n ] satisfies Varient[]);\n });\n });\n\n describe('mixed types', () => {\n it('handles mixed string and number types', () => {\n const spec = createSpec();\n const result = findVarients(spec, [\n { type: 'number' },\n { type: 'string' },\n ]);\n assert.deepStrictEqual(result, [\n {\n name: 'text',\n position: 1,\n type: 'string',\n },\n {\n name: 'number',\n position: 0,\n type: 'number',\n },\n ] satisfies Varient[]);\n });\n });\n});\n\ndescribe('findPolymorphicVarients', () => {\n describe('strings', () => {\n it('returns single variant per position for multiple strings', () => {\n const spec = createSpec();\n const result = findPolymorphicVarients(spec, [\n { type: 'string', format: 'date-time' },\n { type: 'string' },\n { type: 'string', const: 'active' },\n ]);\n\n assert.deepStrictEqual(result, [\n {\n name: 'active',\n position: 2,\n priority: 98,\n type: 'string',\n },\n {\n name: 'dateTime',\n position: 0,\n priority: 90,\n type: 'string',\n },\n {\n name: 'text',\n position: 1,\n type: 'string',\n },\n ] satisfies Varient[]);\n });\n\n it.skip('returns first variant when multiple enums at same position', () => {\n const spec = createSpec();\n const result = findPolymorphicVarients(spec, [\n { type: 'string', enum: ['first', 'second', 'third'] },\n ]);\n\n assert.deepStrictEqual(result, [\n {\n name: 'first',\n position: 0,\n priority: 80,\n type: 'string',\n },\n ] satisfies Varient[]);\n });\n\n it.skip('selects first variant from multiple at same position', () => {\n const spec = createSpec();\n const result = findPolymorphicVarients(spec, [\n { type: 'string', enum: ['option1', 'option2'] },\n { type: 'string', format: 'email' },\n ]);\n\n assert.deepStrictEqual(result, [\n {\n name: 'email',\n position: 1,\n priority: 88,\n type: 'string',\n },\n {\n name: 'option1',\n position: 0,\n priority: 80,\n type: 'string',\n },\n ] satisfies Varient[]);\n });\n\n it.skip('handles mixed types selecting one per position', () => {\n const spec = createSpec();\n const result = findPolymorphicVarients(spec, [\n { type: 'string', enum: ['a', 'b'] },\n { type: 'number' },\n { type: 'string', const: 'fixed' },\n ]);\n\n assert.deepStrictEqual(result, [\n {\n name: 'fixed',\n position: 2,\n priority: 98,\n type: 'string',\n },\n {\n name: 'a',\n position: 0,\n priority: 80,\n type: 'string',\n },\n {\n name: 'number',\n position: 1,\n type: 'number',\n },\n ] satisfies Varient[]);\n });\n\n it('handles plain strings mixed with formatted strings', () => {\n const spec = createSpec();\n const result = findPolymorphicVarients(spec, [\n { type: 'string' },\n { type: 'string', format: 'password' },\n ]);\n\n assert.deepStrictEqual(result, [\n {\n name: 'password',\n position: 1,\n priority: 89,\n type: 'string',\n },\n {\n name: 'text',\n position: 0,\n type: 'string',\n },\n ] satisfies Varient[]);\n });\n it('ignore duplicates', () => {\n const spec = createSpec();\n const result = findPolymorphicVarients(spec, [\n { type: 'string' },\n { type: 'string', format: 'password' },\n { type: 'string' },\n ]);\n\n assert.deepStrictEqual(result, [\n {\n name: 'password',\n position: 1,\n priority: 89,\n type: 'string',\n },\n {\n name: 'text',\n position: 0,\n type: 'string',\n },\n ] satisfies Varient[]);\n });\n });\n\n describe('numbers', () => {\n it('returns single variant per position for multiple numbers', () => {\n const spec = createSpec();\n const result = findPolymorphicVarients(spec, [\n { type: 'number', format: 'float' },\n { type: 'integer' },\n { type: 'number', format: 'double' },\n ]);\n\n assert.deepStrictEqual(result, [\n {\n name: 'float',\n position: 0,\n priority: 90,\n type: 'number',\n },\n {\n name: 'double',\n position: 2,\n priority: 89,\n type: 'number',\n },\n {\n name: 'number',\n position: 1,\n type: 'number',\n },\n ] satisfies Varient[]);\n });\n\n it('returns first variant when multiple number formats at same position', () => {\n const spec = createSpec();\n const result = findPolymorphicVarients(spec, [\n { type: 'number', format: 'float' },\n { type: 'number', format: 'double' },\n ]);\n\n assert.deepStrictEqual(result, [\n {\n name: 'float',\n position: 0,\n priority: 90,\n type: 'number',\n },\n {\n name: 'double',\n position: 1,\n priority: 89,\n type: 'number',\n },\n ] satisfies Varient[]);\n });\n\n it('handles mixed number and integer types', () => {\n const spec = createSpec();\n const result = findPolymorphicVarients(spec, [\n { type: 'integer', format: 'int64' },\n { type: 'number' },\n { type: 'integer' },\n ]);\n\n assert.deepStrictEqual(result, [\n {\n name: 'integer',\n position: 0,\n priority: 89,\n type: 'number',\n },\n {\n name: 'number',\n position: 1,\n type: 'number',\n },\n {\n name: 'number',\n position: 2,\n type: 'number',\n },\n ] satisfies Varient[]);\n });\n\n it('handles plain numbers mixed with formatted numbers', () => {\n const spec = createSpec();\n const result = findPolymorphicVarients(spec, [\n { type: 'number' },\n { type: 'number', format: 'float' },\n { type: 'number' },\n ]);\n\n assert.deepStrictEqual(result, [\n {\n name: 'float',\n position: 1,\n priority: 89,\n type: 'number',\n },\n {\n name: 'number',\n position: 0,\n type: 'number',\n },\n {\n name: 'number',\n position: 2,\n type: 'number',\n },\n ] satisfies Varient[]);\n });\n });\n\n describe('arrays', () => {\n it.only('complex', () => {\n const spec = createSpec({\n components: {\n schemas: {\n RouteConfig: {\n anyOf: [\n {\n type: 'array',\n items: {\n anyOf: [\n {\n type: 'string',\n enum: ['image', 'video', 'audio'],\n },\n {\n type: 'string',\n enum: [\n 'application/andrew-inset',\n 'application/applixware',\n ],\n },\n ],\n },\n },\n {\n type: 'object',\n additionalProperties: {\n type: 'object',\n properties: {\n maxFileSize: {\n type: 'string',\n description:\n 'The maximum file size allowed for a given file type.',\n example: '4MB',\n },\n maxFileCount: {\n type: 'number',\n description:\n 'Maximum allowed files for a given file type.',\n example: 1,\n },\n contentDisposition: {\n type: 'string',\n enum: ['inline', 'attachment'],\n default: 'inline',\n },\n acl: {\n type: 'string',\n enum: ['public-read', 'private'],\n },\n },\n },\n },\n ],\n },\n },\n },\n });\n const varients = findVarients(\n spec,\n (spec.components.schemas.RouteConfig as SchemaObject).anyOf ?? [],\n );\n\n assert.deepStrictEqual(varients, [\n {\n name: 'textList',\n type: 'array',\n subtype: 'string',\n position: 0,\n },\n {\n static: true,\n subtype: 'string',\n source: 'public-read',\n name: 'public-read',\n type: 'object',\n position: 1,\n },\n ]);\n });\n });\n});\n"],
5
- "mappings": "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",
6
- "names": []
7
- }
@@ -1,2 +0,0 @@
1
- export {};
2
- //# sourceMappingURL=ir.test.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"ir.test.d.ts","sourceRoot":"","sources":["../../src/lib/ir.test.ts"],"names":[],"mappings":""}
@@ -1,261 +0,0 @@
1
- import assert from "node:assert/strict";
2
- import { describe, test } from "node:test";
3
- import { determineGenericTag } from "./tag.ts";
4
- const mockOperation = (operationId = "") => ({ operationId });
5
- describe("determineGenericTag", () => {
6
- describe("Heuristic 1: Path-Based Tag Determination", () => {
7
- test("should use the last non-parameter, non-version, non-@ segment", () => {
8
- assert.strictEqual(
9
- determineGenericTag("/users", mockOperation()),
10
- "users"
11
- );
12
- assert.strictEqual(
13
- determineGenericTag("/users/{userId}/orders", mockOperation()),
14
- "orders"
15
- );
16
- assert.strictEqual(
17
- determineGenericTag("/admin/system/logs", mockOperation()),
18
- "logs"
19
- );
20
- });
21
- test("should ignore path parameters", () => {
22
- assert.strictEqual(
23
- determineGenericTag("/users/{userId}", mockOperation()),
24
- "users"
25
- );
26
- assert.strictEqual(
27
- determineGenericTag("/items/{itemId}", mockOperation()),
28
- "items"
29
- );
30
- });
31
- test("should ignore version segments", () => {
32
- assert.strictEqual(
33
- determineGenericTag("/v1/products", mockOperation()),
34
- "products"
35
- );
36
- assert.strictEqual(
37
- determineGenericTag("/api/V2/items/{itemId}/details", mockOperation()),
38
- "details"
39
- );
40
- assert.strictEqual(
41
- determineGenericTag("/api/resource/v2", mockOperation()),
42
- "resource"
43
- );
44
- });
45
- test("should ignore segments starting with @", () => {
46
- assert.strictEqual(
47
- determineGenericTag("/users/@me", mockOperation()),
48
- "users"
49
- );
50
- assert.strictEqual(
51
- determineGenericTag("/users/@me/guilds", mockOperation()),
52
- "guilds"
53
- );
54
- assert.strictEqual(
55
- determineGenericTag(
56
- "/webhooks/{webhookId}/messages/@original",
57
- mockOperation()
58
- ),
59
- "messages"
60
- );
61
- assert.strictEqual(
62
- determineGenericTag("/@admin/users/{userId}", mockOperation()),
63
- "users"
64
- );
65
- assert.strictEqual(
66
- determineGenericTag(
67
- "/guilds/{guild_id}/@audit-log/users/@me/settings",
68
- mockOperation()
69
- ),
70
- "settings"
71
- );
72
- assert.strictEqual(
73
- determineGenericTag("/system/tasks/@scheduled-jobs", mockOperation()),
74
- "tasks"
75
- );
76
- });
77
- test("should sanitize results matching reserved keywords", () => {
78
- assert.strictEqual(
79
- determineGenericTag("/api/v1/public", mockOperation()),
80
- "public_"
81
- );
82
- assert.strictEqual(
83
- determineGenericTag("/api/case/{id}", mockOperation()),
84
- "case_"
85
- );
86
- assert.strictEqual(
87
- determineGenericTag("/permissions/check", mockOperation()),
88
- "check_"
89
- );
90
- });
91
- test("should sanitize results starting with numbers", () => {
92
- assert.strictEqual(
93
- determineGenericTag("/api/2fa/enable", mockOperation()),
94
- "enable"
95
- );
96
- });
97
- test("should handle mixed separators via camelcase", () => {
98
- assert.strictEqual(
99
- determineGenericTag("/user-profiles/{id}", mockOperation()),
100
- "userProfiles"
101
- );
102
- });
103
- });
104
- describe("Heuristic 2: OperationId Fallback", () => {
105
- test("should be used when path has no valid segments (root)", () => {
106
- assert.strictEqual(
107
- determineGenericTag("/", mockOperation("getRootResource")),
108
- "rootResource"
109
- );
110
- assert.strictEqual(
111
- determineGenericTag("/", mockOperation("healthCheck")),
112
- "healthCheck"
113
- );
114
- });
115
- test("should be used when path has only params/version segments", () => {
116
- assert.strictEqual(
117
- determineGenericTag("/v3/{tenantId}/", mockOperation("getTenantRoot")),
118
- "tenantRoot"
119
- );
120
- assert.strictEqual(
121
- determineGenericTag("/v1/{userId}/", mockOperation("listUserItems")),
122
- "userItems"
123
- );
124
- });
125
- test("should extract nouns after common verb prefixes", () => {
126
- assert.strictEqual(
127
- determineGenericTag("/v1/", mockOperation("postUserPreferences")),
128
- "userPreferences"
129
- );
130
- assert.strictEqual(
131
- determineGenericTag("/v1/", mockOperation("doFoo")),
132
- "foo"
133
- );
134
- assert.strictEqual(
135
- determineGenericTag("/v1/", mockOperation("addUser")),
136
- "user"
137
- );
138
- assert.strictEqual(
139
- determineGenericTag("/v1/", mockOperation("makePublic")),
140
- "public_"
141
- );
142
- });
143
- test("should use the full operationId if no common verb prefix", () => {
144
- assert.strictEqual(
145
- determineGenericTag("/v1/", mockOperation("metrics")),
146
- "metrics"
147
- );
148
- assert.strictEqual(
149
- determineGenericTag("/v1/", mockOperation("tenantAdminSettings")),
150
- "tenantAdminSettings"
151
- );
152
- });
153
- test("should handle numbers within the operationId correctly", () => {
154
- assert.strictEqual(
155
- determineGenericTag("/v1/", mockOperation("getUser2FAStatus")),
156
- "user2FAStatus"
157
- );
158
- assert.strictEqual(
159
- determineGenericTag("/api/", mockOperation("get2FAStatus")),
160
- "api"
161
- );
162
- });
163
- test("should sanitize results matching reserved keywords", () => {
164
- assert.strictEqual(
165
- determineGenericTag("/v1/{id}", mockOperation("delete")),
166
- "delete_"
167
- );
168
- assert.strictEqual(
169
- determineGenericTag("/v1/{id}", mockOperation("createCase")),
170
- "case_"
171
- );
172
- assert.strictEqual(
173
- determineGenericTag("/v1/{id}", mockOperation("get")),
174
- "get_"
175
- );
176
- });
177
- test("should use verb if it is the only part and no path fallback", () => {
178
- assert.strictEqual(
179
- determineGenericTag("/v1/", mockOperation("get")),
180
- "get_"
181
- );
182
- assert.strictEqual(
183
- determineGenericTag("/v1/{id}", mockOperation("list")),
184
- "list_"
185
- );
186
- });
187
- });
188
- describe("Heuristic 3: First Path Segment Fallback", () => {
189
- test("should be used when path only has @ segments and no suitable opId", () => {
190
- assert.strictEqual(
191
- determineGenericTag("/@system/@status", mockOperation()),
192
- "system"
193
- );
194
- assert.strictEqual(
195
- determineGenericTag("/@audit-log/@entries", mockOperation()),
196
- "auditLog"
197
- );
198
- });
199
- test("should be used when opId fallback yields only a common verb", () => {
200
- assert.strictEqual(
201
- determineGenericTag("/@system/@status", mockOperation("get")),
202
- "system"
203
- );
204
- });
205
- test("should strip leading @ before using segment", () => {
206
- assert.strictEqual(
207
- determineGenericTag("/@system/@status", mockOperation()),
208
- "system"
209
- );
210
- });
211
- test("should sanitize results matching reserved keywords", () => {
212
- assert.strictEqual(
213
- determineGenericTag("/@public/@data", mockOperation()),
214
- "public_"
215
- );
216
- });
217
- test("should sanitize results starting with numbers", () => {
218
- assert.strictEqual(
219
- determineGenericTag("/@2fa/@status", mockOperation()),
220
- "_2fa"
221
- );
222
- });
223
- });
224
- describe("Heuristic Priority", () => {
225
- test("Path (Heuristic 1) should take priority over OperationId (Heuristic 2)", () => {
226
- const tag = determineGenericTag(
227
- "/users/{id}/permissions/check",
228
- // Path -> 'check' -> sanitized 'check_'
229
- mockOperation("verifyPermissions")
230
- // opId -> 'permissions'
231
- );
232
- assert.strictEqual(tag, "check_");
233
- });
234
- test("OperationId (Heuristic 2) should take priority over First Path Segment (Heuristic 3)", () => {
235
- const tag = determineGenericTag(
236
- "/@system/@status",
237
- mockOperation("getSystemStatus")
238
- );
239
- assert.strictEqual(tag, "systemStatus");
240
- });
241
- test("First Path Segment (Heuristic 3) is used if OperationId is skipped (verb-only)", () => {
242
- const tag = determineGenericTag("/@system/@status", mockOperation("get"));
243
- assert.strictEqual(tag, "system");
244
- });
245
- });
246
- describe("Heuristic 4: Unknown Fallback", () => {
247
- test('should return "unknown" when no path segments and no operationId', () => {
248
- assert.strictEqual(determineGenericTag("/", mockOperation()), "unknown");
249
- });
250
- test('should return "unknown" when path has only params/version and no operationId', () => {
251
- assert.strictEqual(
252
- determineGenericTag("/v3/{tenantId}/", mockOperation()),
253
- "unknown"
254
- );
255
- });
256
- test('should return "unknown" for empty path string', () => {
257
- assert.strictEqual(determineGenericTag("", mockOperation()), "unknown");
258
- });
259
- });
260
- });
261
- //# sourceMappingURL=ir.test.js.map
@@ -1,7 +0,0 @@
1
- {
2
- "version": 3,
3
- "sources": ["../../src/lib/ir.test.ts"],
4
- "sourcesContent": ["import assert from 'node:assert/strict';\nimport { describe, test } from 'node:test';\nimport type { OperationObject } from 'openapi3-ts/oas31';\n\nimport { determineGenericTag } from './tag.ts';\n\nconst mockOperation = (operationId = ''): OperationObject => ({ operationId });\n\ndescribe('determineGenericTag', () => {\n describe('Heuristic 1: Path-Based Tag Determination', () => {\n test('should use the last non-parameter, non-version, non-@ segment', () => {\n assert.strictEqual(\n determineGenericTag('/users', mockOperation()),\n 'users',\n );\n assert.strictEqual(\n determineGenericTag('/users/{userId}/orders', mockOperation()),\n 'orders',\n );\n assert.strictEqual(\n determineGenericTag('/admin/system/logs', mockOperation()),\n 'logs',\n );\n });\n\n test('should ignore path parameters', () => {\n assert.strictEqual(\n determineGenericTag('/users/{userId}', mockOperation()),\n 'users',\n );\n assert.strictEqual(\n determineGenericTag('/items/{itemId}', mockOperation()),\n 'items',\n );\n });\n\n test('should ignore version segments', () => {\n assert.strictEqual(\n determineGenericTag('/v1/products', mockOperation()),\n 'products',\n );\n assert.strictEqual(\n determineGenericTag('/api/V2/items/{itemId}/details', mockOperation()),\n 'details',\n );\n assert.strictEqual(\n determineGenericTag('/api/resource/v2', mockOperation()),\n 'resource',\n );\n });\n\n test('should ignore segments starting with @', () => {\n assert.strictEqual(\n determineGenericTag('/users/@me', mockOperation()),\n 'users',\n );\n assert.strictEqual(\n determineGenericTag('/users/@me/guilds', mockOperation()),\n 'guilds',\n );\n assert.strictEqual(\n determineGenericTag(\n '/webhooks/{webhookId}/messages/@original',\n mockOperation(),\n ),\n 'messages',\n );\n assert.strictEqual(\n determineGenericTag('/@admin/users/{userId}', mockOperation()),\n 'users',\n );\n assert.strictEqual(\n determineGenericTag(\n '/guilds/{guild_id}/@audit-log/users/@me/settings',\n mockOperation(),\n ),\n 'settings',\n );\n assert.strictEqual(\n determineGenericTag('/system/tasks/@scheduled-jobs', mockOperation()),\n 'tasks',\n );\n });\n\n test('should sanitize results matching reserved keywords', () => {\n assert.strictEqual(\n determineGenericTag('/api/v1/public', mockOperation()),\n 'public_',\n );\n assert.strictEqual(\n determineGenericTag('/api/case/{id}', mockOperation()),\n 'case_',\n );\n assert.strictEqual(\n determineGenericTag('/permissions/check', mockOperation()),\n 'check_',\n );\n });\n\n test('should sanitize results starting with numbers', () => {\n // FIX: Expectation changed - last valid segment is 'enable'\n assert.strictEqual(\n determineGenericTag('/api/2fa/enable', mockOperation()),\n 'enable',\n );\n });\n\n test('should handle mixed separators via camelcase', () => {\n assert.strictEqual(\n determineGenericTag('/user-profiles/{id}', mockOperation()),\n 'userProfiles',\n );\n });\n });\n\n describe('Heuristic 2: OperationId Fallback', () => {\n test('should be used when path has no valid segments (root)', () => {\n assert.strictEqual(\n determineGenericTag('/', mockOperation('getRootResource')),\n 'rootResource',\n );\n // FIX: Expectation changed - 'healthCheck' is not reserved\n assert.strictEqual(\n determineGenericTag('/', mockOperation('healthCheck')),\n 'healthCheck',\n );\n });\n\n test('should be used when path has only params/version segments', () => {\n assert.strictEqual(\n determineGenericTag('/v3/{tenantId}/', mockOperation('getTenantRoot')),\n 'tenantRoot',\n );\n assert.strictEqual(\n determineGenericTag('/v1/{userId}/', mockOperation('listUserItems')),\n 'userItems',\n );\n });\n\n test('should extract nouns after common verb prefixes', () => {\n assert.strictEqual(\n determineGenericTag('/v1/', mockOperation('postUserPreferences')),\n 'userPreferences',\n );\n assert.strictEqual(\n determineGenericTag('/v1/', mockOperation('doFoo')),\n 'foo',\n );\n assert.strictEqual(\n determineGenericTag('/v1/', mockOperation('addUser')),\n 'user',\n );\n // FIX: Added 'make' to commonVerbs\n assert.strictEqual(\n determineGenericTag('/v1/', mockOperation('makePublic')),\n 'public_',\n );\n });\n\n test('should use the full operationId if no common verb prefix', () => {\n assert.strictEqual(\n determineGenericTag('/v1/', mockOperation('metrics')),\n 'metrics',\n );\n assert.strictEqual(\n determineGenericTag('/v1/', mockOperation('tenantAdminSettings')),\n 'tenantAdminSettings',\n );\n });\n\n test('should handle numbers within the operationId correctly', () => {\n // FIX: Expectation aligned with stringcase behavior\n assert.strictEqual(\n determineGenericTag('/v1/', mockOperation('getUser2FAStatus')),\n 'user2FAStatus',\n );\n assert.strictEqual(\n determineGenericTag('/api/', mockOperation('get2FAStatus')),\n 'api',\n ); // Sanitized (starts with number after verb removal)\n });\n\n test('should sanitize results matching reserved keywords', () => {\n assert.strictEqual(\n determineGenericTag('/v1/{id}', mockOperation('delete')),\n 'delete_',\n );\n assert.strictEqual(\n determineGenericTag('/v1/{id}', mockOperation('createCase')),\n 'case_',\n );\n assert.strictEqual(\n determineGenericTag('/v1/{id}', mockOperation('get')),\n 'get_',\n );\n });\n\n test('should use verb if it is the only part and no path fallback', () => {\n assert.strictEqual(\n determineGenericTag('/v1/', mockOperation('get')),\n 'get_',\n );\n assert.strictEqual(\n determineGenericTag('/v1/{id}', mockOperation('list')),\n 'list_',\n );\n });\n });\n\n describe('Heuristic 3: First Path Segment Fallback', () => {\n test('should be used when path only has @ segments and no suitable opId', () => {\n assert.strictEqual(\n determineGenericTag('/@system/@status', mockOperation()),\n 'system',\n );\n assert.strictEqual(\n determineGenericTag('/@audit-log/@entries', mockOperation()),\n 'auditLog',\n );\n });\n\n test('should be used when opId fallback yields only a common verb', () => {\n assert.strictEqual(\n determineGenericTag('/@system/@status', mockOperation('get')),\n 'system',\n );\n });\n\n test('should strip leading @ before using segment', () => {\n assert.strictEqual(\n determineGenericTag('/@system/@status', mockOperation()),\n 'system',\n );\n });\n\n test('should sanitize results matching reserved keywords', () => {\n assert.strictEqual(\n determineGenericTag('/@public/@data', mockOperation()),\n 'public_',\n );\n });\n\n test('should sanitize results starting with numbers', () => {\n assert.strictEqual(\n determineGenericTag('/@2fa/@status', mockOperation()),\n '_2fa',\n );\n });\n });\n\n describe('Heuristic Priority', () => {\n test('Path (Heuristic 1) should take priority over OperationId (Heuristic 2)', () => {\n const tag = determineGenericTag(\n '/users/{id}/permissions/check', // Path -> 'check' -> sanitized 'check_'\n mockOperation('verifyPermissions'), // opId -> 'permissions'\n );\n assert.strictEqual(tag, 'check_');\n });\n\n test('OperationId (Heuristic 2) should take priority over First Path Segment (Heuristic 3)', () => {\n const tag = determineGenericTag(\n '/@system/@status',\n mockOperation('getSystemStatus'),\n );\n assert.strictEqual(tag, 'systemStatus');\n });\n\n test('First Path Segment (Heuristic 3) is used if OperationId is skipped (verb-only)', () => {\n const tag = determineGenericTag('/@system/@status', mockOperation('get'));\n assert.strictEqual(tag, 'system');\n });\n });\n\n describe('Heuristic 4: Unknown Fallback', () => {\n test('should return \"unknown\" when no path segments and no operationId', () => {\n assert.strictEqual(determineGenericTag('/', mockOperation()), 'unknown');\n });\n\n test('should return \"unknown\" when path has only params/version and no operationId', () => {\n assert.strictEqual(\n determineGenericTag('/v3/{tenantId}/', mockOperation()),\n 'unknown',\n );\n });\n\n test('should return \"unknown\" for empty path string', () => {\n assert.strictEqual(determineGenericTag('', mockOperation()), 'unknown');\n });\n });\n});\n"],
5
- "mappings": "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",
6
- "names": []
7
- }
@@ -1,2 +0,0 @@
1
- export {};
2
- //# sourceMappingURL=metadata.test.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"metadata.test.d.ts","sourceRoot":"","sources":["../../src/lib/metadata.test.ts"],"names":[],"mappings":""}