import { Logger } from "@lbu/insight"; import { AxiosInstance } from "axios"; /** * Check if value may be output object from a TypeBuilder */ export function isNamedTypeBuilderLike(value: any): boolean; /** * Load a LBU structure from an LBU enabled API */ export function loadFromRemote(axios: AxiosInstance, baseUrl: string): any; /** * Try to convert a OpenAPI spec object to LBU structure * @param defaultGroup Default to group to use for non tagged items in the spec * @param data Raw OpenAPI 3 json object */ export function loadFromOpenAPISpec(defaultGroup: string, data: any): any; interface AppOpts { verbose?: boolean; } interface GenerateOpts { /** * Enabling specific groups so different generator combinations can be used. * The machinery will automatically find referenced types and include those * If this is undefined, all groups will be enabled */ enabledGroups?: string[]; /** * Used to conditional generate various things. * Is inferred when the reactQuery generator is enabled. * isBrowser: true, * isNodeServer: false, * isNode: false, * enabledGenerators: ["type", "validator", "apiClient", "reactQuery"], * useTypescript: true, * dumpStructure: false, * dumpPostgres: false, */ isBrowser?: boolean; /** * Used to conditional generate various things. * Is inferred when the sql or router generator is enabled. * Has a higher precedence than isNode, but also implies isNode. * isBrowser: false, * isNodeServer: true, * isNode: true, * enabledGenerators: ["type", "validator", "sql", "router", "apiClient"], * useTypescript: false, * dumpStructure: true, * dumpPostgres: true, */ isNodeServer?: boolean; /** * Used to conditional generate various things. * Is inferred when the react-query generator is disabled. * Has a lower precedence than isServer. * isBrowser: false, * isNodeServer: false, * isNode: true, * enabledGenerators: ["type", "validator"], * useTypescript: false, * dumpStructure: false, * dumpPostgres: false, */ isNode?: boolean; /** * Enabling specific generators. * If this is undefined, all registered generators are enabled */ enabledGenerators?: string[]; /** * Enable Typescript for the generators that support it */ useTypescript?: boolean; /** * Dump a structure.js file with the used payload in it */ dumpStructure?: boolean; /** * Custom file header to for example disable linting or something */ fileHeader?: string; /** * Directory to write the files to */ outputDirectory: string; } /** * The entry-point to code generation * Provides the structure for creating types, and extending with external sources. * Also maintains the generators */ export class App { /** * List used in the file header to ignore some eslint rules */ static defaultEslintIgnore: string[]; /** * Enable more logging while generating */ public verbose: boolean; /** * Internally used logger */ public logger: Logger; /** * Create a new App instance and inits generators */ static new(options: AppOpts): Promise; /** * Add new TypeBuilders to this app */ add(...builders: TypeBuilder[]): App; /** * Add relations to the provided reference. * The provided reference must already exist. * This only works when referencing in to structure that you've passed in to * `app.extend`. */ addRelations(reference: ReferenceType, ...relations: RelationType[]): App; /** * Add a raw object to this app. * Note that it throws when you are not conforming to at least the structure from the * TypeBuilder */ addRaw(obj: any): App; /** * Add all groups and items to this App instance */ extend(data: any): App; /** * Call the generators with the provided options * and writes the output */ generate(options: GenerateOpts): Promise; } export type TypeBuilderLike = | boolean | number | string | TypeBuilderLikeArray | TypeBuilderLikeObject | TypeBuilder; interface TypeBuilderLikeArray extends Array {} interface TypeBuilderLikeObject extends Record {} /** * Create new instances of registered types and manages grups * Also keeps a Map of registered types on TypeCreator.types * * Note that all functions that return a `T extends TypeBuilder` are dynamically added and * provided by the core. */ export class TypeCreator { constructor(group?: string); /** * Represents any type */ any(name?: string): AnyType; /** * Represent one of the provided types. * @param name */ anyOf(name?: string): AnyOfType; /** * Represents a plain array */ array(name?: string): ArrayType; /** * Boolean support */ bool(name?: string): BooleanType; /** * Inputs ISO dates or js Date objects * @param name */ date(name?: string): DateType; /** * Formidable file object, Blob or Stream depending on the usecase * @param name */ file(name?: string): FileType; /** * A generic object, where both keys and values can be typed */ generic(name?: string): GenericType; /** * Any number, integer by default but floating point can be enabled * @param name */ number(name?: string): NumberType; /** * Plain old js object */ object(name?: string): ObjectType; /** * Omit keys from the provided object type */ omit(name?: string): OmitType; /** * Make a copy of the provided type, making it optional */ optional(name?: string): OptionalType; /** * Pick keys from the provided object type */ pick(name?: string): PickType; /** * Reference any other type, as if it was created inline */ reference(groupOrOther?: string | TypeBuilder, name?: string): ReferenceType; /** * Make a copy of the provided type, making it sql searchable */ searchable(name?: string): SearchableType; /** * Any string use case */ string(name?: string): StringType; /** * Verified uuid */ uuid(name?: string): UuidType; /** * Create a new RouteCreator * Provided by the 'router' generator */ router(path: string): RouteCreator; /** * Create a oneToMany relation */ oneToMany(ownKey: string, reference: ReferenceType): RelationType; /** * Create a manyOneMany relation */ manyToOne( ownKey: string, reference: ReferenceType, referencedKey: string, ): RelationType; /** * Create a oneToOne relation */ oneToOne( ownKey: string, reference: ReferenceType, referencedKey: string, ): RelationType; } /** * Provide base properties for types * This includes the 'type', optional, docs and default value. * Also contains group and name information */ export class TypeBuilder { static baseData: { type?: string; group?: string; name?: string; docString: string; isOptional: boolean; defaultValue?: string; }; static getBaseData(): typeof TypeBuilder.baseData; /** * Create a new TypeBuilder for the provided group */ constructor(type: string, group?: string, name?: string); public data: typeof TypeBuilder.baseData; /** * Add a doc comment, some generators / types may support rendering this */ docs(docValue: string): this; /** * Value can be undefined */ optional(): this; /** * Value may be null, only implemented for the primitives. */ allowNull(): this; /** * Set a raw default value, also makes the type optional * Can be reverted by calling this function with undefined or null */ default(rawString?: string | boolean | number): this; /** * Returns a shallow copy of the data object */ build(): Record; /** * Set this field as searchable for the 'sql' plugin */ searchable(): this; /** * Set this field as primary for the 'sql' plugin */ primary(): this; } /** * 'Router' plugin provided custom builder for api routes */ export class RouteBuilder extends TypeBuilder { /** * Add tags to this route. */ tags(...value: string[]): this; /** * Type of accepted query parameters */ query(builder: TypeBuilderLike): this; /** * Type of accepted path parameters */ params(builder: TypeBuilderLike): this; /** * Type of accepted body parameters */ body(builder: TypeBuilderLike): this; /** * Type of accepted file parameters */ files(builder: TypeBuilderLike): this; /** * Route response type */ response(builder: TypeBuilderLike): this; } export class RouteCreator { /** * Create a new route group. * Path will be concatenated with the current path of this group. * This resets the default tags, query, params, body and response type. */ group(name: string, path: string): this; /** * GET route */ get(path?: string, name?: string); /** * POST route */ post(path?: string, name?: string); /** * PUT route */ put(path?: string, name?: string); /** * PATCH route */ patch(path?: string, name?: string); /** * DELETE route */ delete(path?: string, name?: string); /** * HEAD route */ head(path?: string, name?: string); /** * Default tags for all routes created by this RouteCreator. */ tags(...value: string[]): this; /** * Default query type for all routes created by this RouteCreator. */ query(builder: TypeBuilderLike): this; /** * Default params type for all routes created by this RouteCreator. */ params(builder: TypeBuilderLike): this; /** * Default body type for all routes created by this RouteCreator. */ body(builder: TypeBuilderLike): this; /** * Default files type for all routes created by this RouteCreator. */ files(builder: TypeBuilderLike): this; /** * Default response type for all routes created by this RouteCreator. */ response(builder: TypeBuilderLike): this; } export class AnyType extends TypeBuilder { raw( value: string, importValue?: { javaScript?: string; typeScript?: string }, ): this; } export class AnyOfType extends TypeBuilder { values(...items: TypeBuilderLike[]): this; } export class ArrayType extends TypeBuilder { values(value: TypeBuilderLike): this; /** * Validator converts single item to an array */ convert(): this; /** * Validator enforced minimum length inclusive */ min(min: number): this; /** * Validator enforced maximum length inclusive */ max(max: number): this; } export class BooleanType extends TypeBuilder { /** * Only accepts a specific value */ oneOf(value: boolean): this; /** * Validator converts "true", "false", 0 and 1 to a boolean */ convert(): this; } export class DateType extends TypeBuilder { defaultToNow(): this; } export class FileType extends TypeBuilder {} export class GenericType extends TypeBuilder { keys(key: TypeBuilderLike): this; values(value: TypeBuilderLike): this; } export class NumberType extends TypeBuilder { /** * Only accepts a number from the provided set */ oneOf(...value: number[]): this; /** * Try to convert a string to a number in the validator */ convert(): this; /** * Validator does not enforce an integer */ float(): this; /** * Validator enforced minimum value inclusive */ min(min: number): this; /** * Validator enforced maximum value inclusive */ max(max: number): this; } export class ObjectType extends TypeBuilder { keys(obj: Record): this; /** * Validator allows extra keys on the incoming object */ loose(): this; /** * Generate sql queries for this object * Possibly adding createdAt and updatedAt fields. * When withSoftDeletes is true, it automatically enables withDates. * Added by the 'sql' plugin */ enableQueries(options?: { withSoftDeletes?: true; withDates?: true; withPrimaryKey?: false; isView?: true; }): this; /** * Add SQL relations */ relations(...relations: RelationType[]): this; } export class OmitType extends TypeBuilder { /** * Set the object to operate on */ object(builder: ObjectType | TypeBuilderLikeObject): this; /** * Keys to remove from the provided builder */ keys(...keys: string[]): this; } export class OptionalType extends TypeBuilder { /** * Set the type to operate on */ value(builder: TypeBuilderLike): this; } export class PickType extends TypeBuilder { /** * Set the object to operate on */ object(builder: ObjectType | TypeBuilderLikeObject): this; /** * Keys to keep from the provided builder */ keys(...keys: string[]): this; } export class ReferenceType extends TypeBuilder {} /** * Relations are created by `T.oneToMany`, `T.manyToOne`, etc * The generator will warn you when relations are missing. */ export class RelationType { constructor( subType: string, ownKey: string, reference: ReferenceType, referencedKey?: string, ); /** * Make this side of the relation optional */ optional(): this; } export class SearchableType extends TypeBuilder { /** * Set the type to operate on */ value(builder: TypeBuilderLike): this; } export class StringType extends TypeBuilder { /** * Only accepts a string from the provided set. * Also the way to make enums */ oneOf(...values: string[]): this; /** * Validator tries to convert to string */ convert(): this; /** * Validator trims the input */ trim(): this; /** * Validator upper cases the input */ upperCase(): this; /** * Validator lower cases the input */ lowerCase(): this; /** * Validator enforced minimum length inclusive */ min(min: number): this; /** * Validator enforced maximum length inclusive */ max(max: number): this; /** * Validator enforced pattern */ pattern(pattern: RegExp): this; } export class UuidType extends TypeBuilder {} /** * Returns the list of groups that contain an item with the specified type. * Can be used to find all groups that expose part of the apiClient. */ export function getGroupsThatIncludeType(data: any, type: string): string[];