@cmflow/atlas 3.7.1 → 3.8.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -55,6 +55,25 @@ async function loadOpenApiDocument(url, timeoutMs) {
55
55
  }
56
56
  }
57
57
 
58
+ //#endregion
59
+ //#region src/utils/pickPropertyMetadata.ts
60
+ /**
61
+ * Picks the shape-describing fields (`data_type`/`original_type`/`format`/`pattern`/`is_nullable`/
62
+ * `enum_values`) off any `PropertyMetadata`-shaped source. Spread this at every call site that
63
+ * copies a resolved backend/API property into a catalogue record, instead of repeating the same
64
+ * six fields.
65
+ */
66
+ function pickPropertyMetadata(source) {
67
+ return {
68
+ data_type: source?.data_type,
69
+ original_type: source?.original_type,
70
+ format: source?.format,
71
+ pattern: source?.pattern,
72
+ is_nullable: source?.is_nullable,
73
+ enum_values: source?.enum_values
74
+ };
75
+ }
76
+
58
77
  //#endregion
59
78
  //#region src/services/openapi/utils/resolveOpenApiReference.ts
60
79
  function resolveOpenApiReference(value, document) {
@@ -67,8 +86,210 @@ function resolveOpenApiReference(value, document) {
67
86
  return current === void 0 ? value : current;
68
87
  }
69
88
 
89
+ //#endregion
90
+ //#region src/utils/transformTypeFrom.ts
91
+ /** Known OpenAPI `type`+`format` pairs that promote to a distinct base type. */
92
+ const FORMAT_PROMOTIONS = {
93
+ "integer:int32": "integer",
94
+ "integer:int64": "long",
95
+ "number:float": "float",
96
+ "number:double": "double",
97
+ "string:date": "date",
98
+ "string:date-time": "date-time"
99
+ };
100
+ /** Internal base key used as the default when nothing else matches — spelling matches `PropertyDataType["unknow"]`. */
101
+ const DEFAULT_BASE = "unknow";
102
+ /**
103
+ * Closed, exhaustive set of `data_type` predefined_values (`type: "data_type"` in Directus),
104
+ * keyed by the base half of `PropertyDataType` (i.e. without its `[]` suffix). This is the exact
105
+ * list — ids/labels are NOT derived, they must match the existing rows verbatim (note the
106
+ * historical quirks: the `unknow` base's row id is `UNKNOWN`, correctly spelled, while its label
107
+ * keeps the typo `Unknow`; `UUID_ARRAY` has no `[]` suffix in its label).
108
+ */
109
+ const BASE_TYPES = {
110
+ unknow: {
111
+ id: "UNKNOWN",
112
+ label: "Unknow"
113
+ },
114
+ string: {
115
+ id: "STRING",
116
+ label: "String",
117
+ arrayId: "STRING_ARRAY",
118
+ arrayLabel: "String[]"
119
+ },
120
+ uuid: {
121
+ id: "UUID",
122
+ label: "Uuid",
123
+ arrayId: "UUID_ARRAY",
124
+ arrayLabel: "Uuid"
125
+ },
126
+ number: {
127
+ id: "NUMBER",
128
+ label: "Number",
129
+ arrayId: "NUMBER_ARRAY",
130
+ arrayLabel: "Number[]"
131
+ },
132
+ integer: {
133
+ id: "INTEGER",
134
+ label: "Integer",
135
+ arrayId: "INTEGER_ARRAY",
136
+ arrayLabel: "Integer[]"
137
+ },
138
+ float: {
139
+ id: "FLOAT",
140
+ label: "Float",
141
+ arrayId: "FLOAT_ARRAY",
142
+ arrayLabel: "Float[]"
143
+ },
144
+ double: {
145
+ id: "DOUBLE",
146
+ label: "Double",
147
+ arrayId: "DOUBLE_ARRAY",
148
+ arrayLabel: "Double[]"
149
+ },
150
+ long: {
151
+ id: "LONG",
152
+ label: "Long",
153
+ arrayId: "LONG_ARRAY",
154
+ arrayLabel: "Long[]"
155
+ },
156
+ decimal: {
157
+ id: "DECIMAL",
158
+ label: "Decimal",
159
+ arrayId: "DECIMAL_ARRAY",
160
+ arrayLabel: "Decimal[]"
161
+ },
162
+ boolean: {
163
+ id: "BOOLEAN",
164
+ label: "Boolean",
165
+ arrayId: "BOOLEAN_ARRAY",
166
+ arrayLabel: "Boolean[]"
167
+ },
168
+ date: {
169
+ id: "DATE",
170
+ label: "Date",
171
+ arrayId: "DATE_ARRAY",
172
+ arrayLabel: "Date[]"
173
+ },
174
+ "date-time": {
175
+ id: "DATETIME",
176
+ label: "DateTime",
177
+ arrayId: "DATETIME_ARRAY",
178
+ arrayLabel: "DateTime[]"
179
+ },
180
+ time: {
181
+ id: "TIME",
182
+ label: "Time",
183
+ arrayId: "TIME_ARRAY",
184
+ arrayLabel: "Time[]"
185
+ },
186
+ timestamp: {
187
+ id: "TIMESTAMP",
188
+ label: "Timestamp",
189
+ arrayId: "TIMESTAMP_ARRAY",
190
+ arrayLabel: "Timestamp[]"
191
+ },
192
+ object: {
193
+ id: "OBJECT",
194
+ label: "Object",
195
+ arrayId: "OBJECT_ARRAY",
196
+ arrayLabel: "Object[]"
197
+ }
198
+ };
199
+ /**
200
+ * Raw backend/OpenAPI keywords mapped to a base above. Anything not listed degrades to
201
+ * `unknow` rather than being dropped; the exact original keyword is preserved verbatim in
202
+ * `original_type` instead (a free-form field — see BackendProperty/RouteProperty's dedicated
203
+ * columns). Add new synonyms here as new sources are integrated.
204
+ */
205
+ const TYPE_ALIASES = {
206
+ string: "string",
207
+ number: "number",
208
+ integer: "integer",
209
+ int: "integer",
210
+ float: "float",
211
+ double: "double",
212
+ long: "long",
213
+ decimal: "decimal",
214
+ boolean: "boolean",
215
+ bool: "boolean",
216
+ date: "date",
217
+ "date-time": "date-time",
218
+ datetime: "date-time",
219
+ time: "time",
220
+ timestamp: "timestamp",
221
+ object: "object",
222
+ uuid: "uuid",
223
+ json: "object",
224
+ text: "string",
225
+ localized_text: "string",
226
+ unlocalized_text: "string",
227
+ multiline_text: "string",
228
+ multi_select: "string",
229
+ simple_select: "string",
230
+ switch: "boolean",
231
+ alias: "string"
232
+ };
233
+ /** Raw keywords that are inherently multi-valued (no `[]` suffix needed to detect it). */
234
+ const ARRAY_ALIASES = /* @__PURE__ */ new Set(["multi_select"]);
235
+ function resolveBaseKey(rawType) {
236
+ return TYPE_ALIASES[rawType.trim().toLowerCase()] || DEFAULT_BASE;
237
+ }
238
+ /**
239
+ * Normalizes any raw backend/OpenAPI type (+ optional format, for `int64`/`date-time`-style
240
+ * promotions) to the closed `PropertyDataType` Atlas carries end to end as `data_type`. Handles
241
+ * explicit `Type[]`/`Array<Type>` syntax and inherently plural keywords like `multi_select`.
242
+ * Always resolves to something — an unrecognized type degrades to `unknow` rather than being
243
+ * dropped; callers should keep the original keyword in `original_type`.
244
+ */
245
+ function toPropertyDataType(type, format) {
246
+ const sourceType = typeof type === "string" ? type : void 0;
247
+ const sourceFormat = typeof format === "string" ? format : void 0;
248
+ let rawType = sourceType;
249
+ if (sourceType && sourceFormat) rawType = FORMAT_PROMOTIONS[`${sourceType.toLowerCase()}:${sourceFormat.toLowerCase()}`] ?? sourceType;
250
+ if (!rawType) return DEFAULT_BASE;
251
+ const arrayMatch = rawType.trim().match(/^(.+)\[\]$/) || rawType.trim().match(/^array<(.+)>$/i);
252
+ if (arrayMatch) return `${resolveBaseKey(arrayMatch[1])}[]`;
253
+ const base = resolveBaseKey(rawType);
254
+ return ARRAY_ALIASES.has(rawType.trim().toLowerCase()) ? `${base}[]` : base;
255
+ }
256
+ /**
257
+ * Maps an already-normalized `PropertyDataType` to its Directus `predefined_values` `{id, label}`
258
+ * (`type: "data_type"`). The only caller should be the push step (`resolveDataTypeReference`) —
259
+ * everywhere else in the pipeline carries the closed `PropertyDataType` itself, produced once by
260
+ * `toPropertyDataType` at extraction/declaration time.
261
+ */
262
+ function transformTypeFrom(dataType) {
263
+ const key = dataType || DEFAULT_BASE;
264
+ const isArray = key.endsWith("[]");
265
+ const baseKey = isArray ? key.slice(0, -2) : key;
266
+ const entry = BASE_TYPES[baseKey] ?? BASE_TYPES[DEFAULT_BASE];
267
+ return isArray ? {
268
+ id: entry.arrayId ?? entry.id,
269
+ label: entry.arrayLabel ?? entry.label
270
+ } : {
271
+ id: entry.id,
272
+ label: entry.label
273
+ };
274
+ }
275
+
70
276
  //#endregion
71
277
  //#region src/services/openapi/utils/extractOpenApiLeafProperties.ts
278
+ /**
279
+ * Builds a leaf property's shape from a schema: `original_type`/`format`/`pattern`/`is_nullable`/
280
+ * `enum_values` are copied as-is (free-form, kept verbatim end to end), while `data_type` is
281
+ * normalized up front via `toPropertyDataType` since it's a closed `PropertyDataType` value.
282
+ */
283
+ function toRawShape(schema) {
284
+ return {
285
+ data_type: toPropertyDataType(schema?.type, schema?.format),
286
+ original_type: schema?.type,
287
+ format: schema?.format,
288
+ pattern: schema?.pattern,
289
+ is_nullable: schema?.nullable,
290
+ enum_values: Array.isArray(schema?.enum) ? schema.enum.map(String) : void 0
291
+ };
292
+ }
72
293
  function extractOpenApiLeafProperties(schema, document, currentPath = "") {
73
294
  const resolvedSchema = resolveOpenApiReference(schema, document);
74
295
  if (!resolvedSchema || typeof resolvedSchema !== "object") return [];
@@ -82,7 +303,7 @@ function extractOpenApiLeafProperties(schema, document, currentPath = "") {
82
303
  path: currentPath,
83
304
  description: resolvedSchema.description,
84
305
  deprecated: resolvedSchema.deprecated,
85
- type: resolvedSchema.type
306
+ ...toRawShape(resolvedSchema)
86
307
  }] : [];
87
308
  return Object.entries(properties).flatMap(([propertyName, propertySchema]) => {
88
309
  return extractOpenApiLeafProperties(propertySchema, document, currentPath ? `${currentPath}.${propertyName}` : propertyName);
@@ -127,7 +348,7 @@ function extractOpenApiInputProperties(operation, swagger) {
127
348
  path: parameter.name,
128
349
  description: parameter.description,
129
350
  deprecated: parameter.deprecated,
130
- type: parameter.schema?.type
351
+ ...toRawShape(parameter.schema)
131
352
  }];
132
353
  for (const property of resolvedProperties) map.set(`${location}:${property.path}`, {
133
354
  path: property.path,
@@ -135,7 +356,7 @@ function extractOpenApiInputProperties(operation, swagger) {
135
356
  deprecated: property.deprecated ?? parameter.deprecated ?? false,
136
357
  direction: "input",
137
358
  location,
138
- type: property.type
359
+ ...pickPropertyMetadata(property)
139
360
  });
140
361
  }
141
362
  const requestBody = resolveOpenApiReference(operation.requestBody, swagger);
@@ -147,7 +368,7 @@ function extractOpenApiInputProperties(operation, swagger) {
147
368
  deprecated: property.deprecated ?? false,
148
369
  direction: "input",
149
370
  location: "body",
150
- type: property.type
371
+ ...pickPropertyMetadata(property)
151
372
  });
152
373
  }
