This release is 23 versions behind 1.4.9 — the latest version of @fedify/fedify. Jump to latest
Built and signed on GitHub ActionsBuilt and signed on GitHub Actions
Built and signed on GitHub Actions
An ActivityPub/fediverse server framework
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291import { getFieldName } from "./field.ts"; import type { PropertySchema, TypeSchema } from "./schema.ts"; import { areAllScalarTypes, emitOverride, getTypeGuards, getTypeNames, } from "./type.ts"; function generateParameterType( property: PropertySchema, types: Record<string, TypeSchema>, ): string { const range = property.range; const scalar = areAllScalarTypes(range, types); const code: string[] = []; if (property.functional || property.singularAccessor) { if (scalar) { code.push( `${property.singularName}?: ${getTypeNames(range, types)} | null;`, ); } else { code.push( `${property.singularName}?: ${ getTypeNames(range, types) } | URL | null;`, ); } } if (!property.functional) { if (scalar) { code.push( `${property.pluralName}?: (${getTypeNames(range, types, true)})[];`, ); } else { code.push( `${property.pluralName}?: (${getTypeNames(range, types)} | URL)[];`, ); } } return code.join("\n"); } async function* generateParametersType( typeUri: string, types: Record<string, TypeSchema>, parentheses = true, excludeProperties: string[] = [], ): AsyncIterable<string> { const type = types[typeUri]; if (parentheses) yield "{\n"; if (type.extends == null) { yield `id?: URL | null;\n`; } else { for await ( const code of generateParametersType(type.extends, types, false, [ ...excludeProperties, ...type.properties.map((p) => p.singularName), ]) ) { yield code; } } for (const property of type.properties) { if (excludeProperties.includes(property.singularName)) continue; yield generateParameterType(property, types); } if (parentheses) yield "}\n"; } export async function* generateConstructor( typeUri: string, types: Record<string, TypeSchema>, ): AsyncIterable<string> { const type = types[typeUri]; yield ` /** * Constructs a new instance of ${type.name} with the given values. * @param values The values to initialize the instance with. * @param options The options to use for initialization. */ constructor( values: `; for await (const code of generateParametersType(typeUri, types)) yield code; yield `, { documentLoader, contextLoader, tracerProvider, }: { documentLoader?: DocumentLoader, contextLoader?: DocumentLoader, tracerProvider?: TracerProvider, } = {}, ) { `; if (type.extends == null) { yield ` this.#documentLoader = documentLoader; this.#contextLoader = contextLoader; this.#tracerProvider = tracerProvider; if (values.id == null || values.id instanceof URL) { this.id = values.id ?? null; } else { throw new TypeError("The id must be a URL."); } `; } else { yield "super(values, { documentLoader, contextLoader, tracerProvider });"; } for (const property of type.properties) { const fieldName = await getFieldName(property.uri); if (property.functional || property.singularAccessor) { let typeGuards = getTypeGuards( property.range, types, `values.${property.singularName}`, ); let typeNames = getTypeNames(property.range, types); const scalar = areAllScalarTypes(property.range, types); if (!scalar) { typeGuards = `${typeGuards} || values.${property.singularName} instanceof URL`; typeNames = `${typeNames} | URL`; } yield ` if ("${property.singularName}" in values && \ values.${property.singularName} != null) { if (${typeGuards}) { // @ts-ignore: type is checked above. this.${fieldName} = [values.${property.singularName}]; } else { throw new TypeError( "The ${property.singularName} must be of type " + ${JSON.stringify(typeNames)} + ".", ); } } `; } if (!property.functional) { let typeGuards = getTypeGuards(property.range, types, `v`); let typeNames = getTypeNames(property.range, types); const scalar = areAllScalarTypes(property.range, types); if (!scalar) { typeGuards = `${typeGuards} || v instanceof URL`; typeNames = `${typeNames} | URL`; } yield ` if ("${property.pluralName}" in values && \ values.${property.pluralName} != null) { `; if (property.singularAccessor) { yield ` if ("${property.singularName}" in values && values.${property.singularName} != null) { throw new TypeError( "Cannot initialize both ${property.singularName} and " + "${property.pluralName} at the same time.", ); } `; } yield ` if (Array.isArray(values.${property.pluralName}) && values.${property.pluralName}.every(v => ${typeGuards})) { // @ts-ignore: type is checked above. this.${fieldName} = values.${property.pluralName}; } else { throw new TypeError( "The ${property.pluralName} must be an array of type " + ${JSON.stringify(typeNames)} + ".", ); } } `; } } yield "}\n"; } export async function* generateCloner( typeUri: string, types: Record<string, TypeSchema>, ): AsyncIterable<string> { const type = types[typeUri]; yield ` /** * Clones this instance, optionally updating it with the given values. * @param values The values to update the clone with. * @options The options to use for cloning. * @returns The cloned instance. */ ${emitOverride(typeUri, types)} clone( values: `; for await (const code of generateParametersType(typeUri, types)) yield code; yield ` = {}, options: { documentLoader?: DocumentLoader, contextLoader?: DocumentLoader, } = {} ): ${type.name} { `; if (type.extends == null) { yield ` // @ts-ignore: this.constructor is not recognized as a constructor, but it is. const clone: ${type.name} = new this.constructor( { id: values.id ?? this.id }, options ); `; } else { yield `const clone = super.clone(values, options) as unknown as ${type.name};`; } for (const property of type.properties) { const fieldName = await getFieldName(property.uri); yield `clone.${fieldName} = this.${fieldName};`; if (property.functional || property.singularAccessor) { let typeGuards = getTypeGuards( property.range, types, `values.${property.singularName}`, ); let typeNames = getTypeNames(property.range, types); const scalar = areAllScalarTypes(property.range, types); if (!scalar) { typeGuards = `${typeGuards} || values.${property.singularName} instanceof URL`; typeNames = `${typeNames} | URL`; } yield ` if ("${property.singularName}" in values && \ values.${property.singularName} != null) { if (${typeGuards}) { // @ts-ignore: type is checked above. clone.${fieldName} = [values.${property.singularName}]; } else { throw new TypeError( "The ${property.singularName} must be of type " + ${JSON.stringify(typeNames)} + ".", ); } } `; } if (!property.functional) { let typeGuards = getTypeGuards(property.range, types, `v`); let typeNames = getTypeNames(property.range, types); const scalar = areAllScalarTypes(property.range, types); if (!scalar) { typeGuards = `${typeGuards} || v instanceof URL`; typeNames = `${typeNames} | URL`; } yield ` if ("${property.pluralName}" in values && \ values.${property.pluralName} != null) { `; if (property.singularAccessor) { yield ` if ("${property.singularName}" in values && values.${property.singularName} != null) { throw new TypeError( "Cannot update both ${property.singularName} and " + "${property.pluralName} at the same time.", ); } `; } yield ` if (Array.isArray(values.${property.pluralName}) && values.${property.pluralName}.every(v => ${typeGuards})) { // @ts-ignore: type is checked above. clone.${fieldName} = values.${property.pluralName}; } else { throw new TypeError( "The ${property.pluralName} must be an array of type " + ${JSON.stringify(typeNames)} + ".", ); } } `; } } yield ` return clone; } `; }