UNPKG

@o3r/core

Version:
169 lines (168 loc) • 8.05 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.ngGenerateStoreAction = void 0; const path = require("node:path"); const core_1 = require("@angular-devkit/core"); const schematics_1 = require("@angular-devkit/schematics"); const schematics_2 = require("@o3r/schematics"); const ts = require("typescript"); /** * Compute action name based on action type and given name * @param aType * @param aName */ const computeActionName = (aType, aName) => { const names = aType.split('-'); return `${names[0]}-${aName}` + (names[1] ? `-${names[1]}` : ''); }; /** * Add an Action to an Otter Store * @param options */ function ngGenerateStoreActionFn(options) { /** * Edit .actions.ts file * @param actionFilePath * @param tree * @param context */ const editActionFile = (actionFilePath, tree, context) => { const actionType = options.actionType.replace('-custom-', ''); const name = (actionType ? computeActionName(actionType, options.actionName) : options.actionName) + (options.isCallAction ? '-from-api' : ''); const actionName = core_1.strings.camelize(name); // const actionClassName = strings.capitalize(actionName); const description = options.description ? core_1.strings.capitalize(options.description) : ''; const storeName = core_1.strings.camelize(options.storeName); const labelName = `ACTION_${core_1.strings.underscore(name).toUpperCase()}`; const actionId = `[${core_1.strings.capitalize(storeName)}] ${core_1.strings.underscore(name).replace(/_/g, ' ')}`; let actionDefinitionTemplate = ''; let payloadType = ''; switch (options.actionType) { case 'set': { actionDefinitionTemplate = `export const ${actionName} = createAction(${labelName}, props<object /* TODO: Define type */>());`; break; } case 'set-entities': { payloadType = `Set${options.isCallAction ? 'AsyncStoreItem' : ''}EntitiesActionPayload`; actionDefinitionTemplate = `export const ${actionName} = createAction(${labelName}, props<${payloadType}<object /* TODO: Define type */>>());`; break; } case 'upsert-entities': { payloadType = `Set${options.isCallAction ? 'AsyncStoreItem' : ''}EntitiesActionPayload`; actionDefinitionTemplate = `export const ${actionName} = createAction(${labelName}, props<${payloadType}<object /* TODO: Define type */>>());`; break; } case 'update': { actionDefinitionTemplate = `export const ${actionName} = createAction(${labelName}, props<Partial<object /* TODO: Define type */>>());`; break; } case 'update-entities': { payloadType = `Update${options.isCallAction ? 'AsyncStoreItem' : ''}EntitiesActionPayload`; actionDefinitionTemplate = `export const ${actionName} = createAction(${labelName}, props<${payloadType}<object /* TODO: Define type */>>());`; break; } case 'clear': { actionDefinitionTemplate = `export const ${actionName} = createAction(${labelName});`; break; } case 'fail': { actionDefinitionTemplate = `export const ${actionName} = createAction(${labelName}, props<{error: any}>());`; break; } default: { actionDefinitionTemplate = `export const ${actionName} = createAction(${labelName}, props<object /* TODO: Define type */>());`; } } const labelTemplate = `const ${labelName} = '${actionId}';`; const actionTemplate = ` ${labelTemplate} /** * ${description} */ ${actionDefinitionTemplate}`; const sourceFile = ts.createSourceFile(actionFilePath, tree.read(actionFilePath).toString(), ts.ScriptTarget.ES2015, true); const lastImport = (0, schematics_2.findLastNodeOfKind)(sourceFile, ts.SyntaxKind.ImportDeclaration) || sourceFile.getFirstToken(); if (!lastImport) { context.logger.warn(`Action can not be added in ${actionFilePath}`); return; } const recorder = tree.beginUpdate(actionFilePath); let actionDeclarationNode; const regExpDeclaration = new RegExp('const ACTION_.*='); sourceFile.forEachChild((node) => { if (ts.isVariableStatement(node) && regExpDeclaration.test(node.getText())) { actionDeclarationNode = node; } }); if (actionDeclarationNode) { recorder.insertRight(actionDeclarationNode.end, actionTemplate); context.logger.info(`Your new action has been inserted in ${actionFilePath}`); } else { context.logger.warn(`available action list can not be found in ${actionFilePath}. Inserting the action after last import.`); recorder.insertRight(lastImport.end, actionTemplate); } tree.commitUpdate(recorder); }; /** * Edit .reducer.ts file * @param reducerFilePath * @param tree * @param context */ const editReducerFile = (reducerFilePath, tree, context) => { const actionType = options.actionType.replace('-custom-', ''); const name = (actionType ? computeActionName(actionType, options.actionName) : options.actionName) + (options.isCallAction ? '-from-api' : ''); const actionName = core_1.strings.camelize(name); const reducerTemplate = ` on(actions.${actionName}, (state, _payload) => /* TODO: implement reducer action */ state),`; const sourceFile = ts.createSourceFile(reducerFilePath, tree.read(reducerFilePath).toString(), ts.ScriptTarget.ES2015, true); let reducerList; const regExpDeclaration = new RegExp(': ReducerTypes<.*>\\[\\] ='); sourceFile.forEachChild((node) => { if (ts.isVariableStatement(node) && regExpDeclaration.test(node.getText())) { reducerList = node; } }); if (!reducerList) { context.logger.error('invalid reducer file: Reducer list missing'); return; } const lastReducerItem = (0, schematics_2.findLastNodeOfKind)(sourceFile, ts.SyntaxKind.CallExpression, reducerList); if (!lastReducerItem) { context.logger.error('invalid reducer file: Empty reducer list'); return; } const recorder = tree.beginUpdate(reducerFilePath); recorder.insertLeft(lastReducerItem.end, ',\n\n' + reducerTemplate); tree.commitUpdate(recorder); }; /** * Create a new action in an existing store * @param tree * @param context */ const generateFiles = (tree, context) => { const destination = (0, schematics_2.getDestinationPath)('@o3r/core:store', options.storeDirectory, tree, options.projectName); const storeName = core_1.strings.dasherize(options.storeName); const storeFolder = path.join(destination, storeName); const actionFilePath = path.join(storeFolder, `${storeName}.actions.ts`); const reducerFilePath = path.join(storeFolder, `${storeName}.reducer.ts`); if (!tree.exists(actionFilePath) || !tree.exists(reducerFilePath)) { context.logger.error(`The store ${storeName} is not found in ${destination}`); return tree; } editActionFile(actionFilePath, tree, context); editReducerFile(reducerFilePath, tree, context); return tree; }; return (0, schematics_1.chain)([ generateFiles, options.skipLinter ? (0, schematics_1.noop)() : (0, schematics_2.applyEsLintFix)() ]); } /** * Add an Action to an Otter Store * @param options */ exports.ngGenerateStoreAction = (0, schematics_2.createOtterSchematic)(ngGenerateStoreActionFn); //# sourceMappingURL=index.js.map