153
374
  return [...map.values()];
@@ -165,7 +386,7 @@ function extractOpenApiOutputProperties(operation, swagger) {
165
386
  deprecated: property.deprecated ?? false,
166
387
  direction: "output",
167
388
  location: "body",
168
- type: property.type
389
+ ...pickPropertyMetadata(property)
169
390
  });
170
391
  for (const [headerName, rawHeader] of Object.entries(response?.headers || {})) {
171
392
  const header = resolveOpenApiReference(rawHeader, swagger);
@@ -174,7 +395,7 @@ function extractOpenApiOutputProperties(operation, swagger) {
174
395
  path: headerName,
175
396
  description: header?.description,
176
397
  deprecated: void 0,
177
- type: header?.schema?.type
398
+ ...toRawShape(header?.schema)
178
399
  }];
179
400
  for (const property of resolvedProperties) map.set(`header:${property.path}`, {
180
401
  path: property.path,
@@ -182,7 +403,7 @@ function extractOpenApiOutputProperties(operation, swagger) {
182
403
  deprecated: property.deprecated ?? false,
183
404
  direction: "output",
184
405
  location: "header",
185
- type: property.type
406
+ ...pickPropertyMetadata(property)
186
407
  });
187
408
  }
188
409
  }
@@ -202,7 +423,7 @@ function extractOpenApiBackendProperties(swagger) {
202
423
  description: property.description,
203
424
  direction: property.direction,
204
425
  location: property.location,
205
- type: property.type
426
+ ...pickPropertyMetadata(property)
206
427
  });
207
428
  }
208
429
  }
@@ -6946,5 +7167,5 @@ var require_dist = /* @__PURE__ */ __commonJSMin(((exports) => {
6946
7167
  }));
6947
7168
 
6948
7169
  //#endregion
6949
- export { loadOpenApiDocument as a, extractOpenApiOutputProperties as i, extractOpenApiBackendProperties as n, httpClient as o, extractOpenApiInputProperties as r, require_dist as t };
6950
- //# sourceMappingURL=dist-D8VumL0r.mjs.map
7170
+ export { toPropertyDataType as a, loadOpenApiDocument as c, extractOpenApiOutputProperties as i, httpClient as l, extractOpenApiBackendProperties as n, transformTypeFrom as o, extractOpenApiInputProperties as r, pickPropertyMetadata as s, require_dist as t };
7171
+ //# sourceMappingURL=dist-DIU2ATkt.mjs.map