diff --git a/packages/js-client/.gitignore b/packages/js-client/.gitignore new file mode 100644 index 0000000000..4753a3167d --- /dev/null +++ b/packages/js-client/.gitignore @@ -0,0 +1,3 @@ +# this file will be autognereated +src/index.ts + diff --git a/packages/js-client/src/ast/helpers.test.ts b/packages/js-client/src/ast/helpers.test.ts new file mode 100644 index 0000000000..c93e12af43 --- /dev/null +++ b/packages/js-client/src/ast/helpers.test.ts @@ -0,0 +1,853 @@ +import { test, expect, describe } from 'vitest' + +import { createMethodParams, createTypeFromSchema, printNode } from './helpers.js' +import type { Parameter } from './open-api.js' + +test('should create a simple string type literal property', () => { + const node = createTypeFromSchema({ state: { type: 'string' } }) + expect(printNode(node)).toMatchInlineSnapshot(` + "{ + state?: string; + }" + `) +}) + +test('should create a simple string[] type literal property', () => { + const node = createTypeFromSchema({ state: { type: 'array', items: { type: 'string' } } }) + expect(printNode(node)).toMatchInlineSnapshot(` + "{ + state?: string[]; + }" + `) +}) + +test('should create complex type literal with enums and description', () => { + const schema = { + type: 'object', + properties: { + state: { type: 'string' }, + domains: { type: 'array', items: { type: 'string' } }, + scopes: { + type: 'array', + items: { + type: 'string', + enum: ['builds', 'functions', 'runtime', 'post-processing'], + }, + description: 'The scopes that this environment variable is set to', + }, + created_at: { type: 'string' }, + }, + } + const node = createTypeFromSchema(schema.properties) + expect(printNode(node)).toMatchInlineSnapshot(` + "{ + state?: string; + domains?: string[]; + /** The scopes that this environment variable is set to */ + scopes?: (\\"builds\\" | \\"functions\\" | \\"runtime\\" | \\"post-processing\\")[]; + created_at?: string; + }" + `) +}) + +test('create a type literal with nested objects', () => { + const schema = { + type: 'object', + properties: { + key: { + type: 'string', + description: 'The environment variable key, like ALGOLIA_ID (case-sensitive)', + }, + scopes: { + type: 'array', + items: { + type: 'string', + enum: ['builds', 'functions', 'runtime', 'post-processing'], + }, + description: 'The scopes that this environment variable is set to', + }, + values: { + type: 'array', + items: { + type: 'object', + properties: { + id: { + type: 'string', + description: "The environment variable value's universally unique ID", + }, + value: { + type: 'string', + description: "The environment variable's unencrypted value", + }, + context: { + type: 'string', + enum: ['all', 'dev', 'branch-deploy', 'deploy-preview', 'production', 'branch'], + description: + 'The deploy context in which this value will be used. `dev` refers to local development when running `netlify dev`.', + }, + context_parameter: { + type: 'string', + description: + 'An additional parameter for custom branches. Currently, this is used for specifying a branch name when `context=branch`.', + }, + }, + description: 'Environment variable value model definition', + }, + description: 'An array of Value objects containing values and metadata', + }, + is_secret: { + type: 'boolean', + description: + 'Secret values are only readable by code running on Netlify’s systems. With secrets, only the local development context values are readable from the UI, API, and CLI. By default, environment variable values are not secret. (Enterprise plans only)', + }, + updated_at: { + type: 'string', + format: 'date-time', + description: 'The timestamp of when the value was last updated', + }, + updated_by: { + type: 'object', + properties: { + id: { + type: 'string', + description: "The user's unique identifier", + }, + full_name: { + type: 'string', + description: "The user's full name (first and last)", + }, + email: { + type: 'string', + description: "The user's email address", + }, + avatar_url: { + type: 'string', + description: "A URL pointing to the user's avatar", + }, + }, + }, + }, + description: 'Environment variable model definition', + } + + const node = createTypeFromSchema(schema.properties) + expect(printNode(node)).toMatchInlineSnapshot(` + "{ + /** The environment variable key, like ALGOLIA_ID (case-sensitive) */ + key?: string; + /** The scopes that this environment variable is set to */ + scopes?: (\\"builds\\" | \\"functions\\" | \\"runtime\\" | \\"post-processing\\")[]; + /** An array of Value objects containing values and metadata */ + values?: { + /** The environment variable value's universally unique ID */ + id?: string; + /** The environment variable's unencrypted value */ + value?: string; + /** The deploy context in which this value will be used. \`dev\` refers to local development when running \`netlify dev\`. */ + context?: \\"all\\" | \\"dev\\" | \\"branch-deploy\\" | \\"deploy-preview\\" | \\"production\\" | \\"branch\\"; + /** An additional parameter for custom branches. Currently, this is used for specifying a branch name when \`context=branch\`. */ + context_parameter?: string; + }[]; + /** Secret values are only readable by code running on Netlify’s systems. With secrets, only the local development context values are readable from the UI, API, and CLI. By default, environment variable values are not secret. (Enterprise plans only) */ + is_secret?: boolean; + /** The timestamp of when the value was last updated */ + updated_at?: string; + updated_by?: { + /** The user's unique identifier */ + id?: string; + /** The user's full name (first and last) */ + full_name?: string; + /** The user's email address */ + email?: string; + /** A URL pointing to the user's avatar */ + avatar_url?: string; + }; + }" + `) +}) + +describe('method parameter rendering', () => { + test('render swagger parameters as a method parameter', () => { + const params: Parameter[] = [ + { + name: 'account_id', + description: 'Scope response to account_id', + type: 'string', + required: true, + in: 'path', + }, + { + name: 'key', + description: 'The environment variable key (case-sensitive)', + type: 'string', + required: true, + in: 'path', + }, + { + name: 'site_id', + description: 'If provided, return the environment variable for a specific site (no merging is performed)', + type: 'string', + required: false, + in: 'query', + }, + ] + + const node = createMethodParams(params)[0] + expect(printNode(node)).toMatchInlineSnapshot(` + "config: { + /** Scope response to account_id */ + account_id: string; + /** The environment variable key (case-sensitive) */ + key: string; + /** If provided, return the environment variable for a specific site (no merging is performed) */ + site_id?: string; + }" + `) + }) + + test('render swagger parameters that are all optional as a method parameter', () => { + const params: Parameter[] = [ + { + name: 'account_id', + description: 'Scope response to account_id', + type: 'string', + required: false, + in: 'path', + }, + { + name: 'key', + description: 'The environment variable key (case-sensitive)', + type: 'string', + in: 'path', + }, + { + name: 'site_id', + description: 'If provided, return the environment variable for a specific site (no merging is performed)', + type: 'string', + in: 'query', + }, + ] + + const node = createMethodParams(params) + expect(printNode(node[0])).toMatchInlineSnapshot(` + "config: { + /** Scope response to account_id */ + account_id?: string; + /** The environment variable key (case-sensitive) */ + key?: string; + /** If provided, return the environment variable for a specific site (no merging is performed) */ + site_id?: string; + } = {}" + `) + }) + + test('render nested swagger parameters', () => { + const params: Parameter[] = [ + { + name: 'dns_record', + in: 'body', + required: false, + schema: { + type: 'object', + properties: { + type: { + type: 'string', + }, + hostname: { + type: 'string', + }, + }, + }, + description: 'some description', + }, + { + name: 'other', + in: 'body', + required: false, + type: 'string', + }, + ] + const node = createMethodParams(params)[0] + expect(printNode(node)).toMatchInlineSnapshot(` + "config: { + type?: string; + hostname?: string; + other?: string; + } = {}" + `) + }) + + test('render generic object as parameter', () => { + const params: Parameter[] = [ + { + name: 'branch_tests', + in: 'body', + required: true, + schema: { + type: 'object', + properties: { + branch_tests: { + type: 'object', + }, + }, + }, + }, + ] + const node = createMethodParams(params)[0] + expect(printNode(node)).toMatchInlineSnapshot(` + "config: { + branch_tests?: object; + }" + `) + }) + + test('render parameter with allOf schema', () => { + const params: Parameter[] = [ + { + name: 'site', + in: 'body', + schema: { + allOf: [ + { + type: 'object', + properties: { + id: { + type: 'string', + }, + state: { + type: 'string', + }, + plan: { + type: 'string', + }, + name: { + type: 'string', + }, + custom_domain: { + type: 'string', + }, + domain_aliases: { + type: 'array', + items: { + type: 'string', + }, + }, + branch_deploy_custom_domain: { + type: 'string', + }, + deploy_preview_custom_domain: { + type: 'string', + }, + password: { + type: 'string', + }, + notification_email: { + type: 'string', + }, + url: { + type: 'string', + }, + ssl_url: { + type: 'string', + }, + admin_url: { + type: 'string', + }, + screenshot_url: { + type: 'string', + }, + created_at: { + type: 'string', + format: 'dateTime', + }, + updated_at: { + type: 'string', + format: 'dateTime', + }, + user_id: { + type: 'string', + }, + session_id: { + type: 'string', + }, + ssl: { + type: 'boolean', + }, + force_ssl: { + type: 'boolean', + }, + managed_dns: { + type: 'boolean', + }, + deploy_url: { + type: 'string', + }, + published_deploy: { + type: 'object', + properties: { + id: { + type: 'string', + }, + site_id: { + type: 'string', + }, + user_id: { + type: 'string', + }, + build_id: { + type: 'string', + }, + state: { + type: 'string', + }, + name: { + type: 'string', + }, + url: { + type: 'string', + }, + ssl_url: { + type: 'string', + }, + admin_url: { + type: 'string', + }, + deploy_url: { + type: 'string', + }, + deploy_ssl_url: { + type: 'string', + }, + screenshot_url: { + type: 'string', + }, + review_id: { + type: 'number', + }, + draft: { + type: 'boolean', + }, + required: { + type: 'array', + items: { + type: 'string', + }, + }, + required_functions: { + type: 'array', + items: { + type: 'string', + }, + }, + error_message: { + type: 'string', + }, + branch: { + type: 'string', + }, + commit_ref: { + type: 'string', + }, + commit_url: { + type: 'string', + }, + skipped: { + type: 'boolean', + }, + created_at: { + type: 'string', + format: 'dateTime', + }, + updated_at: { + type: 'string', + format: 'dateTime', + }, + published_at: { + type: 'string', + format: 'dateTime', + }, + title: { + type: 'string', + }, + context: { + type: 'string', + }, + locked: { + type: 'boolean', + }, + review_url: { + type: 'string', + }, + site_capabilities: { + type: 'object', + properties: { + large_media_enabled: { + type: 'boolean', + }, + }, + }, + framework: { + type: 'string', + }, + function_schedules: { + type: 'array', + items: { + type: 'object', + properties: { + name: { + type: 'string', + }, + cron: { + type: 'string', + }, + }, + }, + }, + }, + }, + account_name: { + type: 'string', + }, + account_slug: { + type: 'string', + }, + git_provider: { + type: 'string', + }, + deploy_hook: { + type: 'string', + }, + capabilities: { + type: 'object', + additionalProperties: { + type: 'object', + }, + }, + processing_settings: { + type: 'object', + properties: { + skip: { + type: 'boolean', + }, + css: { + type: 'object', + properties: { + bundle: { + type: 'boolean', + }, + minify: { + type: 'boolean', + }, + }, + }, + js: { + type: 'object', + properties: { + bundle: { + type: 'boolean', + }, + minify: { + type: 'boolean', + }, + }, + }, + images: { + type: 'object', + properties: { + optimize: { + type: 'boolean', + }, + }, + }, + html: { + type: 'object', + properties: { + pretty_urls: { + type: 'boolean', + }, + }, + }, + }, + }, + build_settings: { + type: 'object', + properties: { + id: { + type: 'integer', + }, + provider: { + type: 'string', + }, + deploy_key_id: { + type: 'string', + }, + repo_path: { + type: 'string', + }, + repo_branch: { + type: 'string', + }, + dir: { + type: 'string', + }, + functions_dir: { + type: 'string', + }, + cmd: { + type: 'string', + }, + allowed_branches: { + type: 'array', + items: { + type: 'string', + }, + }, + public_repo: { + type: 'boolean', + }, + private_logs: { + type: 'boolean', + }, + repo_url: { + type: 'string', + }, + env: { + type: 'object', + additionalProperties: { + type: 'string', + }, + }, + installation_id: { + type: 'integer', + }, + stop_builds: { + type: 'boolean', + }, + }, + }, + id_domain: { + type: 'string', + }, + default_hooks_data: { + type: 'object', + properties: { + access_token: { + type: 'string', + }, + }, + }, + }, + }, + { + properties: { + repo: { + type: 'object', + properties: { + allowed_branches: { + type: 'array', + items: { + type: 'string', + }, + }, + repo_url: { + type: 'string', + }, + env: { + type: 'object', + additionalProperties: { + type: 'string', + }, + }, + }, + }, + }, + }, + ], + }, + }, + { + name: 'configure_dns', + type: 'boolean', + in: 'query', + }, + { + name: 'account_slug', + in: 'path', + type: 'string', + required: true, + }, + ] + const node = createMethodParams(params)[0] + expect(printNode(node)).toMatchInlineSnapshot(` + "config: { + site?: { + id?: string; + state?: string; + plan?: string; + name?: string; + custom_domain?: string; + domain_aliases?: string[]; + branch_deploy_custom_domain?: string; + deploy_preview_custom_domain?: string; + password?: string; + notification_email?: string; + url?: string; + ssl_url?: string; + admin_url?: string; + screenshot_url?: string; + created_at?: string; + updated_at?: string; + user_id?: string; + session_id?: string; + ssl?: boolean; + force_ssl?: boolean; + managed_dns?: boolean; + deploy_url?: string; + published_deploy?: { + id?: string; + site_id?: string; + user_id?: string; + build_id?: string; + state?: string; + name?: string; + url?: string; + ssl_url?: string; + admin_url?: string; + deploy_url?: string; + deploy_ssl_url?: string; + screenshot_url?: string; + review_id?: number; + draft?: boolean; + required?: string[]; + required_functions?: string[]; + error_message?: string; + branch?: string; + commit_ref?: string; + commit_url?: string; + skipped?: boolean; + created_at?: string; + updated_at?: string; + published_at?: string; + title?: string; + context?: string; + locked?: boolean; + review_url?: string; + site_capabilities?: { + large_media_enabled?: boolean; + }; + framework?: string; + function_schedules?: { + name?: string; + cron?: string; + }[]; + }; + account_name?: string; + account_slug?: string; + git_provider?: string; + deploy_hook?: string; + capabilities?: object; + processing_settings?: { + skip?: boolean; + css?: { + bundle?: boolean; + minify?: boolean; + }; + js?: { + bundle?: boolean; + minify?: boolean; + }; + images?: { + optimize?: boolean; + }; + html?: { + pretty_urls?: boolean; + }; + }; + build_settings?: { + id?: number; + provider?: string; + deploy_key_id?: string; + repo_path?: string; + repo_branch?: string; + dir?: string; + functions_dir?: string; + cmd?: string; + allowed_branches?: string[]; + public_repo?: boolean; + private_logs?: boolean; + repo_url?: string; + env?: object; + installation_id?: number; + stop_builds?: boolean; + }; + id_domain?: string; + default_hooks_data?: { + access_token?: string; + }; + repo?: { + allowed_branches?: string[]; + repo_url?: string; + env?: object; + }; + }; + configure_dns?: boolean; + account_slug: string; + }" + `) + }) + + test('render parameter with schema object', () => { + const params: Parameter[] = [ + { + name: 'accountAddMemberSetup', + in: 'body', + schema: { + type: 'object', + properties: { + role: { + type: 'string', + enum: ['Owner', 'Collaborator', 'Controller'], + }, + email: { + type: 'string', + }, + }, + }, + required: true, + }, + ] + const node = createMethodParams(params)[0] + expect(printNode(node)).toMatchInlineSnapshot(` + "config: { + role?: \\"Owner\\" | \\"Collaborator\\" | \\"Controller\\"; + email?: string; + }" + `) + }) + + test('render parameter with non type conform names', () => { + const params: Parameter[] = [ + { + name: 'file_body', + in: 'body', + schema: { + type: 'string', + format: 'binary', + }, + required: true, + }, + { + name: 'X-Nf-Retry-Count', + type: 'integer', + in: 'header', + }, + ] + const node = createMethodParams(params)[0] + expect(printNode(node)).toMatchInlineSnapshot(` + "config: { + file_body: string; + \\"X-Nf-Retry-Count\\"?: number; + }" + `) + }) +}) diff --git a/packages/js-client/src/ast/helpers.ts b/packages/js-client/src/ast/helpers.ts new file mode 100644 index 0000000000..cd5eb4127b --- /dev/null +++ b/packages/js-client/src/ast/helpers.ts @@ -0,0 +1,172 @@ +import { camelCase, upperFirst } from 'lodash-es' +import ts from 'typescript' + +import type { Parameter, Property } from './open-api.js' + +const PROPERTY_NEEDS_QUOTES_REGEX = /[^a-zA-Z_$]|^[^a-zA-Z_$]|[\W_]\d/ + +export function printNode(node?: ts.Node): string { + if (!node) { + return '' + } + const printer = ts.createPrinter({ newLine: ts.NewLineKind.LineFeed }) + return printer.printNode(ts.EmitHint.Unspecified, node, node.getSourceFile()) +} + +export function createType(schema: T): ts.TypeNode | undefined { + if (typeof schema === 'object' && 'schema' in schema && schema.schema && typeof schema.schema === 'object') { + // + + if (typeof schema.schema === 'object' && 'allOf' in schema.schema && Array.isArray(schema.schema.allOf)) { + // merge all schema.allOf properties in one object + const properties: ts.PropertySignature[] = [] + for (const part of schema.schema.allOf) { + if ('properties' in part) { + for (const [key, value] of Object.entries(part.properties || {})) { + properties.push(createTypeProperty(value, key)) + } + } else { + throw new Error('not implemented') + } + } + return ts.factory.createTypeLiteralNode(properties) + } + // if there is no schema.schema.allOf it's an object schema so create the type of it + return createType(schema.schema) + } + + if (typeof schema === 'object' && 'type' in schema) { + if ('enum' in schema && Array.isArray(schema.enum)) { + const members = schema.enum.map((type) => { + switch (typeof type) { + case 'string': + return ts.factory.createLiteralTypeNode(ts.factory.createStringLiteral(type)) + } + }) + return ts.factory.createUnionTypeNode(members) + } + + switch (schema.type) { + case 'string': + return ts.factory.createKeywordTypeNode(ts.SyntaxKind.StringKeyword) + case 'number': + case 'integer': + return ts.factory.createKeywordTypeNode(ts.SyntaxKind.NumberKeyword) + case 'boolean': + return ts.factory.createKeywordTypeNode(ts.SyntaxKind.BooleanKeyword) + case 'array': + if ('items' in schema && schema.items && typeof schema.items === 'object') { + const childType = createType(schema.items) + return childType && ts.factory.createArrayTypeNode(childType) + } + return ts.factory.createArrayTypeNode(ts.factory.createKeywordTypeNode(ts.SyntaxKind.UnknownKeyword)) + case 'object': + if ('properties' in schema && schema.properties && typeof schema.properties === 'object') { + return createTypeFromSchema(schema.properties) + } + return ts.factory.createKeywordTypeNode(ts.SyntaxKind.ObjectKeyword) + } + } +} + +export function createTypeProperty(schema: object, name: string, options: { required?: boolean } = {}) { + const required = + options.required !== undefined + ? options.required + : typeof schema === 'object' && 'required' in schema && schema.required === true + const propertySignature = ts.factory.createPropertySignature( + undefined, + PROPERTY_NEEDS_QUOTES_REGEX.test(name) ? ts.factory.createStringLiteral(name) : name, + !required ? ts.factory.createToken(ts.SyntaxKind.QuestionToken) : undefined, + createType(schema), + ) + + if ('description' in schema && typeof schema.description === 'string') { + ts.addSyntheticLeadingComment( + propertySignature, + ts.SyntaxKind.MultiLineCommentTrivia, + `* ${schema.description} `, // multilineCommentTrivia does not use a correct jsdoc annotation + true, + ) + } + + return propertySignature +} + +/** Filters a property signature list and removes duplicates */ +function filterForUniqueProperties(properties: ts.PropertySignature[]): ts.PropertySignature[] { + const uniquePropertyNames = new Set() + return properties.filter((prop) => { + if (ts.isPropertySignature(prop) && prop.name && ts.isIdentifier(prop.name)) { + const propertyName = prop.name.text + if (uniquePropertyNames.has(propertyName)) { + return false // Duplicate found, ignore this member + } + uniquePropertyNames.add(propertyName) + } + return true // Keep this member + }) +} + +/** + * Creates a type literal node from a swagger schema object + */ +export function createTypeFromSchema(schema: T) { + const properties: ts.PropertySignature[] = [] + for (const [key, value] of Object.entries(schema || {})) { + properties.push(createTypeProperty(value, key)) + } + return ts.factory.createTypeLiteralNode(filterForUniqueProperties(properties)) +} + +export function createMethodParams(params: Parameter[] = []) { + if (params.length === 0) return [] + const isOptional = params.every((param) => !param.required) + + const properties: ts.PropertySignature[] = params.flatMap((param) => { + if ('schema' in param && param.schema && 'properties' in param.schema && param.schema.properties) { + return Object.entries(param.schema.properties || {}).map(([key, value]) => createTypeProperty(value, key)) + } + return createTypeProperty(param, param.name) + }) + + return [ + ts.factory.createParameterDeclaration( + undefined, + undefined, + 'config', + undefined, + ts.factory.createTypeLiteralNode(filterForUniqueProperties(properties)), + isOptional ? ts.factory.createObjectLiteralExpression() : undefined, + ), + ] +} + +export function createReturnType( + operationName: string, + responses: Record = {}, +): [ts.TypeAliasDeclaration | undefined, ts.TypeReferenceNode] { + const [, response] = Object.entries(responses || {}).find(([key]) => key !== 'default') || [] + + if (response) { + const responseType = createType(response) + if (responseType) { + const typeName = `${upperFirst(camelCase(operationName))}Response` + const typeAlias = ts.factory.createTypeAliasDeclaration( + [ts.factory.createModifier(ts.SyntaxKind.ExportKeyword)], + typeName, + undefined, + responseType, + ) + return [ + typeAlias, + // wrap the return type in a promise + ts.factory.createTypeReferenceNode('Promise', [ts.factory.createTypeReferenceNode(typeName, undefined)]), + ] + } + } + return [ + undefined, + ts.factory.createTypeReferenceNode('Promise', [ts.factory.createKeywordTypeNode(ts.SyntaxKind.VoidKeyword)]), + ] +} diff --git a/packages/js-client/src/ast/open-api.ts b/packages/js-client/src/ast/open-api.ts new file mode 100644 index 0000000000..57b696dc9e --- /dev/null +++ b/packages/js-client/src/ast/open-api.ts @@ -0,0 +1,90 @@ +export type OpenAPI = { + /** the swagger version */ + swagger: string + info: { + version: string + title: string + description: string + termsOfService: string + } + externalDocs: { + url: string + description: string + } + securityDefinitions: { + netlifyAuth: NetlifyAuth + } + security: Array<{ netlifyAuth: any[] }> + consumes: string[] + produces: string[] + schemes: string[] + responses: Record + host: string + basePath: string + paths: Record + definitions: Record + parameters: Record<'page' | 'perPage' | 'retryCount', Parameter> + tags: Array<{ name: string }> +} + +export type HTTPMethods = 'get' | 'post' | 'put' | 'delete' + +export type Path = Record< + HTTPMethods, + { + operationId: string + tags: string[] + parameters?: Parameter[] + consumes?: string[] + responses: any + description?: string + } +> + +export type Parameter = (SchemaProperty | StringProperty | BooleanProperty | IntegerProperty) & { + name: string + required?: boolean + in: 'header' | 'query' | 'body' | 'path' +} + +export type BaseProperty = { + description?: string +} + +export type Property = + | BooleanProperty + | IntegerProperty + | NumberProperty + | StringProperty + | ArrayProperty + | ObjectProperty + | TypeDefinition + | SchemaProperty + +export type BooleanProperty = BaseProperty & { type: 'boolean' } +export type IntegerProperty = BaseProperty & { type: 'integer'; format?: 'int32' | 'int64' } +export type NumberProperty = BaseProperty & { type: 'number' } +export type StringProperty = BaseProperty & { type: 'string'; format?: 'binary' | 'dateTime'; enum?: string[] } +export type ArrayProperty = BaseProperty & { type: 'array'; items: Property } +export type ObjectProperty = BaseProperty & { + type: 'object' + required?: string[] + properties?: Record + additionalProperties?: Property +} +export type SchemaProperty = BaseProperty & { + // can be either a allOf + // a regular object definition + // or a string with format: binary + schema?: ObjectProperty | TypeDefinition | StringProperty +} + +export type TypeDefinition = BaseProperty & { + allOf?: Array }> +} + +export type NetlifyAuth = { + type: string + flow: string + authorizationUrl: string +} diff --git a/packages/js-client/src/base-api.ts b/packages/js-client/src/base-api.ts new file mode 100644 index 0000000000..fbadb8c289 --- /dev/null +++ b/packages/js-client/src/base-api.ts @@ -0,0 +1,119 @@ +import type { Agent } from 'http' + +import pWaitFor from 'p-wait-for' + +import { getMethods } from './methods/index.js' +import { openApiSpec } from './open_api.js' +import { getOperations } from './operations.js' + +// 1 second +const DEFAULT_TICKET_POLL = 1e3 +// 1 hour +const DEFAULT_TICKET_TIMEOUT = 3.6e6 + +export type APIOptions = { + /** @example 'netlify/js-client' */ + userAgent?: string + /** @example 'https' */ + scheme?: string + /** @example 'api.netlify.com' */ + host?: string + /** @example '/api/v1' */ + pathPrefix?: string + accessToken?: string + /** @example 'HttpsProxyAgent' */ + agent?: Agent + /** + * parameters you want available for every request. + * Global params are only sent of the OpenAPI spec specifies the provided params. + */ + globalParams?: Record +} + +export abstract class BaseAuth { + #accessToken: string | null = null + + defaultHeaders: Record = { + accept: 'application/json', + } + + /** The protocol is used like `https` */ + scheme: NonNullable + host: NonNullable + pathPrefix: NonNullable + agent?: APIOptions['agent'] + globalParams: NonNullable = {} + + // constructor(options?: APIOptions) + // constructor(accessToken: string | undefined, options?: APIOptions) + constructor(firstArg: string | undefined | APIOptions, secondArg?: APIOptions) { + // variadic arguments + const [accessTokenInput, options = {}] = typeof firstArg === 'object' ? [null, firstArg] : [firstArg, secondArg] + + this.globalParams = options.globalParams || {} + this.agent = options.agent + this.scheme = options.scheme || openApiSpec.schemes[0] + this.host = options.host || openApiSpec.host + this.pathPrefix = options.pathPrefix || openApiSpec.basePath + this.#accessToken = options.accessToken || accessTokenInput || null + this.defaultHeaders['User-agent'] = options.userAgent || 'netlify/js-client' + + const methods = getMethods({ + basePath: this.basePath, + defaultHeaders: this.defaultHeaders, + agent: this.agent, + globalParams: this.globalParams, + }) + Object.assign(this, { ...methods }) + } + + /** Retrieves the access token */ + get accessToken(): string | null { + return this.#accessToken + } + + set accessToken(token: string | null) { + if (!token) { + delete this.defaultHeaders.Authorization + this.#accessToken = null + return + } + this.#accessToken = token + this.defaultHeaders.Authorization = `Bearer ${this.#accessToken}` + } + + get basePath() { + return `${this.scheme}://${this.host}${this.pathPrefix}` + } + + async getAccessToken(ticket, { poll = DEFAULT_TICKET_POLL, timeout = DEFAULT_TICKET_TIMEOUT } = {}) { + const { id } = ticket + + // ticket capture + let authorizedTicket + const checkTicket = async () => { + const t = await this.showTicket({ ticketId: id }) + if (t.authorized) { + authorizedTicket = t + } + return Boolean(t.authorized) + } + + await pWaitFor(checkTicket, { + interval: poll, + timeout, + message: 'Timeout while waiting for ticket grant', + } as any) + + const accessTokenResponse = await this.exchangeTicket({ ticketId: authorizedTicket.id }) + // See https://open-api.netlify.com/#/default/exchangeTicket for shape + this.accessToken = accessTokenResponse.access_token + return accessTokenResponse.access_token + } + + // Those functions get implemented through the Open API implementations + abstract showTicket(config: { ticketId: string }): Promise<{ authorized: boolean }> + abstract exchangeTicket(config: { ticketId: string }): Promise<{ access_token: string }> +} + +export const methods = getOperations() diff --git a/packages/js-client/src/generate.ts b/packages/js-client/src/generate.ts new file mode 100644 index 0000000000..46121a5fad --- /dev/null +++ b/packages/js-client/src/generate.ts @@ -0,0 +1,77 @@ +import { writeFile } from 'fs/promises' + +import swagger from '@netlify/open-api/dist/swagger.json' assert { type: 'json' } +import prettier from 'prettier' +import ts from 'typescript' + +import { createMethodParams, createReturnType, printNode } from './ast/helpers.js' + +// Our template where we will add the methods +const code = ` +import { BaseAuth, type APIOptions } from './base-api.js'; + +export class NetlifyAPI extends BaseAuth { + constructor(options?: APIOptions) + constructor(accessToken: string | undefined, options?: APIOptions) + constructor(firstArg: string | undefined | APIOptions, secondArg?: APIOptions) { + super(firstArg, secondArg); + } +} +` + +const sourceFile = ts.createSourceFile('index.ts', code, ts.ScriptTarget.ESNext, true, ts.ScriptKind.TS) + +function updateAPIWithSwagger(sourceFile: ts.SourceFile) { + const statements: ts.Statement[] = [] + const index = sourceFile.statements.findIndex(ts.isClassDeclaration) + const apiClass = index > -1 ? (sourceFile.statements[index] as ts.ClassDeclaration) : undefined + if (apiClass && apiClass.name?.text === 'NetlifyAPI') { + const methods: ts.MethodDeclaration[] = [] + + for (const [, actions] of Object.entries(swagger.paths || {})) { + for (const [, operation] of Object.entries(actions)) { + // if (operation.operationId !== 'uploadDeployFile') { + // continue + // } + + if (operation.operationId?.length) { + const [typeAlias, returnType] = createReturnType(operation.operationId, operation.responses) || [] + if (typeAlias) { + statements.push(typeAlias) + } + methods.push( + ts.factory.createMethodDeclaration( + undefined, + undefined, + operation.operationId, + undefined, + undefined, + createMethodParams([...(operation.parameters || []), ...((actions as any).parameters || [])]), + returnType, + ts.factory.createBlock([], true), + ), + ) + } + } + } + + // update the class declaration with the newly created methods + const updatedClassDeclaration = ts.factory.updateClassDeclaration( + apiClass, + apiClass.modifiers, + apiClass.name, + apiClass.typeParameters, + apiClass.heritageClauses, + [...apiClass.members, ...methods], + ) + const updated = [...sourceFile.statements, ...statements] + updated[index] = updatedClassDeclaration + return ts.factory.updateSourceFile(sourceFile, updated, false, sourceFile.referencedFiles) + } +} + +const formatted = prettier.format(printNode(updateAPIWithSwagger(sourceFile)), { + parser: 'typescript', +}) + +await writeFile('./src/index.ts', `/* eslint-disable */\n${formatted}`) diff --git a/packages/js-client/src/index.js b/packages/js-client/src/index.js deleted file mode 100644 index a5788f0409..0000000000 --- a/packages/js-client/src/index.js +++ /dev/null @@ -1,92 +0,0 @@ -import pWaitFor from 'p-wait-for' - -import { getMethods } from './methods/index.js' -import { openApiSpec } from './open_api.js' -import { getOperations } from './operations.js' - -export class NetlifyAPI { - constructor(firstArg, secondArg) { - // variadic arguments - const [accessTokenInput, opts = {}] = typeof firstArg === 'object' ? [null, firstArg] : [firstArg, secondArg] - - // default opts - const { - userAgent = 'netlify/js-client', - scheme = openApiSpec.schemes[0], - host = openApiSpec.host, - pathPrefix = openApiSpec.basePath, - accessToken = accessTokenInput, - globalParams = {}, - agent, - } = opts - - const defaultHeaders = { - 'User-agent': userAgent, - accept: 'application/json', - } - - const basePath = getBasePath({ scheme, host, pathPrefix }) - const methods = getMethods({ basePath, defaultHeaders, agent, globalParams }) - Object.assign(this, { ...methods, defaultHeaders, scheme, host, pathPrefix, globalParams, accessToken, agent }) - } - - get accessToken() { - const { - defaultHeaders: { Authorization }, - } = this - if (typeof Authorization !== 'string' || !Authorization.startsWith('Bearer ')) { - return null - } - - return Authorization.replace('Bearer ', '') - } - - set accessToken(token) { - if (!token) { - delete this.defaultHeaders.Authorization - return - } - - this.defaultHeaders.Authorization = `Bearer ${token}` - } - - get basePath() { - return getBasePath({ scheme: this.scheme, host: this.host, pathPrefix: this.pathPrefix }) - } - - async getAccessToken(ticket, { poll = DEFAULT_TICKET_POLL, timeout = DEFAULT_TICKET_TIMEOUT } = {}) { - const { id } = ticket - - // ticket capture - let authorizedTicket - const checkTicket = async () => { - const t = await this.showTicket({ ticketId: id }) - if (t.authorized) { - authorizedTicket = t - } - return Boolean(t.authorized) - } - - await pWaitFor(checkTicket, { - interval: poll, - timeout, - message: 'Timeout while waiting for ticket grant', - }) - - const accessTokenResponse = await this.exchangeTicket({ ticketId: authorizedTicket.id }) - // See https://open-api.netlify.com/#/default/exchangeTicket for shape - this.accessToken = accessTokenResponse.access_token - return accessTokenResponse.access_token - } -} - -const getBasePath = function ({ scheme, host, pathPrefix }) { - return `${scheme}://${host}${pathPrefix}` -} - -// 1 second -const DEFAULT_TICKET_POLL = 1e3 -// 1 hour -const DEFAULT_TICKET_TIMEOUT = 3.6e6 - -export const methods = getOperations() diff --git a/packages/js-client/src/index.test.ts b/packages/js-client/src/index.test.ts index e853af29d8..19c799967d 100644 --- a/packages/js-client/src/index.test.ts +++ b/packages/js-client/src/index.test.ts @@ -33,7 +33,7 @@ const getClient = function (opts: any = {}) { } test('Default options', (t) => { - const client: any = new NetlifyAPI({}) + const client = new NetlifyAPI({}) t.is(client.scheme, 'https') t.is(client.host, 'api.netlify.com') t.is(client.pathPrefix, '/api/v1') @@ -47,17 +47,17 @@ test('Default options', (t) => { }) test('Can set|get scheme', (t) => { - const client: any = new NetlifyAPI({ scheme }) + const client = new NetlifyAPI({ scheme }) t.is(client.scheme, scheme) }) test('Can set|get host', (t) => { - const client: any = new NetlifyAPI({ host }) + const client = new NetlifyAPI({ host }) t.is(client.host, host) }) test('Can set|get pathPrefix', (t) => { - const client: any = new NetlifyAPI({ pathPrefix }) + const client = new NetlifyAPI({ pathPrefix }) t.is(client.pathPrefix, pathPrefix) }) @@ -67,7 +67,7 @@ test('Can set|get basePath', (t) => { }) test('Can update basePath', (t) => { - const client: any = new NetlifyAPI({ scheme, host, pathPrefix }) + const client = new NetlifyAPI({ scheme, host, pathPrefix }) const newScheme = 'https' const newHost = `${domain}:1224` @@ -81,18 +81,18 @@ test('Can update basePath', (t) => { test('Can set user agent', (t) => { const userAgent = 'test' - const client: any = new NetlifyAPI({ userAgent }) + const client = new NetlifyAPI({ userAgent }) t.is(client.defaultHeaders['User-agent'], userAgent) }) test('Can set|get globalParams', (t) => { const testGlobalParams = { test: 'test' } - const client: any = new NetlifyAPI({ globalParams: testGlobalParams }) + const client = new NetlifyAPI({ globalParams: testGlobalParams }) t.deepEqual(client.globalParams, testGlobalParams) }) test('Can set|get access token', (t) => { - const client: any = getClient() + const client = getClient() client.accessToken = testAccessToken t.is(client.accessToken, testAccessToken) t.is(client.defaultHeaders.Authorization, `Bearer ${testAccessToken}`) @@ -120,7 +120,7 @@ test('Can use underscored parameters in path variables', async (t) => { const accountId = uuidv4() const scope = nock(origin).get(`${pathPrefix}/accounts/${accountId}`).reply(200) - const client: any = getClient() + const client = getClient() await client.getAccount({ account_id: accountId }) t.true(scope.isDone()) @@ -130,7 +130,7 @@ test('Can use camelcase parameters in path variables', async (t) => { const accountId = uuidv4() const scope = nock(origin).get(`${pathPrefix}/accounts/${accountId}`).reply(200) - const client: any = getClient() + const client = getClient() await client.getAccount({ accountId }) t.true(scope.isDone()) @@ -140,7 +140,7 @@ test('Can use global parameters in path variables', async (t) => { const accountId = uuidv4() const scope = nock(origin).get(`${pathPrefix}/accounts/${accountId}`).reply(200) - const client: any = getClient({ globalParams: { account_id: accountId } }) + const client = getClient({ globalParams: { account_id: accountId } }) await client.getAccount() t.true(scope.isDone()) @@ -150,7 +150,7 @@ test('Can use underscored parameters in query variables', async (t) => { const clientId = uuidv4() const scope = nock(origin).post(`${pathPrefix}/oauth/tickets`).query({ client_id: clientId }).reply(200) - const client: any = getClient() + const client = getClient() await client.createTicket({ client_id: clientId }) t.true(scope.isDone()) @@ -160,7 +160,7 @@ test('Can use camelcase parameters in query variables', async (t) => { const clientId = uuidv4() const scope = nock(origin).post(`${pathPrefix}/oauth/tickets`).query({ client_id: clientId }).reply(200) - const client: any = getClient() + const client = getClient() await client.createTicket({ clientId }) t.true(scope.isDone()) @@ -170,7 +170,7 @@ test('Can use global parameters in query variables', async (t) => { const clientId = uuidv4() const scope = nock(origin).post(`${pathPrefix}/oauth/tickets`).query({ client_id: clientId }).reply(200) - const client: any = getClient({ globalParams: { client_id: clientId } }) + const client = getClient({ globalParams: { client_id: clientId } }) await client.createTicket() t.true(scope.isDone()) @@ -184,7 +184,7 @@ test('Allow array query parameters', async (t) => { ) .reply(200) - const client: any = getClient() + const client = getClient() await client.getLatestPluginRuns({ site_id: siteId, packages: ['@scope/package', '@scope/package-two'] }) t.true(scope.isDone()) @@ -196,7 +196,7 @@ test('Can specify JSON request body as an object', async (t) => { .post(`${pathPrefix}/accounts`, body, { 'Content-Type': 'application/json' } as any) .reply(200) - const client: any = getClient() + const client = getClient() await client.createAccount({ body }) t.true(scope.isDone()) @@ -208,7 +208,7 @@ test('Can specify JSON request body as a function', async (t) => { .post(`${pathPrefix}/accounts`, body, { 'Content-Type': 'application/json' } as any) .reply(200) - const client: any = getClient() + const client = getClient() await client.createAccount({ body: () => body }) t.true(scope.isDone()) @@ -223,7 +223,7 @@ test('Can specify binary request body as a stream', async (t) => { .put(`${pathPrefix}/deploys/${deployId}/files/${path}`, body, { 'Content-Type': 'application/octet-stream' } as any) .reply(200, expectedResponse) - const client: any = getClient() + const client = getClient() const response = await client.uploadDeployFile({ deploy_id: deployId, path, body: fromString(body) }) t.deepEqual(response, expectedResponse) @@ -239,7 +239,7 @@ test('Can specify binary request body as a function', async (t) => { .put(`${pathPrefix}/deploys/${deployId}/files/${path}`, body, { 'Content-Type': 'application/octet-stream' } as any) .reply(200, expectedResponse) - const client: any = getClient() + const client = getClient() const response = await client.uploadDeployFile({ deploy_id: deployId, path, body: () => fromString(body) }) t.deepEqual(response, expectedResponse) @@ -250,7 +250,7 @@ test('Can use global parameters in request body', async (t) => { const body = { test: 'test' } const scope = nock(origin).post(`${pathPrefix}/accounts`, body).reply(200) - const client: any = getClient({ globalParams: { body } }) + const client = getClient({ globalParams: { body } }) await client.createAccount() t.true(scope.isDone()) @@ -269,7 +269,7 @@ test('Can set header parameters', async (t) => { .matchHeader('X-Nf-Retry-Count', retryCount.toString()) .reply(200, expectedResponse) - const client: any = getClient() + const client = getClient() const response = await client.uploadDeployFunction({ deploy_id: deployId, name: functionName, @@ -285,7 +285,7 @@ test('Validates required path parameters', async (t) => { const accountId = uuidv4() const scope = nock(origin).put(`${pathPrefix}/accounts/${accountId}`).reply(200) - const client: any = getClient() + const client = getClient() await t.throwsAsync(client.updateAccount(), { message: "Missing required path variable 'account_id'" }) t.false(scope.isDone()) @@ -295,7 +295,7 @@ test('Validates required query parameters', async (t) => { const zone_id = uuidv4() const scope = nock(origin).post(`${pathPrefix}/dns_zones/${zone_id}/transfer`).reply(200) - const client: any = getClient() + const client = getClient() await t.throwsAsync(client.transferDnsZone({ zone_id }), { message: "Missing required query variable 'account_id'", }) @@ -309,7 +309,7 @@ test('Can set request headers', async (t) => { const accountId = uuidv4() const scope = nock(origin).get(`${pathPrefix}/accounts/${accountId}`).matchHeader(headerName, headerValue).reply(200) - const client: any = getClient() + const client = getClient() await client.getAccount({ account_id: accountId }, { headers: { [headerName]: headerValue } }) t.true(scope.isDone()) @@ -320,7 +320,7 @@ test('Can parse JSON responses', async (t) => { const expectedResponse = { test: 'test' } const scope = nock(origin).get(`${pathPrefix}/accounts/${accountId}`).reply(200, expectedResponse) - const client: any = getClient() + const client = getClient() const response = await client.getAccount({ account_id: accountId }) t.deepEqual(response, expectedResponse) @@ -332,7 +332,7 @@ test('Can parse text responses', async (t) => { const expectedResponse = 'test' const scope = nock(origin).get(`${pathPrefix}/accounts/${accountId}`).reply(200, expectedResponse) - const client: any = getClient() + const client = getClient() const response = await client.getAccount({ account_id: accountId }) t.deepEqual(response, expectedResponse) @@ -345,7 +345,7 @@ test('Handle error empty responses', async (t) => { const expectedResponse = 'test' const scope = nock(origin).get(`${pathPrefix}/accounts/${accountId}`).reply(status, expectedResponse) - const client: any = getClient() + const client = getClient() const error: any = await t.throwsAsync(client.getAccount({ account_id: accountId })) t.is(error.status, status) @@ -362,7 +362,7 @@ test('Handle error text responses', async (t) => { const expectedResponse = 'test' const scope = nock(origin).get(`${pathPrefix}/accounts/${accountId}`).reply(status, expectedResponse) - const client: any = getClient() + const client = getClient() const error: any = await t.throwsAsync(client.getAccount({ account_id: accountId })) t.is(error.status, status) @@ -381,7 +381,7 @@ test('Handle error text responses on JSON endpoints', async (t) => { .get(`${pathPrefix}/accounts/${accountId}`) .reply(status, expectedResponse, { 'Content-Type': 'application/json' }) - const client: any = getClient() + const client = getClient() const error: any = await t.throwsAsync(client.getAccount({ account_id: accountId })) t.is(error.status, status) @@ -398,7 +398,7 @@ test('Handle error JSON responses', async (t) => { const errorJson = { error: true } const scope = nock(origin).get(`${pathPrefix}/accounts/${accountId}`).reply(status, errorJson) - const client: any = getClient() + const client = getClient() const error: any = await t.throwsAsync(client.getAccount({ account_id: accountId })) t.is(error.status, status) @@ -415,7 +415,7 @@ test('Handle network errors', async (t) => { const url = `${pathPrefix}/accounts/${accountId}` const scope = nock(origin).get(url).replyWithError(expectedResponse) - const client: any = getClient() + const client = getClient() const error: any = await t.throwsAsync(client.getAccount({ account_id: accountId })) t.true(error instanceof Error) @@ -507,7 +507,7 @@ test('Does not retry on server errors', async (t) => { .get(`${pathPrefix}/accounts/${accountId}`) .reply(200, expectedResponse) - const client: any = getClient() + const client = getClient() const error: any = await t.throwsAsync(client.getAccount({ account_id: accountId })) t.is(error.status, 500) @@ -527,7 +527,7 @@ test('Retries on server errors for the `getLatestPluginRuns` endpoint', async (t .query({ packages }) .reply(200, expectedResponse) - const client: any = getClient() + const client = getClient() const response = await client.getLatestPluginRuns({ site_id: siteId, packages }) t.deepEqual(response, expectedResponse) @@ -545,7 +545,7 @@ test('Handles API rate limiting', async (t) => { .get(`${pathPrefix}/accounts/${accountId}`) .reply(200, expectedResponse) - const client: any = getClient() + const client = getClient() const response = await client.getAccount({ account_id: accountId }) t.true(Date.now() >= retryAtMs) @@ -562,7 +562,7 @@ test('Handles API rate limiting when date is in the past', async (t) => { .get(`${pathPrefix}/accounts/${accountId}`) .reply(200, expectedResponse) - const client: any = getClient() + const client = getClient() await client.getAccount({ account_id: accountId }) t.true(scope.isDone()) @@ -578,7 +578,7 @@ test('Handles API rate limiting when X-RateLimit-Reset is missing', async (t) => .get(`${pathPrefix}/accounts/${accountId}`) .reply(200, expectedResponse) - const client: any = getClient() + const client = getClient() await client.getAccount({ account_id: accountId }) t.true(scope.isDone()) @@ -596,7 +596,7 @@ test('Gives up retrying on API rate limiting after a timeout', async (t) => { .get(`${pathPrefix}/accounts/${accountId}`) .reply(200, expectedResponse) - const client: any = getClient() + const client = getClient() const error: any = await t.throwsAsync(client.getAccount({ account_id: accountId })) t.is(error.status, 429) @@ -618,7 +618,7 @@ errorCodes.forEach((code) => { .get(`${pathPrefix}/accounts/${accountId}`) .reply(200, expectedResponse) - const client: any = getClient() + const client = getClient() const response: any = await client.getAccount({ account_id: accountId }) t.true(Date.now() >= retryAtMs) @@ -639,7 +639,7 @@ test('Recreates a function body when handling API rate limiting', async (t) => { .reply(429, { retryAt }, { 'X-RateLimit-Reset': retryAt }) .put(`${pathPrefix}/deploys/${deployId}/files/${path}`, body, { 'Content-Type': 'application/octet-stream' } as any) .reply(200, expectedResponse) - const client: any = getClient() + const client = getClient() const response = await client.uploadDeployFile({ deploy_id: deployId, path, body: () => fromString(body) }) t.true(Date.now() >= retryAtMs) @@ -647,8 +647,23 @@ test('Recreates a function body when handling API rate limiting', async (t) => { t.true(scope.isDone()) }) +test('Updates environment variables on a site', async (t) => { + const siteId = uuidv4() + const body = { build_settings: { env: { HELLO: 'WORLD' } } } + const expectedResponse = { test: 'test' } + const scope = nock(origin).patch(`${pathPrefix}/sites/${siteId}`, JSON.stringify(body)).reply(200, expectedResponse) + + const client = getClient() + const response = await client.updateSite({ + siteId, + body, + }) + t.deepEqual(response, expectedResponse) + t.true(scope.isDone()) +}) + test('Can set (proxy) agent', (t) => { - const client: any = getClient({ accessToken: testAccessToken, agent }) + const client = getClient({ accessToken: testAccessToken, agent }) t.is(client.agent, agent) }) @@ -656,7 +671,7 @@ test('(Proxy) agent is passed as request option', async (t) => { const accountId = uuidv4() const scope = nock(origin).get(`${pathPrefix}/accounts/${accountId}`).reply(200) - const client: any = getClient({ accessToken: testAccessToken, agent }) + const client = getClient({ accessToken: testAccessToken, agent }) await client.getAccount({ account_id: accountId }) t.is((scope as any).interceptors[0].req.options.agent, agent) }) @@ -665,7 +680,7 @@ test('(Proxy) agent is not passed as request option if not set', async (t) => { const accountId = uuidv4() const scope = nock(origin).get(`${pathPrefix}/accounts/${accountId}`).reply(200) - const client: any = getClient({ accessToken: testAccessToken }) + const client = getClient({ accessToken: testAccessToken }) await client.getAccount({ account_id: accountId }) t.falsy((scope as any).interceptors[0].req.options.agent) }) diff --git a/packages/js-client/src/index.ts b/packages/js-client/src/index.ts new file mode 100644 index 0000000000..5e686a49ae --- /dev/null +++ b/packages/js-client/src/index.ts @@ -0,0 +1,2978 @@ +/* eslint-disable */ +import { BaseAuth, type APIOptions } from './base-api.js' +export class NetlifyAPI extends BaseAuth { + constructor(options?: APIOptions) + constructor(accessToken: string | undefined, options?: APIOptions) + constructor(firstArg: string | undefined | APIOptions, secondArg?: APIOptions) { + super(firstArg, secondArg) + } + listSites( + config: { + name?: string + filter?: 'all' | 'owner' | 'guest' + page?: number + per_page?: number + } = {}, + ): Promise {} + createSite(config: { + site: { + id?: string + state?: string + plan?: string + name?: string + custom_domain?: string + domain_aliases?: string[] + branch_deploy_custom_domain?: string + deploy_preview_custom_domain?: string + password?: string + notification_email?: string + url?: string + ssl_url?: string + admin_url?: string + screenshot_url?: string + created_at?: string + updated_at?: string + user_id?: string + session_id?: string + ssl?: boolean + force_ssl?: boolean + managed_dns?: boolean + deploy_url?: string + published_deploy?: { + id?: string + site_id?: string + user_id?: string + build_id?: string + state?: string + name?: string + url?: string + ssl_url?: string + admin_url?: string + deploy_url?: string + deploy_ssl_url?: string + screenshot_url?: string + review_id?: number + draft?: boolean + required?: string[] + required_functions?: string[] + error_message?: string + branch?: string + commit_ref?: string + commit_url?: string + skipped?: boolean + created_at?: string + updated_at?: string + published_at?: string + title?: string + context?: string + locked?: boolean + review_url?: string + site_capabilities?: { + large_media_enabled?: boolean + } + framework?: string + function_schedules?: { + name?: string + cron?: string + }[] + } + account_name?: string + account_slug?: string + git_provider?: string + deploy_hook?: string + capabilities?: object + processing_settings?: { + skip?: boolean + css?: { + bundle?: boolean + minify?: boolean + } + js?: { + bundle?: boolean + minify?: boolean + } + images?: { + optimize?: boolean + } + html?: { + pretty_urls?: boolean + } + } + build_settings?: { + id?: number + provider?: string + deploy_key_id?: string + repo_path?: string + repo_branch?: string + dir?: string + functions_dir?: string + cmd?: string + allowed_branches?: string[] + public_repo?: boolean + private_logs?: boolean + repo_url?: string + env?: object + installation_id?: number + stop_builds?: boolean + } + id_domain?: string + default_hooks_data?: { + access_token?: string + } + build_image?: string + prerender?: string + repo?: { + id?: number + provider?: string + deploy_key_id?: string + repo_path?: string + repo_branch?: string + dir?: string + functions_dir?: string + cmd?: string + allowed_branches?: string[] + public_repo?: boolean + private_logs?: boolean + repo_url?: string + env?: object + installation_id?: number + stop_builds?: boolean + } + } + configure_dns?: boolean + }): Promise {} + getSite(config: { feature_flags?: string; site_id: string }): Promise {} + updateSite(config: { + site: { + id?: string + state?: string + plan?: string + name?: string + custom_domain?: string + domain_aliases?: string[] + branch_deploy_custom_domain?: string + deploy_preview_custom_domain?: string + password?: string + notification_email?: string + url?: string + ssl_url?: string + admin_url?: string + screenshot_url?: string + created_at?: string + updated_at?: string + user_id?: string + session_id?: string + ssl?: boolean + force_ssl?: boolean + managed_dns?: boolean + deploy_url?: string + published_deploy?: { + id?: string + site_id?: string + user_id?: string + build_id?: string + state?: string + name?: string + url?: string + ssl_url?: string + admin_url?: string + deploy_url?: string + deploy_ssl_url?: string + screenshot_url?: string + review_id?: number + draft?: boolean + required?: string[] + required_functions?: string[] + error_message?: string + branch?: string + commit_ref?: string + commit_url?: string + skipped?: boolean + created_at?: string + updated_at?: string + published_at?: string + title?: string + context?: string + locked?: boolean + review_url?: string + site_capabilities?: { + large_media_enabled?: boolean + } + framework?: string + function_schedules?: { + name?: string + cron?: string + }[] + } + account_name?: string + account_slug?: string + git_provider?: string + deploy_hook?: string + capabilities?: object + processing_settings?: { + skip?: boolean + css?: { + bundle?: boolean + minify?: boolean + } + js?: { + bundle?: boolean + minify?: boolean + } + images?: { + optimize?: boolean + } + html?: { + pretty_urls?: boolean + } + } + build_settings?: { + id?: number + provider?: string + deploy_key_id?: string + repo_path?: string + repo_branch?: string + dir?: string + functions_dir?: string + cmd?: string + allowed_branches?: string[] + public_repo?: boolean + private_logs?: boolean + repo_url?: string + env?: object + installation_id?: number + stop_builds?: boolean + } + id_domain?: string + default_hooks_data?: { + access_token?: string + } + build_image?: string + prerender?: string + repo?: { + id?: number + provider?: string + deploy_key_id?: string + repo_path?: string + repo_branch?: string + dir?: string + functions_dir?: string + cmd?: string + allowed_branches?: string[] + public_repo?: boolean + private_logs?: boolean + repo_url?: string + env?: object + installation_id?: number + stop_builds?: boolean + } + } + site_id: string + }): Promise {} + deleteSite(config: { site_id: string }): Promise {} + provisionSiteTLSCertificate(config: { + site_id: string + certificate?: string + key?: string + ca_certificates?: string + }): Promise {} + showSiteTLSCertificate(config: { site_id: string }): Promise {} + getEnvVars(config: { + /** Scope response to account_id */ + account_id: string + /** Filter by deploy context */ + context_name?: 'all' | 'dev' | 'branch-deploy' | 'deploy-preview' | 'production' + /** Filter by scope */ + scope?: 'builds' | 'functions' | 'runtime' | 'post-processing' + /** If specified, only return environment variables set on this site */ + site_id?: string + }): Promise {} + createEnvVars(config: { + env_vars?: { + /** The existing or new name of the key, if you wish to rename it (case-sensitive) */ + key?: string + /** The scopes that this environment variable is set to (Pro plans and above) */ + scopes?: ('builds' | 'functions' | 'runtime' | 'post-processing')[] + values?: { + /** The environment variable value's universally unique ID */ + id?: string + /** The environment variable's unencrypted value */ + value?: string + /** The deploy context in which this value will be used. `dev` refers to local development when running `netlify dev`. */ + context?: 'all' | 'dev' | 'branch-deploy' | 'deploy-preview' | 'production' | 'branch' + /** An additional parameter for custom branches. Currently, this is used for specifying a branch name when `context=branch`. */ + context_parameter?: string + }[] + /** Secret values are only readable by code running on Netlify’s systems. With secrets, only the local development context values are readable from the UI, API, and CLI. By default, environment variable values are not secret. (Enterprise plans only) */ + is_secret?: boolean + }[] + /** Scope response to account_id */ + account_id: string + /** If provided, create an environment variable on the site level, not the account level */ + site_id?: string + }): Promise {} + getEnvVar(config: { + /** Scope response to account_id */ + account_id: string + /** The environment variable key (case-sensitive) */ + key: string + /** If provided, return the environment variable for a specific site (no merging is performed) */ + site_id?: string + }): Promise {} + updateEnvVar(config: { + /** Scope response to account_id */ + account_id: string + /** The existing environment variable key name (case-sensitive) */ + key: string + /** The scopes that this environment variable is set to (Pro plans and above) */ + scopes?: ('builds' | 'functions' | 'runtime' | 'post-processing')[] + values?: { + /** The environment variable value's universally unique ID */ + id?: string + /** The environment variable's unencrypted value */ + value?: string + /** The deploy context in which this value will be used. `dev` refers to local development when running `netlify dev`. */ + context?: 'all' | 'dev' | 'branch-deploy' | 'deploy-preview' | 'production' | 'branch' + /** An additional parameter for custom branches. Currently, this is used for specifying a branch name when `context=branch`. */ + context_parameter?: string + }[] + /** Secret values are only readable by code running on Netlify’s systems. With secrets, only the local development context values are readable from the UI, API, and CLI. By default, environment variable values are not secret. (Enterprise plans only) */ + is_secret?: boolean + /** If provided, update an environment variable set on this site */ + site_id?: string + }): Promise {} + setEnvVarValue(config: { + /** Scope response to account_id */ + account_id: string + /** The existing environment variable key name (case-sensitive) */ + key: string + /** If provided, update an environment variable set on this site */ + site_id?: string + /** The deploy context in which this value will be used. `dev` refers to local development when running `netlify dev`. `branch` must be provided with a value in `context_parameter`. */ + context?: 'all' | 'dev' | 'branch-deploy' | 'deploy-preview' | 'production' | 'branch' + /** An additional parameter for custom branches. Currently, this is used for providing a branch name when `context=branch`. */ + context_parameter?: string + /** The environment variable's unencrypted value */ + value?: string + }): Promise {} + deleteEnvVar(config: { + /** Scope response to account_id */ + account_id: string + /** The environment variable key (case-sensitive) */ + key: string + /** If provided, delete the environment variable from this site */ + site_id?: string + }): Promise {} + deleteEnvVarValue(config: { + /** Scope response to account_id */ + account_id: string + /** The environment variable value's ID */ + id: string + /** The environment variable key name (case-sensitive) */ + key: string + /** If provided, delete the value from an environment variable on this site */ + site_id?: string + }): Promise {} + listSiteForms(config: { site_id: string }): Promise {} + deleteSiteForm(config: { site_id: string; form_id: string }): Promise {} + listSiteSubmissions(config: { + site_id: string + page?: number + per_page?: number + }): Promise {} + listSiteFiles(config: { site_id: string }): Promise {} + listSiteAssets(config: { site_id: string }): Promise {} + createSiteAsset(config: { + name: string + size: number + content_type: string + visibility?: string + site_id: string + }): Promise {} + getSiteAssetInfo(config: { site_id: string; asset_id: string }): Promise {} + updateSiteAsset(config: { state: string; site_id: string; asset_id: string }): Promise {} + deleteSiteAsset(config: { site_id: string; asset_id: string }): Promise {} + getSiteAssetPublicSignature(config: { + site_id: string + asset_id: string + }): Promise {} + getSiteFileByPathName(config: { site_id: string; file_path: string }): Promise {} + listSiteSnippets(config: { site_id: string }): Promise {} + createSiteSnippet(config: { + id?: number + site_id?: string + title?: string + general?: string + general_position?: string + goal?: string + goal_position?: string + }): Promise {} + getSiteSnippet(config: { site_id: string; snippet_id: string }): Promise {} + updateSiteSnippet(config: { + id?: number + site_id?: string + title?: string + general?: string + general_position?: string + goal?: string + goal_position?: string + snippet_id: string + }): Promise {} + deleteSiteSnippet(config: { site_id: string; snippet_id: string }): Promise {} + getSiteMetadata(config: { site_id: string }): Promise {} + updateSiteMetadata(config: { metadata: object; site_id: string }): Promise {} + listSiteBuildHooks(config: { site_id: string }): Promise {} + createSiteBuildHook(config: { + title?: string + branch?: string + site_id: string + }): Promise {} + getSiteBuildHook(config: { site_id: string; id: string }): Promise {} + updateSiteBuildHook(config: { title?: string; branch?: string; site_id: string; id: string }): Promise {} + deleteSiteBuildHook(config: { site_id: string; id: string }): Promise {} + listSiteDeploys(config: { + page?: number + per_page?: number + site_id: string + 'deploy-previews'?: boolean + production?: boolean + state?: + | 'new' + | 'pending_review' + | 'accepted' + | 'rejected' + | 'enqueued' + | 'building' + | 'uploading' + | 'uploaded' + | 'preparing' + | 'prepared' + | 'processing' + | 'ready' + | 'error' + | 'retrying' + branch?: string + 'latest-published'?: boolean + }): Promise {} + createSiteDeploy(config: { + title?: string + files?: object + draft?: boolean + async?: boolean + functions?: object + function_schedules?: { + name?: string + cron?: string + }[] + functions_config?: object + branch?: string + framework?: string + site_id: string + 'deploy-previews'?: boolean + production?: boolean + state?: + | 'new' + | 'pending_review' + | 'accepted' + | 'rejected' + | 'enqueued' + | 'building' + | 'uploading' + | 'uploaded' + | 'preparing' + | 'prepared' + | 'processing' + | 'ready' + | 'error' + | 'retrying' + 'latest-published'?: boolean + }): Promise {} + getSiteDeploy(config: { site_id: string; deploy_id: string }): Promise {} + updateSiteDeploy(config: { + site_id: string + deploy_id: string + files?: object + draft?: boolean + async?: boolean + functions?: object + function_schedules?: { + name?: string + cron?: string + }[] + functions_config?: object + branch?: string + framework?: string + }): Promise {} + deleteSiteDeploy(config: { deploy_id: string; site_id: string }): Promise {} + cancelSiteDeploy(config: { deploy_id: string }): Promise {} + restoreSiteDeploy(config: { site_id: string; deploy_id: string }): Promise {} + listSiteBuilds(config: { page?: number; per_page?: number; site_id: string }): Promise {} + createSiteBuild(config: { + image?: string + clear_cache?: boolean + site_id: string + }): Promise {} + listSiteDeployedBranches(config: { site_id: string }): Promise {} + unlinkSiteRepo(config: { site_id: string }): Promise {} + getSiteBuild(config: { build_id: string }): Promise {} + updateSiteBuildLog(config: { + build_id: string + message?: string + error?: boolean + section?: 'initializing' | 'building' | 'deploying' | 'cleanup' | 'postprocessing' + }): Promise {} + notifyBuildStart(config: { build_id: string }): Promise {} + getAccountBuildStatus(config: { account_id: string }): Promise {} + getDNSForSite(config: { site_id: string }): Promise {} + configureDNSForSite(config: { site_id: string }): Promise {} + rollbackSiteDeploy(config: { site_id: string }): Promise {} + getDeploy(config: { deploy_id: string }): Promise {} + deleteDeploy(config: { deploy_id: string }): Promise {} + lockDeploy(config: { deploy_id: string }): Promise {} + unlockDeploy(config: { deploy_id: string }): Promise {} + uploadDeployFile(config: { + deploy_id: string + path: string + size?: number + file_body: string + }): Promise {} + uploadDeployFunction(config: { + deploy_id: string + name: string + runtime?: string + invocation_mode?: string + size?: number + file_body: string + 'X-Nf-Retry-Count'?: number + }): Promise {} + updatePlugin(config: { site_id: string; package: string; pinned_version?: string }): Promise {} + getLatestPluginRuns(config: { site_id: string; packages: string[]; state?: string }): Promise {} + createPluginRun(config: { + deploy_id: string + package?: string + version?: string + state?: string + reporting_event?: string + title?: string + summary?: string + text?: string + }): Promise {} + listFormSubmissions(config: { + form_id: string + page?: number + per_page?: number + }): Promise {} + listHooksBySiteId(config: { site_id: string }): Promise {} + createHookBySiteId(config: { + site_id: string + id?: string + type?: string + event?: string + data?: object + created_at?: string + updated_at?: string + disabled?: boolean + }): Promise {} + getHook(config: { hook_id: string }): Promise {} + updateHook(config: { + id?: string + site_id?: string + type?: string + event?: string + data?: object + created_at?: string + updated_at?: string + disabled?: boolean + hook_id: string + }): Promise {} + deleteHook(config: { hook_id: string }): Promise {} + enableHook(config: { hook_id: string }): Promise {} + listHookTypes(): Promise {} + createTicket(config: { client_id: string }): Promise {} + showTicket(config: { ticket_id: string }): Promise {} + exchangeTicket(config: { ticket_id: string }): Promise {} + listDeployKeys(): Promise {} + createDeployKey(): Promise {} + getDeployKey(config: { key_id: string }): Promise {} + deleteDeployKey(config: { key_id: string }): Promise {} + createSiteInTeam(config: { + site?: { + id?: string + state?: string + plan?: string + name?: string + custom_domain?: string + domain_aliases?: string[] + branch_deploy_custom_domain?: string + deploy_preview_custom_domain?: string + password?: string + notification_email?: string + url?: string + ssl_url?: string + admin_url?: string + screenshot_url?: string + created_at?: string + updated_at?: string + user_id?: string + session_id?: string + ssl?: boolean + force_ssl?: boolean + managed_dns?: boolean + deploy_url?: string + published_deploy?: { + id?: string + site_id?: string + user_id?: string + build_id?: string + state?: string + name?: string + url?: string + ssl_url?: string + admin_url?: string + deploy_url?: string + deploy_ssl_url?: string + screenshot_url?: string + review_id?: number + draft?: boolean + required?: string[] + required_functions?: string[] + error_message?: string + branch?: string + commit_ref?: string + commit_url?: string + skipped?: boolean + created_at?: string + updated_at?: string + published_at?: string + title?: string + context?: string + locked?: boolean + review_url?: string + site_capabilities?: { + large_media_enabled?: boolean + } + framework?: string + function_schedules?: { + name?: string + cron?: string + }[] + } + account_name?: string + account_slug?: string + git_provider?: string + deploy_hook?: string + capabilities?: object + processing_settings?: { + skip?: boolean + css?: { + bundle?: boolean + minify?: boolean + } + js?: { + bundle?: boolean + minify?: boolean + } + images?: { + optimize?: boolean + } + html?: { + pretty_urls?: boolean + } + } + build_settings?: { + id?: number + provider?: string + deploy_key_id?: string + repo_path?: string + repo_branch?: string + dir?: string + functions_dir?: string + cmd?: string + allowed_branches?: string[] + public_repo?: boolean + private_logs?: boolean + repo_url?: string + env?: object + installation_id?: number + stop_builds?: boolean + } + id_domain?: string + default_hooks_data?: { + access_token?: string + } + build_image?: string + prerender?: string + repo?: { + id?: number + provider?: string + deploy_key_id?: string + repo_path?: string + repo_branch?: string + dir?: string + functions_dir?: string + cmd?: string + allowed_branches?: string[] + public_repo?: boolean + private_logs?: boolean + repo_url?: string + env?: object + installation_id?: number + stop_builds?: boolean + } + } + configure_dns?: boolean + account_slug: string + }): Promise {} + listSitesForAccount(config: { + name?: string + account_slug: string + page?: number + per_page?: number + }): Promise {} + listMembersForAccount(config: { account_slug: string }): Promise {} + addMemberToAccount(config: { + role?: 'Owner' | 'Collaborator' | 'Controller' + email?: string + account_slug: string + }): Promise {} + getAccountMember(config: { account_slug: string; member_id: string }): Promise {} + updateAccountMember(config: { + role?: 'Owner' | 'Collaborator' | 'Controller' + site_access?: 'all' | 'none' | 'selected' + site_ids?: string[] + account_slug: string + member_id: string + }): Promise {} + removeAccountMember(config: { account_slug: string; member_id: string }): Promise {} + listPaymentMethodsForUser(): Promise {} + listAccountTypesForUser(): Promise {} + listAccountsForUser(): Promise {} + createAccount(config: { + name?: string + type_id?: string + payment_method_id?: string + period?: 'monthly' | 'yearly' + extra_seats_block?: number + }): Promise {} + getAccount(config: { account_id: string }): Promise {} + updateAccount(config: { + name?: string + slug?: string + type_id?: string + extra_seats_block?: number + billing_name?: string + billing_email?: string + billing_details?: string + account_id: string + }): Promise {} + cancelAccount(config: { account_id: string }): Promise {} + listAccountAuditEvents(config: { + query?: string + log_type?: string + page?: number + per_page?: number + account_id: string + }): Promise {} + listFormSubmission(config: { + query?: string + page?: number + per_page?: number + submission_id: string + }): Promise {} + deleteSubmission(config: { submission_id: string }): Promise {} + listServiceInstancesForSite(config: { site_id: string }): Promise {} + createServiceInstance(config: { + config: object + site_id: string + addon: string + }): Promise {} + showServiceInstance(config: { + site_id: string + addon: string + instance_id: string + }): Promise {} + updateServiceInstance(config: { + config: object + site_id: string + addon: string + instance_id: string + }): Promise {} + deleteServiceInstance(config: { site_id: string; addon: string; instance_id: string }): Promise {} + getServices( + config: { + search?: string + } = {}, + ): Promise {} + showService(config: { addonName: string }): Promise {} + showServiceManifest(config: { addonName: string }): Promise {} + getCurrentUser(): Promise {} + createSplitTest(config: { branch_tests?: object; site_id: string }): Promise {} + getSplitTests(config: { site_id: string }): Promise {} + updateSplitTest(config: { + branch_tests?: object + site_id: string + split_test_id: string + }): Promise {} + getSplitTest(config: { site_id: string; split_test_id: string }): Promise {} + enableSplitTest(config: { site_id: string; split_test_id: string }): Promise {} + disableSplitTest(config: { site_id: string; split_test_id: string }): Promise {} + createDnsZone(config: { account_slug?: string; site_id?: string; name?: string }): Promise {} + getDnsZones( + config: { + account_slug?: string + } = {}, + ): Promise {} + getDnsZone(config: { zone_id: string }): Promise {} + deleteDnsZone(config: { zone_id: string }): Promise {} + transferDnsZone(config: { + zone_id: string + /** the account of the dns zone */ + account_id: string + /** the account you want to transfer the dns zone to */ + transfer_account_id: string + /** the user you want to transfer the dns zone to */ + transfer_user_id: string + }): Promise {} + getDnsRecords(config: { zone_id: string }): Promise {} + createDnsRecord(config: { + type?: string + hostname?: string + value?: string + ttl?: number + priority?: number + weight?: number + port?: number + flag?: number + tag?: string + zone_id: string + }): Promise {} + getIndividualDnsRecord(config: { zone_id: string; dns_record_id: string }): Promise {} + deleteDnsRecord(config: { zone_id: string; dns_record_id: string }): Promise {} +} +export type ListSitesResponse = { + id?: string + state?: string + plan?: string + name?: string + custom_domain?: string + domain_aliases?: string[] + branch_deploy_custom_domain?: string + deploy_preview_custom_domain?: string + password?: string + notification_email?: string + url?: string + ssl_url?: string + admin_url?: string + screenshot_url?: string + created_at?: string + updated_at?: string + user_id?: string + session_id?: string + ssl?: boolean + force_ssl?: boolean + managed_dns?: boolean + deploy_url?: string + published_deploy?: { + id?: string + site_id?: string + user_id?: string + build_id?: string + state?: string + name?: string + url?: string + ssl_url?: string + admin_url?: string + deploy_url?: string + deploy_ssl_url?: string + screenshot_url?: string + review_id?: number + draft?: boolean + required?: string[] + required_functions?: string[] + error_message?: string + branch?: string + commit_ref?: string + commit_url?: string + skipped?: boolean + created_at?: string + updated_at?: string + published_at?: string + title?: string + context?: string + locked?: boolean + review_url?: string + site_capabilities?: { + large_media_enabled?: boolean + } + framework?: string + function_schedules?: { + name?: string + cron?: string + }[] + } + account_name?: string + account_slug?: string + git_provider?: string + deploy_hook?: string + capabilities?: object + processing_settings?: { + skip?: boolean + css?: { + bundle?: boolean + minify?: boolean + } + js?: { + bundle?: boolean + minify?: boolean + } + images?: { + optimize?: boolean + } + html?: { + pretty_urls?: boolean + } + } + build_settings?: { + id?: number + provider?: string + deploy_key_id?: string + repo_path?: string + repo_branch?: string + dir?: string + functions_dir?: string + cmd?: string + allowed_branches?: string[] + public_repo?: boolean + private_logs?: boolean + repo_url?: string + env?: object + installation_id?: number + stop_builds?: boolean + } + id_domain?: string + default_hooks_data?: { + access_token?: string + } + build_image?: string + prerender?: string +}[] +export type CreateSiteResponse = { + id?: string + state?: string + plan?: string + name?: string + custom_domain?: string + domain_aliases?: string[] + branch_deploy_custom_domain?: string + deploy_preview_custom_domain?: string + password?: string + notification_email?: string + url?: string + ssl_url?: string + admin_url?: string + screenshot_url?: string + created_at?: string + updated_at?: string + user_id?: string + session_id?: string + ssl?: boolean + force_ssl?: boolean + managed_dns?: boolean + deploy_url?: string + published_deploy?: { + id?: string + site_id?: string + user_id?: string + build_id?: string + state?: string + name?: string + url?: string + ssl_url?: string + admin_url?: string + deploy_url?: string + deploy_ssl_url?: string + screenshot_url?: string + review_id?: number + draft?: boolean + required?: string[] + required_functions?: string[] + error_message?: string + branch?: string + commit_ref?: string + commit_url?: string + skipped?: boolean + created_at?: string + updated_at?: string + published_at?: string + title?: string + context?: string + locked?: boolean + review_url?: string + site_capabilities?: { + large_media_enabled?: boolean + } + framework?: string + function_schedules?: { + name?: string + cron?: string + }[] + } + account_name?: string + account_slug?: string + git_provider?: string + deploy_hook?: string + capabilities?: object + processing_settings?: { + skip?: boolean + css?: { + bundle?: boolean + minify?: boolean + } + js?: { + bundle?: boolean + minify?: boolean + } + images?: { + optimize?: boolean + } + html?: { + pretty_urls?: boolean + } + } + build_settings?: { + id?: number + provider?: string + deploy_key_id?: string + repo_path?: string + repo_branch?: string + dir?: string + functions_dir?: string + cmd?: string + allowed_branches?: string[] + public_repo?: boolean + private_logs?: boolean + repo_url?: string + env?: object + installation_id?: number + stop_builds?: boolean + } + id_domain?: string + default_hooks_data?: { + access_token?: string + } + build_image?: string + prerender?: string +} +export type GetSiteResponse = { + id?: string + state?: string + plan?: string + name?: string + custom_domain?: string + domain_aliases?: string[] + branch_deploy_custom_domain?: string + deploy_preview_custom_domain?: string + password?: string + notification_email?: string + url?: string + ssl_url?: string + admin_url?: string + screenshot_url?: string + created_at?: string + updated_at?: string + user_id?: string + session_id?: string + ssl?: boolean + force_ssl?: boolean + managed_dns?: boolean + deploy_url?: string + published_deploy?: { + id?: string + site_id?: string + user_id?: string + build_id?: string + state?: string + name?: string + url?: string + ssl_url?: string + admin_url?: string + deploy_url?: string + deploy_ssl_url?: string + screenshot_url?: string + review_id?: number + draft?: boolean + required?: string[] + required_functions?: string[] + error_message?: string + branch?: string + commit_ref?: string + commit_url?: string + skipped?: boolean + created_at?: string + updated_at?: string + published_at?: string + title?: string + context?: string + locked?: boolean + review_url?: string + site_capabilities?: { + large_media_enabled?: boolean + } + framework?: string + function_schedules?: { + name?: string + cron?: string + }[] + } + account_name?: string + account_slug?: string + git_provider?: string + deploy_hook?: string + capabilities?: object + processing_settings?: { + skip?: boolean + css?: { + bundle?: boolean + minify?: boolean + } + js?: { + bundle?: boolean + minify?: boolean + } + images?: { + optimize?: boolean + } + html?: { + pretty_urls?: boolean + } + } + build_settings?: { + id?: number + provider?: string + deploy_key_id?: string + repo_path?: string + repo_branch?: string + dir?: string + functions_dir?: string + cmd?: string + allowed_branches?: string[] + public_repo?: boolean + private_logs?: boolean + repo_url?: string + env?: object + installation_id?: number + stop_builds?: boolean + } + id_domain?: string + default_hooks_data?: { + access_token?: string + } + build_image?: string + prerender?: string +} +export type UpdateSiteResponse = { + id?: string + state?: string + plan?: string + name?: string + custom_domain?: string + domain_aliases?: string[] + branch_deploy_custom_domain?: string + deploy_preview_custom_domain?: string + password?: string + notification_email?: string + url?: string + ssl_url?: string + admin_url?: string + screenshot_url?: string + created_at?: string + updated_at?: string + user_id?: string + session_id?: string + ssl?: boolean + force_ssl?: boolean + managed_dns?: boolean + deploy_url?: string + published_deploy?: { + id?: string + site_id?: string + user_id?: string + build_id?: string + state?: string + name?: string + url?: string + ssl_url?: string + admin_url?: string + deploy_url?: string + deploy_ssl_url?: string + screenshot_url?: string + review_id?: number + draft?: boolean + required?: string[] + required_functions?: string[] + error_message?: string + branch?: string + commit_ref?: string + commit_url?: string + skipped?: boolean + created_at?: string + updated_at?: string + published_at?: string + title?: string + context?: string + locked?: boolean + review_url?: string + site_capabilities?: { + large_media_enabled?: boolean + } + framework?: string + function_schedules?: { + name?: string + cron?: string + }[] + } + account_name?: string + account_slug?: string + git_provider?: string + deploy_hook?: string + capabilities?: object + processing_settings?: { + skip?: boolean + css?: { + bundle?: boolean + minify?: boolean + } + js?: { + bundle?: boolean + minify?: boolean + } + images?: { + optimize?: boolean + } + html?: { + pretty_urls?: boolean + } + } + build_settings?: { + id?: number + provider?: string + deploy_key_id?: string + repo_path?: string + repo_branch?: string + dir?: string + functions_dir?: string + cmd?: string + allowed_branches?: string[] + public_repo?: boolean + private_logs?: boolean + repo_url?: string + env?: object + installation_id?: number + stop_builds?: boolean + } + id_domain?: string + default_hooks_data?: { + access_token?: string + } + build_image?: string + prerender?: string +} +export type ProvisionSiteTlsCertificateResponse = { + state?: string + domains?: string[] + created_at?: string + updated_at?: string + expires_at?: string +} +export type ShowSiteTlsCertificateResponse = { + state?: string + domains?: string[] + created_at?: string + updated_at?: string + expires_at?: string +} +export type GetEnvVarsResponse = { + /** The environment variable key, like ALGOLIA_ID (case-sensitive) */ + key?: string + /** The scopes that this environment variable is set to */ + scopes?: ('builds' | 'functions' | 'runtime' | 'post-processing')[] + /** An array of Value objects containing values and metadata */ + values?: { + /** The environment variable value's universally unique ID */ + id?: string + /** The environment variable's unencrypted value */ + value?: string + /** The deploy context in which this value will be used. `dev` refers to local development when running `netlify dev`. */ + context?: 'all' | 'dev' | 'branch-deploy' | 'deploy-preview' | 'production' | 'branch' + /** An additional parameter for custom branches. Currently, this is used for specifying a branch name when `context=branch`. */ + context_parameter?: string + }[] + /** Secret values are only readable by code running on Netlify’s systems. With secrets, only the local development context values are readable from the UI, API, and CLI. By default, environment variable values are not secret. (Enterprise plans only) */ + is_secret?: boolean + /** The timestamp of when the value was last updated */ + updated_at?: string + updated_by?: { + /** The user's unique identifier */ + id?: string + /** The user's full name (first and last) */ + full_name?: string + /** The user's email address */ + email?: string + /** A URL pointing to the user's avatar */ + avatar_url?: string + } +}[] +export type CreateEnvVarsResponse = { + /** The environment variable key, like ALGOLIA_ID (case-sensitive) */ + key?: string + /** The scopes that this environment variable is set to */ + scopes?: ('builds' | 'functions' | 'runtime' | 'post-processing')[] + /** An array of Value objects containing values and metadata */ + values?: { + /** The environment variable value's universally unique ID */ + id?: string + /** The environment variable's unencrypted value */ + value?: string + /** The deploy context in which this value will be used. `dev` refers to local development when running `netlify dev`. */ + context?: 'all' | 'dev' | 'branch-deploy' | 'deploy-preview' | 'production' | 'branch' + /** An additional parameter for custom branches. Currently, this is used for specifying a branch name when `context=branch`. */ + context_parameter?: string + }[] + /** Secret values are only readable by code running on Netlify’s systems. With secrets, only the local development context values are readable from the UI, API, and CLI. By default, environment variable values are not secret. (Enterprise plans only) */ + is_secret?: boolean + /** The timestamp of when the value was last updated */ + updated_at?: string + updated_by?: { + /** The user's unique identifier */ + id?: string + /** The user's full name (first and last) */ + full_name?: string + /** The user's email address */ + email?: string + /** A URL pointing to the user's avatar */ + avatar_url?: string + } +}[] +export type GetEnvVarResponse = { + /** The environment variable key, like ALGOLIA_ID (case-sensitive) */ + key?: string + /** The scopes that this environment variable is set to */ + scopes?: ('builds' | 'functions' | 'runtime' | 'post-processing')[] + /** An array of Value objects containing values and metadata */ + values?: { + /** The environment variable value's universally unique ID */ + id?: string + /** The environment variable's unencrypted value */ + value?: string + /** The deploy context in which this value will be used. `dev` refers to local development when running `netlify dev`. */ + context?: 'all' | 'dev' | 'branch-deploy' | 'deploy-preview' | 'production' | 'branch' + /** An additional parameter for custom branches. Currently, this is used for specifying a branch name when `context=branch`. */ + context_parameter?: string + }[] + /** Secret values are only readable by code running on Netlify’s systems. With secrets, only the local development context values are readable from the UI, API, and CLI. By default, environment variable values are not secret. (Enterprise plans only) */ + is_secret?: boolean + /** The timestamp of when the value was last updated */ + updated_at?: string + updated_by?: { + /** The user's unique identifier */ + id?: string + /** The user's full name (first and last) */ + full_name?: string + /** The user's email address */ + email?: string + /** A URL pointing to the user's avatar */ + avatar_url?: string + } +} +export type UpdateEnvVarResponse = { + /** The environment variable key, like ALGOLIA_ID (case-sensitive) */ + key?: string + /** The scopes that this environment variable is set to */ + scopes?: ('builds' | 'functions' | 'runtime' | 'post-processing')[] + /** An array of Value objects containing values and metadata */ + values?: { + /** The environment variable value's universally unique ID */ + id?: string + /** The environment variable's unencrypted value */ + value?: string + /** The deploy context in which this value will be used. `dev` refers to local development when running `netlify dev`. */ + context?: 'all' | 'dev' | 'branch-deploy' | 'deploy-preview' | 'production' | 'branch' + /** An additional parameter for custom branches. Currently, this is used for specifying a branch name when `context=branch`. */ + context_parameter?: string + }[] + /** Secret values are only readable by code running on Netlify’s systems. With secrets, only the local development context values are readable from the UI, API, and CLI. By default, environment variable values are not secret. (Enterprise plans only) */ + is_secret?: boolean + /** The timestamp of when the value was last updated */ + updated_at?: string + updated_by?: { + /** The user's unique identifier */ + id?: string + /** The user's full name (first and last) */ + full_name?: string + /** The user's email address */ + email?: string + /** A URL pointing to the user's avatar */ + avatar_url?: string + } +} +export type SetEnvVarValueResponse = { + /** The environment variable key, like ALGOLIA_ID (case-sensitive) */ + key?: string + /** The scopes that this environment variable is set to */ + scopes?: ('builds' | 'functions' | 'runtime' | 'post-processing')[] + /** An array of Value objects containing values and metadata */ + values?: { + /** The environment variable value's universally unique ID */ + id?: string + /** The environment variable's unencrypted value */ + value?: string + /** The deploy context in which this value will be used. `dev` refers to local development when running `netlify dev`. */ + context?: 'all' | 'dev' | 'branch-deploy' | 'deploy-preview' | 'production' | 'branch' + /** An additional parameter for custom branches. Currently, this is used for specifying a branch name when `context=branch`. */ + context_parameter?: string + }[] + /** Secret values are only readable by code running on Netlify’s systems. With secrets, only the local development context values are readable from the UI, API, and CLI. By default, environment variable values are not secret. (Enterprise plans only) */ + is_secret?: boolean + /** The timestamp of when the value was last updated */ + updated_at?: string + updated_by?: { + /** The user's unique identifier */ + id?: string + /** The user's full name (first and last) */ + full_name?: string + /** The user's email address */ + email?: string + /** A URL pointing to the user's avatar */ + avatar_url?: string + } +} +export type ListSiteFormsResponse = { + id?: string + site_id?: string + name?: string + paths?: string[] + submission_count?: number + fields?: object[] + created_at?: string +}[] +export type ListSiteSubmissionsResponse = { + id?: string + number?: number + email?: string + name?: string + first_name?: string + last_name?: string + company?: string + summary?: string + body?: string + data?: object + created_at?: string + site_url?: string +}[] +export type ListSiteFilesResponse = { + id?: string + path?: string + sha?: string + mime_type?: string + size?: number +}[] +export type ListSiteAssetsResponse = { + id?: string + site_id?: string + creator_id?: string + name?: string + state?: string + content_type?: string + url?: string + key?: string + visibility?: string + size?: number + created_at?: string + updated_at?: string +}[] +export type CreateSiteAssetResponse = { + form?: { + url?: string + fields?: object + } + asset?: { + id?: string + site_id?: string + creator_id?: string + name?: string + state?: string + content_type?: string + url?: string + key?: string + visibility?: string + size?: number + created_at?: string + updated_at?: string + } +} +export type GetSiteAssetInfoResponse = { + id?: string + site_id?: string + creator_id?: string + name?: string + state?: string + content_type?: string + url?: string + key?: string + visibility?: string + size?: number + created_at?: string + updated_at?: string +} +export type UpdateSiteAssetResponse = { + id?: string + site_id?: string + creator_id?: string + name?: string + state?: string + content_type?: string + url?: string + key?: string + visibility?: string + size?: number + created_at?: string + updated_at?: string +} +export type GetSiteAssetPublicSignatureResponse = { + url?: string +} +export type GetSiteFileByPathNameResponse = { + id?: string + path?: string + sha?: string + mime_type?: string + size?: number +} +export type ListSiteSnippetsResponse = { + id?: number + site_id?: string + title?: string + general?: string + general_position?: string + goal?: string + goal_position?: string +}[] +export type CreateSiteSnippetResponse = { + id?: number + site_id?: string + title?: string + general?: string + general_position?: string + goal?: string + goal_position?: string +} +export type GetSiteSnippetResponse = { + id?: number + site_id?: string + title?: string + general?: string + general_position?: string + goal?: string + goal_position?: string +} +export type GetSiteMetadataResponse = object +export type ListSiteBuildHooksResponse = { + id?: string + title?: string + branch?: string + url?: string + site_id?: string + created_at?: string +}[] +export type CreateSiteBuildHookResponse = { + id?: string + title?: string + branch?: string + url?: string + site_id?: string + created_at?: string +} +export type GetSiteBuildHookResponse = { + id?: string + title?: string + branch?: string + url?: string + site_id?: string + created_at?: string +} +export type ListSiteDeploysResponse = { + id?: string + site_id?: string + user_id?: string + build_id?: string + state?: string + name?: string + url?: string + ssl_url?: string + admin_url?: string + deploy_url?: string + deploy_ssl_url?: string + screenshot_url?: string + review_id?: number + draft?: boolean + required?: string[] + required_functions?: string[] + error_message?: string + branch?: string + commit_ref?: string + commit_url?: string + skipped?: boolean + created_at?: string + updated_at?: string + published_at?: string + title?: string + context?: string + locked?: boolean + review_url?: string + site_capabilities?: { + large_media_enabled?: boolean + } + framework?: string + function_schedules?: { + name?: string + cron?: string + }[] +}[] +export type CreateSiteDeployResponse = { + id?: string + site_id?: string + user_id?: string + build_id?: string + state?: string + name?: string + url?: string + ssl_url?: string + admin_url?: string + deploy_url?: string + deploy_ssl_url?: string + screenshot_url?: string + review_id?: number + draft?: boolean + required?: string[] + required_functions?: string[] + error_message?: string + branch?: string + commit_ref?: string + commit_url?: string + skipped?: boolean + created_at?: string + updated_at?: string + published_at?: string + title?: string + context?: string + locked?: boolean + review_url?: string + site_capabilities?: { + large_media_enabled?: boolean + } + framework?: string + function_schedules?: { + name?: string + cron?: string + }[] +} +export type GetSiteDeployResponse = { + id?: string + site_id?: string + user_id?: string + build_id?: string + state?: string + name?: string + url?: string + ssl_url?: string + admin_url?: string + deploy_url?: string + deploy_ssl_url?: string + screenshot_url?: string + review_id?: number + draft?: boolean + required?: string[] + required_functions?: string[] + error_message?: string + branch?: string + commit_ref?: string + commit_url?: string + skipped?: boolean + created_at?: string + updated_at?: string + published_at?: string + title?: string + context?: string + locked?: boolean + review_url?: string + site_capabilities?: { + large_media_enabled?: boolean + } + framework?: string + function_schedules?: { + name?: string + cron?: string + }[] +} +export type UpdateSiteDeployResponse = { + id?: string + site_id?: string + user_id?: string + build_id?: string + state?: string + name?: string + url?: string + ssl_url?: string + admin_url?: string + deploy_url?: string + deploy_ssl_url?: string + screenshot_url?: string + review_id?: number + draft?: boolean + required?: string[] + required_functions?: string[] + error_message?: string + branch?: string + commit_ref?: string + commit_url?: string + skipped?: boolean + created_at?: string + updated_at?: string + published_at?: string + title?: string + context?: string + locked?: boolean + review_url?: string + site_capabilities?: { + large_media_enabled?: boolean + } + framework?: string + function_schedules?: { + name?: string + cron?: string + }[] +} +export type CancelSiteDeployResponse = { + id?: string + site_id?: string + user_id?: string + build_id?: string + state?: string + name?: string + url?: string + ssl_url?: string + admin_url?: string + deploy_url?: string + deploy_ssl_url?: string + screenshot_url?: string + review_id?: number + draft?: boolean + required?: string[] + required_functions?: string[] + error_message?: string + branch?: string + commit_ref?: string + commit_url?: string + skipped?: boolean + created_at?: string + updated_at?: string + published_at?: string + title?: string + context?: string + locked?: boolean + review_url?: string + site_capabilities?: { + large_media_enabled?: boolean + } + framework?: string + function_schedules?: { + name?: string + cron?: string + }[] +} +export type RestoreSiteDeployResponse = { + id?: string + site_id?: string + user_id?: string + build_id?: string + state?: string + name?: string + url?: string + ssl_url?: string + admin_url?: string + deploy_url?: string + deploy_ssl_url?: string + screenshot_url?: string + review_id?: number + draft?: boolean + required?: string[] + required_functions?: string[] + error_message?: string + branch?: string + commit_ref?: string + commit_url?: string + skipped?: boolean + created_at?: string + updated_at?: string + published_at?: string + title?: string + context?: string + locked?: boolean + review_url?: string + site_capabilities?: { + large_media_enabled?: boolean + } + framework?: string + function_schedules?: { + name?: string + cron?: string + }[] +} +export type ListSiteBuildsResponse = { + id?: string + deploy_id?: string + sha?: string + done?: boolean + error?: string + created_at?: string +}[] +export type CreateSiteBuildResponse = { + id?: string + deploy_id?: string + sha?: string + done?: boolean + error?: string + created_at?: string +} +export type ListSiteDeployedBranchesResponse = { + id?: string + deploy_id?: string + name?: string + slug?: string + url?: string + ssl_url?: string +}[] +export type UnlinkSiteRepoResponse = { + id?: string + state?: string + plan?: string + name?: string + custom_domain?: string + domain_aliases?: string[] + branch_deploy_custom_domain?: string + deploy_preview_custom_domain?: string + password?: string + notification_email?: string + url?: string + ssl_url?: string + admin_url?: string + screenshot_url?: string + created_at?: string + updated_at?: string + user_id?: string + session_id?: string + ssl?: boolean + force_ssl?: boolean + managed_dns?: boolean + deploy_url?: string + published_deploy?: { + id?: string + site_id?: string + user_id?: string + build_id?: string + state?: string + name?: string + url?: string + ssl_url?: string + admin_url?: string + deploy_url?: string + deploy_ssl_url?: string + screenshot_url?: string + review_id?: number + draft?: boolean + required?: string[] + required_functions?: string[] + error_message?: string + branch?: string + commit_ref?: string + commit_url?: string + skipped?: boolean + created_at?: string + updated_at?: string + published_at?: string + title?: string + context?: string + locked?: boolean + review_url?: string + site_capabilities?: { + large_media_enabled?: boolean + } + framework?: string + function_schedules?: { + name?: string + cron?: string + }[] + } + account_name?: string + account_slug?: string + git_provider?: string + deploy_hook?: string + capabilities?: object + processing_settings?: { + skip?: boolean + css?: { + bundle?: boolean + minify?: boolean + } + js?: { + bundle?: boolean + minify?: boolean + } + images?: { + optimize?: boolean + } + html?: { + pretty_urls?: boolean + } + } + build_settings?: { + id?: number + provider?: string + deploy_key_id?: string + repo_path?: string + repo_branch?: string + dir?: string + functions_dir?: string + cmd?: string + allowed_branches?: string[] + public_repo?: boolean + private_logs?: boolean + repo_url?: string + env?: object + installation_id?: number + stop_builds?: boolean + } + id_domain?: string + default_hooks_data?: { + access_token?: string + } + build_image?: string + prerender?: string +} +export type GetSiteBuildResponse = { + id?: string + deploy_id?: string + sha?: string + done?: boolean + error?: string + created_at?: string +} +export type GetAccountBuildStatusResponse = { + active?: number + pending_concurrency?: number + enqueued?: number + build_count?: number + minutes?: { + current?: number + current_average_sec?: number + previous?: number + period_start_date?: string + period_end_date?: string + last_updated_at?: string + included_minutes?: string + included_minutes_with_packs?: string + } +}[] +export type GetDnsForSiteResponse = { + id?: string + name?: string + errors?: string[] + supported_record_types?: string[] + user_id?: string + created_at?: string + updated_at?: string + records?: { + id?: string + hostname?: string + type?: string + value?: string + ttl?: number + priority?: number + dns_zone_id?: string + site_id?: string + flag?: number + tag?: string + managed?: boolean + }[] + dns_servers?: string[] + account_id?: string + site_id?: string + account_slug?: string + account_name?: string + domain?: string + ipv6_enabled?: boolean + dedicated?: boolean +}[] +export type ConfigureDnsForSiteResponse = { + id?: string + name?: string + errors?: string[] + supported_record_types?: string[] + user_id?: string + created_at?: string + updated_at?: string + records?: { + id?: string + hostname?: string + type?: string + value?: string + ttl?: number + priority?: number + dns_zone_id?: string + site_id?: string + flag?: number + tag?: string + managed?: boolean + }[] + dns_servers?: string[] + account_id?: string + site_id?: string + account_slug?: string + account_name?: string + domain?: string + ipv6_enabled?: boolean + dedicated?: boolean +}[] +export type GetDeployResponse = { + id?: string + site_id?: string + user_id?: string + build_id?: string + state?: string + name?: string + url?: string + ssl_url?: string + admin_url?: string + deploy_url?: string + deploy_ssl_url?: string + screenshot_url?: string + review_id?: number + draft?: boolean + required?: string[] + required_functions?: string[] + error_message?: string + branch?: string + commit_ref?: string + commit_url?: string + skipped?: boolean + created_at?: string + updated_at?: string + published_at?: string + title?: string + context?: string + locked?: boolean + review_url?: string + site_capabilities?: { + large_media_enabled?: boolean + } + framework?: string + function_schedules?: { + name?: string + cron?: string + }[] +} +export type LockDeployResponse = { + id?: string + site_id?: string + user_id?: string + build_id?: string + state?: string + name?: string + url?: string + ssl_url?: string + admin_url?: string + deploy_url?: string + deploy_ssl_url?: string + screenshot_url?: string + review_id?: number + draft?: boolean + required?: string[] + required_functions?: string[] + error_message?: string + branch?: string + commit_ref?: string + commit_url?: string + skipped?: boolean + created_at?: string + updated_at?: string + published_at?: string + title?: string + context?: string + locked?: boolean + review_url?: string + site_capabilities?: { + large_media_enabled?: boolean + } + framework?: string + function_schedules?: { + name?: string + cron?: string + }[] +} +export type UnlockDeployResponse = { + id?: string + site_id?: string + user_id?: string + build_id?: string + state?: string + name?: string + url?: string + ssl_url?: string + admin_url?: string + deploy_url?: string + deploy_ssl_url?: string + screenshot_url?: string + review_id?: number + draft?: boolean + required?: string[] + required_functions?: string[] + error_message?: string + branch?: string + commit_ref?: string + commit_url?: string + skipped?: boolean + created_at?: string + updated_at?: string + published_at?: string + title?: string + context?: string + locked?: boolean + review_url?: string + site_capabilities?: { + large_media_enabled?: boolean + } + framework?: string + function_schedules?: { + name?: string + cron?: string + }[] +} +export type UploadDeployFileResponse = { + id?: string + path?: string + sha?: string + mime_type?: string + size?: number +} +export type UploadDeployFunctionResponse = { + id?: string + name?: string + sha?: string +} +export type UpdatePluginResponse = { + package?: string + pinned_version?: string +} +export type CreatePluginRunResponse = { + package?: string + version?: string + state?: string + reporting_event?: string + title?: string + summary?: string + text?: string + deploy_id?: string +} +export type ListFormSubmissionsResponse = { + id?: string + number?: number + email?: string + name?: string + first_name?: string + last_name?: string + company?: string + summary?: string + body?: string + data?: object + created_at?: string + site_url?: string +}[] +export type ListHooksBySiteIdResponse = { + id?: string + site_id?: string + type?: string + event?: string + data?: object + created_at?: string + updated_at?: string + disabled?: boolean +}[] +export type CreateHookBySiteIdResponse = { + id?: string + site_id?: string + type?: string + event?: string + data?: object + created_at?: string + updated_at?: string + disabled?: boolean +} +export type GetHookResponse = { + id?: string + site_id?: string + type?: string + event?: string + data?: object + created_at?: string + updated_at?: string + disabled?: boolean +} +export type UpdateHookResponse = { + id?: string + site_id?: string + type?: string + event?: string + data?: object + created_at?: string + updated_at?: string + disabled?: boolean +} +export type EnableHookResponse = { + id?: string + site_id?: string + type?: string + event?: string + data?: object + created_at?: string + updated_at?: string + disabled?: boolean +} +export type ListHookTypesResponse = { + name?: string + events?: string[] + fields?: object[] +}[] +export type CreateTicketResponse = { + id?: string + client_id?: string + authorized?: boolean + created_at?: string +} +export type ShowTicketResponse = { + id?: string + client_id?: string + authorized?: boolean + created_at?: string +} +export type ExchangeTicketResponse = { + id?: string + access_token?: string + user_id?: string + user_email?: string + created_at?: string +} +export type ListDeployKeysResponse = { + id?: string + public_key?: string + created_at?: string +}[] +export type CreateDeployKeyResponse = { + id?: string + public_key?: string + created_at?: string +} +export type GetDeployKeyResponse = { + id?: string + public_key?: string + created_at?: string +} +export type CreateSiteInTeamResponse = { + id?: string + state?: string + plan?: string + name?: string + custom_domain?: string + domain_aliases?: string[] + branch_deploy_custom_domain?: string + deploy_preview_custom_domain?: string + password?: string + notification_email?: string + url?: string + ssl_url?: string + admin_url?: string + screenshot_url?: string + created_at?: string + updated_at?: string + user_id?: string + session_id?: string + ssl?: boolean + force_ssl?: boolean + managed_dns?: boolean + deploy_url?: string + published_deploy?: { + id?: string + site_id?: string + user_id?: string + build_id?: string + state?: string + name?: string + url?: string + ssl_url?: string + admin_url?: string + deploy_url?: string + deploy_ssl_url?: string + screenshot_url?: string + review_id?: number + draft?: boolean + required?: string[] + required_functions?: string[] + error_message?: string + branch?: string + commit_ref?: string + commit_url?: string + skipped?: boolean + created_at?: string + updated_at?: string + published_at?: string + title?: string + context?: string + locked?: boolean + review_url?: string + site_capabilities?: { + large_media_enabled?: boolean + } + framework?: string + function_schedules?: { + name?: string + cron?: string + }[] + } + account_name?: string + account_slug?: string + git_provider?: string + deploy_hook?: string + capabilities?: object + processing_settings?: { + skip?: boolean + css?: { + bundle?: boolean + minify?: boolean + } + js?: { + bundle?: boolean + minify?: boolean + } + images?: { + optimize?: boolean + } + html?: { + pretty_urls?: boolean + } + } + build_settings?: { + id?: number + provider?: string + deploy_key_id?: string + repo_path?: string + repo_branch?: string + dir?: string + functions_dir?: string + cmd?: string + allowed_branches?: string[] + public_repo?: boolean + private_logs?: boolean + repo_url?: string + env?: object + installation_id?: number + stop_builds?: boolean + } + id_domain?: string + default_hooks_data?: { + access_token?: string + } + build_image?: string + prerender?: string +} +export type ListSitesForAccountResponse = { + id?: string + state?: string + plan?: string + name?: string + custom_domain?: string + domain_aliases?: string[] + branch_deploy_custom_domain?: string + deploy_preview_custom_domain?: string + password?: string + notification_email?: string + url?: string + ssl_url?: string + admin_url?: string + screenshot_url?: string + created_at?: string + updated_at?: string + user_id?: string + session_id?: string + ssl?: boolean + force_ssl?: boolean + managed_dns?: boolean + deploy_url?: string + published_deploy?: { + id?: string + site_id?: string + user_id?: string + build_id?: string + state?: string + name?: string + url?: string + ssl_url?: string + admin_url?: string + deploy_url?: string + deploy_ssl_url?: string + screenshot_url?: string + review_id?: number + draft?: boolean + required?: string[] + required_functions?: string[] + error_message?: string + branch?: string + commit_ref?: string + commit_url?: string + skipped?: boolean + created_at?: string + updated_at?: string + published_at?: string + title?: string + context?: string + locked?: boolean + review_url?: string + site_capabilities?: { + large_media_enabled?: boolean + } + framework?: string + function_schedules?: { + name?: string + cron?: string + }[] + } + account_name?: string + account_slug?: string + git_provider?: string + deploy_hook?: string + capabilities?: object + processing_settings?: { + skip?: boolean + css?: { + bundle?: boolean + minify?: boolean + } + js?: { + bundle?: boolean + minify?: boolean + } + images?: { + optimize?: boolean + } + html?: { + pretty_urls?: boolean + } + } + build_settings?: { + id?: number + provider?: string + deploy_key_id?: string + repo_path?: string + repo_branch?: string + dir?: string + functions_dir?: string + cmd?: string + allowed_branches?: string[] + public_repo?: boolean + private_logs?: boolean + repo_url?: string + env?: object + installation_id?: number + stop_builds?: boolean + } + id_domain?: string + default_hooks_data?: { + access_token?: string + } + build_image?: string + prerender?: string +}[] +export type ListMembersForAccountResponse = { + id?: string + full_name?: string + email?: string + avatar?: string + role?: string +}[] +export type AddMemberToAccountResponse = { + id?: string + full_name?: string + email?: string + avatar?: string + role?: string +}[] +export type GetAccountMemberResponse = { + id?: string + full_name?: string + email?: string + avatar?: string + role?: string +} +export type UpdateAccountMemberResponse = { + id?: string + full_name?: string + email?: string + avatar?: string + role?: string +} +export type ListPaymentMethodsForUserResponse = { + id?: string + method_name?: string + type?: string + state?: string + data?: { + card_type?: string + last4?: string + email?: string + } + created_at?: string + updated_at?: string +}[] +export type ListAccountTypesForUserResponse = { + id?: string + name?: string + description?: string + capabilities?: object + monthly_dollar_price?: number + yearly_dollar_price?: number + monthly_seats_addon_dollar_price?: number + yearly_seats_addon_dollar_price?: number +}[] +export type ListAccountsForUserResponse = { + id?: string + name?: string + slug?: string + type?: string + capabilities?: { + sites?: { + included?: number + used?: number + } + collaborators?: { + included?: number + used?: number + } + } + billing_name?: string + billing_email?: string + billing_details?: string + billing_period?: string + payment_method_id?: string + type_name?: string + type_id?: string + owner_ids?: string[] + roles_allowed?: string[] + created_at?: string + updated_at?: string +}[] +export type CreateAccountResponse = { + id?: string + name?: string + slug?: string + type?: string + capabilities?: { + sites?: { + included?: number + used?: number + } + collaborators?: { + included?: number + used?: number + } + } + billing_name?: string + billing_email?: string + billing_details?: string + billing_period?: string + payment_method_id?: string + type_name?: string + type_id?: string + owner_ids?: string[] + roles_allowed?: string[] + created_at?: string + updated_at?: string +} +export type GetAccountResponse = { + id?: string + name?: string + slug?: string + type?: string + capabilities?: { + sites?: { + included?: number + used?: number + } + collaborators?: { + included?: number + used?: number + } + } + billing_name?: string + billing_email?: string + billing_details?: string + billing_period?: string + payment_method_id?: string + type_name?: string + type_id?: string + owner_ids?: string[] + roles_allowed?: string[] + created_at?: string + updated_at?: string +}[] +export type UpdateAccountResponse = { + id?: string + name?: string + slug?: string + type?: string + capabilities?: { + sites?: { + included?: number + used?: number + } + collaborators?: { + included?: number + used?: number + } + } + billing_name?: string + billing_email?: string + billing_details?: string + billing_period?: string + payment_method_id?: string + type_name?: string + type_id?: string + owner_ids?: string[] + roles_allowed?: string[] + created_at?: string + updated_at?: string +} +export type ListAccountAuditEventsResponse = { + id?: string + account_id?: string + payload?: { + actor_id?: string + actor_name?: string + actor_email?: string + action?: string + timestamp?: string + log_type?: string + } +}[] +export type ListFormSubmissionResponse = { + id?: string + number?: number + email?: string + name?: string + first_name?: string + last_name?: string + company?: string + summary?: string + body?: string + data?: object + created_at?: string + site_url?: string +}[] +export type ListServiceInstancesForSiteResponse = { + id?: string + url?: string + config?: object + external_attributes?: object + service_slug?: string + service_path?: string + service_name?: string + env?: object + snippets?: object[] + auth_url?: string + created_at?: string + updated_at?: string +}[] +export type CreateServiceInstanceResponse = { + id?: string + url?: string + config?: object + external_attributes?: object + service_slug?: string + service_path?: string + service_name?: string + env?: object + snippets?: object[] + auth_url?: string + created_at?: string + updated_at?: string +} +export type ShowServiceInstanceResponse = { + id?: string + url?: string + config?: object + external_attributes?: object + service_slug?: string + service_path?: string + service_name?: string + env?: object + snippets?: object[] + auth_url?: string + created_at?: string + updated_at?: string +} +export type GetServicesResponse = { + id?: string + name?: string + slug?: string + service_path?: string + long_description?: string + description?: string + events?: object[] + tags?: string[] + icon?: string + manifest_url?: string + environments?: string[] + created_at?: string + updated_at?: string +}[] +export type ShowServiceResponse = { + id?: string + name?: string + slug?: string + service_path?: string + long_description?: string + description?: string + events?: object[] + tags?: string[] + icon?: string + manifest_url?: string + environments?: string[] + created_at?: string + updated_at?: string +} +export type ShowServiceManifestResponse = object +export type GetCurrentUserResponse = { + id?: string + uid?: string + full_name?: string + avatar_url?: string + email?: string + affiliate_id?: string + site_count?: number + created_at?: string + last_login?: string + login_providers?: string[] + onboarding_progress?: { + slides?: string + } +}[] +export type CreateSplitTestResponse = { + id?: string + site_id?: string + name?: string + path?: string + branches?: object[] + active?: boolean + created_at?: string + updated_at?: string + unpublished_at?: string +} +export type GetSplitTestsResponse = { + id?: string + site_id?: string + name?: string + path?: string + branches?: object[] + active?: boolean + created_at?: string + updated_at?: string + unpublished_at?: string +}[] +export type UpdateSplitTestResponse = { + id?: string + site_id?: string + name?: string + path?: string + branches?: object[] + active?: boolean + created_at?: string + updated_at?: string + unpublished_at?: string +} +export type GetSplitTestResponse = { + id?: string + site_id?: string + name?: string + path?: string + branches?: object[] + active?: boolean + created_at?: string + updated_at?: string + unpublished_at?: string +} +export type CreateDnsZoneResponse = { + id?: string + name?: string + errors?: string[] + supported_record_types?: string[] + user_id?: string + created_at?: string + updated_at?: string + records?: { + id?: string + hostname?: string + type?: string + value?: string + ttl?: number + priority?: number + dns_zone_id?: string + site_id?: string + flag?: number + tag?: string + managed?: boolean + }[] + dns_servers?: string[] + account_id?: string + site_id?: string + account_slug?: string + account_name?: string + domain?: string + ipv6_enabled?: boolean + dedicated?: boolean +} +export type GetDnsZonesResponse = { + id?: string + name?: string + errors?: string[] + supported_record_types?: string[] + user_id?: string + created_at?: string + updated_at?: string + records?: { + id?: string + hostname?: string + type?: string + value?: string + ttl?: number + priority?: number + dns_zone_id?: string + site_id?: string + flag?: number + tag?: string + managed?: boolean + }[] + dns_servers?: string[] + account_id?: string + site_id?: string + account_slug?: string + account_name?: string + domain?: string + ipv6_enabled?: boolean + dedicated?: boolean +}[] +export type GetDnsZoneResponse = { + id?: string + name?: string + errors?: string[] + supported_record_types?: string[] + user_id?: string + created_at?: string + updated_at?: string + records?: { + id?: string + hostname?: string + type?: string + value?: string + ttl?: number + priority?: number + dns_zone_id?: string + site_id?: string + flag?: number + tag?: string + managed?: boolean + }[] + dns_servers?: string[] + account_id?: string + site_id?: string + account_slug?: string + account_name?: string + domain?: string + ipv6_enabled?: boolean + dedicated?: boolean +} +export type TransferDnsZoneResponse = { + id?: string + name?: string + errors?: string[] + supported_record_types?: string[] + user_id?: string + created_at?: string + updated_at?: string + records?: { + id?: string + hostname?: string + type?: string + value?: string + ttl?: number + priority?: number + dns_zone_id?: string + site_id?: string + flag?: number + tag?: string + managed?: boolean + }[] + dns_servers?: string[] + account_id?: string + site_id?: string + account_slug?: string + account_name?: string + domain?: string + ipv6_enabled?: boolean + dedicated?: boolean +} +export type GetDnsRecordsResponse = { + id?: string + hostname?: string + type?: string + value?: string + ttl?: number + priority?: number + dns_zone_id?: string + site_id?: string + flag?: number + tag?: string + managed?: boolean +}[] +export type CreateDnsRecordResponse = { + id?: string + hostname?: string + type?: string + value?: string + ttl?: number + priority?: number + dns_zone_id?: string + site_id?: string + flag?: number + tag?: string + managed?: boolean +} +export type GetIndividualDnsRecordResponse = { + id?: string + hostname?: string + type?: string + value?: string + ttl?: number + priority?: number + dns_zone_id?: string + site_id?: string + flag?: number + tag?: string + managed?: boolean +} diff --git a/packages/js-client/src/methods/index.js b/packages/js-client/src/methods/index.js index d78df9a09a..609e7b065d 100644 --- a/packages/js-client/src/methods/index.js +++ b/packages/js-client/src/methods/index.js @@ -27,6 +27,7 @@ const getMethod = function ({ method, basePath, defaultHeaders, agent, globalPar const callMethod = async function ({ method, basePath, defaultHeaders, agent, globalParams, params, opts }) { const requestParams = { ...globalParams, ...params } const url = getUrl(method, basePath, requestParams) + console.log({ url, method, basePath, requestParams }) const response = await makeRequestOrRetry({ url, method, defaultHeaders, agent, requestParams, opts }) const parsedResponse = await parseResponse(response) diff --git a/packages/js-client/tsconfig.json b/packages/js-client/tsconfig.json index f2d102c596..b41bdb8883 100644 --- a/packages/js-client/tsconfig.json +++ b/packages/js-client/tsconfig.json @@ -1,7 +1,8 @@ { "extends": "../../tsconfig.base.json", "compilerOptions": { - "outDir": "lib" /* Specify an output folder for all emitted files. */ + "outDir": "lib" /* Specify an output folder for all emitted files. */, + "resolveJsonModule": true }, "include": ["src/**/*.js", "src/**/*.ts"], "exclude": ["src/**/*.test.js", "src/**/*.test.ts"], diff --git a/packages/js-client/vitest.config.ts b/packages/js-client/vitest.config.ts new file mode 100644 index 0000000000..84ae76ce4d --- /dev/null +++ b/packages/js-client/vitest.config.ts @@ -0,0 +1,11 @@ +import { defineConfig } from 'vitest/config' + +export default defineConfig({ + test: { + restoreMocks: true, + environment: 'node', + onConsoleLog: (log, type) => { + process[type].write(log) + }, + }, +})