riof
Version:
Rio framework
463 lines (456 loc) • 24 kB
JavaScript
"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