UNPKG

@autorest/powershell

Version:
645 lines (643 loc) 38.6 kB
"use strict"; /*--------------------------------------------------------------------------------------------- * Copyright (c) Microsoft Corporation. All rights reserved. * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ Object.defineProperty(exports, "__esModule", { value: true }); exports.createSdkInlinedPropertiesPlugin = exports.singularize = void 0; const codemodel_1 = require("@autorest/codemodel"); const codegen_1 = require("@azure-tools/codegen"); const linq_1 = require("@azure-tools/linq"); const model_state_1 = require("../utils/model-state"); const schema_1 = require("../utils/schema"); const code_namer_1 = require("../utils/code-namer"); const utility_1 = require("../sdk/utility"); function getPluralizationService() { const result = new codegen_1.EnglishPluralizationService(); result.addWord('Database', 'Databases'); result.addWord('database', 'databases'); result.addWord('Premise', 'Premises'); result.addWord('premise', 'premises'); return result; } function singularize(word) { return getPluralizationService().singularize(word); } exports.singularize = singularize; function getNameOptions(typeName, components) { const result = new Set(); // add a variant for each incrementally inclusive parent naming scheme. for (let i = 0; i < (0, linq_1.length)(components); i++) { const subset = (0, codegen_1.pascalCase)([...(0, codegen_1.removeSequentialDuplicates)(components.slice(-1 * i, (0, linq_1.length)(components)))]); result.add(subset); } // add a second-to-last-ditch option as <typename>.<name> result.add((0, codegen_1.pascalCase)([...(0, codegen_1.removeSequentialDuplicates)([...(0, codegen_1.fixLeadingNumber)((0, codegen_1.deconstruct)(typeName)), ...(0, codegen_1.deconstruct)(components.last)])])); return [...result.values()]; } function createVirtualProperties(schema, stack, conflicts) { var _a, _b, _c; // Some properties should be removed are wrongly kept as null and need to clean them if (schema.properties) { schema.properties = schema.properties.filter(each => each); } // dolauli // owned: all properties(obj & nonobj) in the schema, // inherited: Properties from parents, // inlined: for obj properties, flatten them to children, // did we already inline this object if (schema.language.default.inline === 'yes') { return true; } if (schema.language.default.inline === 'no') { return false; } // this is bad. This would happen when we have a circular reference in the tree. // dolauli curious in which case this will happen, got it to use no-inline to skip inline and avoid circular reference if (schema.language.default.inline === 'inprogress') { let text = (`Note: during processing of '${schema.language.default.name}' a circular reference has been discovered.`); text += '\n In order to proceed, you must add a directive to indicate which model you want to not inline.\n'; text += '\ndirective:'; text += '\n- no-inline: # choose ONE of these models to disable inlining'; for (const each of stack) { text += (`\n - ${each} `); } text += '\n'; conflicts.push(text); /* `directive: - no-inline: - MyModel - YourModel - HerModel ` */ // `, and we're skipping inlining.\n ${stack.join(' => ')}`); // mark it as 'not-inlining' schema.language.default.inline = 'no'; return false; } // ok, set to in progress now. schema.language.default.inline = 'inprogress'; // virutual property set. const virtualProperties = schema.language.default.virtualProperties = { owned: new Array(), inherited: new Array(), inlined: new Array(), }; // First we should run thru the properties in parent classes and create inliners for each property they have. // dolauli handle properties in parents for (const parentSchema of (0, linq_1.values)((_a = schema.parents) === null || _a === void 0 ? void 0 : _a.immediate)) { // make sure that the parent is done. // Guess parent should always be an object. if (!(0, codemodel_1.isObjectSchema)(parentSchema)) continue; createVirtualProperties(parentSchema, [...stack, `${schema.language.default.name}`], conflicts); const parentProperties = parentSchema.language.default.virtualProperties || { owned: [], inherited: [], inlined: [], }; // now we go thru the parent's virutal properties and create our own copies for (const virtualProperty of [...parentProperties.inherited, ...parentProperties.inlined, ...parentProperties.owned]) { // make sure that we have a list of shared owners of this property. virtualProperty.sharedWith = virtualProperty.sharedWith || [virtualProperty]; // we are just copying over theirs to ours. const inheritedProperty = { name: (0, code_namer_1.getEscapedReservedName)(virtualProperty.name, 'Property'), property: virtualProperty.property, private: virtualProperty.private, nameComponents: virtualProperty.nameComponents, nameOptions: virtualProperty.nameOptions, accessViaProperty: virtualProperty, accessViaMember: virtualProperty, accessViaSchema: parentSchema, originalContainingSchema: virtualProperty.originalContainingSchema, description: virtualProperty.description, alias: [], create: virtualProperty.create, update: virtualProperty.update, read: virtualProperty.read, readOnly: virtualProperty.readOnly, required: virtualProperty.required, sharedWith: virtualProperty.sharedWith, serializedName: virtualProperty.serializedName }; // add it to the list of virtual properties that share this property. virtualProperty.sharedWith.push(inheritedProperty); // add it to this class. virtualProperties.inherited.push(inheritedProperty); } } // dolauli figure out object properties and non object properties in this class const [objectProperties, nonObjectProperties] = (0, linq_1.values)(schema.properties).bifurcate(each => !schema.language.default['skip-inline'] && // if this schema is marked skip-inline, none can be inlined, treat them all as straight properties. !each.schema.language.default['skip-inline'] && // if the property schema is marked skip-inline, then it should not be processed either. each.extensions && each.extensions['x-ms-client-flatten'] && // only flatten when x-ms-client-flatten is set each.schema.type === codemodel_1.SchemaType.Object && // is it an object (0, schema_1.getAllProperties)(each.schema).length > 0 // does it have properties (or inherit properties) ); // run thru the properties in this class. // dolauli handle properties in this class for (const property of objectProperties) { if ((0, code_namer_1.isReserved)(property.language.default.name)) { property.language.default.name = (0, codegen_1.camelCase)((0, code_namer_1.getEscapedReservedName)(property.language.default.name, 'Property')); } const mutability = (0, schema_1.getMutability)(property); const propertyName = property.language.default.name; // for each object member, make sure that it's inlined it's children that it can. createVirtualProperties(property.schema, [...stack, `${schema.language.default.name}`], conflicts); // this happens if there is a circular reference. // this means that this class should not attempt any inlining of that property at all . // dolauli pay attention to the condition check const isDict = property.schema.type === codemodel_1.SchemaType.Dictionary || ((_c = (_b = property.schema.parents) === null || _b === void 0 ? void 0 : _b.immediate) === null || _c === void 0 ? void 0 : _c.find((s) => s.type === codemodel_1.SchemaType.Dictionary)); const canInline = (!property.schema.language.default['skip-inline']) && (!property.schema.language.default.byReference) && (!isDict) && property.extensions && property.extensions['x-ms-client-flatten'] && property.schema.language.default.inline === 'yes'; // the target has properties that we can inline const virtualChildProperties = property.schema.language.default.virtualProperties || { owned: [], inherited: [], inlined: [], }; const allNotRequired = (0, linq_1.values)((0, schema_1.getAllPublicVirtualProperties)()).all(each => !each.property.language.default.required); if (canInline && (property.language.default.required || allNotRequired)) { // if the child property is low enough (or it's 'properties'), let's create virtual properties for each one. // create a private property for the inlined ones to use. const privateProperty = { name: (0, code_namer_1.getEscapedReservedName)((0, codegen_1.getPascalIdentifier)(propertyName), 'Property'), propertySchema: schema, property, nameComponents: [(0, codegen_1.getPascalIdentifier)(propertyName)], nameOptions: getNameOptions(schema.language.default.name, [propertyName]), private: true, description: property.summary || '', originalContainingSchema: schema, alias: [], required: property.required || property.language.default.required, serializedName: property.serializedName }; virtualProperties.owned.push(privateProperty); for (const inlinedProperty of [...virtualChildProperties.inherited, ...virtualChildProperties.owned]) { // child properties are be inlined without prefixing the name with the property name // unless there is a collision, in which case, we have to resolve // (scan back from the far right) // deeper child properties should be inlined with their parent's name // ie, this.[properties].owner.name should be this.ownerName // const proposedName = getPascalIdentifier(`${propertyName === 'properties' || /*objectProperties.length === 1*/ propertyName === 'error' ? '' : pascalCase(fixLeadingNumber(deconstruct(propertyName)).map(each => singularize(each)))} ${inlinedProperty.name}`); const proposedName = (0, codegen_1.getPascalIdentifier)(inlinedProperty.name); const components = [...(0, codegen_1.removeSequentialDuplicates)([propertyName, ...inlinedProperty.nameComponents])]; let readonly = inlinedProperty.readOnly || property.readOnly; const create = mutability.create && inlinedProperty.create && !readonly; const update = mutability.update && inlinedProperty.update && !readonly; const read = mutability.read && inlinedProperty.read; readonly = readonly || (read && !update && !create); virtualProperties.inlined.push({ name: (0, code_namer_1.getEscapedReservedName)(proposedName, 'Property'), property: inlinedProperty.property, private: inlinedProperty.private, nameComponents: components, nameOptions: getNameOptions(inlinedProperty.property.schema.language.default.name, components), accessViaProperty: privateProperty, accessViaMember: inlinedProperty, accessViaSchema: schema, originalContainingSchema: schema, description: inlinedProperty.description, alias: [], create: create, update: update, read: read, readOnly: readonly, required: inlinedProperty.required && privateProperty.required, serializedName: `${property.serializedName}.${inlinedProperty.serializedName}` }); } for (const inlinedProperty of [...virtualChildProperties.inlined]) { // child properties are be inlined without prefixing the name with the property name // unless there is a collision, in which case, we have to resolve // (scan back from the far right) // deeper child properties should be inlined with their parent's name // ie, this.[properties].owner.name should be this.ownerName const proposedName = (0, codegen_1.getPascalIdentifier)(inlinedProperty.name); let readonly = inlinedProperty.readOnly || property.readOnly; const create = mutability.create && inlinedProperty.create && !readonly; const update = mutability.update && inlinedProperty.update && !readonly; const read = mutability.read && inlinedProperty.read; readonly = readonly || (read && !update && !create); const components = [...(0, codegen_1.removeSequentialDuplicates)([propertyName, ...inlinedProperty.nameComponents])]; virtualProperties.inlined.push({ name: (0, code_namer_1.getEscapedReservedName)(proposedName, 'Property'), property: inlinedProperty.property, private: inlinedProperty.private, nameComponents: components, nameOptions: getNameOptions(inlinedProperty.property.schema.language.default.name, components), accessViaProperty: privateProperty, accessViaMember: inlinedProperty, accessViaSchema: schema, originalContainingSchema: schema, description: inlinedProperty.description, alias: [], create: create, update: update, read: read, readOnly: readonly, required: inlinedProperty.required && privateProperty.required, serializedName: `${property.serializedName}.${inlinedProperty.serializedName}` }); } } else { // otherwise, we're not below the threshold, and we should treat this as a non-inlined property nonObjectProperties.push(property); } } for (const property of nonObjectProperties) { if ((0, code_namer_1.isReserved)(property.language.default.name)) { property.language.default.name = (0, codegen_1.camelCase)((0, code_namer_1.getEscapedReservedName)(property.language.default.name, 'Property')); } const name = (0, code_namer_1.getEscapedReservedName)((0, codegen_1.getPascalIdentifier)(property.language.default.name), 'Property'); // this is not something that has properties, // so we don't need to do any inlining // however, we can add it to our list of virtual properties // so that our consumers can get it. const mutability = (0, schema_1.getMutability)(property); virtualProperties.owned.push({ name, property, nameComponents: [name], nameOptions: [name], description: property.summary || '', originalContainingSchema: schema, alias: [], create: mutability.create && !property.readOnly, update: mutability.update && !property.readOnly, read: mutability.read, readOnly: property.readOnly || (mutability.read && !mutability.create && !mutability.update), required: property.required || property.language.default.required, serializedName: `${property.serializedName}` }); } // resolve name collisions. const allProps = [...virtualProperties.owned, ...virtualProperties.inherited, ...virtualProperties.inlined]; const inlined = new Map(); for (const each of allProps) { // track number of instances of a given name. inlined.set(each.name, (inlined.get(each.name) || 0) + 1); } const usedNames = new Set(inlined.keys()); for (const each of virtualProperties.inlined.sort((a, b) => (0, linq_1.length)(a.nameOptions) - (0, linq_1.length)(b.nameOptions))) { const ct = inlined.get(each.name); if (ct && ct > 1) { // console.error(`Fixing collision on name ${each.name} #${ct} `); each.name = (0, codegen_1.selectName)(each.nameOptions, usedNames); } } schema.language.default.inline = 'yes'; return true; } function parameterGroupName(operationGroup, operation, groupExtension) { if (groupExtension && groupExtension['name']) { return (0, codegen_1.pascalCase)(groupExtension['name']); } else if (groupExtension && groupExtension['postfix']) { return `${(0, codegen_1.pascalCase)(operationGroup.$key)}${(0, codegen_1.pascalCase)(operation.operationId.split('_')[1] || '')}${(0, codegen_1.pascalCase)(groupExtension['postfix'])}`; } else { return `${(0, codegen_1.pascalCase)(operationGroup.$key)}${(0, codegen_1.pascalCase)(operation.operationId.split('_')[1] || '')}Parameters`; } } async function implementGroupParameters(state) { var _a; const parameterGroup = new Map(); const parameterGroupContainerHeader = new Map(); const parameterGroupContainerOthers = new Map(); const parameterAdded = new Map(); for (const operationGroup of state.model.operationGroups) { for (const operation of operationGroup.operations) { const operationGroupParameters = new Array(); // value means if the parameter is required const addedOperationGroupParameters = new Map(); for (const parameter of [...(operation.requests && operation.requests.length > 0 ? operation.requests[0].parameters || [] : []), ...(operation.parameters || [])]) { if (parameter.extensions && parameter.extensions['x-ms-parameter-grouping']) { const key = parameterGroupName(operationGroup, operation, parameter.extensions['x-ms-parameter-grouping']); if (((_a = parameter.protocol.http) === null || _a === void 0 ? void 0 : _a.in) === codemodel_1.ParameterLocation.Header) { parameterGroupContainerHeader.set(key, true); } else { parameterGroupContainerOthers.set(key, true); } const groupObj = parameterGroup.get(key) || new codemodel_1.ObjectSchema(key, ''); if (!parameterGroup.has(key)) { groupObj.extensions = {}; groupObj.extensions['x-ms-parameter-grouping'] = parameter.extensions['x-ms-parameter-grouping']; parameterGroup.set(key, groupObj); parameterAdded.set(key, []); state.model.schemas.objects = state.model.schemas.objects || []; state.model.schemas.objects.push(groupObj); } const prop = new codemodel_1.Property(parameter.language.default.name, parameter.language.default.description, parameter.schema, { required: parameter.required, }); if (parameterAdded.has(key) && (parameterAdded.get(key) || []).indexOf(parameter.language.default.name) === -1) { groupObj.addProperty(prop); parameterAdded.set(key, [...(parameterAdded.get(key) || []), parameter.language.default.name]); } if (!addedOperationGroupParameters.has(key)) { addedOperationGroupParameters.set(key, !!(parameter.required)); const groupParameter = new codemodel_1.Parameter((0, codegen_1.camelCase)(key), '', groupObj); groupParameter.protocol.http = groupParameter.protocol.http || new codemodel_1.Protocol(); groupParameter.protocol.http.in = 'complex'; operationGroupParameters.push(groupParameter); } else { if (!addedOperationGroupParameters.get(key)) { addedOperationGroupParameters.set(key, !!(parameter.required)); } } } else { continue; } } for (const groupParameter of operationGroupParameters) { groupParameter.required = addedOperationGroupParameters.get((0, codegen_1.pascalCase)(groupParameter.language.default.name)) || false; } operation.parameters = [...operationGroupParameters, ...(operation.parameters || [])]; } } implementGroupParametersForPagination(state, parameterGroup, parameterGroupContainerHeader, parameterGroupContainerOthers); } async function implementGroupParametersForPagination(state, GroupObjects, parameterGroupContainHeader, parameterGroupContainOthers) { var _a; const parameterGroup = new Map(); const parameterAdded = new Map(); for (const operationGroup of state.model.operationGroups) { for (const operation of operationGroup.operations) { if (!(operation.extensions && operation.extensions['x-ms-pageable'])) { // skip none pageable operations continue; } const operationGroupParameters = new Array(); // value means if the parameter is required const addedOperationGroupParameters = new Map(); for (const parameter of [...(operation.requests && operation.requests.length > 0 ? operation.requests[0].parameters || [] : []), ...(operation.parameters || [])]) { if (((_a = parameter.protocol.http) === null || _a === void 0 ? void 0 : _a.in) === codemodel_1.ParameterLocation.Header && parameter.extensions && parameter.extensions['x-ms-parameter-grouping']) { const key = parameterGroupName(operationGroup, operation, parameter.extensions['x-ms-parameter-grouping']); if (parameterGroupContainHeader.get(key) && parameterGroupContainOthers.get(key)) { const keyWithModel = `${key}Model`; const groupObj = parameterGroup.get(keyWithModel) || new codemodel_1.ObjectSchema(keyWithModel, ''); if (!parameterGroup.has(keyWithModel)) { groupObj.extensions = {}; groupObj.extensions['x-ms-parameter-grouping'] = parameter.extensions['x-ms-parameter-grouping']; parameterGroup.set(keyWithModel, groupObj); parameterAdded.set(keyWithModel, []); state.model.schemas.objects = state.model.schemas.objects || []; state.model.schemas.objects.push(groupObj); } const prop = new codemodel_1.Property(parameter.language.default.name, parameter.language.default.description, parameter.schema, { required: parameter.required, }); if (parameterAdded.has(keyWithModel) && (parameterAdded.get(keyWithModel) || []).indexOf(parameter.language.default.name) === -1) { groupObj.addProperty(prop); parameterAdded.set(keyWithModel, [...(parameterAdded.get(keyWithModel) || []), parameter.language.default.name]); } if (!addedOperationGroupParameters.has(keyWithModel)) { addedOperationGroupParameters.set(keyWithModel, !!(parameter.required)); const groupParameter = new codemodel_1.Parameter((0, codegen_1.camelCase)(keyWithModel), '', groupObj); groupParameter.protocol.http = groupParameter.protocol.http || new codemodel_1.Protocol(); groupParameter.protocol.http.in = 'complexHeader'; operationGroupParameters.push(groupParameter); } else { if (!addedOperationGroupParameters.get(keyWithModel)) { addedOperationGroupParameters.set(keyWithModel, !!(parameter.required)); } } } else if (parameterGroupContainHeader.get(key)) { if (!addedOperationGroupParameters.has(key)) { addedOperationGroupParameters.set(key, !!(parameter.required)); const groupParameter = new codemodel_1.Parameter((0, codegen_1.camelCase)(key), '', GroupObjects.get(key) || new codemodel_1.ObjectSchema(key, '')); groupParameter.protocol.http = groupParameter.protocol.http || new codemodel_1.Protocol(); groupParameter.protocol.http.in = 'complexHeader'; operationGroupParameters.push(groupParameter); } else { if (!addedOperationGroupParameters.get(key)) { addedOperationGroupParameters.set(key, !!(parameter.required)); } } } } else { continue; } } for (const groupParameter of operationGroupParameters) { groupParameter.required = addedOperationGroupParameters.get((0, codegen_1.pascalCase)(groupParameter.language.default.name)) || false; } operation.parameters = [...operationGroupParameters, ...(operation.parameters || [])]; } } } async function implementOdata(state) { const knownOdataParameters = ['$filter', '$top', '$orderby', '$skip', '$expand']; for (const operationGroup of state.model.operationGroups) { for (const operation of operationGroup.operations) { if (operation.extensions && operation.extensions['x-ms-odata']) { const odata = operation.extensions['x-ms-odata']; operation.parameters = (operation.parameters || []).filter(p => { var _a; return !(((_a = p.protocol.http) === null || _a === void 0 ? void 0 : _a.in) === 'query' && knownOdataParameters.indexOf((p.language.default.serializedName).toLowerCase()) > -1); }); const schemaName = odata.split('/').pop(); const odataSchema = (state.model.schemas.objects || []).find(s => (0, codegen_1.pascalCase)(s.language.default.name) === (0, codegen_1.pascalCase)(schemaName)) || new codemodel_1.ObjectSchema((0, codegen_1.pascalCase)(schemaName), ''); // add the odata parameter const odataParameter = new codemodel_1.Parameter('odataQuery', '', odataSchema, { extensions: { 'x-ms-odata': true }, protocol: { http: { in: 'query' } } }); operation.parameters.unshift(odataParameter); } } } } async function fixModelAsString(state) { for (const operationGroup of state.model.operationGroups) { for (const operation of operationGroup.operations) { (operation.parameters || []).forEach(function (parameter) { // This is a workaround for parameter with the schema x-ms-enum // since modelAsString will be dropped in m4 if (parameter.extensions && parameter.extensions['x-ms-model-as-string'] !== undefined) { parameter.schema.extensions = (parameter.schema.extensions || {}); parameter.schema.extensions['x-ms-model-as-string'] = parameter.extensions['x-ms-model-as-string']; } }); } } } async function implementHeaderResponse(state) { const headerSchemaMap = new Map(); const headerSchemaPropertiesMap = new Map(); for (const operationGroup of state.model.operationGroups) { for (const operation of operationGroup.operations) { for (const response of (0, linq_1.values)(operation.responses)) { if (response.protocol.http && response.protocol.http.headers) { const schemaName = (0, codegen_1.pascalCase)(operationGroup.$key + operation.language.default.name + 'Headers'); const headerSchema = headerSchemaMap.get(schemaName) || new codemodel_1.ObjectSchema(schemaName, ''); headerSchemaMap.set(schemaName, headerSchema); for (const header of (0, linq_1.values)(response.protocol.http.headers)) { if (headerSchemaPropertiesMap.has(schemaName) && (headerSchemaPropertiesMap.get(schemaName) || []).indexOf(header.language.default.name) !== -1) { continue; } else { headerSchemaPropertiesMap.set(schemaName, [...(headerSchemaPropertiesMap.get(schemaName) || []), header.language.default.name]); const property = new codemodel_1.Property((0, codegen_1.camelCase)(header.language.default.name), '', header.schema, { serializedName: header.header, required: header.required, readOnly: header.readOnly }); headerSchema.addProperty(property); } } } } } } headerSchemaMap.forEach((value, key) => { state.model.schemas.objects = state.model.schemas.objects || []; state.model.schemas.objects.push(value); }); } async function handlePayloadFlatteningThreshold(state) { const useDateTimeOffset = await state.getValue('useDateTimeOffset', false); const helper = new utility_1.Helper(useDateTimeOffset); const payloadFlatteningThreshold = await state.getValue('payload-flattening-threshold', 0); for (const operationGroup of state.model.operationGroups) { for (const operation of operationGroup.operations) { if (operation.requests && operation.requests[0].parameters) { const parameters = operation.requests[0].parameters; const bodyParameter = parameters.find(p => { var _a; return ((_a = p.protocol.http) === null || _a === void 0 ? void 0 : _a.in) === 'body'; }); if (bodyParameter && payloadFlatteningThreshold > 0) { const bodyParameterSchema = bodyParameter.schema; if (bodyParameterSchema.type === codemodel_1.SchemaType.Object) { const virtualProperties = (0, schema_1.getAllPublicVirtualProperties)(bodyParameterSchema.language.default.virtualProperties).filter(vp => !vp.readOnly && !(vp.required && (vp.property.schema.type === codemodel_1.SchemaType.Constant || helper.IsConstantEnumProperty(vp)))); if (virtualProperties.length <= payloadFlatteningThreshold && !(bodyParameter.schema.type === codemodel_1.SchemaType.Object && (bodyParameter.schema.discriminator || bodyParameter.schema.discriminatorValue))) { bodyParameter.extensions = bodyParameter.extensions || {}; bodyParameter.extensions['x-ms-client-flatten'] = true; } } } } } } } async function createVirtuals(state) { fixModelAsString(state); // add support for x-ms-odata implementOdata(state); // add support for x-ms-parameter-grouping await implementGroupParameters(state); // add support for header response await implementHeaderResponse(state); /* A model class should provide inlined properties for anything in a property called properties Classes that have $THRESHOLD number of properties should be inlined. Individual models can change the $THRESHOLD for generate */ const conflicts = new Array(); // Move additionalProperties from parent to properties. We need to complete it for all objects before createVirtualProperties for (const schema of (0, linq_1.values)(state.model.schemas.objects)) { moveAdditionalPropertiesFromParentToProperties(schema, state.model.schemas); } for (const schema of (0, linq_1.values)(state.model.schemas.objects)) { // did we already inline this object if (schema.language.default.inlined) { continue; } // we have an object, let's process it. createVirtualProperties(schema, new Array(), conflicts); } if ((0, linq_1.length)(conflicts) > 0) { // dolauli need to figure out how inline-properties is used in README.md state.error('You have one or more circular references in your model, you must add configuration entries to specify which models won\'t be inlined.', ['inline-properties']); for (const each of conflicts) { state.error(each, ['circular reference']); } throw new Error('Circular references exists, must mark models as `no-inline`'); } // handle payload-flattening-threshold // when this value is set, we will flatten the body parameter if the number of non-constant & non-readonly virtual properties is less than or equal to the threshold await handlePayloadFlatteningThreshold(state); return state.model; } function addPropertyWithDuplicateNameReverse(properties, duplicate) { let count = 0; properties.filter(property => { if (property.language.default.name.startsWith(duplicate.language.default.name)) { const name = property.language.default.name.substring(duplicate.language.default.name.length); if (name === '' || typeof Number(name) === 'number') { return true; } } return false; }).sort((a, b) => { const keyA = a.language.default.name.substring(duplicate.language.default.name.length); const keyB = b.language.default.name.substring(duplicate.language.default.name.length); const numA = keyA === '' ? 0 : Number(keyA); const numB = keyB === '' ? 0 : Number(keyB); return numA - numB; }).forEach(property => { const key = property.language.default.name.substring(duplicate.language.default.name.length); const num = key === '' ? 0 : Number(key); if (num === count) { property.language.default.name = duplicate.language.default.name + (++count); } }); properties.unshift(duplicate); } function moveAdditionalPropertiesFromParentToProperties(obj, schemas) { if (obj.parents) { let schema; if (Array.isArray(obj.parents.immediate)) { obj.parents.immediate = obj.parents.immediate.filter(parent => { var _a; if (parent.type === 'dictionary' && parent.language.default.name === obj.language.default.name && ((_a = schemas.dictionaries) === null || _a === void 0 ? void 0 : _a.find(dictionary => dictionary.language.default.name === parent.language.default.name))) { schema = parent; return false; } return true; }); } if (Array.isArray(obj.parents.all)) { obj.parents.all = obj.parents.all.filter(parent => { var _a; if (parent.type === 'dictionary' && parent.language.default.name === obj.language.default.name && ((_a = schemas.dictionaries) === null || _a === void 0 ? void 0 : _a.find(dictionary => dictionary.language.default.name === parent.language.default.name))) { schema = parent; return false; } return true; }); } if (schema) { schema.language.default.name = 'additionalProperties'; // eslint-disable-next-line @typescript-eslint/no-non-null-assertion if (schema.language.csharp) { schema.language.csharp.name = 'additionalProperties'; } const additionalProperties = new codemodel_1.Property('additionalProperties', schema.language.default.description, schema); additionalProperties.language.default = schema.language.default; if (!obj.properties) { obj.properties = []; } additionalProperties.language.default.flavor = 'additionalProperties'; addPropertyWithDuplicateNameReverse(obj.properties, additionalProperties); } } } async function createSdkInlinedPropertiesPlugin(service) { //const session = await startSession<PwshModel>(service, {}, codeModelSchema); //const result = tweakModelV2(session); const state = await new model_state_1.ModelState(service).init(); await service.writeFile({ filename: 'sdk-code-model-v4-create-virtual-properties-v2.yaml', content: (0, codegen_1.serialize)(await createVirtuals(state)), sourceMap: undefined, artifactType: 'code-model-v4' }); //return processCodeModel(createVirtuals, service, 'create-virtual-properties-v2'); } exports.createSdkInlinedPropertiesPlugin = createSdkInlinedPropertiesPlugin; //# sourceMappingURL=sdk-create-inline-properties.js.map