gen and build working I think
This commit is contained in:
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@kittycad/lib",
|
||||
"version": "0.0.6",
|
||||
"version": "0.0.7",
|
||||
"description": "ts lib",
|
||||
"exports": {
|
||||
".": {
|
||||
@ -50,7 +50,8 @@
|
||||
"tsc": "tsc",
|
||||
"build2": "rimraf dist && npm run build:types && npm run build:js",
|
||||
"build:js": "rollup -c",
|
||||
"build:types": "tsc --emitDeclarationOnly"
|
||||
"build:types": "tsc --emitDeclarationOnly",
|
||||
"modelsGen": "ts-node --project ./tsconfig.gen.json ./src/modelsGen.ts && prettier --config .prettierrc --write ./src"
|
||||
},
|
||||
"author": "Kurt Hutten <kurt@kittycad.io>",
|
||||
"license": "MIT",
|
||||
|
||||
265
src/apiGen.ts
265
src/apiGen.ts
@ -42,145 +42,160 @@ export default async function apiGen(lookup: any) {
|
||||
exportsStr: string[];
|
||||
};
|
||||
} = {};
|
||||
const writePromises = Object.entries(operations).map(async ([operationId, operation]) => {
|
||||
if ('hidden' === (operation.specSection as any).tags[0]) {
|
||||
return;
|
||||
}
|
||||
let template: string = await fsp.readFile('./src/template.ts.txt', 'utf8');
|
||||
const path = operation.path;
|
||||
const params = operation.specSection
|
||||
.parameters as OpenAPIV3.ParameterObject[];
|
||||
template = template.replaceAll(',', ',');
|
||||
const inputTypes: string[] = [];
|
||||
const inputParams: string[] = [];
|
||||
let urlPathParams: string[] = path.split('/');
|
||||
const urlQueryParams: string[] = [];
|
||||
(params || []).forEach(({ name, in: _in }) => {
|
||||
inputTypes.push(`${name}: string`);
|
||||
if (!name) {
|
||||
throw 'no name for param';
|
||||
const writePromises = Object.entries(operations).map(
|
||||
async ([operationId, operation]) => {
|
||||
if ('hidden' === (operation.specSection as any).tags[0]) {
|
||||
return;
|
||||
}
|
||||
inputParams.push(name);
|
||||
if (_in === 'path') {
|
||||
urlPathParams = urlPathParams.map((p) => {
|
||||
if (p === `{${name}}`) {
|
||||
return `\${${name}}`;
|
||||
}
|
||||
return p;
|
||||
});
|
||||
let template: string = await fsp.readFile(
|
||||
'./src/template.ts.txt',
|
||||
'utf8',
|
||||
);
|
||||
const path = operation.path;
|
||||
const params = operation.specSection
|
||||
.parameters as OpenAPIV3.ParameterObject[];
|
||||
template = template.replaceAll(',', ',');
|
||||
const inputTypes: string[] = [];
|
||||
const inputParams: string[] = [];
|
||||
let urlPathParams: string[] = path.split('/');
|
||||
const urlQueryParams: string[] = [];
|
||||
(params || []).forEach(({ name, in: _in }) => {
|
||||
inputTypes.push(`${name}: string`);
|
||||
if (!name) {
|
||||
throw 'no name for param';
|
||||
}
|
||||
inputParams.push(name);
|
||||
if (_in === 'path') {
|
||||
urlPathParams = urlPathParams.map((p) => {
|
||||
if (p === `{${name}}`) {
|
||||
return `\${${name}}`;
|
||||
}
|
||||
return p;
|
||||
});
|
||||
} else {
|
||||
urlQueryParams.push(`${name}=\${${name}}`);
|
||||
}
|
||||
});
|
||||
const templateUrlPath = wrapInBacktics(
|
||||
`${urlPathParams.join('/')}${
|
||||
urlQueryParams.length ? `?${urlQueryParams.join('&')}` : ''
|
||||
}`,
|
||||
);
|
||||
const requestBody = operation.specSection
|
||||
?.requestBody as OpenAPIV3.ResponseObject;
|
||||
|
||||
if (requestBody?.content?.['application/octet-stream']) {
|
||||
const schema = requestBody.content['application/octet-stream']
|
||||
.schema as OpenAPIV3.SchemaObject;
|
||||
if (schema?.type !== 'string') {
|
||||
throw 'requestBody type not implemented';
|
||||
}
|
||||
inputTypes.push('body: string');
|
||||
inputParams.push('body');
|
||||
template = template.replaceAll("body: 'BODY'", 'body');
|
||||
} else {
|
||||
urlQueryParams.push(`${name}=\${${name}}`);
|
||||
template = template.replaceAll(/body: 'BODY'.+/g, '');
|
||||
}
|
||||
});
|
||||
const templateUrlPath = wrapInBacktics(
|
||||
`${urlPathParams.join('/')}${
|
||||
urlQueryParams.length ? `?${urlQueryParams.join('&')}` : ''
|
||||
}`,
|
||||
);
|
||||
const requestBody = operation.specSection
|
||||
?.requestBody as OpenAPIV3.ResponseObject;
|
||||
|
||||
if (requestBody?.content?.['application/octet-stream']) {
|
||||
const schema = requestBody.content['application/octet-stream']
|
||||
.schema as OpenAPIV3.SchemaObject;
|
||||
if (schema?.type !== 'string') {
|
||||
throw 'requestBody type not implemented';
|
||||
if (!inputParams.length) {
|
||||
template = replacer(template, [
|
||||
[/interface FunctionNameParams(.|\n)+?}/g, ''],
|
||||
[/functionNameParams: FunctionNameParams.+/g, ''],
|
||||
]);
|
||||
}
|
||||
inputTypes.push('body: string');
|
||||
inputParams.push('body');
|
||||
template = template.replaceAll("body: 'BODY'", 'body');
|
||||
} else {
|
||||
template = template.replaceAll(/body: 'BODY'.+/g, '');
|
||||
}
|
||||
|
||||
if (!inputParams.length) {
|
||||
template = replacer(template, [
|
||||
[/interface FunctionNameParams(.|\n)+?}/g, ''],
|
||||
[/functionNameParams: FunctionNameParams.+/g, ''],
|
||||
]);
|
||||
}
|
||||
const importedTypes: string[] = [];
|
||||
Object.values(operation.specSection?.responses).forEach((response) => {
|
||||
const schema = (response as any)?.content?.['application/json']
|
||||
?.schema as OpenAPIV3.SchemaObject;
|
||||
if (!schema) {
|
||||
let ref = (response as any)?.$ref || '';
|
||||
ref = ref.replace('responses', 'schemas');
|
||||
const typeReference = lookup[ref];
|
||||
|
||||
const importedTypes: string[] = [];
|
||||
Object.values(operation.specSection?.responses).forEach((response) => {
|
||||
const schema = (response as any)?.content?.['application/json']
|
||||
?.schema as OpenAPIV3.SchemaObject;
|
||||
if (!schema) {
|
||||
let ref = (response as any)?.$ref || '';
|
||||
ref = ref.replace('responses', 'schemas');
|
||||
const typeReference = lookup[ref];
|
||||
|
||||
if (!importedTypes.includes(typeReference) && ref) {
|
||||
importedTypes.push(typeReference);
|
||||
}
|
||||
} else if ((response as any)?.content['application/json']?.schema?.$ref) {
|
||||
const ref = (response as any)?.content['application/json']?.schema
|
||||
?.$ref;
|
||||
const typeReference = lookup[ref];
|
||||
if (!importedTypes.includes(typeReference)) {
|
||||
importedTypes.push(typeReference);
|
||||
}
|
||||
} else if (Object.keys(schema).length === 0) {
|
||||
// do nothing
|
||||
} else if (schema.type === 'array') {
|
||||
const items = schema.items as OpenAPIV3.SchemaObject;
|
||||
if ((items as any).$ref) {
|
||||
const typeReference = lookup[(items as any).$ref];
|
||||
if (!importedTypes.includes(typeReference + '[]')) {
|
||||
importedTypes.push(typeReference + '[]');
|
||||
if (!importedTypes.includes(typeReference) && ref) {
|
||||
importedTypes.push(typeReference);
|
||||
}
|
||||
} else if (
|
||||
(response as any)?.content['application/json']?.schema?.$ref
|
||||
) {
|
||||
const ref = (response as any)?.content['application/json']?.schema
|
||||
?.$ref;
|
||||
const typeReference = lookup[ref];
|
||||
if (!importedTypes.includes(typeReference)) {
|
||||
importedTypes.push(typeReference);
|
||||
}
|
||||
} else if (Object.keys(schema).length === 0) {
|
||||
// do nothing
|
||||
} else if (schema.type === 'array') {
|
||||
const items = schema.items as OpenAPIV3.SchemaObject;
|
||||
if ((items as any).$ref) {
|
||||
const typeReference = lookup[(items as any).$ref];
|
||||
if (!importedTypes.includes(typeReference + '[]')) {
|
||||
importedTypes.push(typeReference + '[]');
|
||||
}
|
||||
} else {
|
||||
throw 'not implemented';
|
||||
}
|
||||
} else {
|
||||
console.log(schema);
|
||||
throw 'not implemented';
|
||||
}
|
||||
} else {
|
||||
console.log(schema);
|
||||
throw 'not implemented';
|
||||
});
|
||||
|
||||
const returnTyping = `type ${FC(operationId)}_return = ${
|
||||
importedTypes.length ? importedTypes.join(' | ') : 'any'
|
||||
}`;
|
||||
|
||||
template = replacer(template, [
|
||||
[/interface FunctionNameReturn(.|\n)+?}/g, returnTyping],
|
||||
[`'string' + functionNameParams.exampleParam`, templateUrlPath],
|
||||
[
|
||||
`functionNameParams:`,
|
||||
`{${inputParams.filter((a) => a).join(', ')}}:`,
|
||||
],
|
||||
[`exampleParam: string`, inputTypes.join('; ')],
|
||||
["method: 'METHOD'", `method: 'POST'`],
|
||||
['function functionName', `function ${operationId}`],
|
||||
['FunctionNameReturn', `${FC(operationId)}_return`],
|
||||
['FunctionNameParams', `${FC(operationId)}_params`],
|
||||
[
|
||||
"import * as types from './src/models.ts';",
|
||||
`import {${importedTypes
|
||||
.map((a) => (a || '').replaceAll('[', '').replaceAll(']', ''))
|
||||
.join(', ')}} from '../../models.js';`,
|
||||
],
|
||||
]);
|
||||
|
||||
const tag = operation.specSection?.tags?.[0] || 'err';
|
||||
const safeTag = tag.replaceAll('-', '_');
|
||||
if (!indexFile[safeTag]) {
|
||||
indexFile[safeTag] = {
|
||||
importsStr: [],
|
||||
exportsStr: [],
|
||||
};
|
||||
}
|
||||
});
|
||||
|
||||
const returnTyping = `type ${FC(operationId)}_return = ${
|
||||
importedTypes.length ? importedTypes.join(' | ') : 'any'
|
||||
}`;
|
||||
|
||||
template = replacer(template, [
|
||||
[/interface FunctionNameReturn(.|\n)+?}/g, returnTyping],
|
||||
[`'string' + functionNameParams.exampleParam`, templateUrlPath],
|
||||
[`functionNameParams:`, `{${inputParams.filter((a) => a).join(', ')}}:`],
|
||||
[`exampleParam: string`, inputTypes.join('; ')],
|
||||
["method: 'METHOD'", `method: 'POST'`],
|
||||
['function functionName', `function ${operationId}`],
|
||||
['FunctionNameReturn', `${FC(operationId)}_return`],
|
||||
['FunctionNameParams', `${FC(operationId)}_params`],
|
||||
[
|
||||
"import * as types from './src/models.ts';",
|
||||
`import {${importedTypes
|
||||
.map((a) => (a || '').replaceAll('[', '').replaceAll(']', ''))
|
||||
.join(', ')}} from '../../models.js';`,
|
||||
],
|
||||
]);
|
||||
|
||||
const tag = operation.specSection?.tags?.[0] || 'err';
|
||||
const safeTag = tag.replaceAll('-', '_');
|
||||
if (!indexFile[safeTag]) {
|
||||
indexFile[safeTag] = {
|
||||
importsStr: [],
|
||||
exportsStr: [],
|
||||
};
|
||||
}
|
||||
indexFile[safeTag].importsStr.push(
|
||||
`import ${operationId} from './api/${tag}/${operationId}.js';`,
|
||||
indexFile[safeTag].importsStr.push(
|
||||
`import ${operationId} from './api/${tag}/${operationId}.js';`,
|
||||
);
|
||||
indexFile[safeTag].exportsStr.push(operationId)
|
||||
return fsp.writeFile(`./src/api/${tag}/${operationId}.ts`, template, 'utf8');
|
||||
});
|
||||
indexFile[safeTag].exportsStr.push(operationId);
|
||||
return fsp.writeFile(
|
||||
`./src/api/${tag}/${operationId}.ts`,
|
||||
template,
|
||||
'utf8',
|
||||
);
|
||||
},
|
||||
);
|
||||
await Promise.all(writePromises);
|
||||
console.log('HEYY yo')
|
||||
let indexFileString = ''
|
||||
Object.entries(indexFile).forEach(([tag, { importsStr: imports, exportsStr: exports }]) => {
|
||||
indexFileString += imports.join('\n') + '\n';
|
||||
indexFileString += `export const ${tag} = { ${exports.join(', ')} };\n\n`;
|
||||
})
|
||||
console.log('hmm', indexFile, indexFileString);
|
||||
await fsp.writeFile(`./src/main.ts`, indexFileString, 'utf8');
|
||||
let indexFileString = '';
|
||||
Object.entries(indexFile).forEach(
|
||||
([tag, { importsStr: imports, exportsStr: exports }]) => {
|
||||
indexFileString += imports.join('\n') + '\n';
|
||||
indexFileString += `export const ${tag} = { ${exports.join(', ')} };\n\n`;
|
||||
},
|
||||
);
|
||||
indexFileString += `export * as Models from './models.js';\n`;
|
||||
await fsp.writeFile(`./src/index.ts`, indexFileString, 'utf8');
|
||||
}
|
||||
|
||||
function wrapInBacktics(str: string) {
|
||||
|
||||
64
src/index.ts
64
src/index.ts
@ -1,8 +1,3 @@
|
||||
import get_schema from './api/meta/get_schema.js';
|
||||
import ping from './api/meta/ping.js';
|
||||
import get_metadata from './api/meta/get_metadata.js';
|
||||
export const meta = { get_schema, ping, get_metadata };
|
||||
|
||||
import get_api_call_metrics from './api/api-calls/get_api_call_metrics.js';
|
||||
import get_api_call from './api/api-calls/get_api_call.js';
|
||||
import get_async_operation from './api/api-calls/get_async_operation.js';
|
||||
@ -22,91 +17,98 @@ export const api_calls = {
|
||||
list_api_calls_for_user,
|
||||
};
|
||||
|
||||
import get_file_conversion from './api/file/get_file_conversion.js';
|
||||
import get_schema from './api/meta/get_schema.js';
|
||||
import get_metadata from './api/meta/get_metadata.js';
|
||||
import ping from './api/meta/ping.js';
|
||||
export const meta = { get_schema, get_metadata, ping };
|
||||
|
||||
import create_file_conversion from './api/file/create_file_conversion.js';
|
||||
import create_file_execution from './api/file/create_file_execution.js';
|
||||
import create_file_density from './api/file/create_file_density.js';
|
||||
import create_file_mass from './api/file/create_file_mass.js';
|
||||
import create_file_volume from './api/file/create_file_volume.js';
|
||||
import create_file_density from './api/file/create_file_density.js';
|
||||
import create_file_execution from './api/file/create_file_execution.js';
|
||||
import get_file_conversion from './api/file/get_file_conversion.js';
|
||||
import get_file_conversion_for_user from './api/file/get_file_conversion_for_user.js';
|
||||
export const file = {
|
||||
get_file_conversion,
|
||||
create_file_conversion,
|
||||
create_file_execution,
|
||||
create_file_density,
|
||||
create_file_mass,
|
||||
create_file_volume,
|
||||
create_file_density,
|
||||
create_file_execution,
|
||||
get_file_conversion,
|
||||
get_file_conversion_for_user,
|
||||
};
|
||||
|
||||
import device_auth_request from './api/oauth2/device_auth_request.js';
|
||||
import device_auth_confirm from './api/oauth2/device_auth_confirm.js';
|
||||
import device_access_token from './api/oauth2/device_access_token.js';
|
||||
import device_auth_verify from './api/oauth2/device_auth_verify.js';
|
||||
import listen_oauth2_provider_callback from './api/oauth2/listen_oauth2_provider_callback.js';
|
||||
import device_access_token from './api/oauth2/device_access_token.js';
|
||||
import listen_oauth2_provider_consent from './api/oauth2/listen_oauth2_provider_consent.js';
|
||||
import device_auth_verify from './api/oauth2/device_auth_verify.js';
|
||||
export const oauth2 = {
|
||||
device_auth_request,
|
||||
device_auth_confirm,
|
||||
device_access_token,
|
||||
device_auth_verify,
|
||||
listen_oauth2_provider_callback,
|
||||
device_access_token,
|
||||
listen_oauth2_provider_consent,
|
||||
device_auth_verify,
|
||||
};
|
||||
|
||||
import create_unit_conversion from './api/unit/create_unit_conversion.js';
|
||||
export const unit = { create_unit_conversion };
|
||||
|
||||
import delete_user_self from './api/users/delete_user_self.js';
|
||||
import update_user_self from './api/users/update_user_self.js';
|
||||
import get_user_self from './api/users/get_user_self.js';
|
||||
import update_user_self from './api/users/update_user_self.js';
|
||||
import get_user_self_extended from './api/users/get_user_self_extended.js';
|
||||
import list_users from './api/users/list_users.js';
|
||||
import list_users_extended from './api/users/list_users_extended.js';
|
||||
import list_users from './api/users/list_users.js';
|
||||
import get_user_extended from './api/users/get_user_extended.js';
|
||||
import get_user from './api/users/get_user.js';
|
||||
import delete_user_self from './api/users/delete_user_self.js';
|
||||
export const users = {
|
||||
delete_user_self,
|
||||
update_user_self,
|
||||
get_user_self,
|
||||
update_user_self,
|
||||
get_user_self_extended,
|
||||
list_users,
|
||||
list_users_extended,
|
||||
list_users,
|
||||
get_user_extended,
|
||||
get_user,
|
||||
delete_user_self,
|
||||
};
|
||||
|
||||
import create_api_token_for_user from './api/api-tokens/create_api_token_for_user.js';
|
||||
import list_api_tokens_for_user from './api/api-tokens/list_api_tokens_for_user.js';
|
||||
import delete_api_token_for_user from './api/api-tokens/delete_api_token_for_user.js';
|
||||
import create_api_token_for_user from './api/api-tokens/create_api_token_for_user.js';
|
||||
import get_api_token_for_user from './api/api-tokens/get_api_token_for_user.js';
|
||||
import delete_api_token_for_user from './api/api-tokens/delete_api_token_for_user.js';
|
||||
export const api_tokens = {
|
||||
create_api_token_for_user,
|
||||
list_api_tokens_for_user,
|
||||
delete_api_token_for_user,
|
||||
create_api_token_for_user,
|
||||
get_api_token_for_user,
|
||||
delete_api_token_for_user,
|
||||
};
|
||||
|
||||
import delete_payment_information_for_user from './api/payments/delete_payment_information_for_user.js';
|
||||
import get_payment_information_for_user from './api/payments/get_payment_information_for_user.js';
|
||||
import create_payment_information_for_user from './api/payments/create_payment_information_for_user.js';
|
||||
import update_payment_information_for_user from './api/payments/update_payment_information_for_user.js';
|
||||
import create_payment_intent_for_user from './api/payments/create_payment_intent_for_user.js';
|
||||
import get_payment_balance_for_user from './api/payments/get_payment_balance_for_user.js';
|
||||
import list_payment_methods_for_user from './api/payments/list_payment_methods_for_user.js';
|
||||
import update_payment_information_for_user from './api/payments/update_payment_information_for_user.js';
|
||||
import list_invoices_for_user from './api/payments/list_invoices_for_user.js';
|
||||
import list_payment_methods_for_user from './api/payments/list_payment_methods_for_user.js';
|
||||
import create_payment_intent_for_user from './api/payments/create_payment_intent_for_user.js';
|
||||
import delete_payment_method_for_user from './api/payments/delete_payment_method_for_user.js';
|
||||
export const payments = {
|
||||
delete_payment_information_for_user,
|
||||
get_payment_information_for_user,
|
||||
create_payment_information_for_user,
|
||||
update_payment_information_for_user,
|
||||
create_payment_intent_for_user,
|
||||
get_payment_balance_for_user,
|
||||
list_payment_methods_for_user,
|
||||
update_payment_information_for_user,
|
||||
list_invoices_for_user,
|
||||
list_payment_methods_for_user,
|
||||
create_payment_intent_for_user,
|
||||
delete_payment_method_for_user,
|
||||
};
|
||||
|
||||
import get_session_for_user from './api/sessions/get_session_for_user.js';
|
||||
export const sessions = { get_session_for_user };
|
||||
|
||||
export * as Models from './models.js';
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
import fsp from 'node:fs/promises';
|
||||
import fsp from 'fs/promises';
|
||||
import { OpenAPIV3 } from 'openapi-types';
|
||||
import apiGen from './apiGen.js';
|
||||
import apiGen from './apiGen';
|
||||
|
||||
main();
|
||||
|
||||
@ -62,7 +62,10 @@ async function main() {
|
||||
const items = subSchema.items;
|
||||
if ((items as any).$ref) {
|
||||
const ref = (items as any).$ref;
|
||||
return addCommentInfo(subSchema, `${key}: ${typeNameReference[ref]}[]`);
|
||||
return addCommentInfo(
|
||||
subSchema,
|
||||
`${key}: ${typeNameReference[ref]}[]`,
|
||||
);
|
||||
}
|
||||
return `${makeTypeStringForNode(
|
||||
items as OpenAPIV3.SchemaObject,
|
||||
@ -74,7 +77,10 @@ async function main() {
|
||||
) {
|
||||
if ((subSchema.additionalProperties as any).$ref) {
|
||||
const ref = (subSchema.additionalProperties as any).$ref;
|
||||
return addCommentInfo(subSchema, `${key}: {[key: string] : ${typeNameReference[ref]}}`);
|
||||
return addCommentInfo(
|
||||
subSchema,
|
||||
`${key}: {[key: string] : ${typeNameReference[ref]}}`,
|
||||
);
|
||||
}
|
||||
return `${key}: {[key: string] : ${makeTypeStringForNode(
|
||||
subSchema.additionalProperties as any,
|
||||
@ -142,11 +148,20 @@ async function main() {
|
||||
// console.log(typeReference);
|
||||
// console.log(typeNameReference);
|
||||
await fsp.writeFile(`./src/models.ts`, template, 'utf8');
|
||||
apiGen(typeNameReference)
|
||||
apiGen(typeNameReference);
|
||||
}
|
||||
|
||||
function addCommentInfo(schema: any, typeString: string) {
|
||||
const { enum: _enum, type, allOf, items, properties, additionalProperties, description, ...newSchema } = schema;
|
||||
const {
|
||||
enum: _enum,
|
||||
type,
|
||||
allOf,
|
||||
items,
|
||||
properties,
|
||||
additionalProperties,
|
||||
description,
|
||||
...newSchema
|
||||
} = schema;
|
||||
if (!Object.keys(newSchema).length && !description) {
|
||||
return typeString;
|
||||
} else if (!Object.keys(newSchema).length && description) {
|
||||
|
||||
6
tsconfig.gen.json
Normal file
6
tsconfig.gen.json
Normal file
@ -0,0 +1,6 @@
|
||||
{
|
||||
"extends": "./tsconfig.json",
|
||||
"compilerOptions": {
|
||||
"module": "CommonJS"
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user