UNPKG

riof

Version:

Rio framework

463 lines (456 loc) 24 kB
"use strict"; var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { if (k2 === undefined) k2 = k; Object.defineProperty(o, k2, { enumerable: true, get: function() { return m[k]; } }); }) : (function(o, m, k, k2) { if (k2 === undefined) k2 = k; o[k2] = m[k]; })); var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { Object.defineProperty(o, "default", { enumerable: true, value: v }); }) : function(o, v) { o["default"] = v; }); var __importStar = (this && this.__importStar) || function (mod) { if (mod && mod.__esModule) return mod; var result = {}; if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k); __setModuleDefault(result, mod); return result; }; var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } return new (P || (P = Promise))(function (resolve, reject) { function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } step((generator = generator.apply(thisArg, _arguments || [])).next()); }); }; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); exports.compile = void 0; const ts_morph_1 = require("ts-morph"); const fs_extra_1 = __importDefault(require("fs-extra")); const yaml_1 = __importDefault(require("yaml")); const path = __importStar(require("path")); const child_process_1 = require("child_process"); function compile(sourcePath) { var _a, _b, _c, _d; return __awaiter(this, void 0, void 0, function* () { if (sourcePath) process.chdir(sourcePath); if (fs_extra_1.default.existsSync(path.join(process.cwd(), 'dist'))) { fs_extra_1.default.rmSync(path.join(process.cwd(), 'dist'), { recursive: true, force: true }); } fs_extra_1.default.copySync(path.join(process.cwd(), 'src'), path.join(process.cwd(), 'dist', 'dependencies', 'system', 'src'), { overwrite: true, filter: (src, dest) => !src.includes('__tests__') }); fs_extra_1.default.copySync(path.join(process.cwd(), 'package.json'), path.join(process.cwd(), 'dist', 'package.json'), { overwrite: true }); fs_extra_1.default.copySync(path.join(process.cwd(), 'node_modules'), path.join(process.cwd(), 'dist', 'node_modules'), { overwrite: true }); fs_extra_1.default.mkdirpSync(path.join(process.cwd(), 'dist', 'models')); // `tsconfig.json` dosyasını yükle const configFile = ts_morph_1.ts.readConfigFile('./tsconfig.json', ts_morph_1.ts.sys.readFile); configFile.config.include = ['./**/*.ts', './**/*.yml', './**/*.json', './**/*.js']; configFile.config.compilerOptions.suppressImplicitAnyIndexErrors = true; configFile.config.compilerOptions.baseUrl = '.'; configFile.config.compilerOptions.rootDir = './'; configFile.config.compilerOptions.outDir = './dist'; configFile.config.compilerOptions.paths = { 'system': ['dependencies/system'], 'system/*': ['dependencies/system/*'], }; fs_extra_1.default.writeFileSync(path.join(process.cwd(), 'dist', 'tsconfig.json'), JSON.stringify(configFile.config, undefined, 2)); process.chdir('dist'); const project = new ts_morph_1.Project({ tsConfigFilePath: path.join(process.cwd(), 'tsconfig.json') }); const classFiles = project.getSourceFiles(); const rioRdkMethodName = 'rioRdkMethodCallAutoGenerated'; const getIndexTs = (className) => { return ` import {Data} from "@retter/rdk"; import {RioMethodError} from "riof"; import {#class_name#} from "system/src/#class_name#"; export async function exportRioMethodModels(): Promise<void> { const ref = new #class_name#(); // @ts-ignore await ref.exportRioMethodModels(); } export async function init(data: Data): Promise<Data> { try { const ref = new #class_name#(); // @ts-ignore await ref.init(data); } catch (e: any) { if (e instanceof RioMethodError) { data.response = e.getRioResponse(); } else { const error = new RioMethodError({statusCode: 500, message: 'Unhandled error'}); data.response = error.getRioResponse(); } } return data } export async function _get(data: Data): Promise<Data> { try { const ref = new #class_name#(); // @ts-ignore await ref._get(data); } catch (e: any) { if (e instanceof RioMethodError) { data.response = e.getRioResponse(); } else { const error = new RioMethodError({statusCode: 500, message: 'Unhandled error'}); data.response = error.getRioResponse(); } } return data } export async function authorizer(data: Data): Promise<any> { try { const ref = new #class_name#(); // @ts-ignore if(await ref.authorizer(data)){ return {statusCode: 200}; }else{ return {statusCode: 403} } } catch (e: any) { if (e instanceof RioMethodError) { data.response = e.getRioResponse(); } else { const error = new RioMethodError({statusCode: 500, message: 'Unhandled error'}); data.response = error.getRioResponse(); } } return data.response } export async function getInstanceId(data: Data): Promise<any> { const ref = new #class_name#(); // @ts-ignore return await ref.getInstanceId(data); } export async function getState(data: Data): Promise<any> { try { const ref = new #class_name#(); data.response = { statusCode: 200, // @ts-ignore body: await ref.getState(data) } } catch (e: any) { if (e instanceof RioMethodError) { data.response = e.getRioResponse(); } else { const error = new RioMethodError({statusCode: 500, message: 'Unhandled error'}); data.response = error.getRioResponse(); } } return data.response } export async function destroy(data: Data): Promise<any> { try { const ref = new #class_name#(); // @ts-ignore await ref.destroy(data); } catch (e: any) { if (e instanceof RioMethodError) { data.response = e.getRioResponse(); } else { const error = new RioMethodError({statusCode: 500, message: 'Unhandled error'}); data.response = error.getRioResponse(); } } return data.response } `.replace(/#class_name#/g, className); }; const getIndexTsMethod = (className, methodName) => { return ` export async function #method_name#(data: Data): Promise<Data> { try { const ref = new #class_name#(); // @ts-ignore ref.setDataProperties(data); const res = await ref.#method_name#(data.request); data.response = { statusCode: 200, body: res } // @ts-ignore data.state = ref.state // @ts-ignore data.schedule = ref.schedule // @ts-ignore data.tasks = ref.tasks // @ts-ignore data.events = ref.events } catch (e: any) { if (e instanceof RioMethodError) { data.response = e.getRioResponse(); } else { const error = new RioMethodError({statusCode: 500, message: 'Unhandled error'}); data.response = error.getRioResponse(); } } return data } `.replace(/#class_name#/g, className).replace(/#method_name#/g, methodName); }; const rioTemplates = []; const globalMethodDeclarations = []; for (let i = 0; i < classFiles.length; i++) { for (const sourceClass of classFiles[i].getClasses()) { const className = sourceClass.getName(); if (!className) continue; const classDeclaration = classFiles[i].getClass(className); if (!classDeclaration) continue; if (!classDeclaration.getDecorators().some(d => d.getName() === 'RioClass')) continue; classDeclaration.findReferencesAsNodes(); const classRefs = classDeclaration.findReferencesAsNodes().filter(node => node.getAncestors()[0].getKind() === ts_morph_1.SyntaxKind.NewExpression); for (const ref of classRefs) { const newExpression = ref.getAncestors()[0]; ref.getAncestors()[0].replaceWithText(`await ${newExpression.getText()}.getRioClassInstance()`); } const classTemplate = { init: { handler: "index.init" }, get: { handler: "index._get" }, authorizer: "index.authorizer", getState: "index.getState", getInstanceId: "index.getInstanceId", destroy: "index.destroy", description: "Made in Rio framework", dependencies: [ "system" ], methods: [] }; const classDecoratorRioArgs = (_a = classDeclaration.getDecorators().find(d => d.getName() === 'RioClass')) === null || _a === void 0 ? void 0 : _a.getArguments(); if (classDecoratorRioArgs && classDecoratorRioArgs.length > 0) { for (const classDecoratorRioArg of classDecoratorRioArgs) { classDecoratorRioArg.getDescendantsOfKind(ts_morph_1.SyntaxKind.PropertyAssignment).forEach(p => { const prop = p.getDescendants()[0].getText(); let value = p.getDescendants()[2].getText(); switch (p.getDescendants()[2].getKind()) { case ts_morph_1.SyntaxKind.FalseKeyword: value = false; break; case ts_morph_1.SyntaxKind.TrueKeyword: value = true; break; case ts_morph_1.SyntaxKind.NumberKeyword: value = Number(value); break; default: value = value.replace(/['"]+/g, ''); break; } classTemplate[prop] = value; }); } } let noRDKImport = true; for (const importDeclaration of classFiles[i].getImportDeclarations()) { if (importDeclaration.getModuleSpecifierValue() === '@retter/rdk') { const importClause = (_b = importDeclaration.getImportClause()) === null || _b === void 0 ? void 0 : _b.getText(); if (!importClause || (importClause && importClause !== 'RDK')) { const clause = importDeclaration.getImportClause(); if (clause) { clause.replaceWithText(`RDK, { ${importDeclaration.getNamedImports().map(i => i.getText()).join(', ')} }`); } } noRDKImport = false; break; } } if (noRDKImport) { classFiles[i].addImportDeclaration({ moduleSpecifier: '@retter/rdk', defaultImport: "RDK" }); } let noFSImport = true; for (const importDeclaration of classFiles[i].getImportDeclarations()) { if (importDeclaration.getModuleSpecifierValue() === 'fs/promises') { const importClause = (_c = importDeclaration.getImportClause()) === null || _c === void 0 ? void 0 : _c.getText(); if (!importClause || (importClause && importClause !== 'fs')) { const clause = importDeclaration.getImportClause(); if (clause) { clause.replaceWithText(`fs, { ${importDeclaration.getNamedImports().map(i => i.getText()).join(', ')} }`); } } noFSImport = false; break; } } if (noFSImport) { classFiles[i].addImportDeclaration({ moduleSpecifier: 'fs/promises', defaultImport: "fs" }); } let noZod2SchemaImport = true; for (const importDeclaration of classFiles[i].getImportDeclarations()) { if (importDeclaration.getModuleSpecifierValue() === 'zod-to-json-schema') { const importClause = (_d = importDeclaration.getImportClause()) === null || _d === void 0 ? void 0 : _d.getText(); if (!importClause || (importClause && importClause !== 'zod-to-json-schema')) { const clause = importDeclaration.getImportClause(); if (clause) { clause.replaceWithText(`{ zodToJsonSchema, ${importDeclaration.getNamedImports().map(i => i.getText()).join(', ')} }`); } } noZod2SchemaImport = false; break; } } if (noZod2SchemaImport) { classFiles[i].addImportDeclaration({ moduleSpecifier: 'zod-to-json-schema', namedImports: ['zodToJsonSchema'] }); } if (!classDeclaration.getMethod(rioRdkMethodName)) { classDeclaration.addMethod({ docs: ["!Auto generated method!"], name: rioRdkMethodName, isAsync: true, parameters: [{ name: 'props', type: '{method: string, input: any}' }], returnType: "Promise<any>", statements: `const rdk = new RDK(); const response = await rdk.methodCall({ ...props.input, classId: '${classDeclaration.getName()}', methodName: props.method, instanceId: this.instanceId, lookupKey: this.lookup }); return response?.body;`.replace(/(\r\n|\n|\r)/gm, "").replace(/ {4}/g, '') }); } const uniqueModelNames = []; for (const method of classDeclaration.getMethods().filter(m => m.getDecorators().some(d => d.getName() === 'RioMethod'))) { const methodDeclaration = classDeclaration.getMethod(method.getName()); if (!methodDeclaration) continue; const rioDecorator = methodDeclaration.getDecorators().find(d => d.getName() === 'RioMethod'); if (!rioDecorator) continue; const methodDecoratorRioArgs = rioDecorator.getArguments(); if (methodDecoratorRioArgs && methodDecoratorRioArgs.length > 0) { for (const methodDecoratorRioArg of methodDecoratorRioArgs) { methodDecoratorRioArg.getDescendantsOfKind(ts_morph_1.SyntaxKind.PropertyAssignment).forEach(p => { const prop = p.getDescendants()[0].getText(); let value = p.getDescendants()[2].getText(); const methodIndex = classTemplate.methods.findIndex(m => m.method === method.getName()); if (methodIndex === -1) { const methodObj = { method: method.getName(), handler: `index.${method.getName()}` }; methodObj[prop] = value.replace(/['"]+/g, ''); classTemplate.methods.push(methodObj); } else { value = value.replace(/['"]+/g, ''); classTemplate.methods[methodIndex][prop] = value; } if (['queryStringModel', 'inputModel', 'outputModel', 'errorModel'].includes(prop)) { if (['init', 'getState', 'getInstanceId', 'destroy'].includes(method.getName())) { classTemplate[method.getName()][prop] = `${className}_${value}`; } else { classTemplate.methods[methodIndex][prop] = `${className}_${value}`; } uniqueModelNames.push(value); } }); } } const methodReferences = methodDeclaration.findReferencesAsNodes(); for (const reference of methodReferences) { const ref = reference.getAncestors()[1]; if (ref.getKind() !== ts_morph_1.SyntaxKind.CallExpression) continue; const expression = ref; const argList = expression.getArguments(); const classReference = reference.getAncestors()[0].getChildren()[0].getText(); const methodName = method.getName(); expression.replaceWithText(`${classReference}.${rioRdkMethodName}({method: '${methodName}', input: ${argList.map(a => a.getText()).join(', ')}})`); } //change other classes for (const classFile of classFiles) { const classes = classFile.getClasses(); for (const cls of classes) { if (cls.getName() === classDeclaration.getName()) continue; cls.getDescendantsOfKind(ts_morph_1.SyntaxKind.CallExpression).forEach((call) => { const refValues = call.getDescendantsOfKind(ts_morph_1.SyntaxKind.PropertyAccessExpression).flatMap(exp => exp.getDescendantsOfKind(ts_morph_1.SyntaxKind.Identifier).map(i => i.getText())); if (refValues.length === 2 && refValues[1] === methodDeclaration.getName()) { const argList = call.getArguments(); const classReference = refValues[0]; const methodName = method.getName(); call.replaceWithText(`${classReference}.${rioRdkMethodName}({method: '${methodName}', input: ${argList.map(a => a.getText()).join(', ')}})`); } }); } } rioDecorator.remove(); } let exportModelMethodBody = ` await Promise.all([`; for (const uniqueModelName of uniqueModelNames) { exportModelMethodBody += `fs.writeFile('${path.join('.', 'models', `${className}_${uniqueModelName}.json`)}', JSON.stringify(zodToJsonSchema(${uniqueModelName}, {name: '${uniqueModelName}', $refStrategy: 'none'}).definitions!['${uniqueModelName}'], undefined, 2)),`; } exportModelMethodBody += `])`; classDeclaration.addMethod({ scope: ts_morph_1.Scope.Private, docs: ["!Auto generated method!"], name: 'exportRioMethodModels', isAsync: true, returnType: "Promise<void>", statements: exportModelMethodBody }); rioTemplates.push({ className, template: classTemplate }); } } for (const rioTemplate of rioTemplates) { const classPath = path.join(process.cwd(), 'classes', rioTemplate.className); project.createSourceFile(path.join(classPath, 'template.yml'), yaml_1.default.stringify(rioTemplate.template), { overwrite: true }); let indexFile = getIndexTs(rioTemplate.className); for (const method of rioTemplate.template.methods) { if (['init', 'getState', 'getInstanceId', 'destroy'].includes(method.method)) continue; indexFile += getIndexTsMethod(rioTemplate.className, method.method) + '\n'; } project.createSourceFile(path.join(classPath, 'index.ts'), indexFile, { overwrite: true }); } project.saveSync(); project.emitSync(); fs_extra_1.default.copySync(path.join(process.cwd(), 'dist', 'dependencies'), path.join(process.cwd(), 'node_modules'), { overwrite: true }); const packageFilesWorkers = []; const writeTemplatesToDist = []; let exportModelsCode = `(async () => { await Promise.all([`; for (const rioTemplate of rioTemplates) { exportModelsCode += `require('./classes/${rioTemplate.className}').exportRioMethodModels(),`; writeTemplatesToDist.push(fs_extra_1.default.writeFile(path.join(process.cwd(), 'dist', 'classes', rioTemplate.className, 'template.yml'), yaml_1.default.stringify(rioTemplate.template))); const globalPackageJson = JSON.parse(fs_extra_1.default.readFileSync(path.join(process.cwd(), 'package.json'), 'utf8')); packageFilesWorkers.push(fs_extra_1.default.writeFile(path.join(process.cwd(), 'dist', 'classes', rioTemplate.className, 'package.json'), JSON.stringify({ "name": rioTemplate.className.toLowerCase(), "version": "1.0.0", "dependencies": globalPackageJson.dependencies, }, undefined, 2))); } exportModelsCode += `])})().catch();`; child_process_1.execSync(`ts-node -e "${exportModelsCode}"`, { stdio: 'inherit' }); yield Promise.all(writeTemplatesToDist); fs_extra_1.default.copySync(path.join(process.cwd(), 'models'), path.join(process.cwd(), 'dist', 'models'), { overwrite: true }); }); } exports.compile = compile; //# sourceMappingURL=compiler.js.map