diff --git a/package-lock.json b/package-lock.json index b6476ce..d85ae90 100644 --- a/package-lock.json +++ b/package-lock.json @@ -9564,12 +9564,6 @@ "node": ">=12.0" } }, - "node_modules/serverless-plugin-scripts": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/serverless-plugin-scripts/-/serverless-plugin-scripts-1.0.2.tgz", - "integrity": "sha512-+OL9fFz5r6BXNHfpu9MDLehS/haC0fy/T3V5uJsTfLAnNsn+PzM6BmvefUfWG372hBT7piTbywB1Vl1+4LmI5Q==", - "dev": true - }, "node_modules/serverlessinc-example": { "resolved": "", "link": true @@ -10831,8 +10825,7 @@ "serverless-http": "^3.2.0" }, "devDependencies": { - "serverless-domain-manager": "^7.4.0", - "serverless-plugin-scripts": "^1.0.2" + "serverless-domain-manager": "^7.4.0" } }, "website/app": { diff --git a/website/package.json b/website/package.json index 3b181cf..890859b 100644 --- a/website/package.json +++ b/website/package.json @@ -2,13 +2,13 @@ "name": "website", "version": "1.0.0", "main": "index.js", + "type": "module", "license": "MIT", "dependencies": { "express": "^4.19.2", "serverless-http": "^3.2.0" }, "devDependencies": { - "serverless-domain-manager": "^7.4.0", - "serverless-plugin-scripts": "^1.0.2" + "serverless-domain-manager": "^7.4.0" } } diff --git a/website/scripts.js b/website/scripts.js new file mode 100644 index 0000000..d925186 --- /dev/null +++ b/website/scripts.js @@ -0,0 +1,83 @@ +import { execSync } from "child_process"; + +/** + * This is a custom Serverless Framework Plugin that allows you to + * define and run custom scripts in your serverless.yml file, similar to npm scripts. + * For more information on creating custom plugins, see the documentation: + * https://www.serverless.com/framework/docs/guides/plugins/creating-plugins + * + * In this AI example, we need to run vite build script before deploying the website service. + * So we built this quick plugin, and loaded it in the serverless.yml file. + */ + +class Scripts { + constructor(serverless, options, utils) { + this.serverless = serverless; + this.options = options; // CLI options are passed to the plugin + this.utils = utils; // Helper logging functions are passed to the plugin + + this.commands = {}; + this.hooks = {}; + + this.defineCommands(); + this.defineHooks(); + } + + getConfig() { + const service = this.serverless.service; + return service.custom && service.custom.scripts; + } + + defineCommands() { + const config = this.getConfig(); + const commands = config && config.commands; + if (!commands) return; + + for (const name of Object.keys(commands)) { + if (!this.commands[name]) { + this.commands[name] = { lifecycleEvents: [] }; + } + this.commands[name].lifecycleEvents.push(name); + + this.hooks[`${name}:${name}`] = this.runCommand.bind(this, name); + } + } + + defineHooks() { + const config = this.getConfig(); + const hooks = config && config.hooks; + if (!hooks) return; + + for (const name of Object.keys(hooks)) { + this.hooks[name] = this.runHook.bind(this, name); + } + } + + runCommand(name) { + const commands = this.getConfig().commands; + const command = commands[name]; + this.execute(command); + } + + runHook(name) { + const hooks = this.getConfig().hooks; + const hook = hooks[name]; + this.execute(hook); + } + + execute(command) { + // By default, only show stderr in the terminal + // So that you can see any build errors that may occur + let stdio = ["ignore", "ignore", "inherit"]; + + // But in verbose or debug mode, we show all output + if (this.options.verbose || this.options.debug) { + stdio = "inherit"; + } + + // Execute the command/script in a child service + execSync(command, { stdio }); + } +} + +export default Scripts; diff --git a/website/serverless.yml b/website/serverless.yml index 495549b..7825964 100644 --- a/website/serverless.yml +++ b/website/serverless.yml @@ -5,8 +5,8 @@ provider: runtime: nodejs20.x plugins: - - serverless-plugin-scripts - - serverless-domain-manager + - serverless-domain-manager # Load the community plugin for custom domains installed with npm + - ./scripts # Load our custom scripts plugin build: esbuild: true @@ -25,6 +25,8 @@ custom: apiType: http autoDomain: true enabled: ${param:customDomainNameEnabled} + + # This property is expected by our custom scripts plugin. scripts: hooks: # This hook builds the React App. It sets the environment variables for