UNPKG

@kissflow/form-field-scripts

Version:

Scripts to serve, build, lint, test, etc. a Kissflow's custom form field project.

156 lines (136 loc) 5.56 kB
import path from 'path' import { FORM_FIELD_CONFIG_SCHEMA_INVALID_ERROR, MANDATORY_MODULES_NOT_PRESENT_ERROR, REACT_DOM_VERSION_MISMATCH_ERROR, REACT_VERSION_MISMATCH_ERROR, FORM_FIELD_MODULE_NOT_PRESENT_ERROR, UNABLE_TO_PARSE_A_FORM_FIELD_MODULE, DEFAULT_EXPORT_NOT_FOUND_ERROR, } from './errors.js' import fs from 'fs' import Ajv from 'ajv' import babel from '@babel/core' import { SUPPORTED_REACT_VERSION, SUPPORTED_REACT_DOM_VERSION, FORM_FIELD_PROJECT_CONFIG_SCHEMA, } from '@kissflow/form-field-config' import { getMandatoryModules } from './helpers.js' import { formFieldProjectConfig, getFormFieldProjectConfig, } from '../helpers.js' import { getAppPackageJson } from '../helpers.js' import paths from '../paths.js' import { createRequire } from 'module' const require = createRequire(import.meta.url) const performOnetimeChecks = async () => { // These validations are only performed ones (at instantiating time), // if the dev tries to change things that requires re-instantiating, for example, if he modifies the form-field.config.js or package.json, // the build become obsolete and needs to be restarted again. // Add a file watcher that watch the form-field.config.js and package.json of the custom form field project from which this Webpack plugin is getting instantiating, // kill the build if changes are detecting in these files (add a log explaining why the build was killed, so that the user doesn't get // confused)... await verifyPackageVersions() await validateFormFieldProjectConfigSchema() await isAllMandatoryModulesPresent() } const performRuntimeChecks = async () => { await defaultExportCheckAllModules() } const performPreBuildtimeChecks = async () => { // No need to check if package.json file exists or not, because if package.json doesn't exists the scripts that run the current file // can't won't be invoked. await getFormFieldProjectConfig() // needs need to move 1 level above the compilation tree. } const defaultExportCheckAllModules = async () => { const modulesPresentInFormFieldProject = formFieldProjectConfig for (let [platforms, components] of Object.entries( modulesPresentInFormFieldProject )) { for (const [component, modulePath] of Object.entries(components)) { let hasDefaultExport = false let isReactComponent = false let code = '' try { code = fs.readFileSync( path.join(paths.appRoot, modulePath), 'utf-8' ) } catch (err) { throw new FORM_FIELD_MODULE_NOT_PRESENT_ERROR({ modulePath }) } try { const ast = babel.parse(code, { presets: [ require('@babel/preset-env'), require('@babel/preset-react'), ], }) babel.traverse(ast, { ExportDefaultDeclaration(path) { hasDefaultExport = true }, }) } catch (err) { throw new UNABLE_TO_PARSE_A_FORM_FIELD_MODULE({ component, modulePath, err, }) } if (!hasDefaultExport) { throw new DEFAULT_EXPORT_NOT_FOUND_ERROR({ component, modulePath, }) } } } } const validateFormFieldProjectConfigSchema = async () => { const ajv = new Ajv() const validate = ajv.compile(FORM_FIELD_PROJECT_CONFIG_SCHEMA) const valid = validate(formFieldProjectConfig) if (!valid) { validate.errors.forEach((error) => { const errorMessage = ajv.errorsText([error], { separator: ', ' }) throw new FORM_FIELD_CONFIG_SCHEMA_INVALID_ERROR({ errorMessage }) }) } } const verifyPackageVersions = async () => { // Since the react + react-dom is installed as 'dependencies' // The user might change the versions... We have to prevent this. const packageJson = getAppPackageJson() const { dependencies: deps } = packageJson const reactVersionUsed = deps['react'] const reactDomVersionUsed = deps['react-dom'] if (reactVersionUsed !== SUPPORTED_REACT_VERSION) { throw new REACT_VERSION_MISMATCH_ERROR({ supportedReactVersion: SUPPORTED_REACT_VERSION, suppliedReactVersion: reactVersionUsed, }) } if (reactDomVersionUsed !== SUPPORTED_REACT_DOM_VERSION) { throw new REACT_DOM_VERSION_MISMATCH_ERROR({ suppliedReactDomVersion: reactDomVersionUsed, supportedReactDomVersion: SUPPORTED_REACT_DOM_VERSION, }) } } const isAllMandatoryModulesPresent = async () => { const mandatoryModules = getMandatoryModules() const modulesPresentInFormFieldProject = formFieldProjectConfig for (const [platform, components] of Object.entries(mandatoryModules)) { for (const component of components) { if (!(component in modulesPresentInFormFieldProject[platform])) { throw new MANDATORY_MODULES_NOT_PRESENT_ERROR({ msg: `Mandatory module '${platform}/${component}' is not present!`, }) } } } } export { performRuntimeChecks, performOnetimeChecks, performPreBuildtimeChecks }