UNPKG

webextensions-api-mock

Version:
260 lines (259 loc) 9.9 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); var SchemaType; (function (SchemaType) { SchemaType[SchemaType["Namespace"] = 1] = "Namespace"; SchemaType[SchemaType["Type"] = 2] = "Type"; SchemaType[SchemaType["ObjectProperty"] = 3] = "ObjectProperty"; })(SchemaType = exports.SchemaType || (exports.SchemaType = {})); /** Identifies either a NamespaceSchema or TypeSchema, and helps create schemaIds for references to other TypeSchemas. */ class SchemaId { constructor(name, type) { this.name = name; this.type = type; } get namespace() { if (this.type === SchemaType.Namespace) { return this.name; } else { return this.name.substring(0, this.name.lastIndexOf('.')); } } get namespaceId() { return this.type === SchemaType.Namespace ? this : new SchemaId(this.namespace, SchemaType.Namespace); } toString() { return `${SchemaType[this.type]}::${this.name}`; } withRef(refName) { const name = refName.includes('.') ? refName : `${this.namespace}.${refName}`; return new SchemaId(name, SchemaType.Type); } withObjectProperty(propertyName) { const suffix = propertyName || '{object}'; const name = `${this.name}::${suffix}`; return new SchemaId(name, SchemaType.ObjectProperty); } static withNamespace(namespace) { return new SchemaId(namespace.namespace, SchemaType.Namespace); } static withType(name) { return new SchemaId(name, SchemaType.Type); } } exports.SchemaId = SchemaId; var SchemaWalkerFlags; (function (SchemaWalkerFlags) { SchemaWalkerFlags[SchemaWalkerFlags["None"] = 0] = "None"; SchemaWalkerFlags[SchemaWalkerFlags["SuppressWarnings"] = 2] = "SuppressWarnings"; SchemaWalkerFlags[SchemaWalkerFlags["NoTypeValueReuse"] = 4] = "NoTypeValueReuse"; })(SchemaWalkerFlags = exports.SchemaWalkerFlags || (exports.SchemaWalkerFlags = {})); class SchemaWalker { constructor(delegate, flags) { this.types = new Map(); this.outs = new Map(); this.delegate = delegate; this.flags = flags || SchemaWalkerFlags.None; } walk(schemaNamespaces) { this.extractTypes(schemaNamespaces); this.extractNamespaces(schemaNamespaces); } extractTypes(schemaNamespaces) { Object.values(schemaNamespaces).forEach(namespaces => namespaces.forEach(namespace => { if (!namespace.types) { return; } namespace.types.forEach(type => { if (!type.id) return; const typeId = type.id.includes('.') ? type.id : `${namespace.namespace}.${type.id}`; this.types.set(typeId, { typeschema: type }); }); })); this.types.forEach((value, key) => { this.schema(SchemaId.withType(key), value.typeschema); }); } extractNamespaces(schemaNamespaces) { Object.values(schemaNamespaces).forEach(namespaces => namespaces.forEach(namespace => this.schema(SchemaId.withNamespace(namespace), namespace))); } schema(schemaId, schema, out) { if (schema.$import) { this.delegate.handleImport(schemaId, schema.$import, out); return undefined; } switch (schemaId.type) { case SchemaType.Namespace: // Fall through case SchemaType.ObjectProperty: return this.namespaceOrObjectProperty(schemaId, schema, out); case SchemaType.Type: return this.type(schemaId, schema); } } namespaceOrObjectProperty(schemaId, schema, out) { let node; if (schemaId.type === SchemaType.Namespace) { node = this.outs.get(schemaId.name); if (!node) { node = this.delegate.createNamespaceValue(schemaId, out); this.outs.set(schemaId.name, node); } } else { node = this.delegate.startObjectPropertyValue(schemaId, out); } if (!node) return; if (schema.properties) { Object.keys(schema.properties).forEach(propertyName => { if (!schema.properties) return; const property = schema.properties[propertyName]; const optional = property.optional || property.unsupported; const value = this.value(schemaId, property, node, propertyName); this.field(schemaId, propertyName, value, !!optional, node); }); } if (schema.functions) { schema.functions.forEach(fn => { if (!fn.name || fn.type !== 'function') { return; } const optional = fn.optional || fn.unsupported; const value = this.fn(schemaId, fn, node); this.field(schemaId, fn.name, value, !!optional, node); }); } if (schema.events) { schema.events.forEach(event => { if (!event.name || event.type !== 'function') { return; } const value = this.event(schemaId, node); this.field(schemaId, event.name, value, false, node); }); } if (schemaId.type === SchemaType.ObjectProperty) { const newNode = this.delegate.finishObjectPropertyValue(schemaId, node); if (newNode) node = newNode; } return node; } field(schemaId, name, value, optional, out) { if (value === undefined) { return; } this.delegate.handleField(schemaId, name, value, optional, out); } type(schemaId, schema) { let node = this.outs.get(schemaId.name); if (!node || this.flags & SchemaWalkerFlags.NoTypeValueReuse) { // Circular-reference check const type = this.types.get(schemaId.name); if (type) { if (type.locked) { return this.delegate.valueForCircularType(schemaId); } else { type.locked = true; } } // Create namespace if needed let out = this.outs.get(schemaId.namespace); if (!out) { out = this.schema(schemaId.namespaceId, {}); } // Create type value node = this.value(schemaId, schema, out); if (node) { const newNode = this.delegate.finishTypeValue(schemaId, node, out); if (newNode) node = newNode; this.outs.set(schemaId.name, node); } if (type) type.locked = false; } return node; } value(schemaId, schema, out, name) { if (schema.value) { return schema.value; } else if (schema.$ref) { return this.ref(schemaId.withRef(schema.$ref)); } else if (schema.enum) { const enums = schema.enum.map(enumObj => { return typeof enumObj === 'object' ? enumObj.name : enumObj; }); return this.delegate.createEnumValue(schemaId, schema.type || 'string', enums, out); } else if (schema.type) { switch (schema.type) { case 'string': // Fall through case 'boolean': // Fall through case 'integer': // Fall through case 'number': // Fall through case 'any': // Fall through case 'choices': // Fall through return this.delegate.createPlainValue(schemaId, schema.type, false, out); case 'array': const items = schema.items; if (items) { const arrayType = this.value(schemaId, items, out, name) || 'any'; return this.delegate.createPlainValue(schemaId, arrayType, true, out); } else { return undefined; } case 'function': return this.fn(schemaId, schema, out); case 'event': return this.event(schemaId, out); case 'object': return this.schema(schemaId.withObjectProperty(name), schema, out); } } else if (schema.choices) { return this.delegate.createPlainValue(schemaId, 'choices', false, out); } } event(schemaId, out) { return this.delegate.createEventValue(schemaId, out); } fn(schemaId, schema, out) { let returnValue = undefined; if (schema.returns && schema.returns.$ref) { returnValue = this.ref(schemaId.withRef(schema.returns.$ref)); } return this.delegate.createFnValue(schemaId, returnValue, out); } ref(schemaId) { var _a, _b, _c; const schema = (_a = this.types.get(schemaId.name)) === null || _a === void 0 ? void 0 : _a.typeschema; if (schema) { return this.schema(schemaId, schema); } else { if (((_c = (_b = process) === null || _b === void 0 ? void 0 : _b.env) === null || _c === void 0 ? void 0 : _c.NODE_ENV) !== 'production' && !(this.flags & SchemaWalkerFlags.SuppressWarnings)) { console.warn(`Ref not found '${schemaId.name}'`); } return this.delegate.valueForInvalidRef(schemaId); } } } exports.SchemaWalker = SchemaWalker;