@luvio/generator-ts
Advanced tools
Comparing version 3.5.2 to 3.6.0
@@ -9,3 +9,3 @@ /** | ||
import { ConsoleFileParserLogger, toCamelCase, toPascalCase, toScreamingSnakeCase } from '@luvio/utils'; | ||
import { parseUrl } from '@luvio/model'; | ||
import { parseUrl, extensionFromName } from '@luvio/model'; | ||
import * as path from 'path'; | ||
@@ -376,3 +376,3 @@ import * as prettier from 'prettier'; | ||
function typeDefinitionFor(t, options = {}) { | ||
function typeDefinitionFor$1(t, options = {}) { | ||
var _a, _b; | ||
@@ -392,3 +392,3 @@ // if we're allowed to use references, see if one exists for this type | ||
// skip "any" inherited types | ||
result.push(typeDefinitionFor(inheritedType, { ...options, useReferences: true })); | ||
result.push(typeDefinitionFor$1(inheritedType, { ...options, useReferences: true })); | ||
} | ||
@@ -429,3 +429,3 @@ } | ||
// ok to reference type names once we're inside a type | ||
result.push(code `Array<${typeDefinitionFor(t.items, { | ||
result.push(code `Array<${typeDefinitionFor$1(t.items, { | ||
...options, | ||
@@ -438,3 +438,3 @@ useReferences: true, | ||
case 'union': { | ||
const unionCodes = t.anyOf.map((anyOfType) => typeDefinitionFor(anyOfType, { ...options, useReferences: true })); | ||
const unionCodes = t.anyOf.map((anyOfType) => typeDefinitionFor$1(anyOfType, { ...options, useReferences: true })); | ||
// Note: prettier will remove the parenthesis when not needed. | ||
@@ -476,3 +476,3 @@ result.push(code `(${Code.join(unionCodes, '|')})`); | ||
Code.join(t.discriminatorValueMapping.map(({ value, type }) => { | ||
return code `(${typeDefinitionFor(type, { | ||
return code `(${typeDefinitionFor$1(type, { | ||
...options, | ||
@@ -490,3 +490,3 @@ useReferences: true, | ||
// ok to reference type names once we're inside a type | ||
code `${name}${required ? '' : '?'}:${typeDefinitionFor(type, { | ||
code `${name}${required ? '' : '?'}:${typeDefinitionFor$1(type, { | ||
...options, | ||
@@ -526,3 +526,3 @@ useReferences: true, | ||
} | ||
const patternPropertyTypes = patternProperties.map(({ type }) => typeDefinitionFor(type, { ...options, useReferences: true })); | ||
const patternPropertyTypes = patternProperties.map(({ type }) => typeDefinitionFor$1(type, { ...options, useReferences: true })); | ||
const unsupportedPatterns = patternProperties | ||
@@ -599,3 +599,3 @@ .map(({ pattern }) => pattern) | ||
// build the type declaration | ||
const declaration = code `export type ${typename}=${typeDefinitionFor(type, { | ||
const declaration = code `export type ${typename}=${typeDefinitionFor$1(type, { | ||
referenceFor, | ||
@@ -605,3 +605,3 @@ })};`; | ||
if (type.type === 'object' && type.discriminator) { | ||
const discriminatedDeclaration = code `export type ${typename}Discriminated=${typeDefinitionFor(type, { | ||
const discriminatedDeclaration = code `export type ${typename}Discriminated=${typeDefinitionFor$1(type, { | ||
referenceFor, | ||
@@ -632,2 +632,14 @@ discriminated: true, | ||
function typeDefinitionFor(services, type) { | ||
return type | ||
? typeDefinitionFor$1(type, { | ||
referenceFor: (t) => { | ||
const typename = services.api.api.types.nameOf(t); | ||
return typename ? services.typeDeclaration.build(typename) : undefined; | ||
}, | ||
useReferences: true, | ||
}) | ||
: code `void`; | ||
} | ||
const NETWORK_COMMAND = { | ||
@@ -638,22 +650,2 @@ module: '@luvio/runtime', | ||
}; | ||
const FETCH_SERVICE = { | ||
module: '@luvio/runtime', | ||
exportedSymbol: 'FetchService', | ||
isType: true, | ||
}; | ||
const WITHERRORS_TYPE = { | ||
module: '@luvio/runtime', | ||
exportedSymbol: 'WithErrors', | ||
isType: true, | ||
}; | ||
const TYPEOF_TYPE = { | ||
module: '@luvio/utils', | ||
exportedSymbol: 'TypeOf', | ||
isType: true, | ||
}; | ||
const CONVERT_FETCH_RESPONSE_TO_DATA = { | ||
module: '@luvio/runtime', | ||
exportedSymbol: 'convertFetchResponseToData', | ||
isType: false, | ||
}; | ||
const JSON_SCHEMA = { | ||
@@ -665,3 +657,2 @@ module: '@luvio/jsonschema-validate', | ||
const MEDIATYPE_APP_JSON = 'application/json'; | ||
const HEADER_CONTENT_TYPE = 'Content-Type'; | ||
const INPUT_PAYLOAD_MEMBER_NAME = 'inputPayload'; | ||
@@ -747,11 +738,3 @@ /** | ||
typeDefinitionFor(type) { | ||
return type | ||
? typeDefinitionFor(type, { | ||
referenceFor: (t) => { | ||
const typename = this.services.api.api.types.nameOf(t); | ||
return typename ? this.services.typeDeclaration.build(typename) : undefined; | ||
}, | ||
useReferences: true, | ||
}) | ||
: code `void`; | ||
return typeDefinitionFor(this.services, type); | ||
} | ||
@@ -799,3 +782,3 @@ getServer(endpoint, operation) { | ||
} | ||
generateUrl(config) { | ||
processUrl(config) { | ||
const { endpoint, operation, request, server } = config; | ||
@@ -818,68 +801,6 @@ const uriParams = getParameterMembers(server.uriParameters, endpoint.uriParameters, request === null || request === void 0 ? void 0 : request.uriParameters).reduce((result, param) => { | ||
}); | ||
return code `let url: Parameters<${TYPEOF_TYPE}<${FETCH_SERVICE}>>[0] = \`${url}\`;`; | ||
return url; | ||
} | ||
generateQueryParams(config) { | ||
const { endpoint, operation, request } = config; | ||
// resolve query params | ||
let result = undefined; | ||
const queryParameters = getParameterMembers(request === null || request === void 0 ? void 0 : request.queryParameters); | ||
if (queryParameters.length > 0) { | ||
result = code `let queryParams: string[] = [];`; | ||
queryParameters.forEach((param) => { | ||
const paramName = toCamelCase(param.name); | ||
const value = this.encodeParam(paramName, param.type); | ||
if (!value) { | ||
throw new Error(`unsupported type for ${param.name} in ${operation.method} ${endpoint.path} operation query parameters`); | ||
} | ||
result.push(param.required ? '' : `if (this.config.${paramName} !== undefined) {`, `queryParams.push('${param.name}=' + ${value});`, param.required ? '' : `}`); | ||
}); | ||
result.push(`if (queryParams.length > 0) { url += '?' + queryParams.join('&'); }`); | ||
} | ||
return result; | ||
} | ||
generateHeaders(config) { | ||
const { request, hasInputPayload } = config; | ||
const requestHeaders = getParameterMembers(request === null || request === void 0 ? void 0 : request.headers); | ||
const hasHeaders = requestHeaders.length > 0 || hasInputPayload; | ||
let result = undefined; | ||
if (hasHeaders) { | ||
// TODO - resolve cookies? | ||
result = code `const headers: Record<string, any> = {`; | ||
if (hasInputPayload) { | ||
result.push(`'${HEADER_CONTENT_TYPE}': '${MEDIATYPE_APP_JSON}',`); | ||
} | ||
const headers = requestHeaders.filter((hdr) => hdr.name.toLowerCase() !== HEADER_CONTENT_TYPE.toLowerCase()); | ||
headers | ||
.filter((hdr) => hdr.required) | ||
.forEach((hdr) => result.push(`'${hdr.name}': this.config.${toCamelCase(hdr.name)},`)); | ||
result.push(`};`); | ||
headers | ||
.filter((hdr) => !hdr.required) | ||
.forEach((hdr) => { | ||
const headerName = toCamelCase(hdr.name); | ||
result.push(`if (this.config.${headerName} !== undefined) { headers['${hdr.name}'] = this.config.${headerName};}`); | ||
}); | ||
} | ||
return result; | ||
} | ||
generateFetch(config) { | ||
const { request, operation, hasInputPayload } = config; | ||
const result = code `fetch(): PromiseLike<${WITHERRORS_TYPE}<${this.typeDefinitionFor(config.outputType)}>> { | ||
${this.generateUrl(config)}${this.generateQueryParams(config)}${this.generateHeaders(config)}`; | ||
const hasHeaders = getParameterMembers(request === null || request === void 0 ? void 0 : request.headers).length > 0 || hasInputPayload; | ||
result.push(code `const params: Parameters<${TYPEOF_TYPE}<${FETCH_SERVICE}>>[1] = { | ||
method: '${operation.method.toUpperCase()}', | ||
cache: 'no-cache',`); | ||
if (hasHeaders) { | ||
result.push(`headers`); | ||
} | ||
if (hasInputPayload) { | ||
result.push(`, body: JSON.stringify(this.config.${INPUT_PAYLOAD_MEMBER_NAME})`); | ||
} | ||
result.push(`};`); | ||
result.push(code `return ${CONVERT_FETCH_RESPONSE_TO_DATA}(this.services.fetch(url, params));}`); | ||
return result; | ||
} | ||
build(params) { | ||
const { endpoint, operation } = params; | ||
const { api, endpoint, operation } = params; | ||
const { operationId } = operation; | ||
@@ -918,6 +839,8 @@ if (!operationId) { | ||
// command | ||
const { service, serviceInfo } = this.serviceInfo; | ||
const className = toPascalCase(commandName); | ||
const outputType = getPayloadForMediaType(response.payloads); | ||
const schemaConfigConst = toScreamingSnakeCase(`${commandConfigType.exportedSymbol}Schema`); | ||
file.push(code `export const ${schemaConfigConst}: ${JSON_SCHEMA} = ${jsonSchemaFor(configType)};`, code `export class ${className} extends ${NETWORK_COMMAND}<${commandConfigType},${this.typeDefinitionFor(outputType)},${FETCH_SERVICE}>{`, this.generateFetch({ | ||
file.push(code `export const ${schemaConfigConst}: ${JSON_SCHEMA} = ${jsonSchemaFor(configType)};`, code `export class ${className} extends ${NETWORK_COMMAND}<${commandConfigType},${this.typeDefinitionFor(outputType)},${service}>{`, this.generateFetch({ | ||
api, | ||
endpoint, | ||
@@ -931,2 +854,4 @@ operation, | ||
return { | ||
method: operation.method, | ||
commandServicesInfo: [serviceInfo], | ||
commandConfigType, | ||
@@ -943,14 +868,362 @@ commandClass: { | ||
}, | ||
outputTypeDef: outputType, | ||
}; | ||
} | ||
} | ||
const WITHERRORS_TYPE$1 = { | ||
module: '@luvio/utils', | ||
exportedSymbol: 'WithErrors', | ||
isType: true, | ||
}; | ||
const TYPEOF_TYPE$1 = { | ||
module: '@luvio/utils', | ||
exportedSymbol: 'TypeOf', | ||
isType: true, | ||
}; | ||
const CONVERT_AURA_RESPONSE_TO_DATA = { | ||
module: '@luvio/runtime', | ||
exportedSymbol: 'convertAuraResponseToData', | ||
isType: false, | ||
}; | ||
const AURA_NETWORK_SERVICE_INFO = { | ||
module: '@luvio/service-network', | ||
exportedSymbol: 'AuraNetworkServiceInfo', | ||
isType: false, | ||
}; | ||
const AURA_NETWORK_SERVICE = { | ||
module: '@luvio/service-network', | ||
exportedSymbol: 'AuraNetworkService', | ||
isType: true, | ||
}; | ||
const RECORD_INPUT_MEMBER_NAME = 'recordInput'; | ||
const EXTENSIONS_CONNECT = 'connect'; | ||
const EXTENSION_CONNECT_FAMILY = 'family'; | ||
const EXTENSIONS_LDS = 'lds'; | ||
const EXTENSION_LDS_AURA_CONTROLLER = 'aura-controller'; | ||
const EXTENSION_LDS_AURA_METHOD = 'aura-method'; | ||
const EXTENSION_LDS_AURA_RECORD_INPUT = 'aura-record-input'; | ||
class AuraOperationCommand extends OperationCommand { | ||
get serviceInfo() { | ||
return { | ||
service: AURA_NETWORK_SERVICE, | ||
serviceInfo: AURA_NETWORK_SERVICE_INFO, | ||
}; | ||
} | ||
processExtensions(config) { | ||
var _a, _b, _c, _d; | ||
const { api, endpoint, operation } = config; | ||
const allExtensions = [api.extensions, endpoint.extensions, operation.extensions]; | ||
// retrieve Connect API extensions... | ||
const connectExtensions = extensionFromName(EXTENSIONS_CONNECT, ...allExtensions); | ||
// ... and get family name | ||
const connectFamilyName = (_a = connectExtensions[EXTENSION_CONNECT_FAMILY]) === null || _a === void 0 ? void 0 : _a.value; | ||
// build the default controller name from the family name, if provided | ||
const connectControllerName = connectFamilyName !== undefined ? `${connectFamilyName}Controller` : undefined; | ||
// retrieve LDS extensions... | ||
const ldsExtensions = extensionFromName(EXTENSIONS_LDS, ...allExtensions); | ||
// ... and retrieve Aura controller name, using the connect one as default value | ||
const auraController = ((_b = ldsExtensions[EXTENSION_LDS_AURA_CONTROLLER]) === null || _b === void 0 ? void 0 : _b.value) || connectControllerName; | ||
if (auraController === undefined) { | ||
// controller name is mandatory | ||
throw new Error(`Missing Connect API family name or Aura controller name in extensions for ${operation.method} ${endpoint.path} operation`); | ||
} | ||
// retrieve Aura method name, using operationId as its default value (operationId is mandatory) | ||
const auraMethod = ((_c = ldsExtensions[EXTENSION_LDS_AURA_METHOD]) === null || _c === void 0 ? void 0 : _c.value) || operation.operationId; | ||
const auraInputPayload = ((_d = ldsExtensions[EXTENSION_LDS_AURA_RECORD_INPUT]) === null || _d === void 0 ? void 0 : _d.value) || RECORD_INPUT_MEMBER_NAME; | ||
return { auraController, auraMethod, auraInputPayload }; | ||
} | ||
generateFetch(config) { | ||
const { endpoint, request, server, hasInputPayload } = config; | ||
const result = code `fetch(): PromiseLike<${WITHERRORS_TYPE$1}<${this.typeDefinitionFor(config.outputType)}>> {`; | ||
// make sure all parameters part of server+url specification are available, even if we don't use the | ||
// processed url directly, these will be needed on Aura controller side | ||
this.processUrl(config); | ||
// read information from extensions | ||
const { auraController, auraMethod, auraInputPayload } = this.processExtensions(config); | ||
// generate endpoint | ||
result.push(code `const endpoint = '${auraController}.${auraMethod}';`); | ||
// handle uri params, query params and input payload | ||
const queryParameters = getParameterMembers(server.uriParameters, endpoint.uriParameters, request === null || request === void 0 ? void 0 : request.uriParameters, request === null || request === void 0 ? void 0 : request.queryParameters); | ||
result.push(code `const params: Parameters<${TYPEOF_TYPE$1}<${this.serviceInfo.service}>>[1] = {`); | ||
if (queryParameters.length > 0) { | ||
queryParameters.forEach((param) => { | ||
result.push(code `'${param.name}'${param.required ? '' : '?'}: this.config.${toCamelCase(param.name)}, `); | ||
}); | ||
} | ||
if (hasInputPayload) { | ||
result.push(code `${auraInputPayload}: this.config.${INPUT_PAYLOAD_MEMBER_NAME}, `); | ||
} | ||
result.push(`};`); | ||
// generate config | ||
result.push(code `const actionConfig: Parameters<${TYPEOF_TYPE$1}<${this.serviceInfo.service}>>[2] = { | ||
background: false, | ||
hotspot: true, | ||
longRunning: false, | ||
storable: false,`, ``, ``, ` };`); | ||
result.push(code `return ${CONVERT_AURA_RESPONSE_TO_DATA}(this.services.auraNetwork(endpoint, params, actionConfig));}`); | ||
return result; | ||
} | ||
} | ||
/** | ||
* Creates an OperationCommandService. | ||
* Creates an AuraOperationCommandService. | ||
*/ | ||
function operationCommandService(services) { | ||
function auraOperationCommandService(services) { | ||
return { | ||
operationCommand: new OperationCommand(services), | ||
fetchOperationCommand: new AuraOperationCommand(services), | ||
}; | ||
} | ||
export { Code, FILE_PER_TYPE, File, SINGLE_FILE, amfAPIService, asAPIService, code, fileService, isImportableReference, jsonSchemaFor, operationCommandService, typeDeclarationService, typeDefinitionFor, writeFiles }; | ||
const HEADER_CONTENT_TYPE = 'Content-Type'; | ||
const WITHERRORS_TYPE = { | ||
module: '@luvio/utils', | ||
exportedSymbol: 'WithErrors', | ||
isType: true, | ||
}; | ||
const TYPEOF_TYPE = { | ||
module: '@luvio/utils', | ||
exportedSymbol: 'TypeOf', | ||
isType: true, | ||
}; | ||
const CONVERT_FETCH_RESPONSE_TO_DATA = { | ||
module: '@luvio/runtime', | ||
exportedSymbol: 'convertFetchResponseToData', | ||
isType: false, | ||
}; | ||
const FETCH_SERVICE_INFO = { | ||
module: '@luvio/service-network', | ||
exportedSymbol: 'FetchServiceInfo', | ||
isType: false, | ||
}; | ||
const FETCH_SERVICE = { | ||
module: '@luvio/service-network', | ||
exportedSymbol: 'FetchService', | ||
isType: true, | ||
}; | ||
class FetchOperationCommand extends OperationCommand { | ||
get serviceInfo() { | ||
return { | ||
service: FETCH_SERVICE, | ||
serviceInfo: FETCH_SERVICE_INFO, | ||
}; | ||
} | ||
generateUrl(config) { | ||
const url = this.processUrl(config); | ||
return code `let url: Parameters<${TYPEOF_TYPE}<${this.serviceInfo.service}>>[0] = \`${url}\`;`; | ||
} | ||
generateHeaders(config) { | ||
const { request, hasInputPayload } = config; | ||
const requestHeaders = getParameterMembers(request === null || request === void 0 ? void 0 : request.headers); | ||
const hasHeaders = requestHeaders.length > 0 || hasInputPayload; | ||
let result = undefined; | ||
if (hasHeaders) { | ||
// TODO - resolve cookies? | ||
result = code `const headers: Record<string, any> = {`; | ||
if (hasInputPayload) { | ||
result.push(`'${HEADER_CONTENT_TYPE}': '${MEDIATYPE_APP_JSON}',`); | ||
} | ||
const headers = requestHeaders.filter((hdr) => hdr.name.toLowerCase() !== HEADER_CONTENT_TYPE.toLowerCase()); | ||
headers | ||
.filter((hdr) => hdr.required) | ||
.forEach((hdr) => result.push(`'${hdr.name}': this.config.${toCamelCase(hdr.name)},`)); | ||
result.push(`};`); | ||
headers | ||
.filter((hdr) => !hdr.required) | ||
.forEach((hdr) => { | ||
const headerName = toCamelCase(hdr.name); | ||
result.push(`if (this.config.${headerName} !== undefined) { headers['${hdr.name}'] = this.config.${headerName};}`); | ||
}); | ||
} | ||
return result; | ||
} | ||
generateQueryParams(config) { | ||
const { endpoint, operation, request } = config; | ||
// resolve query params | ||
let result = undefined; | ||
const queryParameters = getParameterMembers(request === null || request === void 0 ? void 0 : request.queryParameters); | ||
if (queryParameters.length > 0) { | ||
result = code `let queryParams: string[] = [];`; | ||
queryParameters.forEach((param) => { | ||
const paramName = toCamelCase(param.name); | ||
const value = this.encodeParam(paramName, param.type); | ||
if (!value) { | ||
throw new Error(`unsupported type for ${param.name} in ${operation.method} ${endpoint.path} operation query parameters`); | ||
} | ||
result.push(param.required ? '' : `if (this.config.${paramName} !== undefined) {`, `queryParams.push('${param.name}=' + ${value});`, param.required ? '' : `}`); | ||
}); | ||
result.push(`if (queryParams.length > 0) { url += '?' + queryParams.join('&'); }`); | ||
} | ||
return result; | ||
} | ||
generateFetch(config) { | ||
const { request, operation, hasInputPayload } = config; | ||
const result = code `fetch(): PromiseLike<${WITHERRORS_TYPE}<${this.typeDefinitionFor(config.outputType)}>> { | ||
${this.generateUrl(config)}${this.generateQueryParams(config)}${this.generateHeaders(config)}`; | ||
const hasHeaders = getParameterMembers(request === null || request === void 0 ? void 0 : request.headers).length > 0 || hasInputPayload; | ||
result.push(code `const params: Parameters<${TYPEOF_TYPE}<${this.serviceInfo.service}>>[1] = { | ||
method: '${operation.method.toUpperCase()}', | ||
cache: 'no-cache',`); | ||
if (hasHeaders) { | ||
result.push(`headers`); | ||
} | ||
if (hasInputPayload) { | ||
result.push(`, body: JSON.stringify(this.config.${INPUT_PAYLOAD_MEMBER_NAME})`); | ||
} | ||
result.push(`};`); | ||
result.push(code `return ${CONVERT_FETCH_RESPONSE_TO_DATA}(this.services.fetch(url, params));}`); | ||
return result; | ||
} | ||
} | ||
/** | ||
* Creates a FetchOperationCommandService. | ||
*/ | ||
function fetchOperationCommandService(services) { | ||
return { | ||
fetchOperationCommand: new FetchOperationCommand(services), | ||
}; | ||
} | ||
const REGISTER = { | ||
module: '@luvio/registry', | ||
exportedSymbol: 'register', | ||
isType: false, | ||
}; | ||
const COMMAND_MODULE_REGISTRATION = { | ||
module: '@luvio/runtime', | ||
exportedSymbol: 'CommandModuleRegistration', | ||
isType: true, | ||
}; | ||
const WIRE_ADAPTER_CONSTRUCTOR = { | ||
module: 'lwc', | ||
exportedSymbol: 'WireAdapterConstructor', | ||
isType: true, | ||
}; | ||
const COMMAND_WIRE_ADAPTER_CONSTRUCTOR = { | ||
module: '@luvio/lwc-bindings', | ||
exportedSymbol: 'CommandWireAdapterConstructor', | ||
isType: false, | ||
}; | ||
const BUILD_ASYNC_IMPERATIVE_INVOKER = { | ||
module: '@luvio/lwc-bindings', | ||
exportedSymbol: 'buildAsyncImperativeInvoker', | ||
isType: false, | ||
}; | ||
const JSON_SCHEMA_TYPE = { | ||
module: '@luvio/jsonschema-validate', | ||
exportedSymbol: 'JSONSchema', | ||
isType: true, | ||
}; | ||
/** | ||
* An implementation of OperationLwcBindingsService that generates TypeScript adapters type declarations | ||
* in Files from a FileService. | ||
*/ | ||
class OperationLwcBindings { | ||
constructor(services) { | ||
this.services = services; | ||
} | ||
typeDefinitionFor(type) { | ||
return typeDefinitionFor(this.services, type); | ||
} | ||
generateWireAdapterCode(params) { | ||
const { adapterName, commandClass, commandConfigType, commandSchemaConfigConst, outputTypeDef, } = params; | ||
const declaration = code `export let ${adapterName}: ${WIRE_ADAPTER_CONSTRUCTOR}`; | ||
const instantiation = code `${adapterName}: (${adapterName} = class extends ${COMMAND_WIRE_ADAPTER_CONSTRUCTOR}< | ||
${this.typeDefinitionFor(outputTypeDef)} | ||
> { | ||
configSchema = ${commandSchemaConfigConst}; | ||
getCommand() { return new ${commandClass}(this.config as ${commandConfigType}, {}, services); } | ||
})`; | ||
return { declaration, instantiation }; | ||
} | ||
generateImperativeInvokerCode(params) { | ||
const { adapterName, commandClass, commandConfigType, commandSchemaConfigConst, outputTypeDef, } = params; | ||
const declaration = code `export let ${adapterName}: (config: ${commandConfigType}) => PromiseLike<${this.typeDefinitionFor(outputTypeDef)}>`; | ||
const instantiation = code `${adapterName}: (${adapterName} = ${BUILD_ASYNC_IMPERATIVE_INVOKER}< | ||
Parameters<typeof ${adapterName}>, | ||
${this.typeDefinitionFor(outputTypeDef)} | ||
>(({ params, assertIsValid }) => { | ||
const config = params[0]; | ||
const _: <T>(data: unknown, _: ${JSON_SCHEMA_TYPE}) => asserts data is T = assertIsValid; | ||
_<${commandConfigType}>(config, ${commandSchemaConfigConst}); | ||
return new ${commandClass}(config, {}, services); | ||
}))`; | ||
return { declaration, instantiation }; | ||
} | ||
build(params) { | ||
const { commands } = params; | ||
const filename = 'artifacts/lwc-bindings.ts'; | ||
const file = this.services.file.build(filename); | ||
// pre-generate adapter code for declaration and instantiation | ||
let bindings = []; | ||
for (let commandInfo of commands) { | ||
const { method, commandClass } = commandInfo; | ||
const adapterName = commandClass.exportedSymbol | ||
.replace(/^(.)/, (_, m) => m.toLowerCase()) | ||
.replace(/Command$/, ''); | ||
const adapterCode = method === 'GET' | ||
? this.generateWireAdapterCode({ adapterName, ...commandInfo }) | ||
: this.generateImperativeInvokerCode({ adapterName, ...commandInfo }); | ||
bindings.push({ adapterName, adapterCode, commandInfo }); | ||
} | ||
let allServicesInfo = []; | ||
let servicesInfo = []; | ||
let commandServices = []; | ||
for (let binding of bindings) { | ||
const { adapterCode, commandInfo } = binding; | ||
const { commandClass, commandServicesInfo } = commandInfo; | ||
// generate adapter declaration | ||
file.push(code `${adapterCode.declaration};`); | ||
// add services info declaration | ||
commandServicesInfo.forEach((info) => { | ||
// note: this might result in dupes being generated if service definitions | ||
// are not singletons | ||
if (!allServicesInfo.includes(info)) { | ||
allServicesInfo.push(info); | ||
servicesInfo.push(code `services[${info}.NAME] = ${info}.VERSION;`); | ||
} | ||
}); | ||
// add service type to command services type definition | ||
commandServices.push(code `ConstructorParameters<typeof ${commandClass}>[2]`); | ||
} | ||
// generate services info | ||
file.push(code `let services: Record<string, string> = {};`); | ||
file.push(servicesInfo); | ||
// generate command services type | ||
file.push(code `type CommandServices = `); | ||
commandServices.forEach((cs, i) => { | ||
file.push(i > 0 ? '&' : '').push(cs); | ||
}); | ||
// generate registration | ||
let importableReferences = []; | ||
file.push(code ` | ||
${REGISTER}({ | ||
id: 'commandModule', | ||
services, | ||
setServices: (services: CommandServices) => { | ||
return {`); | ||
for (let binding of bindings) { | ||
const { adapterName, adapterCode } = binding; | ||
file.push(code `${adapterCode.instantiation},`); | ||
importableReferences.push({ | ||
module: filename, | ||
exportedSymbol: adapterName, | ||
isType: false, | ||
}); | ||
} | ||
file.push(code ` | ||
}; | ||
}, | ||
} as ${COMMAND_MODULE_REGISTRATION}<CommandServices>);`); | ||
return importableReferences; | ||
} | ||
} | ||
/** | ||
* Creates an OperationLwcBindingsService. | ||
*/ | ||
function operationLwcBindingsService(services) { | ||
return { | ||
operationLwcBindings: new OperationLwcBindings(services), | ||
}; | ||
} | ||
export { Code, FILE_PER_TYPE, File, SINGLE_FILE, amfAPIService, asAPIService, auraOperationCommandService, code, fetchOperationCommandService, fileService, isImportableReference, jsonSchemaFor, operationLwcBindingsService, typeDeclarationService, typeDefinitionFor$1 as typeDefinitionFor, writeFiles }; |
@@ -1,2 +0,3 @@ | ||
export { operationCommandService } from './operation-command'; | ||
export type { OperationCommandImportableReferences, OperationCommandService, } from './operation-command'; | ||
export { auraOperationCommandService } from './aura-operation-command'; | ||
export { fetchOperationCommandService } from './fetch-operation-command'; | ||
export type { FetchOperationCommandService, OperationCommandInfo } from './operation-command'; |
@@ -1,21 +0,16 @@ | ||
import type { Service, TypeOf } from '@luvio/utils'; | ||
import type { EndPoint, ObjectType, Operation, Parameter, Payload, Request, Server, ScalarType, Type } from '@luvio/model'; | ||
import { type Service } from '@luvio/utils'; | ||
import type { EndPoint, ObjectType, Operation, Parameter, Payload, Request, Server, ScalarType, Type, HttpMethod, API } from '@luvio/model'; | ||
import type { APIService } from '../api'; | ||
import type { FileService, ImportableReference, Code } from '../files'; | ||
import type { TypeDeclarationService } from '../types'; | ||
export declare const enum OperationCommandServiceInfo { | ||
NAME = "operationCommand", | ||
VERSION = "1.0" | ||
} | ||
export type OperationCommandImportableReferences = { | ||
export declare const MEDIATYPE_APP_JSON = "application/json"; | ||
export declare const INPUT_PAYLOAD_MEMBER_NAME = "inputPayload"; | ||
export type OperationCommandInfo = { | ||
method: HttpMethod; | ||
commandServicesInfo: ReadonlyArray<ImportableReference>; | ||
commandConfigType: ImportableReference; | ||
commandClass: ImportableReference; | ||
commandSchemaConfigConst: ImportableReference; | ||
outputTypeDef: Type | undefined; | ||
}; | ||
export type OperationCommandService = Service<OperationCommandServiceInfo.NAME, { | ||
build(params: { | ||
endpoint: EndPoint; | ||
operation: Operation; | ||
}): OperationCommandImportableReferences; | ||
}>; | ||
/** | ||
@@ -52,2 +47,13 @@ * Converts a set of parameter specification from Record<string, Parameter> to a list of named parameters info. | ||
export declare function getPayloadForMediaType(payloads: Array<Payload>, mediaType?: string): Type | undefined; | ||
export declare const enum FetchOperationCommandServiceInfo { | ||
NAME = "fetchOperationCommand", | ||
VERSION = "1.0" | ||
} | ||
export type FetchOperationCommandService = Service<FetchOperationCommandServiceInfo.NAME, { | ||
build(params: { | ||
api: API; | ||
endpoint: EndPoint; | ||
operation: Operation; | ||
}): OperationCommandInfo; | ||
}>; | ||
/** | ||
@@ -57,10 +63,10 @@ * An implementation of OperationCommandService that consumes EndPoint and Operation from an APIService | ||
*/ | ||
export declare class OperationCommand implements TypeOf<OperationCommandService> { | ||
export declare abstract class OperationCommand { | ||
private services; | ||
constructor(services: APIService & FileService & TypeDeclarationService); | ||
private typeDefinitionFor; | ||
typeDefinitionFor(type: Type | undefined): Code; | ||
getServer(endpoint: EndPoint, operation: Operation): Server; | ||
createConfigType(endpoint: EndPoint, operation: Operation, request: Request, server: Server): ObjectType; | ||
encodeParam(name: string, type: ScalarType): string | undefined; | ||
generateUrl(config: { | ||
processUrl(config: { | ||
endpoint: EndPoint; | ||
@@ -70,16 +76,12 @@ operation: Operation; | ||
server: Server; | ||
}): Code; | ||
generateQueryParams(config: { | ||
}): string; | ||
abstract get serviceInfo(): { | ||
service: ImportableReference; | ||
serviceInfo: ImportableReference; | ||
}; | ||
abstract generateFetch(config: { | ||
api: API; | ||
endpoint: EndPoint; | ||
operation: Operation; | ||
request: Request; | ||
}): Code | undefined; | ||
generateHeaders(config: { | ||
request: Request; | ||
hasInputPayload: boolean; | ||
}): Code | undefined; | ||
generateFetch(config: { | ||
endpoint: EndPoint; | ||
operation: Operation; | ||
request: Request; | ||
server: Server; | ||
@@ -90,9 +92,6 @@ hasInputPayload: boolean; | ||
build(params: { | ||
api: API; | ||
endpoint: EndPoint; | ||
operation: Operation; | ||
}): OperationCommandImportableReferences; | ||
}): OperationCommandInfo; | ||
} | ||
/** | ||
* Creates an OperationCommandService. | ||
*/ | ||
export declare function operationCommandService(services: APIService & FileService & TypeDeclarationService): OperationCommandService; |
@@ -5,1 +5,2 @@ export * from './api'; | ||
export * from './commands'; | ||
export * from './lwc-bindings'; |
@@ -7,2 +7,3 @@ import type { API, ReadOnlyTypeRegistry, TypeRegistry } from '@luvio/model'; | ||
get types(): ReadOnlyTypeRegistry; | ||
get extensions(): {}; | ||
} |
@@ -7,2 +7,3 @@ import type { API, ReadOnlyTypeRegistry, TypeRegistry } from '@luvio/model'; | ||
get types(): ReadOnlyTypeRegistry; | ||
get extensions(): {}; | ||
} |
@@ -7,2 +7,3 @@ import type { API, ReadOnlyTypeRegistry, TypeRegistry } from '@luvio/model'; | ||
get types(): ReadOnlyTypeRegistry; | ||
get extensions(): {}; | ||
} |
@@ -7,4 +7,5 @@ import type { API, ReadOnlyTypeRegistry, TypeRegistry } from '@luvio/model'; | ||
get types(): ReadOnlyTypeRegistry; | ||
get extensions(): {}; | ||
buildStringDiscriminatedType(): void; | ||
buildNumberDiscriminatedType(): void; | ||
} |
@@ -7,2 +7,3 @@ import type { API, ReadOnlyTypeRegistry, TypeRegistry } from '@luvio/model'; | ||
get types(): ReadOnlyTypeRegistry; | ||
get extensions(): {}; | ||
} |
@@ -7,2 +7,3 @@ import type { API, ReadOnlyTypeRegistry, TypeRegistry } from '@luvio/model'; | ||
get types(): ReadOnlyTypeRegistry; | ||
get extensions(): {}; | ||
} |
@@ -7,2 +7,3 @@ import type { API, ReadOnlyTypeRegistry, TypeRegistry } from '@luvio/model'; | ||
get types(): ReadOnlyTypeRegistry; | ||
get extensions(): {}; | ||
} |
@@ -7,2 +7,3 @@ import type { API, ReadOnlyTypeRegistry, TypeRegistry } from '@luvio/model'; | ||
get types(): ReadOnlyTypeRegistry; | ||
get extensions(): {}; | ||
} |
@@ -7,2 +7,3 @@ import type { API, ReadOnlyTypeRegistry, TypeRegistry } from '@luvio/model'; | ||
get types(): ReadOnlyTypeRegistry; | ||
get extensions(): {}; | ||
} |
{ | ||
"name": "@luvio/generator-ts", | ||
"version": "3.5.2", | ||
"version": "3.6.0", | ||
"description": "Luvio TypeScript code generation", | ||
@@ -24,4 +24,4 @@ "repository": { | ||
"dependencies": { | ||
"@luvio/model": "^3.5.2", | ||
"@luvio/utils": "^3.5.2", | ||
"@luvio/model": "^3.6.0", | ||
"@luvio/utils": "^3.6.0", | ||
"prettier": "^2.7.1" | ||
@@ -28,0 +28,0 @@ }, |
67440
30
1713
Updated@luvio/model@^3.6.0
Updated@luvio/utils@^3.6.0