UNPKG

@kitchenshelf/serverless-rspack

Version:

[Serverless Framework](https://www.serverless.com) plugin for zero-config JavaScript and TypeScript code bundling using the high performance Rust-based JavaScript bundler [`rspack`](https://rspack.dev/guide/start/introduction)

153 lines 7.72 kB
import { __awaiter } from "tslib"; import { assert } from 'node:console'; import { readdirSync } from 'node:fs'; import { rm } from 'node:fs/promises'; import path from 'node:path'; import { bundle } from './bundle.js'; import { SERVERLESS_FOLDER, WORK_FOLDER } from './constants.js'; import { determineFileParts, enabledViaConfigObject, enabledViaSimpleConfig, isNodeFunction, } from './helpers.js'; import { AfterDeployFunctionPackageFunction } from './hooks/deploy-function/after-package-function.js'; import { BeforeDeployFunctionPackageFunction } from './hooks/deploy-function/before-package-function.js'; import { Initialize } from './hooks/initialize.js'; import { BeforeInvokeLocalInvoke } from './hooks/invoke-local/before-invoke.js'; import { BeforeOfflineStartInit } from './hooks/offline/start-init.js'; import { AfterPackageCreateDeploymentArtifacts } from './hooks/package/after-create-deployment-artifacts.js'; import { BeforePackageCreateDeploymentArtifacts } from './hooks/package/before-create-deployment-artifacts.js'; import { pack } from './pack.js'; import { scripts } from './scripts.js'; import { PluginOptionsSchema, } from './types.js'; export class RspackServerlessPlugin { constructor(serverless, options, logging) { this.functionEntries = {}; this.functionScripts = {}; this.offlineMode = false; this.timings = new Map(); this.bundle = bundle.bind(this); this.pack = pack.bind(this); this.scripts = scripts.bind(this); assert(logging, 'Please use serverless V4'); serverless.configSchemaHandler.defineFunctionProperties('aws', { properties: { rspack: { oneOf: [ { type: 'boolean' }, { type: 'object', properties: { enable: { type: 'boolean' }, scripts: { type: 'array', items: { type: 'string' } }, }, required: [], }, ], }, }, }); this.serverless = serverless; this.options = options; this.log = logging.log; this.serviceDirPath = this.serverless.config.serviceDir; this.packageOutputFolder = SERVERLESS_FOLDER; this.buildOutputFolder = WORK_FOLDER; this.buildOutputFolderPath = path.join(this.serviceDirPath, this.buildOutputFolder); this.hooks = { initialize: Initialize.bind(this), 'before:package:createDeploymentArtifacts': BeforePackageCreateDeploymentArtifacts.bind(this), 'after:package:createDeploymentArtifacts': AfterPackageCreateDeploymentArtifacts.bind(this), 'before:deploy:function:packageFunction': BeforeDeployFunctionPackageFunction.bind(this), 'after:deploy:function:packageFunction': AfterDeployFunctionPackageFunction.bind(this), 'before:invoke:local:invoke': BeforeInvokeLocalInvoke.bind(this), 'before:offline:start:init': BeforeOfflineStartInit.bind(this), }; } buildFunctionEntries(functions) { this.log.verbose(`[sls-rspack] Building function entries for: ${functions}`); let entries = {}; functions.forEach((functionName) => { const functionDefinitionHandler = this.serverless.service.getFunction(functionName); if (this.isEnabledViaRspack(functionDefinitionHandler) || this.isEnabledNodeFunction(functionDefinitionHandler)) { // TODO: support container images const entry = this.getEntryForFunction(functionName, functionDefinitionHandler); entries = Object.assign(Object.assign({}, entries), entry); } }); return entries; } buildFunctionScripts(functions) { this.log.verbose(`[sls-rspack] Building function scripts for: ${functions}`); const scripts = {}; functions.forEach((functionName) => { const functionDefinitionHandler = this.serverless.service.getFunction(functionName); if (functionDefinitionHandler.rspack && !enabledViaSimpleConfig(functionDefinitionHandler.rspack) && functionDefinitionHandler.rspack.enable !== false && functionDefinitionHandler.rspack.scripts) { this.log.verbose(`[sls-rspack] Found ${functionDefinitionHandler.rspack.scripts.length} scripts for function ${functionName}`); scripts[functionName] = functionDefinitionHandler.rspack.scripts; } }); return scripts; } cleanup() { return __awaiter(this, void 0, void 0, function* () { if (!this.pluginOptions.keepOutputDirectory) { yield rm(path.join(this.buildOutputFolderPath), { recursive: true }); } }); } getPluginOptions() { var _a, _b; return PluginOptionsSchema.parse((_b = (_a = this.serverless.service.custom) === null || _a === void 0 ? void 0 : _a['rspack']) !== null && _b !== void 0 ? _b : {}); } isEnabledNodeFunction(functionDefinitionHandler) { return (isNodeFunction(functionDefinitionHandler, this.serverless.service.provider.runtime) && !this.isDisabledViaRspack(functionDefinitionHandler)); } isDisabledViaRspack(functionDefinitionHandler) { return (functionDefinitionHandler.rspack !== undefined && !enabledViaSimpleConfig(functionDefinitionHandler.rspack) && !enabledViaConfigObject(functionDefinitionHandler.rspack)); } isEnabledViaRspack(functionDefinitionHandler) { return (functionDefinitionHandler.rspack && (enabledViaSimpleConfig(functionDefinitionHandler.rspack) || enabledViaConfigObject(functionDefinitionHandler.rspack))); } getEntryForFunction(name, serverlessFunction) { const handler = serverlessFunction.handler; this.log.verbose(`[sls-rspack] Processing function ${name} with provided handler ${handler}`); const handlerFile = this.getHandlerFile(handler); const { filePath, fileName } = determineFileParts(handlerFile); const safeFilePath = filePath ? '/' + filePath + '/' : '/'; const files = readdirSync(`./${filePath}`); const file = files.find((file) => { return file.startsWith(fileName); }); if (!file) { throw new this.serverless.classes.Error(`Unable to find file [${fileName}] in path: [./${filePath}]`); } const ext = path.extname(file); this.log.verbose(`[sls-rspack] Determined: filePath: [${safeFilePath}] - fileName: [${fileName}] - ext: [${ext}]`); const outputExtension = this.isESM() ? 'mjs' : 'js'; return { [name]: { import: `./${handlerFile}${ext}`, filename: `[name]${safeFilePath}${fileName}.${outputExtension}`, }, }; } getHandlerFile(handler) { // Check if handler is a well-formed path based handler. const handlerEntry = /(.*)\..*?$/.exec(handler); if (handlerEntry) { return handlerEntry[1]; } throw new this.serverless.classes.Error(`malformed handler: ${handler}`); } isESM() { var _a, _b; return (((_b = (_a = this.providedRspackConfig) === null || _a === void 0 ? void 0 : _a.experiments) === null || _b === void 0 ? void 0 : _b.outputModule) || this.pluginOptions.esm); } } //# sourceMappingURL=serverless-rspack.js.map