metal-orm 1.0.87 → 1.0.89
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.cjs +226 -62
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +27 -2
- package/dist/index.d.ts +27 -2
- package/dist/index.js +226 -62
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
- package/src/openapi/schema-extractor-input.ts +193 -0
- package/src/openapi/schema-extractor-output.ts +427 -0
- package/src/openapi/schema-extractor-utils.ts +110 -0
- package/src/openapi/schema-extractor.ts +51 -517
- package/src/openapi/schema-types.ts +30 -1
package/dist/index.cjs
CHANGED
|
@@ -7249,47 +7249,52 @@ var getTemporalFormat = (sqlType) => {
|
|
|
7249
7249
|
}
|
|
7250
7250
|
};
|
|
7251
7251
|
|
|
7252
|
-
// src/openapi/schema-extractor.ts
|
|
7253
|
-
var
|
|
7254
|
-
var
|
|
7255
|
-
|
|
7256
|
-
|
|
7257
|
-
|
|
7258
|
-
|
|
7259
|
-
|
|
7260
|
-
|
|
7252
|
+
// src/openapi/schema-extractor-utils.ts
|
|
7253
|
+
var hasComputedProjection = (projectionNodes) => Boolean(projectionNodes && projectionNodes.some((node) => node.type !== "Column"));
|
|
7254
|
+
var shouldUseSelectedSchema = (options, plan, projectionNodes) => {
|
|
7255
|
+
if (!plan || options.mode !== "selected") return false;
|
|
7256
|
+
if (hasComputedProjection(projectionNodes)) return false;
|
|
7257
|
+
if (options.refMode === "components" && options.selectedRefMode !== "components") return false;
|
|
7258
|
+
return true;
|
|
7259
|
+
};
|
|
7260
|
+
var resolveComponentName = (table, options) => options.componentName ? options.componentName(table) : table.name;
|
|
7261
|
+
var normalizeColumns = (columns) => Array.from(new Set(columns)).sort((a, b) => a.localeCompare(b));
|
|
7262
|
+
var buildSelectionSignature = (plan) => {
|
|
7263
|
+
const relations = plan.relations.map((relation) => ({
|
|
7264
|
+
name: relation.name,
|
|
7265
|
+
columns: normalizeColumns(relation.columns)
|
|
7266
|
+
})).sort((a, b) => a.name.localeCompare(b.name));
|
|
7267
|
+
return JSON.stringify({
|
|
7268
|
+
root: normalizeColumns(plan.rootColumns),
|
|
7269
|
+
relations
|
|
7270
|
+
});
|
|
7271
|
+
};
|
|
7272
|
+
var hashString = (value) => {
|
|
7273
|
+
let hash = 2166136261;
|
|
7274
|
+
for (let i = 0; i < value.length; i += 1) {
|
|
7275
|
+
hash ^= value.charCodeAt(i);
|
|
7276
|
+
hash = hash * 16777619 >>> 0;
|
|
7261
7277
|
}
|
|
7262
|
-
|
|
7263
|
-
const input = extractInputSchema(table, inputContext, inputOptions);
|
|
7264
|
-
return { output, input };
|
|
7278
|
+
return hash.toString(16).padStart(8, "0");
|
|
7265
7279
|
};
|
|
7266
|
-
var
|
|
7267
|
-
|
|
7268
|
-
|
|
7269
|
-
|
|
7270
|
-
|
|
7271
|
-
|
|
7272
|
-
|
|
7273
|
-
|
|
7274
|
-
|
|
7275
|
-
|
|
7276
|
-
|
|
7277
|
-
|
|
7278
|
-
|
|
7279
|
-
|
|
7280
|
-
|
|
7281
|
-
|
|
7282
|
-
|
|
7283
|
-
|
|
7284
|
-
includeEnums: input.includeEnums ?? options.includeEnums,
|
|
7285
|
-
includeExamples: input.includeExamples ?? options.includeExamples,
|
|
7286
|
-
includeDefaults: input.includeDefaults ?? options.includeDefaults,
|
|
7287
|
-
includeNullable: input.includeNullable ?? options.includeNullable,
|
|
7288
|
-
maxDepth: input.maxDepth ?? options.maxDepth ?? DEFAULT_MAX_DEPTH,
|
|
7289
|
-
omitReadOnly: input.omitReadOnly ?? true,
|
|
7290
|
-
excludePrimaryKey: input.excludePrimaryKey ?? false,
|
|
7291
|
-
requirePrimaryKey: input.requirePrimaryKey ?? mode === "update"
|
|
7292
|
-
};
|
|
7280
|
+
var resolveSelectedComponentName = (table, plan, options) => {
|
|
7281
|
+
const base = resolveComponentName(table, options);
|
|
7282
|
+
const signature = buildSelectionSignature(plan);
|
|
7283
|
+
return `${base}__sel_${hashString(signature)}`;
|
|
7284
|
+
};
|
|
7285
|
+
var ensureComponentRef = (table, componentName, context, schemaFactory) => {
|
|
7286
|
+
if (context.components && !context.components.schemas[componentName]) {
|
|
7287
|
+
if (!context.visitedTables.has(table.name)) {
|
|
7288
|
+
context.components.schemas[componentName] = schemaFactory();
|
|
7289
|
+
}
|
|
7290
|
+
}
|
|
7291
|
+
return { $ref: `#/components/schemas/${componentName}` };
|
|
7292
|
+
};
|
|
7293
|
+
var registerComponentSchema = (name, schema, context) => {
|
|
7294
|
+
if (!context.components) return;
|
|
7295
|
+
if (!context.components.schemas[name]) {
|
|
7296
|
+
context.components.schemas[name] = schema;
|
|
7297
|
+
}
|
|
7293
7298
|
};
|
|
7294
7299
|
var createContext = (maxDepth) => ({
|
|
7295
7300
|
visitedTables: /* @__PURE__ */ new Set(),
|
|
@@ -7297,19 +7302,18 @@ var createContext = (maxDepth) => ({
|
|
|
7297
7302
|
depth: 0,
|
|
7298
7303
|
maxDepth
|
|
7299
7304
|
});
|
|
7300
|
-
var
|
|
7301
|
-
|
|
7302
|
-
|
|
7303
|
-
|
|
7304
|
-
|
|
7305
|
-
|
|
7306
|
-
|
|
7307
|
-
}
|
|
7308
|
-
|
|
7309
|
-
|
|
7310
|
-
|
|
7311
|
-
|
|
7312
|
-
};
|
|
7305
|
+
var buildCircularReferenceSchema = (tableName, kind) => ({
|
|
7306
|
+
type: "object",
|
|
7307
|
+
properties: {
|
|
7308
|
+
_ref: {
|
|
7309
|
+
type: "string",
|
|
7310
|
+
description: `Circular ${kind} reference to ${tableName}`
|
|
7311
|
+
}
|
|
7312
|
+
},
|
|
7313
|
+
required: []
|
|
7314
|
+
});
|
|
7315
|
+
|
|
7316
|
+
// src/openapi/schema-extractor-input.ts
|
|
7313
7317
|
var extractInputSchema = (table, context, options) => {
|
|
7314
7318
|
const cacheKey = `${table.name}:${options.mode ?? "create"}`;
|
|
7315
7319
|
if (context.schemaCache.has(cacheKey)) {
|
|
@@ -7337,6 +7341,7 @@ var extractInputSchema = (table, context, options) => {
|
|
|
7337
7341
|
if (options.includeRelations && context.depth < context.maxDepth) {
|
|
7338
7342
|
for (const [relationName, relation] of Object.entries(table.relations)) {
|
|
7339
7343
|
properties[relationName] = extractInputRelationSchema(
|
|
7344
|
+
relationName,
|
|
7340
7345
|
relation,
|
|
7341
7346
|
{ ...context, depth: context.depth + 1 },
|
|
7342
7347
|
options
|
|
@@ -7371,7 +7376,7 @@ var buildPrimaryKeySchema = (table, options) => {
|
|
|
7371
7376
|
}
|
|
7372
7377
|
return mapColumnType(column, options);
|
|
7373
7378
|
};
|
|
7374
|
-
var extractInputRelationSchema = (relation, context, options) => {
|
|
7379
|
+
var extractInputRelationSchema = (relationName, relation, context, options) => {
|
|
7375
7380
|
const { type: relationType, isNullable } = mapRelationType(relation.type);
|
|
7376
7381
|
const relationMode = options.relationMode ?? "mixed";
|
|
7377
7382
|
const allowIds = relationMode !== "objects";
|
|
@@ -7381,7 +7386,11 @@ var extractInputRelationSchema = (relation, context, options) => {
|
|
|
7381
7386
|
variants.push(buildPrimaryKeySchema(relation.target, options));
|
|
7382
7387
|
}
|
|
7383
7388
|
if (allowObjects) {
|
|
7384
|
-
|
|
7389
|
+
let targetSchema = extractInputSchema(relation.target, context, options);
|
|
7390
|
+
targetSchema = applyRelationSelection(targetSchema, options.relationSelections?.[relationName]);
|
|
7391
|
+
if (options.excludeRelationForeignKeys && isRelationForeignKeyToParent(relation)) {
|
|
7392
|
+
targetSchema = removeForeignKey(targetSchema, relation.foreignKey);
|
|
7393
|
+
}
|
|
7385
7394
|
variants.push(targetSchema);
|
|
7386
7395
|
}
|
|
7387
7396
|
const itemSchema = variants.length === 1 ? variants[0] : { anyOf: variants };
|
|
@@ -7397,6 +7406,55 @@ var extractInputRelationSchema = (relation, context, options) => {
|
|
|
7397
7406
|
nullable: isNullable
|
|
7398
7407
|
};
|
|
7399
7408
|
};
|
|
7409
|
+
var applyRelationSelection = (schema, selection) => {
|
|
7410
|
+
if (!selection || selection.pick === void 0 && selection.omit === void 0) {
|
|
7411
|
+
return schema;
|
|
7412
|
+
}
|
|
7413
|
+
const hasPick = selection.pick !== void 0;
|
|
7414
|
+
const pick = hasPick ? new Set(selection.pick ?? []) : void 0;
|
|
7415
|
+
const omit = selection.omit !== void 0 ? new Set(selection.omit ?? []) : void 0;
|
|
7416
|
+
const properties = Object.entries(schema.properties).reduce(
|
|
7417
|
+
(acc, [key, value]) => {
|
|
7418
|
+
if (pick && !pick.has(key)) return acc;
|
|
7419
|
+
if (omit && omit.has(key)) return acc;
|
|
7420
|
+
acc[key] = value;
|
|
7421
|
+
return acc;
|
|
7422
|
+
},
|
|
7423
|
+
{}
|
|
7424
|
+
);
|
|
7425
|
+
const required = schema.required.filter((name) => properties[name] !== void 0);
|
|
7426
|
+
return {
|
|
7427
|
+
...schema,
|
|
7428
|
+
properties,
|
|
7429
|
+
required
|
|
7430
|
+
};
|
|
7431
|
+
};
|
|
7432
|
+
var removeForeignKey = (schema, foreignKey) => {
|
|
7433
|
+
if (!foreignKey || !schema.properties[foreignKey]) return schema;
|
|
7434
|
+
const properties = { ...schema.properties };
|
|
7435
|
+
delete properties[foreignKey];
|
|
7436
|
+
const required = schema.required.filter((name) => name !== foreignKey);
|
|
7437
|
+
return {
|
|
7438
|
+
...schema,
|
|
7439
|
+
properties,
|
|
7440
|
+
required
|
|
7441
|
+
};
|
|
7442
|
+
};
|
|
7443
|
+
var isRelationForeignKeyToParent = (relation) => {
|
|
7444
|
+
return relation.type === RelationKinds.HasMany || relation.type === RelationKinds.HasOne;
|
|
7445
|
+
};
|
|
7446
|
+
|
|
7447
|
+
// src/openapi/schema-extractor-output.ts
|
|
7448
|
+
var extractOutputSchema = (table, plan, projectionNodes, context, options) => {
|
|
7449
|
+
const hasComputedFields = hasComputedProjection(projectionNodes);
|
|
7450
|
+
if (hasComputedFields) {
|
|
7451
|
+
return extractFromProjectionNodes(table, projectionNodes, context, options);
|
|
7452
|
+
}
|
|
7453
|
+
if (shouldUseSelectedSchema(options, plan, projectionNodes)) {
|
|
7454
|
+
return extractSelectedSchema(table, plan, context, options);
|
|
7455
|
+
}
|
|
7456
|
+
return extractFullTableSchema(table, context, options);
|
|
7457
|
+
};
|
|
7400
7458
|
var extractFromProjectionNodes = (table, projectionNodes, context, options) => {
|
|
7401
7459
|
const properties = {};
|
|
7402
7460
|
const required = [];
|
|
@@ -7602,6 +7660,52 @@ var extractFullTableSchema = (table, context, options) => {
|
|
|
7602
7660
|
var extractRelationSchema = (relation, relationPlan, selectedColumns, context, options) => {
|
|
7603
7661
|
const targetTable = relation.target;
|
|
7604
7662
|
const { type: relationType, isNullable } = mapRelationType(relation.type);
|
|
7663
|
+
if (options.refMode === "components" && context.components) {
|
|
7664
|
+
if (relationPlan && selectedColumns.length > 0 && options.selectedRefMode === "components") {
|
|
7665
|
+
const plan = {
|
|
7666
|
+
rootTable: targetTable.name,
|
|
7667
|
+
rootPrimaryKey: relationPlan.targetPrimaryKey,
|
|
7668
|
+
rootColumns: selectedColumns,
|
|
7669
|
+
relations: []
|
|
7670
|
+
};
|
|
7671
|
+
const componentName2 = resolveSelectedComponentName(targetTable, plan, options);
|
|
7672
|
+
const ref2 = ensureComponentRef(
|
|
7673
|
+
targetTable,
|
|
7674
|
+
componentName2,
|
|
7675
|
+
context,
|
|
7676
|
+
() => extractSelectedSchema(targetTable, plan, context, options)
|
|
7677
|
+
);
|
|
7678
|
+
if (relationType === "array") {
|
|
7679
|
+
return {
|
|
7680
|
+
type: "array",
|
|
7681
|
+
items: ref2,
|
|
7682
|
+
nullable: isNullable
|
|
7683
|
+
};
|
|
7684
|
+
}
|
|
7685
|
+
return {
|
|
7686
|
+
...ref2,
|
|
7687
|
+
nullable: isNullable
|
|
7688
|
+
};
|
|
7689
|
+
}
|
|
7690
|
+
const componentName = resolveComponentName(targetTable, options);
|
|
7691
|
+
const ref = ensureComponentRef(
|
|
7692
|
+
targetTable,
|
|
7693
|
+
componentName,
|
|
7694
|
+
context,
|
|
7695
|
+
() => extractFullTableSchema(targetTable, context, options)
|
|
7696
|
+
);
|
|
7697
|
+
if (relationType === "array") {
|
|
7698
|
+
return {
|
|
7699
|
+
type: "array",
|
|
7700
|
+
items: ref,
|
|
7701
|
+
nullable: isNullable
|
|
7702
|
+
};
|
|
7703
|
+
}
|
|
7704
|
+
return {
|
|
7705
|
+
...ref,
|
|
7706
|
+
nullable: isNullable
|
|
7707
|
+
};
|
|
7708
|
+
}
|
|
7605
7709
|
let targetSchema;
|
|
7606
7710
|
if (relationPlan && selectedColumns.length > 0) {
|
|
7607
7711
|
const plan = {
|
|
@@ -7629,16 +7733,76 @@ var extractRelationSchema = (relation, relationPlan, selectedColumns, context, o
|
|
|
7629
7733
|
description: targetSchema.description
|
|
7630
7734
|
};
|
|
7631
7735
|
};
|
|
7632
|
-
|
|
7633
|
-
|
|
7634
|
-
|
|
7635
|
-
|
|
7636
|
-
|
|
7637
|
-
|
|
7736
|
+
|
|
7737
|
+
// src/openapi/schema-extractor.ts
|
|
7738
|
+
var DEFAULT_MAX_DEPTH = 5;
|
|
7739
|
+
var extractSchema = (table, plan, projectionNodes, options = {}) => {
|
|
7740
|
+
const outputOptions = resolveOutputOptions(options);
|
|
7741
|
+
const outputContext = createContext(outputOptions.maxDepth ?? DEFAULT_MAX_DEPTH);
|
|
7742
|
+
if (outputOptions.refMode === "components") {
|
|
7743
|
+
outputContext.components = { schemas: {} };
|
|
7744
|
+
}
|
|
7745
|
+
const outputSchema = extractOutputSchema(table, plan, projectionNodes, outputContext, outputOptions);
|
|
7746
|
+
let output = outputSchema;
|
|
7747
|
+
const useSelected = shouldUseSelectedSchema(outputOptions, plan, projectionNodes);
|
|
7748
|
+
const hasComputedFields = hasComputedProjection(projectionNodes);
|
|
7749
|
+
const canUseComponents = outputOptions.refMode === "components" && outputContext.components && !hasComputedFields;
|
|
7750
|
+
if (canUseComponents) {
|
|
7751
|
+
const componentName = useSelected && plan ? resolveSelectedComponentName(table, plan, outputOptions) : resolveComponentName(table, outputOptions);
|
|
7752
|
+
registerComponentSchema(componentName, outputSchema, outputContext);
|
|
7753
|
+
if (outputOptions.outputAsRef) {
|
|
7754
|
+
output = { $ref: `#/components/schemas/${componentName}` };
|
|
7638
7755
|
}
|
|
7639
|
-
}
|
|
7640
|
-
|
|
7756
|
+
}
|
|
7757
|
+
const inputOptions = resolveInputOptions(options);
|
|
7758
|
+
if (!inputOptions) {
|
|
7759
|
+
return {
|
|
7760
|
+
output,
|
|
7761
|
+
components: outputContext.components && Object.keys(outputContext.components.schemas).length ? outputContext.components : void 0
|
|
7762
|
+
};
|
|
7763
|
+
}
|
|
7764
|
+
const inputContext = createContext(inputOptions.maxDepth ?? DEFAULT_MAX_DEPTH);
|
|
7765
|
+
const input = extractInputSchema(table, inputContext, inputOptions);
|
|
7766
|
+
return {
|
|
7767
|
+
output,
|
|
7768
|
+
input,
|
|
7769
|
+
components: outputContext.components && Object.keys(outputContext.components.schemas).length ? outputContext.components : void 0
|
|
7770
|
+
};
|
|
7771
|
+
};
|
|
7772
|
+
var resolveOutputOptions = (options) => ({
|
|
7773
|
+
mode: options.mode ?? "full",
|
|
7774
|
+
includeDescriptions: options.includeDescriptions,
|
|
7775
|
+
includeEnums: options.includeEnums,
|
|
7776
|
+
includeExamples: options.includeExamples,
|
|
7777
|
+
includeDefaults: options.includeDefaults,
|
|
7778
|
+
includeNullable: options.includeNullable,
|
|
7779
|
+
maxDepth: options.maxDepth ?? DEFAULT_MAX_DEPTH,
|
|
7780
|
+
refMode: options.refMode ?? "inline",
|
|
7781
|
+
selectedRefMode: options.selectedRefMode ?? "inline",
|
|
7782
|
+
componentName: options.componentName,
|
|
7783
|
+
outputAsRef: options.outputAsRef ?? false
|
|
7641
7784
|
});
|
|
7785
|
+
var resolveInputOptions = (options) => {
|
|
7786
|
+
if (options.input === false) return void 0;
|
|
7787
|
+
const input = options.input ?? {};
|
|
7788
|
+
const mode = input.mode ?? "create";
|
|
7789
|
+
return {
|
|
7790
|
+
mode,
|
|
7791
|
+
includeRelations: input.includeRelations ?? true,
|
|
7792
|
+
relationMode: input.relationMode ?? "mixed",
|
|
7793
|
+
includeDescriptions: input.includeDescriptions ?? options.includeDescriptions,
|
|
7794
|
+
includeEnums: input.includeEnums ?? options.includeEnums,
|
|
7795
|
+
includeExamples: input.includeExamples ?? options.includeExamples,
|
|
7796
|
+
includeDefaults: input.includeDefaults ?? options.includeDefaults,
|
|
7797
|
+
includeNullable: input.includeNullable ?? options.includeNullable,
|
|
7798
|
+
maxDepth: input.maxDepth ?? options.maxDepth ?? DEFAULT_MAX_DEPTH,
|
|
7799
|
+
omitReadOnly: input.omitReadOnly ?? true,
|
|
7800
|
+
excludePrimaryKey: input.excludePrimaryKey ?? false,
|
|
7801
|
+
requirePrimaryKey: input.requirePrimaryKey ?? mode === "update",
|
|
7802
|
+
excludeRelationForeignKeys: input.excludeRelationForeignKeys ?? false,
|
|
7803
|
+
relationSelections: input.relationSelections
|
|
7804
|
+
};
|
|
7805
|
+
};
|
|
7642
7806
|
var schemaToJson = (schema, pretty = false) => {
|
|
7643
7807
|
return JSON.stringify(schema, null, pretty ? 2 : 0);
|
|
7644
7808
|
};
|