├── .editorconfig ├── .eslintignore ├── .eslintrc.js ├── .gitattributes ├── .github └── workflows │ ├── test.yml │ └── validate.yml ├── .gitignore ├── .npmignore ├── .npmrc ├── .prettierignore ├── LICENSE ├── README.md ├── __tests__ ├── express.test.ts └── nextjs.test.ts ├── commitlint.config.js ├── docs ├── README.md ├── advanced.md ├── configure.md ├── develop.md ├── faq.md ├── output.md └── upload │ ├── express.md │ ├── koa.md │ ├── nextjs.md │ └── nuxtjs.md ├── examples ├── django │ ├── .gitignore │ ├── djangodemo │ │ ├── __init__.py │ │ ├── asgi.py │ │ ├── settings.py │ │ ├── urls.py │ │ ├── views.py │ │ └── wsgi.py │ ├── manage.py │ ├── requirements.txt │ ├── serverless.yml │ └── templates │ │ └── index.html ├── egg │ ├── .gitignore │ ├── app │ │ ├── controller │ │ │ ├── home.js │ │ │ └── user.js │ │ ├── public │ │ │ └── styles │ │ │ │ └── index.css │ │ ├── router.js │ │ ├── utils │ │ │ ├── constants.js │ │ │ └── index.js │ │ └── view │ │ │ └── index.html │ ├── appveyor.yml │ ├── config │ │ ├── config.default.js │ │ └── plugin.js │ ├── jsconfig.json │ ├── package.json │ ├── serverless.yml │ └── sls.js ├── express │ ├── index.html │ ├── logo.png │ ├── package.json │ ├── serverless.yml │ └── sls.js ├── flask │ ├── .gitignore │ ├── __test__ │ │ ├── serverless_wsgi.py │ │ ├── sl_handler.py │ │ └── sl_test.py │ ├── app.py │ ├── requirements.txt │ ├── serverless.yml │ └── templates │ │ └── index.html ├── koa │ ├── index.html │ ├── package.json │ ├── serverless.yml │ └── sls.js ├── laravel │ ├── .editorconfig │ ├── .env.example │ ├── .env.production │ ├── .gitattributes │ ├── .gitignore │ ├── .styleci.yml │ ├── __test__ │ │ ├── sl_arr.php │ │ ├── sl_handler.php │ │ └── sl_test.php │ ├── app │ │ ├── Console │ │ │ └── Kernel.php │ │ ├── Exceptions │ │ │ └── Handler.php │ │ ├── Http │ │ │ ├── Controllers │ │ │ │ └── Controller.php │ │ │ ├── Kernel.php │ │ │ └── Middleware │ │ │ │ ├── Authenticate.php │ │ │ │ ├── CheckForMaintenanceMode.php │ │ │ │ ├── EncryptCookies.php │ │ │ │ ├── RedirectIfAuthenticated.php │ │ │ │ ├── TrimStrings.php │ │ │ │ ├── TrustHosts.php │ │ │ │ ├── TrustProxies.php │ │ │ │ └── VerifyCsrfToken.php │ │ ├── Providers │ │ │ ├── AppServiceProvider.php │ │ │ ├── AuthServiceProvider.php │ │ │ ├── BroadcastServiceProvider.php │ │ │ ├── EventServiceProvider.php │ │ │ └── RouteServiceProvider.php │ │ └── User.php │ ├── artisan │ ├── bootstrap │ │ ├── app.php │ │ └── cache │ │ │ └── .gitignore │ ├── composer.json │ ├── composer.lock │ ├── config │ │ ├── app.php │ │ ├── auth.php │ │ ├── broadcasting.php │ │ ├── cache.php │ │ ├── cors.php │ │ ├── database.php │ │ ├── filesystems.php │ │ ├── hashing.php │ │ ├── logging.php │ │ ├── mail.php │ │ ├── queue.php │ │ ├── services.php │ │ ├── session.php │ │ └── view.php │ ├── database │ │ ├── .gitignore │ │ ├── factories │ │ │ └── UserFactory.php │ │ ├── migrations │ │ │ ├── 2014_10_12_000000_create_users_table.php │ │ │ └── 2019_08_19_000000_create_failed_jobs_table.php │ │ └── seeds │ │ │ └── DatabaseSeeder.php │ ├── package.json │ ├── phpunit.xml │ ├── public │ │ ├── .htaccess │ │ ├── favicon.ico │ │ ├── index.php │ │ ├── robots.txt │ │ └── web.config │ ├── resources │ │ ├── js │ │ │ ├── app.js │ │ │ └── bootstrap.js │ │ ├── lang │ │ │ └── en │ │ │ │ ├── auth.php │ │ │ │ ├── pagination.php │ │ │ │ ├── passwords.php │ │ │ │ └── validation.php │ │ ├── sass │ │ │ └── app.scss │ │ └── views │ │ │ └── welcome.blade.php │ ├── routes │ │ ├── api.php │ │ ├── channels.php │ │ ├── console.php │ │ └── web.php │ ├── server.php │ ├── serverless.yml │ └── webpack.mix.js ├── nestjs │ ├── .gitignore │ ├── .prettierrc │ ├── nest-cli.json │ ├── package.json │ ├── serverless.yml │ ├── sls.js │ ├── src │ │ ├── app.controller.spec.ts │ │ ├── app.controller.ts │ │ ├── app.module.ts │ │ ├── app.service.ts │ │ └── main.ts │ ├── tsconfig.build.json │ ├── tsconfig.json │ └── views │ │ └── index.hbs ├── nextjs │ ├── .env.example │ ├── .gitignore │ ├── next.config.js │ ├── package.json │ ├── pages │ │ ├── _app.js │ │ ├── api │ │ │ └── hello.js │ │ └── index.js │ ├── public │ │ └── favicon.ico │ ├── serverless.yml │ └── styles │ │ ├── Home.module.css │ │ └── globals.css ├── nuxtjs │ ├── .editorconfig │ ├── .env.example │ ├── .gitignore │ ├── assets │ │ └── README.md │ ├── components │ │ ├── Logo.vue │ │ └── README.md │ ├── layouts │ │ ├── README.md │ │ └── default.vue │ ├── middleware │ │ └── README.md │ ├── nuxt.config.js │ ├── package.json │ ├── pages │ │ ├── README.md │ │ └── index.vue │ ├── plugins │ │ └── README.md │ ├── serverless.yml │ ├── static │ │ ├── README.md │ │ └── favicon.ico │ └── store │ │ └── README.md └── thinkphp │ ├── .example.env │ ├── .gitignore │ ├── .travis.yml │ ├── README.md │ ├── __test__ │ ├── sl_arr.php │ ├── sl_handler.php │ └── sl_test.php │ ├── app │ ├── .htaccess │ ├── AppService.php │ ├── BaseController.php │ ├── ExceptionHandle.php │ ├── Request.php │ ├── common.php │ ├── controller │ │ └── Index.php │ ├── event.php │ ├── middleware.php │ ├── provider.php │ └── service.php │ ├── composer.json │ ├── composer.lock │ ├── config │ ├── app.php │ ├── cache.php │ ├── console.php │ ├── cookie.php │ ├── database.php │ ├── filesystem.php │ ├── lang.php │ ├── log.php │ ├── middleware.php │ ├── route.php │ ├── session.php │ ├── trace.php │ └── view.php │ ├── extend │ └── .gitignore │ ├── public │ ├── .htaccess │ ├── favicon.ico │ ├── index.php │ ├── robots.txt │ ├── router.php │ └── static │ │ └── .gitignore │ ├── route │ └── app.php │ ├── runtime │ └── .gitignore │ ├── serverless.yml │ ├── think │ └── view │ ├── README.md │ └── index │ └── index.html ├── jest.config.js ├── package.json ├── prettier.config.js ├── release.config.js ├── scripts ├── bootstrap.ts ├── config.ts ├── deploy.ts ├── example.ts ├── logger.ts ├── utils.ts └── version.ts ├── src ├── _fixtures │ ├── public │ │ └── .gitkeep │ └── python │ │ └── serverless_wsgi.py ├── _shims │ ├── django │ │ └── sl_handler.py │ ├── egg │ │ ├── handler.js │ │ ├── package.json │ │ └── sls.js │ ├── express │ │ ├── handler.js │ │ ├── package.json │ │ └── sls.js │ ├── flask │ │ └── sl_handler.py │ ├── koa │ │ ├── handler.js │ │ ├── package.json │ │ └── sls.js │ ├── laravel │ │ ├── sl_arr.php │ │ └── sl_handler.php │ ├── nestjs │ │ ├── handler.js │ │ └── package.json │ ├── nextjs │ │ ├── handler.js │ │ ├── package.json │ │ └── sls.js │ ├── nuxtjs │ │ ├── handler.js │ │ ├── package.json │ │ └── sls.js │ └── thinkphp │ │ ├── sl_arr.php │ │ └── sl_handler.php ├── config.ts ├── formatter.ts ├── index.ts ├── interface │ ├── index.ts │ ├── inputs.ts │ ├── outputs.ts │ └── state.ts ├── package.json ├── serverless-core.d.ts ├── serverless.ts └── utils.ts ├── tsconfig.json ├── typings └── index.ts └── version.yml /.editorconfig: -------------------------------------------------------------------------------- 1 | # EditorConfig is awesome: http://EditorConfig.org 2 | 3 | # top-most EditorConfig file 4 | root = true 5 | 6 | [*] 7 | charset = utf-8 8 | end_of_line = lf 9 | insert_final_newline = true 10 | indent_size = 2 11 | indent_style = space 12 | trim_trailing_whitespace = true 13 | 14 | [*.md] 15 | trim_trailing_whitespace = false -------------------------------------------------------------------------------- /.eslintignore: -------------------------------------------------------------------------------- 1 | coverage 2 | dist 3 | node_modules 4 | example 5 | *.test.js 6 | src/_src 7 | .next 8 | .nuxt 9 | build 10 | 11 | src/_shims 12 | src/_fixtures 13 | examples 14 | 15 | *.d.ts 16 | -------------------------------------------------------------------------------- /.eslintrc.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | root: true, 3 | extends: ['prettier'], 4 | plugins: ['import', 'prettier'], 5 | env: { 6 | es6: true, 7 | jest: true, 8 | node: true, 9 | }, 10 | parser: '@typescript-eslint/parser', 11 | parserOptions: { 12 | ecmaVersion: 2018, 13 | sourceType: 'module', 14 | ecmaFeatures: { 15 | jsx: true, 16 | }, 17 | }, 18 | globals: { 19 | on: true, // for the Socket file 20 | }, 21 | rules: { 22 | 'array-bracket-spacing': [ 23 | 'error', 24 | 'never', 25 | { 26 | objectsInArrays: false, 27 | arraysInArrays: false, 28 | }, 29 | ], 30 | 'arrow-parens': ['error', 'always'], 31 | 'arrow-spacing': ['error', { before: true, after: true }], 32 | curly: 'error', 33 | 'eol-last': 'error', 34 | 'func-names': 'off', 35 | 'id-length': [ 36 | 'error', 37 | { 38 | min: 1, 39 | max: 50, 40 | properties: 'never', 41 | exceptions: ['e', 'i', 'n', 't', 'x', 'y', 'z', '_', '$'], 42 | }, 43 | ], 44 | 'no-alert': 'error', 45 | 'no-console': 'off', 46 | 'no-const-assign': 'error', 47 | 'no-else-return': 'error', 48 | 'no-empty': 'off', 49 | 'no-shadow': 'error', 50 | 'no-undef': 'error', 51 | 'no-unused-vars': 'error', 52 | 'no-use-before-define': 'error', 53 | 'no-useless-constructor': 'error', 54 | 'object-curly-newline': 'off', 55 | 'object-shorthand': 'off', 56 | 'prefer-const': 'error', 57 | 'prefer-destructuring': ['error', { object: true, array: false }], 58 | quotes: [ 59 | 'error', 60 | 'single', 61 | { 62 | allowTemplateLiterals: true, 63 | avoidEscape: true, 64 | }, 65 | ], 66 | semi: ['error', 'always'], 67 | 'comma-dangle': ['error', 'always-multiline'], 68 | 'spaced-comment': 'error', 69 | strict: ['error', 'global'], 70 | 'prettier/prettier': 'error', 71 | }, 72 | }; 73 | -------------------------------------------------------------------------------- /.gitattributes: -------------------------------------------------------------------------------- 1 | src/_shims/** linguist-vendored 2 | src/_fixtures/** linguist-vendored 3 | examples/** linguist-vendored 4 | -------------------------------------------------------------------------------- /.github/workflows/test.yml: -------------------------------------------------------------------------------- 1 | name: Test 2 | 3 | on: 4 | pull_request: 5 | branches: [master] 6 | 7 | jobs: 8 | test: 9 | name: Test 10 | runs-on: ubuntu-latest 11 | steps: 12 | - name: Checkout repository 13 | uses: actions/checkout@v2 14 | with: 15 | # Ensure connection with 'master' branch 16 | fetch-depth: 2 17 | 18 | - name: Install Node.js and npm 19 | uses: actions/setup-node@v1 20 | with: 21 | node-version: 14.x 22 | registry-url: https://registry.npmjs.org 23 | 24 | - name: Retrieve dependencies from cache 25 | id: cacheNpm 26 | uses: actions/cache@v2 27 | with: 28 | path: | 29 | ~/.npm 30 | node_modules 31 | key: npm-v14-${{ runner.os }}-${{ github.ref }}-${{ hashFiles('package.json') }} 32 | restore-keys: | 33 | npm-v14-${{ runner.os }}-${{ github.ref }}- 34 | npm-v14-${{ runner.os }}-refs/heads/master- 35 | 36 | - name: Install dependencies 37 | if: steps.cacheNpm.outputs.cache-hit != 'true' 38 | run: | 39 | npm update --no-save 40 | npm update --save-dev --no-save 41 | - name: Running tests 42 | run: npm run test 43 | env: 44 | SERVERLESS_PLATFORM_VENDOR: tencent 45 | GLOBAL_ACCELERATOR_NA: true 46 | TENCENT_APP_ID: ${{ secrets.TENCENT_APP_ID }} 47 | TENCENT_SECRET_ID: ${{ secrets.TENCENT_SECRET_ID }} 48 | TENCENT_SECRET_KEY: ${{ secrets.TENCENT_SECRET_KEY }} 49 | -------------------------------------------------------------------------------- /.github/workflows/validate.yml: -------------------------------------------------------------------------------- 1 | name: Validate 2 | 3 | on: 4 | pull_request: 5 | branches: [master] 6 | 7 | jobs: 8 | lintAndFormatting: 9 | name: Lint & Formatting 10 | runs-on: ubuntu-latest 11 | steps: 12 | - name: Checkout repository 13 | uses: actions/checkout@v2 14 | with: 15 | # Ensure connection with 'master' branch 16 | fetch-depth: 2 17 | 18 | - name: Install Node.js and npm 19 | uses: actions/setup-node@v1 20 | with: 21 | node-version: 14.x 22 | registry-url: https://registry.npmjs.org 23 | 24 | - name: Retrieve dependencies from cache 25 | id: cacheNpm 26 | uses: actions/cache@v2 27 | with: 28 | path: | 29 | ~/.npm 30 | node_modules 31 | key: npm-v14-${{ runner.os }}-${{ github.ref }}-${{ hashFiles('package.json') }} 32 | restore-keys: | 33 | npm-v14-${{ runner.os }}-${{ github.ref }}- 34 | npm-v14-${{ runner.os }}-refs/heads/master- 35 | 36 | - name: Install dependencies 37 | if: steps.cacheNpm.outputs.cache-hit != 'true' 38 | run: | 39 | npm update --no-save 40 | npm update --save-dev --no-save 41 | 42 | - name: Validate Formatting 43 | run: npm run prettier:fix 44 | - name: Validate Lint rules 45 | run: npm run lint:fix 46 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | *.sublime-project 3 | *.sublime-workspace 4 | *.log 5 | .serverless 6 | v8-compile-cache-* 7 | jest/* 8 | coverage 9 | .serverless_plugins 10 | testProjects/*/package-lock.json 11 | testProjects/*/yarn.lock 12 | .serverlessUnzipped 13 | node_modules 14 | .vscode/ 15 | .eslintcache 16 | dist 17 | .idea 18 | build/ 19 | .env* 20 | !.env.example 21 | env.js 22 | package-lock.json 23 | test 24 | yarn.lock 25 | test/src/node_modules 26 | test/src/.next 27 | test/src/package-lock.json 28 | __pycache__ 29 | -------------------------------------------------------------------------------- /.npmignore: -------------------------------------------------------------------------------- 1 | test 2 | example -------------------------------------------------------------------------------- /.npmrc: -------------------------------------------------------------------------------- 1 | package-lock=false 2 | -------------------------------------------------------------------------------- /.prettierignore: -------------------------------------------------------------------------------- 1 | coverage 2 | dist 3 | node_modules 4 | CHANGELOG.md 5 | *.test.js 6 | tests/src/.next 7 | tests/src/node_modules 8 | 9 | .next 10 | .nuxt 11 | build 12 | 13 | src/_shims 14 | src/_fixtures 15 | examples 16 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2020 Tencent Cloud Inc. 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /__tests__/express.test.ts: -------------------------------------------------------------------------------- 1 | import { generateId, getServerlessSdk, getExampleConfig, resolveSrcConfig } from '../scripts/utils'; 2 | import { spawnSync } from 'child_process'; 3 | import axios from 'axios'; 4 | 5 | const appId = process.env.TENCENT_APP_ID as string; 6 | const credentials = { 7 | tencent: { 8 | SecretId: process.env.TENCENT_SECRET_ID, 9 | SecretKey: process.env.TENCENT_SECRET_KEY, 10 | }, 11 | }; 12 | 13 | const framework = 'express'; 14 | const { examplePath, yamlConfig } = getExampleConfig(framework); 15 | yamlConfig.name = `${framework}-integration-test-${generateId()}`; 16 | yamlConfig.org = appId; 17 | yamlConfig.component = `${framework}@dev`; 18 | 19 | const srcConfig = resolveSrcConfig(examplePath, yamlConfig.inputs.src!); 20 | 21 | if (srcConfig.hook) { 22 | const commandArr = srcConfig.hook.split(' '); 23 | spawnSync(commandArr[0], commandArr.slice(1), { cwd: examplePath }); 24 | delete srcConfig.hook; 25 | } 26 | 27 | const sdk = getServerlessSdk(yamlConfig.org!, appId); 28 | 29 | describe(framework, () => { 30 | it('deploy use template', async () => { 31 | delete yamlConfig.inputs.src; 32 | 33 | const instance = await sdk.deploy(yamlConfig, credentials); 34 | 35 | expect(instance).toBeDefined(); 36 | expect(instance.instanceName).toEqual(yamlConfig.name); 37 | expect(instance.outputs.templateUrl).toBeDefined(); 38 | expect(instance.outputs.region).toEqual('ap-guangzhou'); 39 | expect(instance.outputs.apigw).toBeDefined(); 40 | expect(instance.outputs.apigw.environment).toEqual('release'); 41 | expect(instance.outputs.scf).toBeDefined(); 42 | expect(instance.outputs.scf.runtime).toEqual('Nodejs10.15'); 43 | 44 | const response = await axios.get(instance.outputs.apigw.url); 45 | expect(response.data.includes('Serverless')).toBeTruthy(); 46 | }); 47 | 48 | it('update source code', async () => { 49 | yamlConfig.inputs.src = srcConfig; 50 | 51 | spawnSync('npm', ['install'], { cwd: examplePath }); 52 | 53 | const instance = await sdk.deploy(yamlConfig, credentials); 54 | const response = await axios.get(instance.outputs.apigw.url); 55 | 56 | expect(response.data.includes('Serverless')).toBeTruthy(); 57 | expect(instance.outputs.templateUrl).not.toBeDefined(); 58 | }); 59 | 60 | it('remove', async () => { 61 | await sdk.remove(yamlConfig, credentials); 62 | const result = await sdk.getInstance( 63 | yamlConfig.org, 64 | yamlConfig.stage, 65 | yamlConfig.app, 66 | yamlConfig.name, 67 | ); 68 | 69 | expect(result.instance.instanceStatus).toEqual('inactive'); 70 | }); 71 | }); 72 | -------------------------------------------------------------------------------- /__tests__/nextjs.test.ts: -------------------------------------------------------------------------------- 1 | import { generateId, getServerlessSdk, getExampleConfig, resolveSrcConfig } from '../scripts/utils'; 2 | import { spawnSync } from 'child_process'; 3 | import axios from 'axios'; 4 | 5 | const appId = process.env.TENCENT_APP_ID as string; 6 | const credentials = { 7 | tencent: { 8 | SecretId: process.env.TENCENT_SECRET_ID, 9 | SecretKey: process.env.TENCENT_SECRET_KEY, 10 | }, 11 | }; 12 | 13 | const framework = 'nextjs'; 14 | process.env.STATIC_URL = `https://${framework}-demo-1303241281.cos.ap-guangzhou.myqcloud.com`; 15 | const { examplePath, yamlConfig } = getExampleConfig(framework); 16 | yamlConfig.name = `${framework}-integration-test-${generateId()}`; 17 | yamlConfig.org = appId; 18 | yamlConfig.component = `${framework}@dev`; 19 | 20 | const srcConfig = resolveSrcConfig(examplePath, yamlConfig.inputs.src!); 21 | if (srcConfig.hook) { 22 | const commandArr = srcConfig.hook.split(' '); 23 | spawnSync(commandArr[0], commandArr.slice(1), { cwd: examplePath }); 24 | delete srcConfig.hook; 25 | } 26 | 27 | const sdk = getServerlessSdk(yamlConfig.org!, appId); 28 | 29 | describe(framework, () => { 30 | it('deploy use template', async () => { 31 | delete yamlConfig.inputs.src; 32 | 33 | const instance = await sdk.deploy(yamlConfig, credentials); 34 | 35 | expect(instance).toBeDefined(); 36 | expect(instance.instanceName).toEqual(yamlConfig.name); 37 | expect(instance.outputs.templateUrl).toBeDefined(); 38 | expect(instance.outputs.region).toEqual('ap-guangzhou'); 39 | expect(instance.outputs.apigw).toBeDefined(); 40 | expect(instance.outputs.apigw.environment).toEqual('release'); 41 | expect(instance.outputs.scf).toBeDefined(); 42 | expect(instance.outputs.scf.runtime).toEqual('Nodejs10.15'); 43 | 44 | const response = await axios.get(instance.outputs.apigw.url); 45 | expect(response.data.includes('Serverless')).toBeTruthy(); 46 | }); 47 | 48 | it('update source code', async () => { 49 | yamlConfig.inputs.src = srcConfig; 50 | 51 | spawnSync('npm', ['install'], { cwd: examplePath }); 52 | 53 | const instance = await sdk.deploy(yamlConfig, credentials); 54 | const response = await axios.get(instance.outputs.apigw.url); 55 | 56 | expect(response.data.includes('Serverless')).toBeTruthy(); 57 | expect(instance.outputs.templateUrl).not.toBeDefined(); 58 | }); 59 | 60 | it('remove', async () => { 61 | await sdk.remove(yamlConfig, credentials); 62 | const result = await sdk.getInstance( 63 | yamlConfig.org, 64 | yamlConfig.stage, 65 | yamlConfig.app, 66 | yamlConfig.name, 67 | ); 68 | 69 | expect(result.instance.instanceStatus).toEqual('inactive'); 70 | }); 71 | }); 72 | -------------------------------------------------------------------------------- /commitlint.config.js: -------------------------------------------------------------------------------- 1 | const Configuration = { 2 | /* 3 | * Resolve and load @commitlint/config-conventional from node_modules. 4 | * Referenced packages must be installed 5 | */ 6 | extends: ['@commitlint/config-conventional'], 7 | }; 8 | 9 | module.exports = Configuration; 10 | -------------------------------------------------------------------------------- /docs/README.md: -------------------------------------------------------------------------------- 1 | # 文档 2 | 3 | ## 目录 4 | 5 | - [使用说明](../README.md) 6 | - [配置参数](./configure.md) 7 | - [部署 outputs 参数](./output.md) 8 | - [高级配置](./advanced.md) 9 | - [文件上传](./upload/) 10 | - [express 上传](./upload/express.md) 11 | - [koa 上传](./upload/koa.md) 12 | - [nextjs 上传](./upload/nextjs.md) 13 | - [nuxtjs 上传](./upload/nuxtjs.md) 14 | - [组件开发](./develop.md) 15 | - [常见问题](./faq.md) 16 | -------------------------------------------------------------------------------- /docs/advanced.md: -------------------------------------------------------------------------------- 1 | ## 高级功能 2 | 3 | 以下功能针对 Node.js 框架服务 4 | 5 | ## 静态资源服务 6 | 7 | 如果想要支持返回静态资源,比如图片之类的,需要在入口文件 `sls.js` 中指定相关 `MIME` 类型的文件为二进制,这样云函数在返回请求结果给 API 网关是,会对指定类型进行 `Base64` 编码,最终返回给客户端才能正常显示。如下: 8 | 9 | ```js 10 | const express = require('express'); 11 | const app = express(); 12 | 13 | // Routes 14 | // ... 15 | 16 | app.binaryTypes = ['*/*']; 17 | 18 | module.exports = app; 19 | ``` 20 | 21 | `['*/*']` 代表所有文件类型将进行 `Base64` 编码,如果需要定制化,可以配置为 `['image/png']`,意思是指定 `png` 格式的图片类型。 22 | 23 | 更多文件类型的 `MIME` 类型,可参考 [mime-db](https://github.com/jshttp/mime-db/blob/master/db.json)。 24 | 25 | ## slsInitialize 应用初始化 26 | 27 | 有些时候,Nodejs 框架服务在启动前,需要进行一个初始化操作,比如数据库建连,就可以通过在 Web 实例对象上添加 `slsInitialize` 函数来实现, 28 | 29 | Express 框架入口文件示例如下: 30 | 31 | ```js 32 | const express = require('express'); 33 | const mysql = require('mysql2/promise'); 34 | 35 | const app = new express(); 36 | 37 | // ... 38 | app.slsInitialize = async () => { 39 | app.db = await mysql.createConnection({ 40 | host: 'localhost', 41 | user: 'root', 42 | database: 'test', 43 | }); 44 | }; 45 | 46 | module.exports = app; 47 | ``` 48 | 49 | 这样应用部署到云函数后,在函数服务逻辑执行前,会先执行 `slsInitialize()` 函数,来初始化数据库连接。 50 | -------------------------------------------------------------------------------- /docs/faq.md: -------------------------------------------------------------------------------- 1 | ## 常见问题 2 | 3 | 4 | -------------------------------------------------------------------------------- /docs/output.md: -------------------------------------------------------------------------------- 1 | # 部署 `output` 参数介绍 2 | 3 | > 组件输出可以在别的组件中通过 `${output:${stage}:${app}:.}` 获取 4 | > 5 | > 例如,如果该组件名称是 `test_name`, ·且只部署于一个地域,则可以通过 `${output:${stage}:${app}:test_name.apigw.url}` 在别的组件中获取该组件的 API 网关的 `url`。 6 | 7 | | 名称 | 类型 | 描述 | 8 | | :---------- | :-------------------------------: | :------------------------------- | 9 | | templateUrl | string | 未提供代码时的模板代码 url | 10 | | region | string | 地域信息(只有一个地域时才提供) | 11 | | scf | [FunctionOutput](#FunctionOutput) | 云函数输出信息 | 12 | | apigw | [ApigwOutput](#ApigwOutput) | API 网关输出信息 | 13 | | static | [StaticOutput](#StaticOutput) | 静态资源输出信息 | 14 | 15 | ## FunctionOutput 16 | 17 | 云函数输出 18 | 19 | | 名称 | 类型 | 描述 | 20 | | :------------------- | :------------: | :--------------------- | 21 | | functionName | string | 云函数名称 | 22 | | runtime | string | 云运行环境 | 23 | | namespace | string | 云函数名称空间 | 24 | | lastVersion | string | 云函数版本 | 25 | | traffic | `number (0~1)` | 将多少流量导向该云函数 | 26 | | configTrafficVersion | string | | 27 | 28 | ## ApigwOutput 29 | 30 | API 网关输出 31 | 32 | | 名称 | 类型 | 描述 | 33 | | :------------ | :-----------------------------: | :------------------------- | 34 | | serviceId | string | API 网关 ID | 35 | | subDomain | string | API 网关子域名 | 36 | | enviroment | `"release" | "prepub" | "test"` | API 网关 | 37 | | url | string | API 网关对外的完整 URL | 38 | | traffic | number (0~1) | 将多少流量导向该云函数 | 39 | | customDomains | [CustomDomain](#CustomDomain)[] | API 网关自定义域名输出列表 | 40 | 41 | ### CustomDomain 42 | 43 | API 网关自定义域名输出 44 | 45 | | 名称 | 类型 | 描述 | 46 | | :-------- | :----: | :------------------------------ | 47 | | url | string | 自定义域名访问链接 | 48 | | subDomain | string | 自定义域名 | 49 | | cname | string | 自定义域名需要配置的 cname 记录 | 50 | 51 | ## StaticOutput 52 | 53 | 静态资源输出 54 | 55 | | 名称 | 类型 | 描述 | 56 | | :--- | :---------: | :--------- | 57 | | cos | [Cos](#Cos) | 云函数名称 | 58 | | cdn | [Cdn](#Cdn) | 云运行环境 | 59 | 60 | ### Cos 61 | 62 | COS 配置输出 63 | 64 | | 名称 | 类型 | 描述 | 65 | | :-------- | :----: | :--------------- | 66 | | region | string | 地域 | 67 | | bucket | string | COS 桶名称 | 68 | | cosOrigin | string | COS 资源访问域名 | 69 | 70 | ### Cdn 71 | 72 | Cdn 配置输出 73 | 74 | | 名称 | 类型 | 描述 | 75 | | :----- | :----: | :----------- | 76 | | domain | string | CDN 域名 | 77 | | url | string | CDN 访问链接 | 78 | -------------------------------------------------------------------------------- /docs/upload/express.md: -------------------------------------------------------------------------------- 1 | ## 文件上传说明 2 | 3 | 项目中如果涉及到文件上传,需要依赖 API 网关提供的 [Base64 编码能力](https://cloud.tencent.com/document/product/628/51799),使用时只需要 `serverless.yml` 中配置 `isBase64Encoded` 为 `true`,如下: 4 | 5 | ```yaml 6 | app: appDemo 7 | stage: dev 8 | component: express 9 | name: expressDemo 10 | 11 | inputs: 12 | # 省略... 13 | apigatewayConf: 14 | isBase64Encoded: true 15 | # 省略... 16 | # 省略... 17 | ``` 18 | 19 | 当前 API 网关支持上传最大文件大小为 `2M`,如果文件过大,请修改为前端直传对象存储方案。 20 | 21 | ## Base64 示例 22 | 23 | 入口文件 `sls.js` 如下: 24 | 25 | ```js 26 | const multer = require('multer'); 27 | const express = require('express'); 28 | const path = require('path'); 29 | 30 | const app = express(); 31 | const isServerless = process.env.SERVERLESS; 32 | const upload = multer({ dest: isServerless ? '/tmp/upload' : './upload' }); 33 | 34 | // Routes 35 | app.post('/upload', upload.single('file'), (req, res) => { 36 | res.send({ 37 | success: true, 38 | data: req.file, 39 | }); 40 | }); 41 | // ... 42 | 43 | if (isServerless) { 44 | module.exports = app; 45 | } else { 46 | app.listen(3000, () => { 47 | console.log(`Server start on http://localhost:3000`); 48 | }); 49 | } 50 | ``` 51 | 52 | 实例代码实现了文件上传接口 `POST /upload`,如果要支持文件上传,需要安装 `multer` 包。 53 | 54 | 同时需要在 `serverless.yml` 的 `apigatewayConf` 中配置 `isBase64Encoded` 为 `true`。 55 | -------------------------------------------------------------------------------- /docs/upload/koa.md: -------------------------------------------------------------------------------- 1 | ## 文件上传说明 2 | 3 | 项目中如果涉及到文件上传,需要依赖 API 网关提供的 [Base64 编码能力](https://cloud.tencent.com/document/product/628/51799),使用时只需要 `serverless.yml` 中配置 `isBase64Encoded` 为 `true`,如下: 4 | 5 | ```yaml 6 | app: appDemo 7 | stage: dev 8 | component: koa 9 | name: koaDemo 10 | 11 | inputs: 12 | # 省略... 13 | apigatewayConf: 14 | isBase64Encoded: true 15 | # 省略... 16 | # 省略... 17 | ``` 18 | 19 | 当前 API 网关支持上传最大文件大小为 `2M`,如果文件过大,请修改为前端直传对象存储方案。 20 | 21 | ## Base64 示例 22 | 23 | 入口文件 `sls.js` 如下: 24 | 25 | ```js 26 | const Koa = require('koa'); 27 | const KoaRouter = require('@koa/router'); 28 | const multer = require('@koa/multer'); 29 | 30 | const isServerless = process.env.SERVERLESS; 31 | const app = new Koa(); 32 | const router = new KoaRouter(); 33 | const upload = multer({ dest: isServerless ? '/tmp/upload' : './upload' }); 34 | 35 | router.post('/upload', upload.single('file'), (ctx) => { 36 | ctx.body = { 37 | success: true, 38 | data: ctx.file, 39 | }; 40 | }); 41 | 42 | app.use(router.routes()).use(router.allowedMethods()); 43 | 44 | if (isServerless) { 45 | module.exports = app; 46 | } else { 47 | app.listen(3000, () => { 48 | console.log(`Server start on http://localhost:3000`); 49 | }); 50 | } 51 | ``` 52 | 53 | 示例代码实现了文件上传接口 `POST /upload`,如果要支持文件上传,需要安装 `@koajs/multer` 和 `multer` 包。 54 | 55 | 同时需要在 `serverless.yml` 的 `apigatewayConf` 中配置 `isBase64Encoded` 为 `true`。 56 | -------------------------------------------------------------------------------- /docs/upload/nextjs.md: -------------------------------------------------------------------------------- 1 | ## 文件上传说明 2 | 3 | 项目中如果涉及到文件上传,需要依赖 API 网关提供的 [Base64 编码能力](https://cloud.tencent.com/document/product/628/51799),使用时只需要 `serverless.yml` 中配置 `isBase64Encoded` 为 `true`,如下: 4 | 5 | ```yaml 6 | app: appDemo 7 | stage: dev 8 | component: nextjs 9 | name: nextjsDemo 10 | 11 | inputs: 12 | # 省略... 13 | apigatewayConf: 14 | isBase64Encoded: true 15 | # 省略... 16 | # 省略... 17 | ``` 18 | 19 | 当前 API 网关支持上传最大文件大小为 `2M`,如果文件过大,请修改为前端直传对象存储方案。 20 | 21 | ## Base64 示例 22 | 23 | 自定义服务为 Express: 24 | 25 | ```js 26 | const multer = require('multer'); 27 | const express = require('express'); 28 | const next = require('next'); 29 | 30 | const isServerless = process.env.SERVERLESS; 31 | 32 | async function createServer() { 33 | const upload = multer({ dest: isServerless ? '/tmp/upload' : './upload' }); 34 | 35 | const server = express(); 36 | const app = next({ dev: false }); 37 | const handle = app.getRequestHandler(); 38 | 39 | server.post('/upload', upload.single('file'), (req, res) => { 40 | res.send({ 41 | success: true, 42 | data: req.file, 43 | }); 44 | }); 45 | 46 | server.all('*', (req, res, next) => { 47 | return handle(req, res); 48 | }); 49 | 50 | // define binary type for response 51 | // if includes, will return base64 encoded, very useful for images 52 | server.binaryTypes = ['*/*']; 53 | 54 | return server; 55 | } 56 | 57 | module.exports = createServer; 58 | 59 | if (isServerless) { 60 | module.exports = createServer; 61 | } else { 62 | createServer().then((server) => { 63 | server.listen(3000, () => { 64 | console.log(`Server start on http://localhost:3000`); 65 | }); 66 | }); 67 | } 68 | ``` 69 | 70 | 自定义服务为 Koa: 71 | 72 | ```js 73 | const Koa = require('koa'); 74 | const Router = require('@koa/router'); 75 | const multer = require('@koa/multer'); 76 | const next = require('next'); 77 | 78 | const isServerless = process.env.SERVERLESS; 79 | 80 | async function createServer() { 81 | const server = new Koa(); 82 | const router = new Router(); 83 | const upload = multer({ dest: isServerless ? '/tmp/upload' : './upload' }); 84 | const app = next({ dev: false }); 85 | const handle = app.getRequestHandler(); 86 | 87 | router.post('/upload', upload.single('file'), (ctx) => { 88 | ctx.body = { 89 | success: true, 90 | data: ctx.file, 91 | }; 92 | }); 93 | 94 | server.use(router.routes()).use(router.allowedMethods()); 95 | 96 | server.use((ctx) => { 97 | ctx.status = 200; 98 | ctx.respond = false; 99 | ctx.req.ctx = ctx; 100 | 101 | return handle(ctx.req, ctx.res); 102 | }); 103 | 104 | // define binary type for response 105 | // if includes, will return base64 encoded, very useful for images 106 | server.binaryTypes = ['*/*']; 107 | 108 | return server; 109 | } 110 | 111 | if (process.env.SERVERLESS) { 112 | module.exports = createServer; 113 | } else { 114 | createServer().then((server) => { 115 | server.listen(3000, () => { 116 | console.log(`Server start on http://localhost:3000`); 117 | }); 118 | }); 119 | } 120 | ``` 121 | 122 | 开发者可根据个人项目需要参考修改,使用时需要将使用的自定服务的示例复制为 `sls.js` 文件。 123 | 124 | 上述代码中实现了文件上传接口 `POST /upload`。使用 Koa 的项目,如果要支持文件上传,需要安装 `@koajs/multer` 和 `multer` 包。使用 Express 的项目,如果要支持文件上传,需要安装 `multer` 包。 125 | 126 | 同时需要在 `serverless.yml` 的 `apigatewayConf` 中配置 `isBase64Encoded` 为 `true`。 127 | -------------------------------------------------------------------------------- /docs/upload/nuxtjs.md: -------------------------------------------------------------------------------- 1 | ## 文件上传说明 2 | 3 | 项目中如果涉及到文件上传,需要依赖 API 网关提供的 [Base64 编码能力](https://cloud.tencent.com/document/product/628/51799),使用时只需要 `serverless.yml` 中配置 `isBase64Encoded` 为 `true`,如下: 4 | 5 | ```yaml 6 | app: appDemo 7 | stage: dev 8 | component: nuxtjs 9 | name: nuxtjsDemo 10 | 11 | inputs: 12 | # 省略... 13 | apigatewayConf: 14 | isBase64Encoded: true 15 | # 省略... 16 | # 省略... 17 | ``` 18 | 19 | 当前 API 网关支持上传最大文件大小为 `2M`,如果文件过大,请修改为前端直传对象存储方案。 20 | 21 | ## Base64 示例 22 | 23 | 自定义服务为 Express: 24 | 25 | ```js 26 | const multer = require('multer'); 27 | const express = require('express'); 28 | const { loadNuxt } = require('nuxt'); 29 | 30 | const isServerless = process.env.SERVERLESS; 31 | 32 | async function createServer() { 33 | const upload = multer({ dest: isServerless ? '/tmp/upload' : './upload' }); 34 | 35 | const server = express(); 36 | const nuxt = await loadNuxt('start'); 37 | 38 | server.post('/upload', upload.single('file'), (req, res) => { 39 | res.send({ 40 | success: true, 41 | data: req.file, 42 | }); 43 | }); 44 | 45 | server.all('*', (req, res, next) => { 46 | return nuxt.render(req, res, next); 47 | }); 48 | 49 | // define binary type for response 50 | // if includes, will return base64 encoded, very useful for images 51 | server.binaryTypes = ['*/*']; 52 | 53 | return server; 54 | } 55 | 56 | module.exports = createServer; 57 | 58 | if (isServerless) { 59 | module.exports = createServer; 60 | } else { 61 | createServer().then((server) => { 62 | server.listen(3000, () => { 63 | console.log(`Server start on http://localhost:3000`); 64 | }); 65 | }); 66 | } 67 | ``` 68 | 69 | 自定义服务为 Koa: 70 | 71 | ```js 72 | const Koa = require('koa'); 73 | const Router = require('@koa/router'); 74 | const multer = require('@koa/multer'); 75 | 76 | const { loadNuxt } = require('nuxt'); 77 | 78 | const isServerless = process.env.SERVERLESS; 79 | 80 | async function createServer() { 81 | const server = new Koa(); 82 | const router = new Router(); 83 | const upload = multer({ dest: isServerless ? '/tmp/upload' : './upload' }); 84 | const nuxt = await loadNuxt('start'); 85 | 86 | router.post('/upload', upload.single('file'), (ctx) => { 87 | ctx.body = { 88 | success: true, 89 | data: ctx.file, 90 | }; 91 | }); 92 | 93 | server.use(router.routes()).use(router.allowedMethods()); 94 | 95 | server.use((ctx) => { 96 | ctx.status = 200; 97 | ctx.respond = false; 98 | ctx.req.ctx = ctx; 99 | 100 | nuxt.render(ctx.req, ctx.res); 101 | }); 102 | 103 | // define binary type for response 104 | // if includes, will return base64 encoded, very useful for images 105 | server.binaryTypes = ['*/*']; 106 | 107 | return server; 108 | } 109 | 110 | if (process.env.SERVERLESS) { 111 | module.exports = createServer; 112 | } else { 113 | createServer().then((server) => { 114 | server.listen(3000, () => { 115 | console.log(`Server start on http://localhost:3000`); 116 | }); 117 | }); 118 | } 119 | ``` 120 | 121 | 开发者可根据个人项目需要参考修改,使用时需要将使用的自定服务的示例复制为 `sls.js` 文件。 122 | 123 | 上述代码中实现了文件上传接口 `POST /upload`。使用 Koa 的项目,如果要支持文件上传,需要安装 `@koajs/multer` 和 `multer` 包。使用 Express 的项目,如果要支持文件上传,需要安装 `multer` 包。 124 | 125 | 同时需要在 `serverless.yml` 的 `apigatewayConf` 中配置 `isBase64Encoded` 为 `true`。 126 | -------------------------------------------------------------------------------- /examples/django/.gitignore: -------------------------------------------------------------------------------- 1 | requirements 2 | asgiref 3 | asgiref-3.3.1.dist-info 4 | bin 5 | django 6 | Django-3.1.3.dist-info 7 | pytz 8 | pytz-2020.4.dist-info 9 | pytz-2021.1.dist-info 10 | sqlparse 11 | sqlparse-0.4.1.dist-info 12 | -------------------------------------------------------------------------------- /examples/django/djangodemo/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/serverless-components/tencent-framework-components/97c001520604ea54a3ee8e78c177dc421942dc8c/examples/django/djangodemo/__init__.py -------------------------------------------------------------------------------- /examples/django/djangodemo/asgi.py: -------------------------------------------------------------------------------- 1 | """ 2 | ASGI config for djangodemo project. 3 | 4 | It exposes the ASGI callable as a module-level variable named ``application``. 5 | 6 | For more information on this file, see 7 | https://docs.djangoproject.com/en/3.1/howto/deployment/asgi/ 8 | """ 9 | 10 | import os 11 | 12 | from django.core.asgi import get_asgi_application 13 | 14 | os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'djangodemo.settings') 15 | 16 | application = get_asgi_application() 17 | -------------------------------------------------------------------------------- /examples/django/djangodemo/urls.py: -------------------------------------------------------------------------------- 1 | """djangodemo URL Configuration 2 | 3 | The `urlpatterns` list routes URLs to views. For more information please see: 4 | https://docs.djangoproject.com/en/3.1/topics/http/urls/ 5 | Examples: 6 | Function views 7 | 1. Add an import: from my_app import views 8 | 2. Add a URL to urlpatterns: path('', views.home, name='home') 9 | Class-based views 10 | 1. Add an import: from other_app.views import Home 11 | 2. Add a URL to urlpatterns: path('', Home.as_view(), name='home') 12 | Including another URLconf 13 | 1. Import the include() function: from django.urls import include, path 14 | 2. Add a URL to urlpatterns: path('blog/', include('blog.urls')) 15 | """ 16 | from django.contrib import admin 17 | from django.urls import path 18 | from djangodemo.views import index, author, event 19 | 20 | 21 | urlpatterns = [ 22 | path('', index), 23 | path('author/', author), 24 | path('event/', event), 25 | path('admin/', admin.site.urls), 26 | ] 27 | -------------------------------------------------------------------------------- /examples/django/djangodemo/views.py: -------------------------------------------------------------------------------- 1 | import os 2 | import json 3 | from django.shortcuts import render 4 | from django.http import HttpResponse 5 | 6 | # Create your views here. 7 | 8 | def index(request): 9 | return render(request, 'index.html', context={'hello': 'world'}) 10 | 11 | def author(request): 12 | return HttpResponse("Tencent Cloud Serverless Team") 13 | 14 | # 获取函数 event 15 | def event(request): 16 | event = os.environ.get("__SLS_EVENT__") 17 | event = json.loads(event) 18 | msg = { 19 | "globalEvent": event, 20 | "requestEvent": request.environ.get("event") 21 | } 22 | return HttpResponse(json.dumps(msg), content_type="application/json") 23 | -------------------------------------------------------------------------------- /examples/django/djangodemo/wsgi.py: -------------------------------------------------------------------------------- 1 | """ 2 | WSGI config for djangodemo project. 3 | 4 | It exposes the WSGI callable as a module-level variable named ``application``. 5 | 6 | For more information on this file, see 7 | https://docs.djangoproject.com/en/3.1/howto/deployment/wsgi/ 8 | """ 9 | 10 | import os 11 | 12 | from django.core.wsgi import get_wsgi_application 13 | 14 | os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'djangodemo.settings') 15 | 16 | application = get_wsgi_application() 17 | -------------------------------------------------------------------------------- /examples/django/manage.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | """Django's command-line utility for administrative tasks.""" 3 | import os 4 | import sys 5 | 6 | 7 | def main(): 8 | """Run administrative tasks.""" 9 | os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'djangodemo.settings') 10 | try: 11 | from django.core.management import execute_from_command_line 12 | except ImportError as exc: 13 | raise ImportError( 14 | "Couldn't import Django. Are you sure it's installed and " 15 | "available on your PYTHONPATH environment variable? Did you " 16 | "forget to activate a virtual environment?" 17 | ) from exc 18 | execute_from_command_line(sys.argv) 19 | 20 | 21 | if __name__ == '__main__': 22 | main() 23 | -------------------------------------------------------------------------------- /examples/django/requirements.txt: -------------------------------------------------------------------------------- 1 | Django==3.1.3 2 | -------------------------------------------------------------------------------- /examples/django/serverless.yml: -------------------------------------------------------------------------------- 1 | app: appDemo 2 | stage: dev 3 | component: django 4 | name: djangoDemo 5 | inputs: 6 | src: 7 | hook: pip3 install -r requirements.txt -t ./ 8 | dist: ./ 9 | exclude: 10 | - .env 11 | - __pycache__/** 12 | region: ap-guangzhou 13 | functionConf: 14 | projectName: djangodemo 15 | name: ${name} 16 | runtime: Python3.6 17 | apigatewayConf: 18 | protocols: 19 | - http 20 | - https 21 | environment: release 22 | -------------------------------------------------------------------------------- /examples/django/templates/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | Serverless - Django 9 | 16 | 17 | 18 |

19 | 欢迎访问 Django 应用 20 |
21 | 22 | 腾讯云 Serverless 23 | 24 | 为您提供服务 25 |

26 | 27 | 28 | -------------------------------------------------------------------------------- /examples/egg/.gitignore: -------------------------------------------------------------------------------- 1 | logs/ 2 | npm-debug.log 3 | yarn-error.log 4 | node_modules/ 5 | package-lock.json 6 | yarn.lock 7 | coverage/ 8 | .idea/ 9 | run/ 10 | .DS_Store 11 | *.sw* 12 | *.un~ 13 | typings/ 14 | .nyc_output/ 15 | -------------------------------------------------------------------------------- /examples/egg/app/controller/home.js: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | 3 | const Controller = require('egg').Controller 4 | 5 | class HomeController extends Controller { 6 | async index() { 7 | const { ctx } = this 8 | 9 | ctx.set('content-type', 'text/html') 10 | await ctx.render('index.html', { 11 | msg: 'hi, egg' 12 | }) 13 | } 14 | 15 | async event() { 16 | const { ctx } = this 17 | ctx.body = { 18 | req: ctx.req.__SLS_EVENT__, 19 | request: ctx.request.__SLS_EVENT__ 20 | } 21 | } 22 | 23 | async getConfig() { 24 | const { ctx } = this 25 | ctx.body = this.config 26 | } 27 | } 28 | 29 | module.exports = HomeController 30 | -------------------------------------------------------------------------------- /examples/egg/app/controller/user.js: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | 3 | const { Controller } = require('egg') 4 | const { sleep } = require('../utils/index') 5 | 6 | class UserController extends Controller { 7 | async list() { 8 | const { ctx } = this 9 | await sleep(Math.random()) 10 | ctx.body = [ 11 | { 12 | id: 1, 13 | name: 'yugasun', 14 | email: 'yuga_sun@163.com' 15 | } 16 | ] 17 | } 18 | } 19 | 20 | module.exports = UserController 21 | -------------------------------------------------------------------------------- /examples/egg/app/public/styles/index.css: -------------------------------------------------------------------------------- 1 | html { 2 | font-family: sans-serif; 3 | /* 1 */ 4 | -ms-text-size-adjust: 100%; 5 | /* 2 */ 6 | -webkit-text-size-adjust: 100%; 7 | /* 2 */ 8 | } 9 | /** 10 | * Remove the margin in all browsers (opinionated). 11 | */ 12 | body { 13 | margin: 0; 14 | } 15 | 16 | .link { 17 | text-decoration: none; 18 | margin-top: 10px; 19 | font-size: 30px; 20 | color: #6e717c; 21 | } 22 | 23 | .link:hover { 24 | color: #148a1a; 25 | } 26 | 27 | .banner { 28 | text-align: center; 29 | padding: 100px 0; 30 | max-width: 1136px; 31 | margin: 44px auto 100px; 32 | } 33 | .banner h1 { 34 | font-size: 46px; 35 | font-weight: 200; 36 | letter-spacing: 1.5px; 37 | margin-bottom: 10px; 38 | } 39 | .banner .banner-info { 40 | width: 60%; 41 | } 42 | .banner .banner-info h1 { 43 | text-align: left; 44 | } 45 | .banner .banner-info p { 46 | text-align: left; 47 | } 48 | .banner .banner-logo { 49 | float: right; 50 | padding-right: 13%; 51 | margin-top: -60px; 52 | } 53 | .banner .banner-logo img { 54 | width: 120%; 55 | } 56 | .banner .banner-button { 57 | padding-top: 50px; 58 | } 59 | .banner .banner-promo-link { 60 | padding: 40px 0 0; 61 | } 62 | .banner .banner-promo-link img { 63 | display: inline-block; 64 | vertical-align: middle; 65 | margin-right: 5px; 66 | } 67 | .banner .banner-promo-link a { 68 | color: #6e717c; 69 | display: inline-block; 70 | font-size: 16px; 71 | } 72 | .banner .banner-promo-link a:hover { 73 | color: #148a1a; 74 | } 75 | -------------------------------------------------------------------------------- /examples/egg/app/router.js: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | 3 | /** 4 | * @param {Egg.Application} app - egg application 5 | */ 6 | module.exports = (app) => { 7 | const { 8 | router, 9 | controller, 10 | config: { apiPrefix } 11 | } = app 12 | router.get('/', controller.home.index) 13 | router.get('/event', controller.home.event) 14 | 15 | router.get('/user', controller.user.list) 16 | } 17 | -------------------------------------------------------------------------------- /examples/egg/app/utils/constants.js: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | 3 | module.exports = { 4 | ONE_SECOND: 1000 5 | } 6 | -------------------------------------------------------------------------------- /examples/egg/app/utils/index.js: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | 3 | const { ONE_SECOND } = require('./constants') 4 | 5 | async function sleep(seconds) { 6 | setTimeout(() => { 7 | Promise.resolve(true) 8 | }, seconds * ONE_SECOND) 9 | } 10 | 11 | module.exports = { 12 | sleep 13 | } 14 | -------------------------------------------------------------------------------- /examples/egg/app/view/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | Serverless - Egg.js 9 | 16 | 17 | 18 |

19 | 欢迎访问 Egg.js 应用 20 |
21 |
22 | 23 | 腾讯云 Serverless 24 | 25 | 为您提供服务 26 |

27 | 28 | 29 | -------------------------------------------------------------------------------- /examples/egg/appveyor.yml: -------------------------------------------------------------------------------- 1 | environment: 2 | matrix: 3 | - nodejs_version: '10' 4 | 5 | install: 6 | - ps: Install-Product node $env:nodejs_version 7 | - npm i npminstall && node_modules\.bin\npminstall 8 | 9 | test_script: 10 | - node --version 11 | - npm --version 12 | - npm run test 13 | 14 | build: off 15 | -------------------------------------------------------------------------------- /examples/egg/config/config.default.js: -------------------------------------------------------------------------------- 1 | /* eslint valid-jsdoc: "off" */ 2 | 3 | 'use strict' 4 | 5 | /** 6 | * @param {Egg.EggAppInfo} appInfo app info 7 | */ 8 | module.exports = (appInfo) => { 9 | /** 10 | * built-in config 11 | * @type {Egg.EggAppConfig} 12 | **/ 13 | const config = {} 14 | 15 | // use for cookie sign key, should change to your own and keep security 16 | config.keys = appInfo.name + '_1576384476895_3620' 17 | 18 | // add your middleware config here 19 | config.middleware = [] 20 | 21 | // add your user config here 22 | const userConfig = { 23 | view: { 24 | mapping: { 25 | '.html': 'nunjucks' 26 | } 27 | } 28 | } 29 | 30 | return { 31 | ...config, 32 | ...userConfig 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /examples/egg/config/plugin.js: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | 3 | /** @type Egg.EggPlugin */ 4 | module.exports = { 5 | // had enabled by egg 6 | static: { 7 | enable: true 8 | }, 9 | nunjucks: { 10 | enable: true, 11 | package: 'egg-view-nunjucks' 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /examples/egg/jsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "include": ["**/*"] 3 | } 4 | -------------------------------------------------------------------------------- /examples/egg/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "egg-example", 3 | "version": "1.0.0", 4 | "description": "demo", 5 | "private": true, 6 | "egg": { 7 | "declarations": true 8 | }, 9 | "dependencies": { 10 | "egg": "^2.29.1", 11 | "egg-view-nunjucks": "^2.2.0" 12 | }, 13 | "engines": { 14 | "node": ">=10.0.0" 15 | }, 16 | "scripts": { 17 | "lint": "eslint .", 18 | "ci": "npm run lint && npm run cov" 19 | }, 20 | "ci": { 21 | "version": "10" 22 | }, 23 | "repository": { 24 | "type": "git", 25 | "url": "" 26 | }, 27 | "author": "yugasun", 28 | "license": "MIT" 29 | } 30 | -------------------------------------------------------------------------------- /examples/egg/serverless.yml: -------------------------------------------------------------------------------- 1 | app: appDemo 2 | stage: dev 3 | component: egg 4 | name: eggDemo 5 | inputs: 6 | src: 7 | src: ./ 8 | exclude: 9 | - .env 10 | functionConf: 11 | name: ${name} 12 | apigatewayConf: 13 | protocols: 14 | - http 15 | - https 16 | -------------------------------------------------------------------------------- /examples/egg/sls.js: -------------------------------------------------------------------------------- 1 | const { Application } = require('egg') 2 | 3 | Object.defineProperty(Application.prototype, Symbol.for('egg#eggPath'), { 4 | value: '/opt' 5 | }) 6 | 7 | const app = new Application({ 8 | mode: 'single', 9 | env: 'prod' 10 | }) 11 | 12 | app.binaryTypes = ['*/*'] 13 | 14 | module.exports = app 15 | -------------------------------------------------------------------------------- /examples/express/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | Serverless - Express.js 9 | 16 | 17 | 18 |

19 | 欢迎访问 Express.js 应用 20 |
21 | 22 | 腾讯云 Serverless 23 | 24 | 为您提供服务 25 |

26 | 27 | 28 | -------------------------------------------------------------------------------- /examples/express/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/serverless-components/tencent-framework-components/97c001520604ea54a3ee8e78c177dc421942dc8c/examples/express/logo.png -------------------------------------------------------------------------------- /examples/express/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "express-demo", 3 | "version": "1.0.0", 4 | "description": "", 5 | "main": "sls.js", 6 | "scripts": { 7 | "test": "echo \"Error: no test specified\" && exit 1" 8 | }, 9 | "author": "yugasun", 10 | "license": "MIT", 11 | "dependencies": { 12 | "express": "^4.17.1" 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /examples/express/serverless.yml: -------------------------------------------------------------------------------- 1 | app: appDemo 2 | stage: dev 3 | component: express 4 | name: expressDemo 5 | inputs: 6 | src: 7 | src: ./ 8 | exclude: 9 | - .env 10 | functionConf: 11 | name: ${name} 12 | apigatewayConf: 13 | protocols: 14 | - http 15 | - https 16 | -------------------------------------------------------------------------------- /examples/express/sls.js: -------------------------------------------------------------------------------- 1 | const express = require('express') 2 | const path = require('path') 3 | const fs = require('fs') 4 | const app = express() 5 | 6 | // Routes 7 | app.get(`/`, (req, res) => { 8 | res.sendFile(path.join(__dirname, 'index.html')) 9 | }) 10 | 11 | // 获取 event 12 | app.get(`/event`, (req, res) => { 13 | const event = req.__SLS_EVENT__ 14 | res.send(event) 15 | }) 16 | 17 | app.get(`/logo`, (req, res) => { 18 | const logo = path.join(__dirname, 'logo.png') 19 | const content = fs.readFileSync(logo, { 20 | encoding: 'base64' 21 | }); 22 | res.set('Content-Type', 'image/png') 23 | res.send(Buffer.from(content, 'base64')) 24 | res.status(200).end(); 25 | }) 26 | 27 | app.get('/user', (req, res) => { 28 | res.send([ 29 | { 30 | title: 'serverless framework', 31 | link: 'https://serverless.com' 32 | } 33 | ]) 34 | }) 35 | 36 | app.get('/user/:id', (req, res) => { 37 | const id = req.params.id 38 | res.send({ 39 | id: id, 40 | title: 'serverless framework', 41 | link: 'https://serverless.com' 42 | }) 43 | }) 44 | 45 | app.get('/404', (req, res) => { 46 | res.status(404).send('Not found') 47 | }) 48 | 49 | app.get('/500', (req, res) => { 50 | res.status(500).send('Server Error') 51 | }) 52 | 53 | // Error handler 54 | app.use(function(err, req, res, next) { 55 | console.error(err) 56 | res.status(500).send('Internal Serverless Error') 57 | }) 58 | 59 | // 指定特定的 mime 类型返回,会经过 Base64 编码,以便通过 API 网关正常返回给客户端 60 | app.binaryTypes = ['image/png'] 61 | 62 | if (process.env.SERVERLESS) { 63 | module.exports = app 64 | } else { 65 | app.listen(3000, () => { 66 | console.log(`Server start on http://localhost:3000`); 67 | }) 68 | } 69 | 70 | -------------------------------------------------------------------------------- /examples/flask/.gitignore: -------------------------------------------------------------------------------- 1 | requirements 2 | bin 3 | click* 4 | flask 5 | Flask-* 6 | itsdangerous 7 | itsdangerous-* 8 | jinja2 9 | Jinja2-* 10 | markupsafe 11 | Markupsafe-* 12 | werkzeug 13 | Werkzeug-* 14 | 15 | /uploads 16 | -------------------------------------------------------------------------------- /examples/flask/__test__/sl_handler.py: -------------------------------------------------------------------------------- 1 | import sys 2 | sys.path.append("..") 3 | 4 | import app # Replace with your actual application 5 | import serverless_wsgi 6 | 7 | # If you need to send additional content types as text, add then directly 8 | # to the whitelist: 9 | # 10 | # serverless_wsgi.TEXT_MIME_TYPES.append("application/custom+json") 11 | 12 | def handler(event, context): 13 | return serverless_wsgi.handle_request(app.app, event, context) 14 | -------------------------------------------------------------------------------- /examples/flask/__test__/sl_test.py: -------------------------------------------------------------------------------- 1 | import sl_handler 2 | 3 | event = { 4 | "requestContext": { 5 | "serviceId": "service-abcdefg", 6 | "path": "/", 7 | "httpMethod": "GET", 8 | "requestId": "c6af9ac6-7b61-11e6-9a41-93e8deadbeef", 9 | "sourceIp": "10.0.2.14", 10 | "stage": "release" 11 | }, 12 | "headers": { 13 | "accept-Language": "en-US,en,cn", 14 | "accept": "text/html,application/xml,application/json", 15 | "host": "localhost", 16 | "user-Agent": "User Agent String" 17 | }, 18 | "body": "{}", 19 | "pathParameters": { 20 | "path": "value" 21 | }, 22 | "queryStringParameters": { 23 | "foo": "bar" 24 | }, 25 | "headerParameters":{ 26 | "Refer": "127.0.0.1" 27 | }, 28 | "stageVariables": { 29 | "stage": "release" 30 | }, 31 | "path": "/", 32 | "queryString": { 33 | "foo" : "bar", 34 | "bob" : "alice" 35 | }, 36 | "httpMethod": "GET" 37 | } 38 | 39 | res = sl_handler.handler(event, {}); 40 | 41 | print(res) 42 | -------------------------------------------------------------------------------- /examples/flask/app.py: -------------------------------------------------------------------------------- 1 | import os 2 | import json 3 | from flask import Flask, jsonify, render_template, request, url_for, send_from_directory 4 | from werkzeug.utils import secure_filename 5 | 6 | IS_SERVERLESS = bool(os.environ.get('SERVERLESS')) 7 | 8 | app = Flask(__name__) 9 | 10 | def initUploadDir(): 11 | UPLOAD_DIR = '/tmp/uploads' if IS_SERVERLESS else os.getcwd() + '/uploads' 12 | if not os.path.exists(UPLOAD_DIR): 13 | os.makedirs(UPLOAD_DIR) 14 | app.config['UPLOAD_DIR'] = UPLOAD_DIR 15 | 16 | initUploadDir() 17 | 18 | @app.route("/") 19 | def index(): 20 | return render_template('index.html') 21 | 22 | # 获取函数 event 23 | @app.route("/event") 24 | def event(): 25 | event = os.environ.get("__SLS_EVENT__") 26 | event = json.loads(event) 27 | msg = { 28 | "globalEvent": event, 29 | "requestEvent": request.environ.get("event") 30 | } 31 | return jsonify(data=msg) 32 | 33 | @app.route("/users", methods=['GET', 'POST']) 34 | def users(): 35 | if request.method == 'POST': 36 | print(request.form) 37 | id = request.form.get('id'); 38 | user = {'id': id, 'name': 'test1'} 39 | return jsonify(data=user) 40 | else: 41 | limit = request.args.get('limit') 42 | data = { 43 | 'count': limit or 2, 44 | 'users': [{'name': 'test1'}, {'name': 'test2'}] 45 | } 46 | return jsonify(data=data) 47 | 48 | @app.route("/users/") 49 | def getUser(id): 50 | return jsonify(data={'name': 'test1'}) 51 | 52 | # 上传文件示例 53 | @app.route('/upload',methods=['POST']) 54 | def upload(): 55 | if request.method == 'POST': 56 | if 'avatar' not in request.files: 57 | res = {"error": "No avatar file upload"} 58 | return jsonify(data=res) 59 | avatar = request.files['avatar'] 60 | 61 | if avatar.filename == '': 62 | res = {"error": "No avatar file selected"} 63 | return jsonify(data=res) 64 | 65 | if avatar: 66 | filename = secure_filename(avatar.filename); 67 | filePath = os.path.join(app.config['UPLOAD_DIR'], filename) 68 | avatar.save(filePath) 69 | uploadUrl = url_for('uploaded_file', filename=filename) 70 | res = {'upload': uploadUrl} 71 | return jsonify(data=res) 72 | 73 | @app.route('/uploads/') 74 | def uploaded_file(filename): 75 | return send_from_directory(app.config['UPLOAD_DIR'], filename) 76 | 77 | if IS_SERVERLESS != True: 78 | # run app in debug mode on port 5000 79 | app.run(debug=True, port=5000) 80 | -------------------------------------------------------------------------------- /examples/flask/requirements.txt: -------------------------------------------------------------------------------- 1 | Flask==1.0.2 2 | werkzeug==0.16.0 3 | -------------------------------------------------------------------------------- /examples/flask/serverless.yml: -------------------------------------------------------------------------------- 1 | app: appDemo 2 | stage: dev 3 | component: flask 4 | name: flaskDemo 5 | inputs: 6 | src: 7 | hook: pip3 install -r requirements.txt -t ./ 8 | dist: ./ 9 | exclude: 10 | - .env 11 | - __pycache__/** 12 | region: ap-guangzhou 13 | functionConf: 14 | name: ${name} 15 | runtime: Python3.6 16 | apigatewayConf: 17 | protocols: 18 | - http 19 | - https 20 | environment: release 21 | -------------------------------------------------------------------------------- /examples/flask/templates/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | Serverless - Flask 9 | 16 | 17 | 18 |

19 | 欢迎访问 Flask 应用 20 |
21 | 22 | 腾讯云 Serverless 23 | 24 | 为您提供服务 25 |

26 | 27 | 28 | -------------------------------------------------------------------------------- /examples/koa/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | Serverless - Koa.js 9 | 16 | 17 | 18 |

19 | 欢迎访问 Koa.js 应用 20 |
21 | 22 | 腾讯云 Serverless 23 | 24 | 为您提供服务 25 |

26 | 27 | 28 | -------------------------------------------------------------------------------- /examples/koa/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "koa-demo", 3 | "version": "1.0.0", 4 | "description": "", 5 | "main": "sls.js", 6 | "scripts": { 7 | "test": "echo \"Error: no test specified\" && exit 1" 8 | }, 9 | "author": "yugasun", 10 | "license": "MIT", 11 | "dependencies": { 12 | "koa": "^2.11.0", 13 | "koa-router": "^8.0.8", 14 | "koa-sendfile": "^2.0.1" 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /examples/koa/serverless.yml: -------------------------------------------------------------------------------- 1 | app: appDemo 2 | stage: dev 3 | component: koa 4 | name: koaDemo 5 | inputs: 6 | src: 7 | src: ./ 8 | exclude: 9 | - .env 10 | functionConf: 11 | name: ${name} 12 | environment: # 环境变量 13 | variables: # 环境变量数组 14 | TEST: vale 15 | ENV: TEST 16 | ENV2: TEST2 17 | apigatewayConf: 18 | protocols: 19 | - http 20 | - https 21 | -------------------------------------------------------------------------------- /examples/koa/sls.js: -------------------------------------------------------------------------------- 1 | const Koa = require('koa') 2 | const KoaRouter = require('koa-router') 3 | const sendFile = require('koa-sendfile') 4 | const path = require('path') 5 | 6 | const app = new Koa() 7 | const router = new KoaRouter() 8 | 9 | // Routes 10 | router.get(`/`, async (ctx) => { 11 | await sendFile(ctx, path.join(__dirname, 'index.html')) 12 | }) 13 | 14 | router.get('/event', async (ctx) => { 15 | const event = ctx.request.__SLS_EVENT__; 16 | ctx.body = event 17 | }) 18 | 19 | app.use(router.allowedMethods()).use(router.routes()) 20 | 21 | // don't forget to export! 22 | module.exports = app 23 | -------------------------------------------------------------------------------- /examples/laravel/.editorconfig: -------------------------------------------------------------------------------- 1 | root = true 2 | 3 | [*] 4 | charset = utf-8 5 | end_of_line = lf 6 | insert_final_newline = true 7 | indent_style = space 8 | indent_size = 4 9 | trim_trailing_whitespace = true 10 | 11 | [*.md] 12 | trim_trailing_whitespace = false 13 | 14 | [*.{yml,yaml}] 15 | indent_size = 2 16 | -------------------------------------------------------------------------------- /examples/laravel/.env.example: -------------------------------------------------------------------------------- 1 | APP_NAME=Laravel 2 | APP_ENV=local 3 | APP_KEY= 4 | APP_DEBUG=true 5 | APP_URL=http://localhost 6 | 7 | LOG_CHANNEL=stack 8 | 9 | DB_CONNECTION=mysql 10 | DB_HOST=127.0.0.1 11 | DB_PORT=3306 12 | DB_DATABASE=laravel 13 | DB_USERNAME=root 14 | DB_PASSWORD= 15 | 16 | BROADCAST_DRIVER=log 17 | CACHE_DRIVER=file 18 | QUEUE_CONNECTION=sync 19 | SESSION_DRIVER=file 20 | SESSION_LIFETIME=120 21 | 22 | REDIS_HOST=127.0.0.1 23 | REDIS_PASSWORD=null 24 | REDIS_PORT=6379 25 | 26 | MAIL_MAILER=smtp 27 | MAIL_HOST=smtp.mailtrap.io 28 | MAIL_PORT=2525 29 | MAIL_USERNAME=null 30 | MAIL_PASSWORD=null 31 | MAIL_ENCRYPTION=null 32 | MAIL_FROM_ADDRESS=null 33 | MAIL_FROM_NAME="${APP_NAME}" 34 | 35 | AWS_ACCESS_KEY_ID= 36 | AWS_SECRET_ACCESS_KEY= 37 | AWS_DEFAULT_REGION=us-east-1 38 | AWS_BUCKET= 39 | 40 | PUSHER_APP_ID= 41 | PUSHER_APP_KEY= 42 | PUSHER_APP_SECRET= 43 | PUSHER_APP_CLUSTER=mt1 44 | 45 | MIX_PUSHER_APP_KEY="${PUSHER_APP_KEY}" 46 | MIX_PUSHER_APP_CLUSTER="${PUSHER_APP_CLUSTER}" 47 | 48 | # tencent crendential 49 | TENCENT_SECRET_ID=xxx 50 | TENCENT_SECRET_KEY=xxx 51 | -------------------------------------------------------------------------------- /examples/laravel/.env.production: -------------------------------------------------------------------------------- 1 | APP_NAME=Laravel 2 | APP_ENV=local 3 | APP_KEY=base64:GF7ltREmZbBOpMFO/Xa0SP+x18EkRlPwBCb8ORejhPQ= 4 | APP_DEBUG=true 5 | APP_URL=http://localhost 6 | 7 | LOG_CHANNEL=stack 8 | 9 | DB_CONNECTION=mysql 10 | DB_HOST=127.0.0.1 11 | DB_PORT=3306 12 | DB_DATABASE=laravel 13 | DB_USERNAME=root 14 | DB_PASSWORD= 15 | 16 | BROADCAST_DRIVER=log 17 | CACHE_DRIVER=file 18 | QUEUE_CONNECTION=sync 19 | SESSION_DRIVER=cookie 20 | SESSION_LIFETIME=120 21 | 22 | REDIS_HOST=127.0.0.1 23 | REDIS_PASSWORD=null 24 | REDIS_PORT=6379 25 | 26 | MAIL_DRIVER=smtp 27 | MAIL_HOST=smtp.mailtrap.io 28 | MAIL_PORT=2525 29 | MAIL_USERNAME=null 30 | MAIL_PASSWORD=null 31 | MAIL_ENCRYPTION=null 32 | 33 | AWS_ACCESS_KEY_ID= 34 | AWS_SECRET_ACCESS_KEY= 35 | AWS_DEFAULT_REGION=us-east-1 36 | AWS_BUCKET= 37 | 38 | PUSHER_APP_ID= 39 | PUSHER_APP_KEY= 40 | PUSHER_APP_SECRET= 41 | PUSHER_APP_CLUSTER=mt1 42 | 43 | MIX_PUSHER_APP_KEY="${PUSHER_APP_KEY}" 44 | MIX_PUSHER_APP_CLUSTER="${PUSHER_APP_CLUSTER}" 45 | -------------------------------------------------------------------------------- /examples/laravel/.gitattributes: -------------------------------------------------------------------------------- 1 | * text=auto 2 | *.css linguist-vendored 3 | *.scss linguist-vendored 4 | *.js linguist-vendored 5 | CHANGELOG.md export-ignore 6 | -------------------------------------------------------------------------------- /examples/laravel/.gitignore: -------------------------------------------------------------------------------- 1 | /node_modules 2 | /public/hot 3 | /public/storage 4 | /storage/*.key 5 | /vendor 6 | .env 7 | !.env.local 8 | !.env.production 9 | .env.backup 10 | .phpunit.result.cache 11 | Homestead.json 12 | Homestead.yaml 13 | npm-debug.log 14 | yarn-error.log 15 | 16 | /storage/ 17 | -------------------------------------------------------------------------------- /examples/laravel/.styleci.yml: -------------------------------------------------------------------------------- 1 | php: 2 | preset: laravel 3 | disabled: 4 | - unused_use 5 | finder: 6 | not-name: 7 | - index.php 8 | - server.php 9 | js: 10 | finder: 11 | not-name: 12 | - webpack.mix.js 13 | css: true 14 | -------------------------------------------------------------------------------- /examples/laravel/__test__/sl_test.php: -------------------------------------------------------------------------------- 1 | false, 7 | "requestContext" => [ 8 | "serviceId" => "service-abcdefg", 9 | "path" => "/api/event", 10 | "httpMethod" => "GET", 11 | "requestId" => "c6af9ac6-7b61-11e6-9a41-93e8deadbeef", 12 | "sourceIp" => "10.0.2.14", 13 | "stage" => "release" 14 | ], 15 | "headers" => [ 16 | "accept-Language" => "en-US,en,cn", 17 | "accept" => "text/html,application/xml,application/json", 18 | "host" => "localhost", 19 | "user-Agent" => "User Agent String" 20 | ], 21 | "pathParameters" => [ 22 | "path" => "value" 23 | ], 24 | "queryStringParameters" => [ 25 | "foo" => "bar" 26 | ], 27 | "headerParameters" => [ 28 | "Refer" => "127.0.0.1" 29 | ], 30 | "stageVariables" => [ 31 | "stage" => "release" 32 | ], 33 | "path" => "/api/event", 34 | "queryString" => [ 35 | "foo" => "bar", 36 | "bob" => "alice" 37 | ], 38 | "httpMethod" => "GET" 39 | ]; 40 | 41 | 42 | $res = handler($event, null); 43 | 44 | var_dump($res); 45 | -------------------------------------------------------------------------------- /examples/laravel/app/Console/Kernel.php: -------------------------------------------------------------------------------- 1 | command('inspire')->hourly(); 28 | } 29 | 30 | /** 31 | * Register the commands for the application. 32 | * 33 | * @return void 34 | */ 35 | protected function commands() 36 | { 37 | $this->load(__DIR__.'/Commands'); 38 | 39 | require base_path('routes/console.php'); 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /examples/laravel/app/Exceptions/Handler.php: -------------------------------------------------------------------------------- 1 | [ 33 | \App\Http\Middleware\EncryptCookies::class, 34 | \Illuminate\Cookie\Middleware\AddQueuedCookiesToResponse::class, 35 | \Illuminate\Session\Middleware\StartSession::class, 36 | // \Illuminate\Session\Middleware\AuthenticateSession::class, 37 | \Illuminate\View\Middleware\ShareErrorsFromSession::class, 38 | \App\Http\Middleware\VerifyCsrfToken::class, 39 | \Illuminate\Routing\Middleware\SubstituteBindings::class, 40 | ], 41 | 42 | 'api' => [ 43 | 'throttle:60,1', 44 | \Illuminate\Routing\Middleware\SubstituteBindings::class, 45 | ], 46 | ]; 47 | 48 | /** 49 | * The application's route middleware. 50 | * 51 | * These middleware may be assigned to groups or used individually. 52 | * 53 | * @var array 54 | */ 55 | protected $routeMiddleware = [ 56 | 'auth' => \App\Http\Middleware\Authenticate::class, 57 | 'auth.basic' => \Illuminate\Auth\Middleware\AuthenticateWithBasicAuth::class, 58 | 'bindings' => \Illuminate\Routing\Middleware\SubstituteBindings::class, 59 | 'cache.headers' => \Illuminate\Http\Middleware\SetCacheHeaders::class, 60 | 'can' => \Illuminate\Auth\Middleware\Authorize::class, 61 | 'guest' => \App\Http\Middleware\RedirectIfAuthenticated::class, 62 | 'password.confirm' => \Illuminate\Auth\Middleware\RequirePassword::class, 63 | 'signed' => \Illuminate\Routing\Middleware\ValidateSignature::class, 64 | 'throttle' => \Illuminate\Routing\Middleware\ThrottleRequests::class, 65 | 'verified' => \Illuminate\Auth\Middleware\EnsureEmailIsVerified::class, 66 | ]; 67 | } 68 | -------------------------------------------------------------------------------- /examples/laravel/app/Http/Middleware/Authenticate.php: -------------------------------------------------------------------------------- 1 | expectsJson()) { 18 | return route('login'); 19 | } 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /examples/laravel/app/Http/Middleware/CheckForMaintenanceMode.php: -------------------------------------------------------------------------------- 1 | check()) { 22 | return redirect(RouteServiceProvider::HOME); 23 | } 24 | 25 | return $next($request); 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /examples/laravel/app/Http/Middleware/TrimStrings.php: -------------------------------------------------------------------------------- 1 | allSubdomainsOfApplicationUrl(), 18 | ]; 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /examples/laravel/app/Http/Middleware/TrustProxies.php: -------------------------------------------------------------------------------- 1 | 'App\Policies\ModelPolicy', 17 | ]; 18 | 19 | /** 20 | * Register any authentication / authorization services. 21 | * 22 | * @return void 23 | */ 24 | public function boot() 25 | { 26 | $this->registerPolicies(); 27 | 28 | // 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /examples/laravel/app/Providers/BroadcastServiceProvider.php: -------------------------------------------------------------------------------- 1 | [ 19 | SendEmailVerificationNotification::class, 20 | ], 21 | ]; 22 | 23 | /** 24 | * Register any events for your application. 25 | * 26 | * @return void 27 | */ 28 | public function boot() 29 | { 30 | parent::boot(); 31 | 32 | // 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /examples/laravel/app/Providers/RouteServiceProvider.php: -------------------------------------------------------------------------------- 1 | mapApiRoutes(); 46 | 47 | $this->mapWebRoutes(); 48 | 49 | // 50 | } 51 | 52 | /** 53 | * Define the "web" routes for the application. 54 | * 55 | * These routes all receive session state, CSRF protection, etc. 56 | * 57 | * @return void 58 | */ 59 | protected function mapWebRoutes() 60 | { 61 | Route::middleware('web') 62 | ->namespace($this->namespace) 63 | ->group(base_path('routes/web.php')); 64 | } 65 | 66 | /** 67 | * Define the "api" routes for the application. 68 | * 69 | * These routes are typically stateless. 70 | * 71 | * @return void 72 | */ 73 | protected function mapApiRoutes() 74 | { 75 | Route::prefix('api') 76 | ->middleware('api') 77 | ->namespace($this->namespace) 78 | ->group(base_path('routes/api.php')); 79 | } 80 | } 81 | -------------------------------------------------------------------------------- /examples/laravel/app/User.php: -------------------------------------------------------------------------------- 1 | 'datetime', 38 | ]; 39 | } 40 | -------------------------------------------------------------------------------- /examples/laravel/artisan: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env php 2 | make(Illuminate\Contracts\Console\Kernel::class); 34 | 35 | $status = $kernel->handle( 36 | $input = new Symfony\Component\Console\Input\ArgvInput, 37 | new Symfony\Component\Console\Output\ConsoleOutput 38 | ); 39 | 40 | /* 41 | |-------------------------------------------------------------------------- 42 | | Shutdown The Application 43 | |-------------------------------------------------------------------------- 44 | | 45 | | Once Artisan has finished running, we will fire off the shutdown events 46 | | so that any final work may be done by the application before we shut 47 | | down the process. This is the last thing to happen to the request. 48 | | 49 | */ 50 | 51 | $kernel->terminate($input, $status); 52 | 53 | exit($status); 54 | -------------------------------------------------------------------------------- /examples/laravel/bootstrap/app.php: -------------------------------------------------------------------------------- 1 | singleton( 30 | Illuminate\Contracts\Http\Kernel::class, 31 | App\Http\Kernel::class 32 | ); 33 | 34 | $app->singleton( 35 | Illuminate\Contracts\Console\Kernel::class, 36 | App\Console\Kernel::class 37 | ); 38 | 39 | $app->singleton( 40 | Illuminate\Contracts\Debug\ExceptionHandler::class, 41 | App\Exceptions\Handler::class 42 | ); 43 | 44 | /* 45 | |-------------------------------------------------------------------------- 46 | | Return The Application 47 | |-------------------------------------------------------------------------- 48 | | 49 | | This script returns the application instance. The instance is given to 50 | | the calling script so we can separate the building of the instances 51 | | from the actual running of the application and sending responses. 52 | | 53 | */ 54 | 55 | return $app; 56 | -------------------------------------------------------------------------------- /examples/laravel/bootstrap/cache/.gitignore: -------------------------------------------------------------------------------- 1 | * 2 | !.gitignore 3 | -------------------------------------------------------------------------------- /examples/laravel/composer.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "laravel/laravel", 3 | "type": "project", 4 | "description": "The Laravel Framework.", 5 | "keywords": [ 6 | "framework", 7 | "laravel" 8 | ], 9 | "license": "MIT", 10 | "require": { 11 | "php": "^7.2.0", 12 | "fideloper/proxy": "^4.2", 13 | "fruitcake/laravel-cors": "^1.0", 14 | "guzzlehttp/guzzle": "^6.3", 15 | "laravel/framework": "^7.0", 16 | "laravel/tinker": "^2.0" 17 | }, 18 | "require-dev": { 19 | "facade/ignition": "^2.0", 20 | "fzaninotto/faker": "^1.9.1", 21 | "mockery/mockery": "^1.3.1", 22 | "nunomaduro/collision": "^4.1", 23 | "phpunit/phpunit": "^8.5" 24 | }, 25 | "config": { 26 | "optimize-autoloader": true, 27 | "preferred-install": "dist", 28 | "sort-packages": true 29 | }, 30 | "extra": { 31 | "laravel": { 32 | "dont-discover": [] 33 | } 34 | }, 35 | "autoload": { 36 | "psr-4": { 37 | "App\\": "app/" 38 | }, 39 | "classmap": [ 40 | "database/seeds", 41 | "database/factories" 42 | ] 43 | }, 44 | "autoload-dev": { 45 | "psr-4": { 46 | "Tests\\": "tests/" 47 | } 48 | }, 49 | "minimum-stability": "dev", 50 | "prefer-stable": true, 51 | "scripts": { 52 | "post-autoload-dump": [ 53 | "Illuminate\\Foundation\\ComposerScripts::postAutoloadDump", 54 | "@php artisan package:discover --ansi" 55 | ], 56 | "post-root-package-install": [ 57 | "@php -r \"file_exists('.env') || copy('.env.example', '.env');\"" 58 | ], 59 | "post-create-project-cmd": [ 60 | "@php artisan key:generate --ansi" 61 | ] 62 | } 63 | } 64 | -------------------------------------------------------------------------------- /examples/laravel/config/broadcasting.php: -------------------------------------------------------------------------------- 1 | env('BROADCAST_DRIVER', 'null'), 19 | 20 | /* 21 | |-------------------------------------------------------------------------- 22 | | Broadcast Connections 23 | |-------------------------------------------------------------------------- 24 | | 25 | | Here you may define all of the broadcast connections that will be used 26 | | to broadcast events to other systems or over websockets. Samples of 27 | | each available type of connection are provided inside this array. 28 | | 29 | */ 30 | 31 | 'connections' => [ 32 | 33 | 'pusher' => [ 34 | 'driver' => 'pusher', 35 | 'key' => env('PUSHER_APP_KEY'), 36 | 'secret' => env('PUSHER_APP_SECRET'), 37 | 'app_id' => env('PUSHER_APP_ID'), 38 | 'options' => [ 39 | 'cluster' => env('PUSHER_APP_CLUSTER'), 40 | 'useTLS' => true, 41 | ], 42 | ], 43 | 44 | 'redis' => [ 45 | 'driver' => 'redis', 46 | 'connection' => 'default', 47 | ], 48 | 49 | 'log' => [ 50 | 'driver' => 'log', 51 | ], 52 | 53 | 'null' => [ 54 | 'driver' => 'null', 55 | ], 56 | 57 | ], 58 | 59 | ]; 60 | -------------------------------------------------------------------------------- /examples/laravel/config/cache.php: -------------------------------------------------------------------------------- 1 | env('CACHE_DRIVER', 'file'), 22 | 23 | /* 24 | |-------------------------------------------------------------------------- 25 | | Cache Stores 26 | |-------------------------------------------------------------------------- 27 | | 28 | | Here you may define all of the cache "stores" for your application as 29 | | well as their drivers. You may even define multiple stores for the 30 | | same cache driver to group types of items stored in your caches. 31 | | 32 | */ 33 | 34 | 'stores' => [ 35 | 36 | 'apc' => [ 37 | 'driver' => 'apc', 38 | ], 39 | 40 | 'array' => [ 41 | 'driver' => 'array', 42 | 'serialize' => false, 43 | ], 44 | 45 | 'database' => [ 46 | 'driver' => 'database', 47 | 'table' => 'cache', 48 | 'connection' => null, 49 | ], 50 | 51 | 'file' => [ 52 | 'driver' => 'file', 53 | 'path' => storage_path('framework/cache/data'), 54 | ], 55 | 56 | 'memcached' => [ 57 | 'driver' => 'memcached', 58 | 'persistent_id' => env('MEMCACHED_PERSISTENT_ID'), 59 | 'sasl' => [ 60 | env('MEMCACHED_USERNAME'), 61 | env('MEMCACHED_PASSWORD'), 62 | ], 63 | 'options' => [ 64 | // Memcached::OPT_CONNECT_TIMEOUT => 2000, 65 | ], 66 | 'servers' => [ 67 | [ 68 | 'host' => env('MEMCACHED_HOST', '127.0.0.1'), 69 | 'port' => env('MEMCACHED_PORT', 11211), 70 | 'weight' => 100, 71 | ], 72 | ], 73 | ], 74 | 75 | 'redis' => [ 76 | 'driver' => 'redis', 77 | 'connection' => 'cache', 78 | ], 79 | 80 | 'dynamodb' => [ 81 | 'driver' => 'dynamodb', 82 | 'key' => env('AWS_ACCESS_KEY_ID'), 83 | 'secret' => env('AWS_SECRET_ACCESS_KEY'), 84 | 'region' => env('AWS_DEFAULT_REGION', 'us-east-1'), 85 | 'table' => env('DYNAMODB_CACHE_TABLE', 'cache'), 86 | 'endpoint' => env('DYNAMODB_ENDPOINT'), 87 | ], 88 | 89 | ], 90 | 91 | /* 92 | |-------------------------------------------------------------------------- 93 | | Cache Key Prefix 94 | |-------------------------------------------------------------------------- 95 | | 96 | | When utilizing a RAM based store such as APC or Memcached, there might 97 | | be other applications utilizing the same cache. So, we'll specify a 98 | | value to get prefixed to all our keys so we can avoid collisions. 99 | | 100 | */ 101 | 102 | 'prefix' => env('CACHE_PREFIX', Str::slug(env('APP_NAME', 'laravel'), '_').'_cache'), 103 | 104 | ]; 105 | -------------------------------------------------------------------------------- /examples/laravel/config/cors.php: -------------------------------------------------------------------------------- 1 | ['api/*'], 19 | 20 | 'allowed_methods' => ['*'], 21 | 22 | 'allowed_origins' => ['*'], 23 | 24 | 'allowed_origins_patterns' => [], 25 | 26 | 'allowed_headers' => ['*'], 27 | 28 | 'exposed_headers' => [], 29 | 30 | 'max_age' => 0, 31 | 32 | 'supports_credentials' => false, 33 | 34 | ]; 35 | -------------------------------------------------------------------------------- /examples/laravel/config/filesystems.php: -------------------------------------------------------------------------------- 1 | env('FILESYSTEM_DRIVER', 'local'), 17 | 18 | /* 19 | |-------------------------------------------------------------------------- 20 | | Default Cloud Filesystem Disk 21 | |-------------------------------------------------------------------------- 22 | | 23 | | Many applications store files both locally and in the cloud. For this 24 | | reason, you may specify a default "cloud" driver here. This driver 25 | | will be bound as the Cloud disk implementation in the container. 26 | | 27 | */ 28 | 29 | 'cloud' => env('FILESYSTEM_CLOUD', 's3'), 30 | 31 | /* 32 | |-------------------------------------------------------------------------- 33 | | Filesystem Disks 34 | |-------------------------------------------------------------------------- 35 | | 36 | | Here you may configure as many filesystem "disks" as you wish, and you 37 | | may even configure multiple disks of the same driver. Defaults have 38 | | been setup for each driver as an example of the required options. 39 | | 40 | | Supported Drivers: "local", "ftp", "sftp", "s3" 41 | | 42 | */ 43 | 44 | 'disks' => [ 45 | 46 | 'local' => [ 47 | 'driver' => 'local', 48 | 'root' => storage_path('app'), 49 | ], 50 | 51 | 'public' => [ 52 | 'driver' => 'local', 53 | 'root' => storage_path('app/public'), 54 | 'url' => env('APP_URL').'/storage', 55 | 'visibility' => 'public', 56 | ], 57 | 58 | 's3' => [ 59 | 'driver' => 's3', 60 | 'key' => env('AWS_ACCESS_KEY_ID'), 61 | 'secret' => env('AWS_SECRET_ACCESS_KEY'), 62 | 'region' => env('AWS_DEFAULT_REGION'), 63 | 'bucket' => env('AWS_BUCKET'), 64 | 'url' => env('AWS_URL'), 65 | 'endpoint' => env('AWS_ENDPOINT'), 66 | ], 67 | 68 | ], 69 | 70 | /* 71 | |-------------------------------------------------------------------------- 72 | | Symbolic Links 73 | |-------------------------------------------------------------------------- 74 | | 75 | | Here you may configure the symbolic links that will be created when the 76 | | `storage:link` Artisan command is executed. The array keys should be 77 | | the locations of the links and the values should be their targets. 78 | | 79 | */ 80 | 81 | 'links' => [ 82 | public_path('storage') => storage_path('app/public'), 83 | ], 84 | 85 | ]; 86 | -------------------------------------------------------------------------------- /examples/laravel/config/hashing.php: -------------------------------------------------------------------------------- 1 | 'bcrypt', 19 | 20 | /* 21 | |-------------------------------------------------------------------------- 22 | | Bcrypt Options 23 | |-------------------------------------------------------------------------- 24 | | 25 | | Here you may specify the configuration options that should be used when 26 | | passwords are hashed using the Bcrypt algorithm. This will allow you 27 | | to control the amount of time it takes to hash the given password. 28 | | 29 | */ 30 | 31 | 'bcrypt' => [ 32 | 'rounds' => env('BCRYPT_ROUNDS', 10), 33 | ], 34 | 35 | /* 36 | |-------------------------------------------------------------------------- 37 | | Argon Options 38 | |-------------------------------------------------------------------------- 39 | | 40 | | Here you may specify the configuration options that should be used when 41 | | passwords are hashed using the Argon algorithm. These will allow you 42 | | to control the amount of time it takes to hash the given password. 43 | | 44 | */ 45 | 46 | 'argon' => [ 47 | 'memory' => 1024, 48 | 'threads' => 2, 49 | 'time' => 2, 50 | ], 51 | 52 | ]; 53 | -------------------------------------------------------------------------------- /examples/laravel/config/logging.php: -------------------------------------------------------------------------------- 1 | env('LOG_CHANNEL', 'stack'), 21 | 22 | /* 23 | |-------------------------------------------------------------------------- 24 | | Log Channels 25 | |-------------------------------------------------------------------------- 26 | | 27 | | Here you may configure the log channels for your application. Out of 28 | | the box, Laravel uses the Monolog PHP logging library. This gives 29 | | you a variety of powerful log handlers / formatters to utilize. 30 | | 31 | | Available Drivers: "single", "daily", "slack", "syslog", 32 | | "errorlog", "monolog", 33 | | "custom", "stack" 34 | | 35 | */ 36 | 37 | 'channels' => [ 38 | 'stack' => [ 39 | 'driver' => 'stack', 40 | 'channels' => ['single'], 41 | 'ignore_exceptions' => false, 42 | ], 43 | 44 | 'single' => [ 45 | 'driver' => 'single', 46 | 'path' => storage_path('logs/laravel.log'), 47 | 'level' => 'debug', 48 | ], 49 | 50 | 'daily' => [ 51 | 'driver' => 'daily', 52 | 'path' => storage_path('logs/laravel.log'), 53 | 'level' => 'debug', 54 | 'days' => 14, 55 | ], 56 | 57 | 'slack' => [ 58 | 'driver' => 'slack', 59 | 'url' => env('LOG_SLACK_WEBHOOK_URL'), 60 | 'username' => 'Laravel Log', 61 | 'emoji' => ':boom:', 62 | 'level' => 'critical', 63 | ], 64 | 65 | 'papertrail' => [ 66 | 'driver' => 'monolog', 67 | 'level' => 'debug', 68 | 'handler' => SyslogUdpHandler::class, 69 | 'handler_with' => [ 70 | 'host' => env('PAPERTRAIL_URL'), 71 | 'port' => env('PAPERTRAIL_PORT'), 72 | ], 73 | ], 74 | 75 | 'stderr' => [ 76 | 'driver' => 'monolog', 77 | 'handler' => StreamHandler::class, 78 | 'formatter' => env('LOG_STDERR_FORMATTER'), 79 | 'with' => [ 80 | 'stream' => 'php://stderr', 81 | ], 82 | ], 83 | 84 | 'syslog' => [ 85 | 'driver' => 'syslog', 86 | 'level' => 'debug', 87 | ], 88 | 89 | 'errorlog' => [ 90 | 'driver' => 'errorlog', 91 | 'level' => 'debug', 92 | ], 93 | 94 | 'null' => [ 95 | 'driver' => 'monolog', 96 | 'handler' => NullHandler::class, 97 | ], 98 | 99 | 'emergency' => [ 100 | 'path' => storage_path('logs/laravel.log'), 101 | ], 102 | ], 103 | 104 | ]; 105 | -------------------------------------------------------------------------------- /examples/laravel/config/queue.php: -------------------------------------------------------------------------------- 1 | env('QUEUE_CONNECTION', 'sync'), 17 | 18 | /* 19 | |-------------------------------------------------------------------------- 20 | | Queue Connections 21 | |-------------------------------------------------------------------------- 22 | | 23 | | Here you may configure the connection information for each server that 24 | | is used by your application. A default configuration has been added 25 | | for each back-end shipped with Laravel. You are free to add more. 26 | | 27 | | Drivers: "sync", "database", "beanstalkd", "sqs", "redis", "null" 28 | | 29 | */ 30 | 31 | 'connections' => [ 32 | 33 | 'sync' => [ 34 | 'driver' => 'sync', 35 | ], 36 | 37 | 'database' => [ 38 | 'driver' => 'database', 39 | 'table' => 'jobs', 40 | 'queue' => 'default', 41 | 'retry_after' => 90, 42 | ], 43 | 44 | 'beanstalkd' => [ 45 | 'driver' => 'beanstalkd', 46 | 'host' => 'localhost', 47 | 'queue' => 'default', 48 | 'retry_after' => 90, 49 | 'block_for' => 0, 50 | ], 51 | 52 | 'sqs' => [ 53 | 'driver' => 'sqs', 54 | 'key' => env('AWS_ACCESS_KEY_ID'), 55 | 'secret' => env('AWS_SECRET_ACCESS_KEY'), 56 | 'prefix' => env('SQS_PREFIX', 'https://sqs.us-east-1.amazonaws.com/your-account-id'), 57 | 'queue' => env('SQS_QUEUE', 'your-queue-name'), 58 | 'suffix' => env('SQS_SUFFIX'), 59 | 'region' => env('AWS_DEFAULT_REGION', 'us-east-1'), 60 | ], 61 | 62 | 'redis' => [ 63 | 'driver' => 'redis', 64 | 'connection' => 'default', 65 | 'queue' => env('REDIS_QUEUE', 'default'), 66 | 'retry_after' => 90, 67 | 'block_for' => null, 68 | ], 69 | 70 | ], 71 | 72 | /* 73 | |-------------------------------------------------------------------------- 74 | | Failed Queue Jobs 75 | |-------------------------------------------------------------------------- 76 | | 77 | | These options configure the behavior of failed queue job logging so you 78 | | can control which database and table are used to store the jobs that 79 | | have failed. You may change them to any database / table you wish. 80 | | 81 | */ 82 | 83 | 'failed' => [ 84 | 'driver' => env('QUEUE_FAILED_DRIVER', 'database'), 85 | 'database' => env('DB_CONNECTION', 'mysql'), 86 | 'table' => 'failed_jobs', 87 | ], 88 | 89 | ]; 90 | -------------------------------------------------------------------------------- /examples/laravel/config/services.php: -------------------------------------------------------------------------------- 1 | [ 18 | 'domain' => env('MAILGUN_DOMAIN'), 19 | 'secret' => env('MAILGUN_SECRET'), 20 | 'endpoint' => env('MAILGUN_ENDPOINT', 'api.mailgun.net'), 21 | ], 22 | 23 | 'postmark' => [ 24 | 'token' => env('POSTMARK_TOKEN'), 25 | ], 26 | 27 | 'ses' => [ 28 | 'key' => env('AWS_ACCESS_KEY_ID'), 29 | 'secret' => env('AWS_SECRET_ACCESS_KEY'), 30 | 'region' => env('AWS_DEFAULT_REGION', 'us-east-1'), 31 | ], 32 | 33 | ]; 34 | -------------------------------------------------------------------------------- /examples/laravel/config/view.php: -------------------------------------------------------------------------------- 1 | [ 17 | resource_path('views'), 18 | ], 19 | 20 | /* 21 | |-------------------------------------------------------------------------- 22 | | Compiled View Path 23 | |-------------------------------------------------------------------------- 24 | | 25 | | This option determines where all the compiled Blade templates will be 26 | | stored for your application. Typically, this is within the storage 27 | | directory. However, as usual, you are free to change this value. 28 | | 29 | */ 30 | 31 | 'compiled' => env( 32 | 'VIEW_COMPILED_PATH', 33 | realpath(storage_path('framework/views')) 34 | ), 35 | 36 | ]; 37 | -------------------------------------------------------------------------------- /examples/laravel/database/.gitignore: -------------------------------------------------------------------------------- 1 | *.sqlite 2 | *.sqlite-journal 3 | -------------------------------------------------------------------------------- /examples/laravel/database/factories/UserFactory.php: -------------------------------------------------------------------------------- 1 | define(User::class, function (Faker $faker) { 21 | return [ 22 | 'name' => $faker->name, 23 | 'email' => $faker->unique()->safeEmail, 24 | 'email_verified_at' => now(), 25 | 'password' => '$2y$10$92IXUNpkjO0rOQ5byMi.Ye4oKoEa3Ro9llC/.og/at2.uheWG/igi', // password 26 | 'remember_token' => Str::random(10), 27 | ]; 28 | }); 29 | -------------------------------------------------------------------------------- /examples/laravel/database/migrations/2014_10_12_000000_create_users_table.php: -------------------------------------------------------------------------------- 1 | id(); 18 | $table->string('name'); 19 | $table->string('email')->unique(); 20 | $table->timestamp('email_verified_at')->nullable(); 21 | $table->string('password'); 22 | $table->rememberToken(); 23 | $table->timestamps(); 24 | }); 25 | } 26 | 27 | /** 28 | * Reverse the migrations. 29 | * 30 | * @return void 31 | */ 32 | public function down() 33 | { 34 | Schema::dropIfExists('users'); 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /examples/laravel/database/migrations/2019_08_19_000000_create_failed_jobs_table.php: -------------------------------------------------------------------------------- 1 | id(); 18 | $table->text('connection'); 19 | $table->text('queue'); 20 | $table->longText('payload'); 21 | $table->longText('exception'); 22 | $table->timestamp('failed_at')->useCurrent(); 23 | }); 24 | } 25 | 26 | /** 27 | * Reverse the migrations. 28 | * 29 | * @return void 30 | */ 31 | public function down() 32 | { 33 | Schema::dropIfExists('failed_jobs'); 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /examples/laravel/database/seeds/DatabaseSeeder.php: -------------------------------------------------------------------------------- 1 | call(UserSeeder::class); 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /examples/laravel/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "private": true, 3 | "scripts": { 4 | "dev": "npm run development", 5 | "development": "cross-env NODE_ENV=development node_modules/webpack/bin/webpack.js --progress --hide-modules --config=node_modules/laravel-mix/setup/webpack.config.js", 6 | "watch": "npm run development -- --watch", 7 | "watch-poll": "npm run watch -- --watch-poll", 8 | "hot": "cross-env NODE_ENV=development node_modules/webpack-dev-server/bin/webpack-dev-server.js --inline --hot --disable-host-check --config=node_modules/laravel-mix/setup/webpack.config.js", 9 | "prod": "npm run production", 10 | "production": "cross-env NODE_ENV=production node_modules/webpack/bin/webpack.js --no-progress --hide-modules --config=node_modules/laravel-mix/setup/webpack.config.js" 11 | }, 12 | "devDependencies": { 13 | "axios": "^0.19", 14 | "cross-env": "^7.0", 15 | "laravel-mix": "^5.0.1", 16 | "lodash": "^4.17.13", 17 | "resolve-url-loader": "^3.1.0", 18 | "sass": "^1.15.2", 19 | "sass-loader": "^8.0.0" 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /examples/laravel/phpunit.xml: -------------------------------------------------------------------------------- 1 | 2 | 7 | 8 | 9 | ./tests/Unit 10 | 11 | 12 | ./tests/Feature 13 | 14 | 15 | 16 | 17 | ./app 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | -------------------------------------------------------------------------------- /examples/laravel/public/.htaccess: -------------------------------------------------------------------------------- 1 | 2 | 3 | Options -MultiViews -Indexes 4 | 5 | 6 | RewriteEngine On 7 | 8 | # Handle Authorization Header 9 | RewriteCond %{HTTP:Authorization} . 10 | RewriteRule .* - [E=HTTP_AUTHORIZATION:%{HTTP:Authorization}] 11 | 12 | # Redirect Trailing Slashes If Not A Folder... 13 | RewriteCond %{REQUEST_FILENAME} !-d 14 | RewriteCond %{REQUEST_URI} (.+)/$ 15 | RewriteRule ^ %1 [L,R=301] 16 | 17 | # Send Requests To Front Controller... 18 | RewriteCond %{REQUEST_FILENAME} !-d 19 | RewriteCond %{REQUEST_FILENAME} !-f 20 | RewriteRule ^ index.php [L] 21 | 22 | -------------------------------------------------------------------------------- /examples/laravel/public/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/serverless-components/tencent-framework-components/97c001520604ea54a3ee8e78c177dc421942dc8c/examples/laravel/public/favicon.ico -------------------------------------------------------------------------------- /examples/laravel/public/index.php: -------------------------------------------------------------------------------- 1 | 8 | */ 9 | 10 | define('LARAVEL_START', microtime(true)); 11 | 12 | /* 13 | |-------------------------------------------------------------------------- 14 | | Register The Auto Loader 15 | |-------------------------------------------------------------------------- 16 | | 17 | | Composer provides a convenient, automatically generated class loader for 18 | | our application. We just need to utilize it! We'll simply require it 19 | | into the script here so that we don't have to worry about manual 20 | | loading any of our classes later on. It feels great to relax. 21 | | 22 | */ 23 | 24 | require __DIR__.'/../vendor/autoload.php'; 25 | 26 | /* 27 | |-------------------------------------------------------------------------- 28 | | Turn On The Lights 29 | |-------------------------------------------------------------------------- 30 | | 31 | | We need to illuminate PHP development, so let us turn on the lights. 32 | | This bootstraps the framework and gets it ready for use, then it 33 | | will load up this application so that we can run it and send 34 | | the responses back to the browser and delight our users. 35 | | 36 | */ 37 | 38 | $app = require_once __DIR__.'/../bootstrap/app.php'; 39 | 40 | /* 41 | |-------------------------------------------------------------------------- 42 | | Run The Application 43 | |-------------------------------------------------------------------------- 44 | | 45 | | Once we have the application, we can handle the incoming request 46 | | through the kernel, and send the associated response back to 47 | | the client's browser allowing them to enjoy the creative 48 | | and wonderful application we have prepared for them. 49 | | 50 | */ 51 | 52 | $kernel = $app->make(Illuminate\Contracts\Http\Kernel::class); 53 | 54 | $response = $kernel->handle( 55 | $request = Illuminate\Http\Request::capture() 56 | ); 57 | 58 | $response->send(); 59 | 60 | $kernel->terminate($request, $response); 61 | -------------------------------------------------------------------------------- /examples/laravel/public/robots.txt: -------------------------------------------------------------------------------- 1 | User-agent: * 2 | Disallow: 3 | -------------------------------------------------------------------------------- /examples/laravel/public/web.config: -------------------------------------------------------------------------------- 1 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | -------------------------------------------------------------------------------- /examples/laravel/resources/js/app.js: -------------------------------------------------------------------------------- 1 | require('./bootstrap'); 2 | -------------------------------------------------------------------------------- /examples/laravel/resources/js/bootstrap.js: -------------------------------------------------------------------------------- 1 | window._ = require('lodash'); 2 | 3 | /** 4 | * We'll load the axios HTTP library which allows us to easily issue requests 5 | * to our Laravel back-end. This library automatically handles sending the 6 | * CSRF token as a header based on the value of the "XSRF" token cookie. 7 | */ 8 | 9 | window.axios = require('axios'); 10 | 11 | window.axios.defaults.headers.common['X-Requested-With'] = 'XMLHttpRequest'; 12 | 13 | /** 14 | * Echo exposes an expressive API for subscribing to channels and listening 15 | * for events that are broadcast by Laravel. Echo and event broadcasting 16 | * allows your team to easily build robust real-time web applications. 17 | */ 18 | 19 | // import Echo from 'laravel-echo'; 20 | 21 | // window.Pusher = require('pusher-js'); 22 | 23 | // window.Echo = new Echo({ 24 | // broadcaster: 'pusher', 25 | // key: process.env.MIX_PUSHER_APP_KEY, 26 | // cluster: process.env.MIX_PUSHER_APP_CLUSTER, 27 | // forceTLS: true 28 | // }); 29 | -------------------------------------------------------------------------------- /examples/laravel/resources/lang/en/auth.php: -------------------------------------------------------------------------------- 1 | 'These credentials do not match our records.', 17 | 'throttle' => 'Too many login attempts. Please try again in :seconds seconds.', 18 | 19 | ]; 20 | -------------------------------------------------------------------------------- /examples/laravel/resources/lang/en/pagination.php: -------------------------------------------------------------------------------- 1 | '« Previous', 17 | 'next' => 'Next »', 18 | 19 | ]; 20 | -------------------------------------------------------------------------------- /examples/laravel/resources/lang/en/passwords.php: -------------------------------------------------------------------------------- 1 | 'Your password has been reset!', 17 | 'sent' => 'We have emailed your password reset link!', 18 | 'throttled' => 'Please wait before retrying.', 19 | 'token' => 'This password reset token is invalid.', 20 | 'user' => "We can't find a user with that email address.", 21 | 22 | ]; 23 | -------------------------------------------------------------------------------- /examples/laravel/resources/sass/app.scss: -------------------------------------------------------------------------------- 1 | // 2 | -------------------------------------------------------------------------------- /examples/laravel/resources/views/welcome.blade.php: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | Serverless - Laravel 9 | 16 | 17 | 18 |

19 | 欢迎访问 Laravel 应用 20 |
21 | 22 | 腾讯云 Serverless 23 | 24 | 为您提供服务 25 |

26 | 27 | 28 | -------------------------------------------------------------------------------- /examples/laravel/routes/api.php: -------------------------------------------------------------------------------- 1 | get('/user', function (Request $request) { 18 | return $request->user(); 19 | }); 20 | 21 | Route::get('/event', function (Request $request) { 22 | $event = $request->__SLS_EVENT__; 23 | 24 | return response()->json([ 25 | 'event' => $event, 26 | ]); 27 | }); 28 | 29 | Route::get('/headers', function (Request $request) { 30 | $headers = $request->headers->all(); 31 | 32 | return response()->json([ 33 | 'title' => 'serverless', 34 | 'headers' => $headers, 35 | ]); 36 | }); 37 | 38 | Route::get('/posts', function (Request $request) { 39 | $input = $request->all(); 40 | 41 | return response()->json([ 42 | 'title' => 'serverless', 43 | 'get' => $input 44 | ]); 45 | }); 46 | 47 | Route::post('/posts', function (Request $request) { 48 | $input = $request->all(); 49 | 50 | return response()->json([ 51 | 'title' => 'serverless', 52 | 'data' => $input 53 | ]); 54 | }); 55 | 56 | // 上传文件接口示例 57 | Route::post('/upload', function (Request $request) { 58 | // 表单中字段为 file 59 | if ($request->file) { 60 | // TODO: 这里只是将文件临时存储到 /tmp 下,用户需要根据个人需要存储到持久化服务,比如腾讯云的对象存储、文件存储等。 61 | $upload = $request->file->store('upload'); 62 | $uploadFile = storage_path()."/app/".$upload; 63 | } 64 | 65 | return response()->json([ 66 | 'title' => 'serverless', 67 | 'upload' => $uploadFile ?? null, 68 | ]); 69 | }); 70 | -------------------------------------------------------------------------------- /examples/laravel/routes/channels.php: -------------------------------------------------------------------------------- 1 | id === (int) $id; 18 | }); 19 | -------------------------------------------------------------------------------- /examples/laravel/routes/console.php: -------------------------------------------------------------------------------- 1 | comment(Inspiring::quote()); 19 | })->describe('Display an inspiring quote'); 20 | -------------------------------------------------------------------------------- /examples/laravel/routes/web.php: -------------------------------------------------------------------------------- 1 | 8 | */ 9 | 10 | $uri = urldecode( 11 | parse_url($_SERVER['REQUEST_URI'], PHP_URL_PATH) 12 | ); 13 | 14 | // This file allows us to emulate Apache's "mod_rewrite" functionality from the 15 | // built-in PHP web server. This provides a convenient way to test a Laravel 16 | // application without having installed a "real" web server software here. 17 | if ($uri !== '/' && file_exists(__DIR__.'/public'.$uri)) { 18 | return false; 19 | } 20 | 21 | require_once __DIR__.'/public/index.php'; 22 | -------------------------------------------------------------------------------- /examples/laravel/serverless.yml: -------------------------------------------------------------------------------- 1 | app: appDemo 2 | stage: dev 3 | component: laravel 4 | name: laravelDemo 5 | inputs: 6 | src: ./ 7 | region: ap-guangzhou 8 | functionConf: 9 | name: ${name} 10 | runtime: Php7 11 | environments: 12 | variables: 13 | APP_ENV: production 14 | apigatewayConf: 15 | protocols: 16 | - http 17 | - https 18 | environment: release 19 | -------------------------------------------------------------------------------- /examples/laravel/webpack.mix.js: -------------------------------------------------------------------------------- 1 | const mix = require('laravel-mix'); 2 | 3 | /* 4 | |-------------------------------------------------------------------------- 5 | | Mix Asset Management 6 | |-------------------------------------------------------------------------- 7 | | 8 | | Mix provides a clean, fluent API for defining some Webpack build steps 9 | | for your Laravel application. By default, we are compiling the Sass 10 | | file for the application as well as bundling up all the JS files. 11 | | 12 | */ 13 | 14 | mix.js('resources/js/app.js', 'public/js') 15 | .sass('resources/sass/app.scss', 'public/css'); 16 | -------------------------------------------------------------------------------- /examples/nestjs/.gitignore: -------------------------------------------------------------------------------- 1 | # compiled output 2 | /dist 3 | /node_modules 4 | 5 | # Logs 6 | logs 7 | *.log 8 | npm-debug.log* 9 | yarn-debug.log* 10 | yarn-error.log* 11 | lerna-debug.log* 12 | 13 | # OS 14 | .DS_Store 15 | 16 | # Tests 17 | /coverage 18 | /.nyc_output 19 | 20 | # IDEs and editors 21 | /.idea 22 | .project 23 | .classpath 24 | .c9/ 25 | *.launch 26 | .settings/ 27 | *.sublime-workspace 28 | 29 | # IDE - VSCode 30 | .vscode/* 31 | !.vscode/settings.json 32 | !.vscode/tasks.json 33 | !.vscode/launch.json 34 | !.vscode/extensions.json -------------------------------------------------------------------------------- /examples/nestjs/.prettierrc: -------------------------------------------------------------------------------- 1 | { 2 | "singleQuote": true, 3 | "trailingComma": "all" 4 | } -------------------------------------------------------------------------------- /examples/nestjs/nest-cli.json: -------------------------------------------------------------------------------- 1 | { 2 | "collection": "@nestjs/schematics", 3 | "sourceRoot": "src" 4 | } 5 | -------------------------------------------------------------------------------- /examples/nestjs/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "nestjs-demo", 3 | "version": "0.0.1", 4 | "description": "", 5 | "author": "", 6 | "private": true, 7 | "license": "UNLICENSED", 8 | "scripts": { 9 | "prebuild": "rimraf dist", 10 | "build": "nest build", 11 | "format": "prettier --write \"src/**/*.ts\" \"test/**/*.ts\"", 12 | "lint": "eslint \"{src,apps,libs,test}/**/*.ts\" --fix", 13 | "start": "NODE_ENV=local nest start", 14 | "start:dev": "NODE_ENV=local nest start --watch", 15 | "start:debug": "NODE_ENV=local nest start --debug --watch" 16 | }, 17 | "dependencies": { 18 | "@nestjs/common": "^7.0.0", 19 | "@nestjs/core": "^7.0.0", 20 | "@nestjs/platform-express": "^7.0.0", 21 | "hbs": "^4.1.1", 22 | "reflect-metadata": "^0.1.13", 23 | "rimraf": "^3.0.2", 24 | "rxjs": "^6.5.4" 25 | }, 26 | "devDependencies": { 27 | "@nestjs/cli": "^7.0.0", 28 | "@nestjs/schematics": "^7.0.0", 29 | "@nestjs/testing": "^7.0.0", 30 | "@types/express": "^4.17.3", 31 | "@types/jest": "26.0.10", 32 | "@types/node": "^13.9.1", 33 | "@types/supertest": "^2.0.8", 34 | "@typescript-eslint/eslint-plugin": "3.9.1", 35 | "@typescript-eslint/parser": "3.9.1", 36 | "eslint": "7.7.0", 37 | "eslint-config-prettier": "^6.10.0", 38 | "eslint-plugin-import": "^2.20.1", 39 | "jest": "26.4.2", 40 | "prettier": "^1.19.1", 41 | "supertest": "^4.0.2", 42 | "ts-jest": "26.2.0", 43 | "ts-loader": "^6.2.1", 44 | "ts-node": "9.0.0", 45 | "tsconfig-paths": "^3.9.0", 46 | "typescript": "^3.7.4" 47 | }, 48 | "jest": { 49 | "moduleFileExtensions": [ 50 | "js", 51 | "json", 52 | "ts" 53 | ], 54 | "rootDir": "src", 55 | "testRegex": ".spec.ts$", 56 | "transform": { 57 | "^.+\\.(t|j)s$": "ts-jest" 58 | }, 59 | "coverageDirectory": "../coverage", 60 | "testEnvironment": "node" 61 | } 62 | } 63 | -------------------------------------------------------------------------------- /examples/nestjs/serverless.yml: -------------------------------------------------------------------------------- 1 | app: appDemo 2 | stage: dev 3 | component: nestjs 4 | name: nestDemo 5 | inputs: 6 | src: 7 | src: ./ 8 | exclude: 9 | - .env 10 | functionConf: 11 | name: ${name} 12 | apigatewayConf: 13 | protocols: 14 | - http 15 | - https 16 | -------------------------------------------------------------------------------- /examples/nestjs/sls.js: -------------------------------------------------------------------------------- 1 | // Notice: change filename to your real project entry filename 2 | const { bootstrap } = require('./dist/main'); 3 | 4 | module.exports = bootstrap; 5 | -------------------------------------------------------------------------------- /examples/nestjs/src/app.controller.spec.ts: -------------------------------------------------------------------------------- 1 | import { Test, TestingModule } from '@nestjs/testing'; 2 | import { AppController } from './app.controller'; 3 | import { AppService } from './app.service'; 4 | 5 | describe('AppController', () => { 6 | let appController: AppController; 7 | 8 | beforeEach(async () => { 9 | const app: TestingModule = await Test.createTestingModule({ 10 | controllers: [AppController], 11 | providers: [AppService], 12 | }).compile(); 13 | 14 | appController = app.get(AppController); 15 | }); 16 | 17 | describe('root', () => { 18 | it('should return "Hello World!"', () => { 19 | expect(appController.getHello()).toBe('Hello World!'); 20 | }); 21 | }); 22 | }); 23 | -------------------------------------------------------------------------------- /examples/nestjs/src/app.controller.ts: -------------------------------------------------------------------------------- 1 | import { Controller, Get, Render, Req } from '@nestjs/common'; 2 | import { Request } from 'express'; 3 | import { AppService } from './app.service'; 4 | 5 | @Controller() 6 | export class AppController { 7 | constructor(private readonly appService: AppService) {} 8 | 9 | @Get() 10 | @Render('index') 11 | root() { 12 | return { 13 | message: 'Serverless Framework', 14 | }; 15 | } 16 | 17 | @Get('/event') 18 | event(@Req() request: Request) { 19 | // @ts-ignore 20 | const event = request.__SLS_EVENT__; 21 | return { 22 | event: event || {} 23 | }; 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /examples/nestjs/src/app.module.ts: -------------------------------------------------------------------------------- 1 | import { Module } from '@nestjs/common'; 2 | import { AppController } from './app.controller'; 3 | import { AppService } from './app.service'; 4 | 5 | @Module({ 6 | imports: [], 7 | controllers: [AppController], 8 | providers: [AppService], 9 | }) 10 | export class AppModule {} 11 | -------------------------------------------------------------------------------- /examples/nestjs/src/app.service.ts: -------------------------------------------------------------------------------- 1 | import { Injectable } from '@nestjs/common'; 2 | 3 | @Injectable() 4 | export class AppService { 5 | getHello(): string { 6 | return 'Hello World!'; 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /examples/nestjs/src/main.ts: -------------------------------------------------------------------------------- 1 | import { NestFactory } from '@nestjs/core'; 2 | import { NestExpressApplication } from '@nestjs/platform-express'; 3 | import { join } from 'path'; 4 | import { AppModule } from './app.module'; 5 | 6 | async function bootstrap() { 7 | const app = await NestFactory.create(AppModule); 8 | app.enableCors(); 9 | app.setBaseViewsDir(join(__dirname, '..', 'views')); 10 | app.setViewEngine('hbs'); 11 | 12 | return app; 13 | } 14 | 15 | // TODO: 通过注入 NODE_ENV 为 local,来方便本地启动服务,进行开发调试 16 | const isLocal = process.env.NODE_ENV === 'local'; 17 | if (isLocal) { 18 | bootstrap().then(app => { 19 | app.listen(3000, () => { 20 | console.log(`Server start on http://localhost:3000`); 21 | }); 22 | }); 23 | } 24 | 25 | export { bootstrap }; 26 | -------------------------------------------------------------------------------- /examples/nestjs/tsconfig.build.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "./tsconfig.json", 3 | "exclude": ["node_modules", "test", "dist", "**/*spec.ts"] 4 | } 5 | -------------------------------------------------------------------------------- /examples/nestjs/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "module": "commonjs", 4 | "declaration": true, 5 | "removeComments": true, 6 | "emitDecoratorMetadata": true, 7 | "experimentalDecorators": true, 8 | "allowSyntheticDefaultImports": true, 9 | "target": "es2017", 10 | "sourceMap": true, 11 | "outDir": "./dist", 12 | "baseUrl": "./", 13 | "incremental": true 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /examples/nestjs/views/index.hbs: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | Serverless - Nest.js 9 | 16 | 17 | 18 |

19 | 欢迎访问 Nest.js 应用 20 |
21 | 22 | 腾讯云 Serverless 23 | 24 | 为您提供服务 25 |

26 | 27 | 28 | -------------------------------------------------------------------------------- /examples/nextjs/.env.example: -------------------------------------------------------------------------------- 1 | TENCENT_SECRET_ID=123 2 | TENCENT_SECRET_KEY=123 3 | 4 | STATIC_URL=https://nextjs-demo-123456789.cos.ap-guangzhou.myqcloud.com 5 | -------------------------------------------------------------------------------- /examples/nextjs/.gitignore: -------------------------------------------------------------------------------- 1 | # See https://help.github.com/articles/ignoring-files/ for more about ignoring files. 2 | 3 | # dependencies 4 | /node_modules 5 | /.pnp 6 | .pnp.js 7 | 8 | # testing 9 | /coverage 10 | 11 | # next.js 12 | /.next/ 13 | /out/ 14 | 15 | # production 16 | /build 17 | 18 | # misc 19 | .DS_Store 20 | *.pem 21 | 22 | # debug 23 | npm-debug.log* 24 | yarn-debug.log* 25 | yarn-error.log* 26 | 27 | # local env files 28 | .env 29 | .env.local 30 | .env.development.local 31 | .env.test.local 32 | .env.production.local 33 | 34 | # vercel 35 | .vercel 36 | 37 | # debug 38 | npm-debug.log* 39 | yarn-debug.log* 40 | yarn-error.log* 41 | 42 | .serverless 43 | .next 44 | -------------------------------------------------------------------------------- /examples/nextjs/next.config.js: -------------------------------------------------------------------------------- 1 | const isProd = process.env.NODE_ENV === 'production' 2 | 3 | module.exports = { 4 | env: { 5 | STATIC_URL: isProd ? process.env.STATIC_URL : '' 6 | }, 7 | assetPrefix: isProd ? process.env.STATIC_URL : '', 8 | reactStrictMode: true, 9 | eslint: { 10 | ignoreDuringBuilds: true 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /examples/nextjs/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "example", 3 | "version": "0.1.0", 4 | "private": true, 5 | "scripts": { 6 | "dev": "next dev", 7 | "build": "next build", 8 | "start": "next start" 9 | }, 10 | "dependencies": { 11 | "next": "11.0.1", 12 | "react": "17.0.2", 13 | "react-dom": "17.0.2" 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /examples/nextjs/pages/_app.js: -------------------------------------------------------------------------------- 1 | import '../styles/globals.css' 2 | 3 | function MyApp({ Component, pageProps }) { 4 | return 5 | } 6 | 7 | export default MyApp 8 | -------------------------------------------------------------------------------- /examples/nextjs/pages/api/hello.js: -------------------------------------------------------------------------------- 1 | // Next.js API route support: https://nextjs.org/docs/api-routes/introduction 2 | 3 | export default function handler(req, res) { 4 | res.status(200).json({ name: 'John Doe' }) 5 | } 6 | -------------------------------------------------------------------------------- /examples/nextjs/pages/index.js: -------------------------------------------------------------------------------- 1 | import Head from 'next/head' 2 | import styles from '../styles/Home.module.css' 3 | 4 | export default function Home() { 5 | return ( 6 |
7 | 8 | Serverless - Next.js 9 | 10 | 11 | 12 | 13 | 14 |
15 |

欢迎访问 Next.js 应用

16 | 17 |

18 | 19 | 腾讯云 Serverless 20 | 21 | 为您提供服务 22 |

23 |
24 |
25 | ) 26 | } 27 | -------------------------------------------------------------------------------- /examples/nextjs/public/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/serverless-components/tencent-framework-components/97c001520604ea54a3ee8e78c177dc421942dc8c/examples/nextjs/public/favicon.ico -------------------------------------------------------------------------------- /examples/nextjs/serverless.yml: -------------------------------------------------------------------------------- 1 | app: appDemo 2 | stage: dev 3 | component: nextjs 4 | name: nextjsDemo 5 | 6 | inputs: 7 | src: 8 | dist: ./ 9 | hook: npm run build 10 | exclude: 11 | - .env 12 | region: ap-guangzhou 13 | functionConf: 14 | name: ${name} 15 | runtime: Nodejs10.15 16 | apigatewayConf: 17 | protocols: 18 | - http 19 | - https 20 | environment: release 21 | staticConf: 22 | cosConf: 23 | replace: true 24 | bucket: nextjs-demo 25 | -------------------------------------------------------------------------------- /examples/nextjs/styles/Home.module.css: -------------------------------------------------------------------------------- 1 | .container { 2 | min-height: 100vh; 3 | padding: 0 0.5rem; 4 | display: flex; 5 | flex-direction: column; 6 | justify-content: center; 7 | align-items: center; 8 | height: 100vh; 9 | } 10 | 11 | .main { 12 | padding: 5rem 0; 13 | flex: 1; 14 | display: flex; 15 | flex-direction: column; 16 | justify-content: center; 17 | align-items: center; 18 | } 19 | 20 | .footer { 21 | width: 100%; 22 | height: 100px; 23 | border-top: 1px solid #eaeaea; 24 | display: flex; 25 | justify-content: center; 26 | align-items: center; 27 | } 28 | 29 | .footer a { 30 | display: flex; 31 | justify-content: center; 32 | align-items: center; 33 | flex-grow: 1; 34 | } 35 | 36 | .title a, 37 | .description a { 38 | color: #0070f3; 39 | text-decoration: none; 40 | } 41 | 42 | .title a:hover, 43 | .title a:focus, 44 | .title a:active { 45 | text-decoration: underline; 46 | } 47 | 48 | .title { 49 | margin: 0; 50 | line-height: 1.15; 51 | font-size: 4rem; 52 | } 53 | 54 | .title, 55 | .description { 56 | text-align: center; 57 | } 58 | 59 | .description { 60 | line-height: 1.5; 61 | font-size: 1.5rem; 62 | } 63 | 64 | .code { 65 | background: #fafafa; 66 | border-radius: 5px; 67 | padding: 0.75rem; 68 | font-size: 1.1rem; 69 | font-family: Menlo, Monaco, Lucida Console, Liberation Mono, DejaVu Sans Mono, 70 | Bitstream Vera Sans Mono, Courier New, monospace; 71 | } 72 | 73 | .grid { 74 | display: flex; 75 | align-items: center; 76 | justify-content: center; 77 | flex-wrap: wrap; 78 | max-width: 800px; 79 | margin-top: 3rem; 80 | } 81 | 82 | .card { 83 | margin: 1rem; 84 | padding: 1.5rem; 85 | text-align: left; 86 | color: inherit; 87 | text-decoration: none; 88 | border: 1px solid #eaeaea; 89 | border-radius: 10px; 90 | transition: color 0.15s ease, border-color 0.15s ease; 91 | width: 45%; 92 | } 93 | 94 | .card:hover, 95 | .card:focus, 96 | .card:active { 97 | color: #0070f3; 98 | border-color: #0070f3; 99 | } 100 | 101 | .card h2 { 102 | margin: 0 0 1rem 0; 103 | font-size: 1.5rem; 104 | } 105 | 106 | .card p { 107 | margin: 0; 108 | font-size: 1.25rem; 109 | line-height: 1.5; 110 | } 111 | 112 | .logo { 113 | height: 1em; 114 | margin-left: 0.5rem; 115 | } 116 | 117 | @media (max-width: 600px) { 118 | .grid { 119 | width: 100%; 120 | flex-direction: column; 121 | } 122 | } 123 | -------------------------------------------------------------------------------- /examples/nextjs/styles/globals.css: -------------------------------------------------------------------------------- 1 | html, 2 | body { 3 | padding: 0; 4 | margin: 0; 5 | font-family: -apple-system, BlinkMacSystemFont, Segoe UI, Roboto, Oxygen, 6 | Ubuntu, Cantarell, Fira Sans, Droid Sans, Helvetica Neue, sans-serif; 7 | } 8 | 9 | a { 10 | color: inherit; 11 | text-decoration: none; 12 | } 13 | 14 | * { 15 | box-sizing: border-box; 16 | } 17 | -------------------------------------------------------------------------------- /examples/nuxtjs/.editorconfig: -------------------------------------------------------------------------------- 1 | # editorconfig.org 2 | root = true 3 | 4 | [*] 5 | indent_style = space 6 | indent_size = 2 7 | end_of_line = lf 8 | charset = utf-8 9 | trim_trailing_whitespace = true 10 | insert_final_newline = true 11 | 12 | [*.md] 13 | trim_trailing_whitespace = false 14 | -------------------------------------------------------------------------------- /examples/nuxtjs/.env.example: -------------------------------------------------------------------------------- 1 | TENCENT_SECRET_ID=123 2 | TENCENT_SECRET_KEY=123 3 | 4 | # please change to your real appid 5 | STATIC_URL=https://nuxtjs-demo-.cos.ap-guangzhou.myqcloud.com 6 | -------------------------------------------------------------------------------- /examples/nuxtjs/.gitignore: -------------------------------------------------------------------------------- 1 | # Created by .ignore support plugin (hsz.mobi) 2 | ### Node template 3 | # Logs 4 | /logs 5 | *.log 6 | npm-debug.log* 7 | yarn-debug.log* 8 | yarn-error.log* 9 | 10 | # Runtime data 11 | pids 12 | *.pid 13 | *.seed 14 | *.pid.lock 15 | 16 | # Directory for instrumented libs generated by jscoverage/JSCover 17 | lib-cov 18 | 19 | # Coverage directory used by tools like istanbul 20 | coverage 21 | 22 | # nyc test coverage 23 | .nyc_output 24 | 25 | # Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files) 26 | .grunt 27 | 28 | # Bower dependency directory (https://bower.io/) 29 | bower_components 30 | 31 | # node-waf configuration 32 | .lock-wscript 33 | 34 | # Compiled binary addons (https://nodejs.org/api/addons.html) 35 | build/Release 36 | 37 | # Dependency directories 38 | node_modules/ 39 | jspm_packages/ 40 | 41 | # TypeScript v1 declaration files 42 | typings/ 43 | 44 | # Optional npm cache directory 45 | .npm 46 | 47 | # Optional eslint cache 48 | .eslintcache 49 | 50 | # Optional REPL history 51 | .node_repl_history 52 | 53 | # Output of 'npm pack' 54 | *.tgz 55 | 56 | # Yarn Integrity file 57 | .yarn-integrity 58 | 59 | # dotenv environment variables file 60 | .env 61 | 62 | # parcel-bundler cache (https://parceljs.org/) 63 | .cache 64 | 65 | # next.js build output 66 | .next 67 | 68 | # nuxt.js build output 69 | .nuxt 70 | 71 | # Nuxt generate 72 | dist 73 | 74 | # vuepress build output 75 | .vuepress/dist 76 | 77 | # Serverless directories 78 | .serverless 79 | 80 | # IDE / Editor 81 | .idea 82 | 83 | # Service worker 84 | sw.* 85 | 86 | # macOS 87 | .DS_Store 88 | 89 | # Vim swap files 90 | *.swp 91 | -------------------------------------------------------------------------------- /examples/nuxtjs/assets/README.md: -------------------------------------------------------------------------------- 1 | # ASSETS 2 | 3 | **This directory is not required, you can delete it if you don't want to use it.** 4 | 5 | This directory contains your un-compiled assets such as LESS, SASS, or JavaScript. 6 | 7 | More information about the usage of this directory in [the documentation](https://nuxtjs.org/guide/assets#webpacked). 8 | -------------------------------------------------------------------------------- /examples/nuxtjs/components/Logo.vue: -------------------------------------------------------------------------------- 1 | 20 | 35 | -------------------------------------------------------------------------------- /examples/nuxtjs/components/README.md: -------------------------------------------------------------------------------- 1 | # COMPONENTS 2 | 3 | **This directory is not required, you can delete it if you don't want to use it.** 4 | 5 | The components directory contains your Vue.js Components. 6 | 7 | _Nuxt.js doesn't supercharge these components._ 8 | -------------------------------------------------------------------------------- /examples/nuxtjs/layouts/README.md: -------------------------------------------------------------------------------- 1 | # LAYOUTS 2 | 3 | **This directory is not required, you can delete it if you don't want to use it.** 4 | 5 | This directory contains your Application Layouts. 6 | 7 | More information about the usage of this directory in [the documentation](https://nuxtjs.org/guide/views#layouts). 8 | -------------------------------------------------------------------------------- /examples/nuxtjs/layouts/default.vue: -------------------------------------------------------------------------------- 1 | 6 | 7 | 65 | -------------------------------------------------------------------------------- /examples/nuxtjs/middleware/README.md: -------------------------------------------------------------------------------- 1 | # MIDDLEWARE 2 | 3 | **This directory is not required, you can delete it if you don't want to use it.** 4 | 5 | This directory contains your application middleware. 6 | Middleware let you define custom functions that can be run before rendering either a page or a group of pages. 7 | 8 | More information about the usage of this directory in [the documentation](https://nuxtjs.org/guide/routing#middleware). 9 | -------------------------------------------------------------------------------- /examples/nuxtjs/nuxt.config.js: -------------------------------------------------------------------------------- 1 | export default { 2 | env: { 3 | STATIC_URL: process.env.STATIC_URL || '' 4 | }, 5 | /* 6 | ** Build configuration 7 | */ 8 | build: { 9 | extend(config, { isDev, isClient }) { 10 | if (!isDev && process.env.STATIC_URL) { 11 | config.output.publicPath = process.env.STATIC_URL 12 | } 13 | } 14 | }, 15 | /* 16 | ** Headers of the page 17 | */ 18 | head: { 19 | title: 'Serverless - Nuxt.js Application', 20 | meta: [ 21 | { charset: 'utf-8' }, 22 | { name: 'viewport', content: 'width=device-width, initial-scale=1' }, 23 | { 24 | hid: 'description', 25 | name: 'description', 26 | content: 'Serverless Nuxt.js 应用' 27 | }, 28 | { 29 | hid: 'keywords', 30 | name: 'keywords', 31 | content: 'nuxt,nuxt.js,serverless,无服务' 32 | } 33 | ], 34 | link: [ 35 | { rel: 'icon', type: 'image/x-icon', href: `${process.env.STATIC_URL || ''}/favicon.ico` } 36 | ] 37 | }, 38 | /* 39 | ** Customize the progress-bar color 40 | */ 41 | loading: { color: '#fff' }, 42 | /* 43 | ** Global CSS 44 | */ 45 | css: [], 46 | /* 47 | ** Plugins to load before mounting the App 48 | */ 49 | plugins: [], 50 | /* 51 | ** Nuxt.js dev-modules 52 | */ 53 | buildModules: [], 54 | /* 55 | ** Nuxt.js modules 56 | */ 57 | modules: [] 58 | } 59 | -------------------------------------------------------------------------------- /examples/nuxtjs/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "nuxt-demo", 3 | "version": "1.0.0", 4 | "description": "Serverless Nuxt.js Application Created By Serverless Framework", 5 | "author": "Tencent Cloud, Inc.", 6 | "private": true, 7 | "scripts": { 8 | "dev": "nuxt", 9 | "build": "nuxt build", 10 | "start": "nuxt start", 11 | "generate": "nuxt generate" 12 | }, 13 | "dependencies": { 14 | "nuxt": "^2.14.3" 15 | }, 16 | "devDependencies": {} 17 | } 18 | -------------------------------------------------------------------------------- /examples/nuxtjs/pages/README.md: -------------------------------------------------------------------------------- 1 | # PAGES 2 | 3 | This directory contains your Application Views and Routes. 4 | The framework reads all the `*.vue` files inside this directory and creates the router of your application. 5 | 6 | More information about the usage of this directory in [the documentation](https://nuxtjs.org/guide/routing). 7 | -------------------------------------------------------------------------------- /examples/nuxtjs/pages/index.vue: -------------------------------------------------------------------------------- 1 | 15 | 16 | 25 | 26 | 58 | -------------------------------------------------------------------------------- /examples/nuxtjs/plugins/README.md: -------------------------------------------------------------------------------- 1 | # PLUGINS 2 | 3 | **This directory is not required, you can delete it if you don't want to use it.** 4 | 5 | This directory contains Javascript plugins that you want to run before mounting the root Vue.js application. 6 | 7 | More information about the usage of this directory in [the documentation](https://nuxtjs.org/guide/plugins). 8 | -------------------------------------------------------------------------------- /examples/nuxtjs/serverless.yml: -------------------------------------------------------------------------------- 1 | app: appDemo 2 | stage: dev 3 | component: nuxtjs 4 | name: nuxtjsDemo 5 | inputs: 6 | src: 7 | hook: npm run build 8 | dist: ./ 9 | exclude: 10 | - .env 11 | region: ap-guangzhou 12 | functionConf: 13 | name: ${name} 14 | runtime: Nodejs10.15 15 | apigatewayConf: 16 | protocols: 17 | - http 18 | - https 19 | environment: release 20 | staticConf: 21 | cosConf: 22 | replace: true 23 | bucket: nuxtjs-demo 24 | -------------------------------------------------------------------------------- /examples/nuxtjs/static/README.md: -------------------------------------------------------------------------------- 1 | # STATIC 2 | 3 | **This directory is not required, you can delete it if you don't want to use it.** 4 | 5 | This directory contains your static files. 6 | Each file inside this directory is mapped to `/`. 7 | Thus you'd want to delete this README.md before deploying to production. 8 | 9 | Example: `/static/robots.txt` is mapped as `/robots.txt`. 10 | 11 | More information about the usage of this directory in [the documentation](https://nuxtjs.org/guide/assets#static). 12 | -------------------------------------------------------------------------------- /examples/nuxtjs/static/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/serverless-components/tencent-framework-components/97c001520604ea54a3ee8e78c177dc421942dc8c/examples/nuxtjs/static/favicon.ico -------------------------------------------------------------------------------- /examples/nuxtjs/store/README.md: -------------------------------------------------------------------------------- 1 | # STORE 2 | 3 | **This directory is not required, you can delete it if you don't want to use it.** 4 | 5 | This directory contains your Vuex Store files. 6 | Vuex Store option is implemented in the Nuxt.js framework. 7 | 8 | Creating a file in this directory automatically activates the option in the framework. 9 | 10 | More information about the usage of this directory in [the documentation](https://nuxtjs.org/guide/vuex-store). 11 | -------------------------------------------------------------------------------- /examples/thinkphp/.example.env: -------------------------------------------------------------------------------- 1 | APP_DEBUG = true 2 | 3 | [APP] 4 | DEFAULT_TIMEZONE = Asia/Shanghai 5 | 6 | [DATABASE] 7 | TYPE = mysql 8 | HOSTNAME = 127.0.0.1 9 | DATABASE = test 10 | USERNAME = username 11 | PASSWORD = password 12 | HOSTPORT = 3306 13 | CHARSET = utf8 14 | DEBUG = true 15 | 16 | [LANG] 17 | default_lang = zh-cn 18 | 19 | # tencent auth 20 | TENCENT_SECRET_ID=123 21 | TENCENT_SECRET_KEY=123 22 | -------------------------------------------------------------------------------- /examples/thinkphp/.gitignore: -------------------------------------------------------------------------------- 1 | /.idea 2 | /.vscode 3 | /vendor 4 | *.log 5 | .env 6 | composer.lock 7 | -------------------------------------------------------------------------------- /examples/thinkphp/.travis.yml: -------------------------------------------------------------------------------- 1 | sudo: false 2 | 3 | language: php 4 | 5 | branches: 6 | only: 7 | - stable 8 | 9 | cache: 10 | directories: 11 | - $HOME/.composer/cache 12 | 13 | before_install: 14 | - composer self-update 15 | 16 | install: 17 | - composer install --no-dev --no-interaction --ignore-platform-reqs 18 | - zip -r --exclude='*.git*' --exclude='*.zip' --exclude='*.travis.yml' ThinkPHP_Core.zip . 19 | - composer require --update-no-dev --no-interaction "topthink/think-image:^1.0" 20 | - composer require --update-no-dev --no-interaction "topthink/think-migration:^1.0" 21 | - composer require --update-no-dev --no-interaction "topthink/think-captcha:^1.0" 22 | - composer require --update-no-dev --no-interaction "topthink/think-mongo:^1.0" 23 | - composer require --update-no-dev --no-interaction "topthink/think-worker:^1.0" 24 | - composer require --update-no-dev --no-interaction "topthink/think-helper:^1.0" 25 | - composer require --update-no-dev --no-interaction "topthink/think-queue:^1.0" 26 | - composer require --update-no-dev --no-interaction "topthink/think-angular:^1.0" 27 | - composer require --dev --update-no-dev --no-interaction "topthink/think-testing:^1.0" 28 | - zip -r --exclude='*.git*' --exclude='*.zip' --exclude='*.travis.yml' ThinkPHP_Full.zip . 29 | 30 | script: 31 | - php think unit 32 | 33 | deploy: 34 | provider: releases 35 | api_key: 36 | secure: TSF6bnl2JYN72UQOORAJYL+CqIryP2gHVKt6grfveQ7d9rleAEoxlq6PWxbvTI4jZ5nrPpUcBUpWIJHNgVcs+bzLFtyh5THaLqm39uCgBbrW7M8rI26L8sBh/6nsdtGgdeQrO/cLu31QoTzbwuz1WfAVoCdCkOSZeXyT/CclH99qV6RYyQYqaD2wpRjrhA5O4fSsEkiPVuk0GaOogFlrQHx+C+lHnf6pa1KxEoN1A0UxxVfGX6K4y5g4WQDO5zT4bLeubkWOXK0G51XSvACDOZVIyLdjApaOFTwamPcD3S1tfvuxRWWvsCD5ljFvb2kSmx5BIBNwN80MzuBmrGIC27XLGOxyMerwKxB6DskNUO9PflKHDPI61DRq0FTy1fv70SFMSiAtUv9aJRT41NQh9iJJ0vC8dl+xcxrWIjU1GG6+l/ZcRqVx9V1VuGQsLKndGhja7SQ+X1slHl76fRq223sMOql7MFCd0vvvxVQ2V39CcFKao/LB1aPH3VhODDEyxwx6aXoTznvC/QPepgWsHOWQzKj9ftsgDbsNiyFlXL4cu8DWUty6rQy8zT2b4O8b1xjcwSUCsy+auEjBamzQkMJFNlZAIUrukL/NbUhQU37TAbwsFyz7X0E/u/VMle/nBCNAzgkMwAUjiHM6FqrKKBRWFbPrSIixjfjkCnrMEPw= 37 | file: 38 | - ThinkPHP_Core.zip 39 | - ThinkPHP_Full.zip 40 | skip_cleanup: true 41 | on: 42 | tags: true 43 | -------------------------------------------------------------------------------- /examples/thinkphp/README.md: -------------------------------------------------------------------------------- 1 | [![Tencent ThinkPHP Serverless Component](https://img.serverlesscloud.cn/2020310/1583829094880-thinkPHP_%E9%95%BF.png)](http://serverless.com) 2 | 3 | # 腾讯云 ThinkPHP Serverless Component 4 | 5 | 简体中文 | [English](https://github.com/serverless-components/tencent-thinkphp/blob/master/README.en.md) 6 | 7 | ## 简介 8 | 9 | 腾讯云 [ThinkPHP](https://github.com/top-think/think) Serverless Component, 支持 Restful API 服务的部署。 10 | 11 | > 注意:支持 ThinkPHP >= 6.x 12 | 13 | ## 目录 14 | 15 | 0. [准备](#0-准备) 16 | 1. [安装](#1-安装) 17 | 1. [配置](#2-配置) 18 | 1. [部署](#3-部署) 19 | 1. [移除](#4-移除) 20 | 21 | ### 0. 准备 22 | 23 | #### 初始化 ThinkPHP 项目 24 | 25 | 在使用此组件之前,你需要先自己初始化一个 `ThinkPHP` 项目 26 | 27 | ```bash 28 | $ composer create-project topthink/think serverless-thinkphp 29 | ``` 30 | 31 | > 注意:ThinkPHP 使用 Composer 管理依赖的,所以你需要先自行安装 Composer,请参考 [官方安装文档](https://getcomposer.org/doc/00-intro.md#installation-linux-unix-macos) 32 | 33 | ### 1. 安装 34 | 35 | 通过 npm 全局安装 [serverless cli](https://github.com/serverless/serverless) 36 | 37 | ```bash 38 | $ npm install -g serverless 39 | ``` 40 | 41 | ### 2. 配置 42 | 43 | 在项目根目录,创建 `serverless.yml` 文件,在其中进行如下配置 44 | 45 | ```bash 46 | $ touch serverless.yml 47 | ``` 48 | 49 | ```yml 50 | # serverless.yml 51 | org: orgDemo 52 | app: appDemo 53 | stage: dev 54 | component: thinkphp 55 | name: thinkphpDemo 56 | 57 | inputs: 58 | src: ./ # (optional) path to the source folder. default is a hello world app. 59 | region: ap-guangzhou 60 | runtime: Php7 61 | apigatewayConf: 62 | protocols: 63 | - http 64 | - https 65 | environment: release 66 | ``` 67 | 68 | - [更多配置](https://github.com/serverless-components/tencent-thinkphp/tree/master/docs/configure.md) 69 | 70 | ### 3. 部署 71 | 72 | > 注意:**在部署前,你需要先清理本地运行的配置缓存,执行 `php think clear` 即可。** 73 | 74 | 如您的账号未 [登陆](https://cloud.tencent.com/login) 或 [注册](https://cloud.tencent.com/register) 腾讯云,您可以直接通过 `微信` 扫描命令行中的二维码进行授权登陆和注册。 75 | 76 | 通过 `sls` 命令进行部署,并可以添加 `--debug` 参数查看部署过程中的信息 77 | 78 | ```bash 79 | $ sls deploy --debug 80 | ``` 81 | 82 | > 注意: `sls` 是 `serverless` 命令的简写。 83 | 84 | ### 4. 移除 85 | 86 | 通过以下命令移除部署的 API 网关 87 | 88 | ```bash 89 | $ sls remove --debug 90 | ``` 91 | 92 | ### 账号配置(可选) 93 | 94 | 当前默认支持 CLI 扫描二维码登录,如您希望配置持久的环境变量/秘钥信息,也可以本地创建 `.env` 文件 95 | 96 | 在 `.env` 文件中配置腾讯云的 SecretId 和 SecretKey 信息并保存 97 | 98 | 如果没有腾讯云账号,可以在此 [注册新账号](https://cloud.tencent.com/register)。 99 | 100 | 如果已有腾讯云账号,可以在 [API 密钥管理](https://console.cloud.tencent.com/cam/capi) 中获取 `SecretId` 和`SecretKey`. 101 | 102 | ```text 103 | # .env 104 | TENCENT_SECRET_ID=123 105 | TENCENT_SECRET_KEY=123 106 | ``` 107 | 108 | ### 更多组件 109 | 110 | 可以在 [Serverless Components](https://github.com/serverless/components) repo 中查询更多组件的信息。 111 | -------------------------------------------------------------------------------- /examples/thinkphp/__test__/sl_test.php: -------------------------------------------------------------------------------- 1 | false, 7 | "requestContext" => [ 8 | "serviceId" => "service-abcdefg", 9 | "path" => "/event", 10 | "httpMethod" => "GET", 11 | "requestId" => "c6af9ac6-7b61-11e6-9a41-93e8deadbeef", 12 | "sourceIp" => "10.0.2.14", 13 | "stage" => "release" 14 | ], 15 | "headers" => [ 16 | "accept-Language" => "en-US,en,cn", 17 | "accept" => "text/html,application/xml,application/json", 18 | "host" => "localhost", 19 | "user-Agent" => "User Agent String" 20 | ], 21 | "pathParameters" => [ 22 | "path" => "value" 23 | ], 24 | "queryStringParameters" => [ 25 | "foo" => "bar" 26 | ], 27 | "headerParameters" => [ 28 | "Refer" => "127.0.0.1" 29 | ], 30 | "stageVariables" => [ 31 | "stage" => "release" 32 | ], 33 | "path" => "/event", 34 | "queryString" => [ 35 | "foo" => "bar", 36 | "bob" => "alice" 37 | ], 38 | "httpMethod" => "GET" 39 | ]; 40 | 41 | 42 | $res = handler($event, null); 43 | 44 | var_dump($res); 45 | -------------------------------------------------------------------------------- /examples/thinkphp/app/.htaccess: -------------------------------------------------------------------------------- 1 | deny from all -------------------------------------------------------------------------------- /examples/thinkphp/app/AppService.php: -------------------------------------------------------------------------------- 1 | app = $app; 47 | $this->request = $this->app->request; 48 | 49 | // 控制器初始化 50 | $this->initialize(); 51 | } 52 | 53 | // 初始化 54 | protected function initialize() 55 | {} 56 | 57 | /** 58 | * 验证数据 59 | * @access protected 60 | * @param array $data 数据 61 | * @param string|array $validate 验证器名或者验证规则数组 62 | * @param array $message 提示信息 63 | * @param bool $batch 是否批量验证 64 | * @return array|string|true 65 | * @throws ValidateException 66 | */ 67 | protected function validate(array $data, $validate, array $message = [], bool $batch = false) 68 | { 69 | if (is_array($validate)) { 70 | $v = new Validate(); 71 | $v->rule($validate); 72 | } else { 73 | if (strpos($validate, '.')) { 74 | // 支持场景 75 | [$validate, $scene] = explode('.', $validate); 76 | } 77 | $class = false !== strpos($validate, '\\') ? $validate : $this->app->parseClass('validate', $validate); 78 | $v = new $class(); 79 | if (!empty($scene)) { 80 | $v->scene($scene); 81 | } 82 | } 83 | 84 | $v->message($message); 85 | 86 | // 是否批量验证 87 | if ($batch || $this->batchValidate) { 88 | $v->batch(true); 89 | } 90 | 91 | return $v->failException(true)->check($data); 92 | } 93 | 94 | } 95 | -------------------------------------------------------------------------------- /examples/thinkphp/app/ExceptionHandle.php: -------------------------------------------------------------------------------- 1 | get(); 23 | return json([ 24 | "title" => 'serverless', 25 | "get" => $inputs 26 | ]); 27 | } 28 | 29 | public function createPost(Request $request) { 30 | $inputs = $request->post(); 31 | return json([ 32 | "title" => 'serverless', 33 | "post" => $inputs 34 | ]); 35 | } 36 | 37 | public function upload(Request $request) { 38 | $avatar = $request->file('avatar'); 39 | if ($avatar) { 40 | $savename = \think\facade\Filesystem::putFile('avatar', $avatar); 41 | } 42 | 43 | return json([ 44 | "title" => 'serverless', 45 | "upload" => $savename ?? null 46 | ]); 47 | } 48 | 49 | public function event(Request $request) { 50 | $event = $request->__SLS_EVENT__; 51 | return json([ 52 | "event" => $event, 53 | ]); 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /examples/thinkphp/app/event.php: -------------------------------------------------------------------------------- 1 | [ 5 | ], 6 | 7 | 'listen' => [ 8 | 'AppInit' => [], 9 | 'HttpRun' => [], 10 | 'HttpEnd' => [], 11 | 'LogLevel' => [], 12 | 'LogWrite' => [], 13 | ], 14 | 15 | 'subscribe' => [ 16 | ], 17 | ]; 18 | -------------------------------------------------------------------------------- /examples/thinkphp/app/middleware.php: -------------------------------------------------------------------------------- 1 | Request::class, 8 | 'think\exception\Handle' => ExceptionHandle::class, 9 | ]; 10 | -------------------------------------------------------------------------------- /examples/thinkphp/app/service.php: -------------------------------------------------------------------------------- 1 | =7.1.0", 24 | "topthink/framework": "^6.0.0", 25 | "topthink/think-orm": "^2.0", 26 | "topthink/think-view": "^1.0" 27 | }, 28 | "require-dev": { 29 | "symfony/var-dumper": "^4.2", 30 | "topthink/think-trace":"^1.0" 31 | }, 32 | "autoload": { 33 | "psr-4": { 34 | "app\\": "app" 35 | }, 36 | "psr-0": { 37 | "": "extend/" 38 | } 39 | }, 40 | "config": { 41 | "preferred-install": "dist" 42 | }, 43 | "scripts": { 44 | "post-autoload-dump": [ 45 | "@php think service:discover", 46 | "@php think vendor:publish" 47 | ] 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /examples/thinkphp/config/app.php: -------------------------------------------------------------------------------- 1 | env('app.host', ''), 9 | // 应用的命名空间 10 | 'app_namespace' => '', 11 | // 是否启用路由 12 | 'with_route' => true, 13 | // 是否启用事件 14 | 'with_event' => true, 15 | // 默认应用 16 | 'default_app' => 'index', 17 | // 默认时区 18 | 'default_timezone' => 'Asia/Shanghai', 19 | 20 | // 应用映射(自动多应用模式有效) 21 | 'app_map' => [], 22 | // 域名绑定(自动多应用模式有效) 23 | 'domain_bind' => [], 24 | // 禁止URL访问的应用列表(自动多应用模式有效) 25 | 'deny_app_list' => [], 26 | 27 | // 异常页面的模板文件 28 | 'exception_tmpl' => app()->getThinkPath() . 'tpl/think_exception.tpl', 29 | 30 | // 错误显示信息,非调试模式有效 31 | 'error_message' => '页面错误!请稍后再试~', 32 | // 显示错误信息 33 | 'show_error_msg' => false, 34 | ]; 35 | -------------------------------------------------------------------------------- /examples/thinkphp/config/cache.php: -------------------------------------------------------------------------------- 1 | env('cache.driver', 'file'), 10 | 11 | // 缓存连接方式配置 12 | 'stores' => [ 13 | 'file' => [ 14 | // 驱动方式 15 | 'type' => 'File', 16 | // 缓存保存目录 17 | 'path' => '', 18 | // 缓存前缀 19 | 'prefix' => '', 20 | // 缓存有效期 0表示永久缓存 21 | 'expire' => 0, 22 | // 缓存标签前缀 23 | 'tag_prefix' => 'tag:', 24 | // 序列化机制 例如 ['serialize', 'unserialize'] 25 | 'serialize' => [], 26 | ], 27 | // 更多的缓存连接 28 | ], 29 | ]; 30 | -------------------------------------------------------------------------------- /examples/thinkphp/config/console.php: -------------------------------------------------------------------------------- 1 | [ 8 | ], 9 | ]; 10 | -------------------------------------------------------------------------------- /examples/thinkphp/config/cookie.php: -------------------------------------------------------------------------------- 1 | 0, 8 | // cookie 保存路径 9 | 'path' => '/', 10 | // cookie 有效域名 11 | 'domain' => '', 12 | // cookie 启用安全传输 13 | 'secure' => false, 14 | // httponly设置 15 | 'httponly' => false, 16 | // 是否使用 setcookie 17 | 'setcookie' => true, 18 | ]; 19 | -------------------------------------------------------------------------------- /examples/thinkphp/config/database.php: -------------------------------------------------------------------------------- 1 | env('database.driver', 'mysql'), 6 | 7 | // 自定义时间查询规则 8 | 'time_query_rule' => [], 9 | 10 | // 自动写入时间戳字段 11 | // true为自动识别类型 false关闭 12 | // 字符串则明确指定时间字段类型 支持 int timestamp datetime date 13 | 'auto_timestamp' => true, 14 | 15 | // 时间字段取出后的默认时间格式 16 | 'datetime_format' => 'Y-m-d H:i:s', 17 | 18 | // 数据库连接配置信息 19 | 'connections' => [ 20 | 'mysql' => [ 21 | // 数据库类型 22 | 'type' => env('database.type', 'mysql'), 23 | // 服务器地址 24 | 'hostname' => env('database.hostname', '127.0.0.1'), 25 | // 数据库名 26 | 'database' => env('database.database', ''), 27 | // 用户名 28 | 'username' => env('database.username', 'root'), 29 | // 密码 30 | 'password' => env('database.password', ''), 31 | // 端口 32 | 'hostport' => env('database.hostport', '3306'), 33 | // 数据库连接参数 34 | 'params' => [], 35 | // 数据库编码默认采用utf8 36 | 'charset' => env('database.charset', 'utf8'), 37 | // 数据库表前缀 38 | 'prefix' => env('database.prefix', ''), 39 | 40 | // 数据库部署方式:0 集中式(单一服务器),1 分布式(主从服务器) 41 | 'deploy' => 0, 42 | // 数据库读写是否分离 主从式有效 43 | 'rw_separate' => false, 44 | // 读写分离后 主服务器数量 45 | 'master_num' => 1, 46 | // 指定从服务器序号 47 | 'slave_no' => '', 48 | // 是否严格检查字段是否存在 49 | 'fields_strict' => true, 50 | // 是否需要断线重连 51 | 'break_reconnect' => false, 52 | // 监听SQL 53 | 'trigger_sql' => env('app_debug', true), 54 | // 开启字段缓存 55 | 'fields_cache' => false, 56 | // 字段缓存路径 57 | 'schema_cache_path' => app()->getRuntimePath() . 'schema' . DIRECTORY_SEPARATOR, 58 | ], 59 | 60 | // 更多的数据库配置信息 61 | ], 62 | ]; 63 | -------------------------------------------------------------------------------- /examples/thinkphp/config/filesystem.php: -------------------------------------------------------------------------------- 1 | env('filesystem.driver', 'local'), 6 | // 磁盘列表 7 | 'disks' => [ 8 | 'local' => [ 9 | 'type' => 'local', 10 | 'root' => app()->getRuntimePath() . 'storage', 11 | ], 12 | 'public' => [ 13 | // 磁盘类型 14 | 'type' => 'local', 15 | // 磁盘路径 16 | 'root' => app()->getRootPath() . 'public/storage', 17 | // 磁盘路径对应的外部URL路径 18 | 'url' => '/storage', 19 | // 可见性 20 | 'visibility' => 'public', 21 | ], 22 | // 更多的磁盘配置信息 23 | ], 24 | ]; 25 | -------------------------------------------------------------------------------- /examples/thinkphp/config/lang.php: -------------------------------------------------------------------------------- 1 | env('lang.default_lang', 'zh-cn'), 9 | // 允许的语言列表 10 | 'allow_lang_list' => [], 11 | // 多语言自动侦测变量名 12 | 'detect_var' => 'lang', 13 | // 是否使用Cookie记录 14 | 'use_cookie' => true, 15 | // 多语言cookie变量 16 | 'cookie_var' => 'think_lang', 17 | // 扩展语言包 18 | 'extend_list' => [], 19 | // Accept-Language转义为对应语言包名称 20 | 'accept_language' => [ 21 | 'zh-hans-cn' => 'zh-cn', 22 | ], 23 | // 是否支持语言分组 24 | 'allow_group' => false, 25 | ]; 26 | -------------------------------------------------------------------------------- /examples/thinkphp/config/log.php: -------------------------------------------------------------------------------- 1 | env('log.channel', 'file'), 9 | // 日志记录级别 10 | 'level' => [], 11 | // 日志类型记录的通道 ['error'=>'email',...] 12 | 'type_channel' => [], 13 | // 关闭全局日志写入 14 | 'close' => false, 15 | // 全局日志处理 支持闭包 16 | 'processor' => null, 17 | 18 | // 日志通道列表 19 | 'channels' => [ 20 | 'file' => [ 21 | // 日志记录方式 22 | 'type' => 'File', 23 | // 日志保存目录 24 | 'path' => '', 25 | // 单文件日志写入 26 | 'single' => false, 27 | // 独立日志级别 28 | 'apart_level' => [], 29 | // 最大日志文件数量 30 | 'max_files' => 0, 31 | // 使用JSON格式记录 32 | 'json' => false, 33 | // 日志处理 34 | 'processor' => null, 35 | // 关闭通道日志写入 36 | 'close' => false, 37 | // 日志输出格式化 38 | 'format' => '[%s][%s] %s', 39 | // 是否实时写入 40 | 'realtime_write' => false, 41 | ], 42 | // 其它日志通道配置 43 | ], 44 | 45 | ]; 46 | -------------------------------------------------------------------------------- /examples/thinkphp/config/middleware.php: -------------------------------------------------------------------------------- 1 | [], 6 | // 优先级设置,此数组中的中间件会按照数组中的顺序优先执行 7 | 'priority' => [], 8 | ]; 9 | -------------------------------------------------------------------------------- /examples/thinkphp/config/route.php: -------------------------------------------------------------------------------- 1 | '/', 9 | // URL伪静态后缀 10 | 'url_html_suffix' => 'html', 11 | // URL普通方式参数 用于自动生成 12 | 'url_common_param' => true, 13 | // 是否开启路由延迟解析 14 | 'url_lazy_route' => false, 15 | // 是否强制使用路由 16 | 'url_route_must' => false, 17 | // 合并路由规则 18 | 'route_rule_merge' => false, 19 | // 路由是否完全匹配 20 | 'route_complete_match' => false, 21 | // 访问控制器层名称 22 | 'controller_layer' => 'controller', 23 | // 空控制器名 24 | 'empty_controller' => 'Error', 25 | // 是否使用控制器后缀 26 | 'controller_suffix' => false, 27 | // 默认的路由变量规则 28 | 'default_route_pattern' => '[\w\.]+', 29 | // 是否开启请求缓存 true自动缓存 支持设置请求缓存规则 30 | 'request_cache' => false, 31 | // 请求缓存有效期 32 | 'request_cache_expire' => null, 33 | // 全局请求缓存排除规则 34 | 'request_cache_except' => [], 35 | // 默认控制器名 36 | 'default_controller' => 'Index', 37 | // 默认操作名 38 | 'default_action' => 'index', 39 | // 操作方法后缀 40 | 'action_suffix' => '', 41 | // 默认JSONP格式返回的处理方法 42 | 'default_jsonp_handler' => 'jsonpReturn', 43 | // 默认JSONP处理方法 44 | 'var_jsonp_handler' => 'callback', 45 | ]; 46 | -------------------------------------------------------------------------------- /examples/thinkphp/config/session.php: -------------------------------------------------------------------------------- 1 | 'PHPSESSID', 9 | // SESSION_ID的提交变量,解决flash上传跨域 10 | 'var_session_id' => '', 11 | // 驱动方式 支持file cache 12 | 'type' => 'file', 13 | // 存储连接标识 当type使用cache的时候有效 14 | 'store' => null, 15 | // 过期时间 16 | 'expire' => 1440, 17 | // 前缀 18 | 'prefix' => '', 19 | ]; 20 | -------------------------------------------------------------------------------- /examples/thinkphp/config/trace.php: -------------------------------------------------------------------------------- 1 | 'Html', 8 | // 读取的日志通道名 9 | 'channel' => '', 10 | ]; 11 | -------------------------------------------------------------------------------- /examples/thinkphp/config/view.php: -------------------------------------------------------------------------------- 1 | 'Think', 9 | // 默认模板渲染规则 1 解析为小写+下划线 2 全部转换小写 3 保持操作方法 10 | 'auto_rule' => 1, 11 | // 模板目录名 12 | 'view_dir_name' => 'view', 13 | // 模板后缀 14 | 'view_suffix' => 'html', 15 | // 模板文件名分隔符 16 | 'view_depr' => DIRECTORY_SEPARATOR, 17 | // 模板引擎普通标签开始标记 18 | 'tpl_begin' => '{', 19 | // 模板引擎普通标签结束标记 20 | 'tpl_end' => '}', 21 | // 标签库标签开始标记 22 | 'taglib_begin' => '{', 23 | // 标签库标签结束标记 24 | 'taglib_end' => '}', 25 | ]; 26 | -------------------------------------------------------------------------------- /examples/thinkphp/extend/.gitignore: -------------------------------------------------------------------------------- 1 | * 2 | !.gitignore -------------------------------------------------------------------------------- /examples/thinkphp/public/.htaccess: -------------------------------------------------------------------------------- 1 | 2 | Options +FollowSymlinks -Multiviews 3 | RewriteEngine On 4 | 5 | RewriteCond %{REQUEST_FILENAME} !-d 6 | RewriteCond %{REQUEST_FILENAME} !-f 7 | RewriteRule ^(.*)$ index.php/$1 [QSA,PT,L] 8 | 9 | -------------------------------------------------------------------------------- /examples/thinkphp/public/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/serverless-components/tencent-framework-components/97c001520604ea54a3ee8e78c177dc421942dc8c/examples/thinkphp/public/favicon.ico -------------------------------------------------------------------------------- /examples/thinkphp/public/index.php: -------------------------------------------------------------------------------- 1 | 10 | // +---------------------------------------------------------------------- 11 | 12 | // [ 应用入口文件 ] 13 | namespace think; 14 | 15 | require __DIR__ . '/../vendor/autoload.php'; 16 | 17 | // 执行HTTP应用并响应 18 | $http = (new App())->http; 19 | 20 | $response = $http->run(); 21 | 22 | $response->send(); 23 | 24 | $http->end($response); 25 | -------------------------------------------------------------------------------- /examples/thinkphp/public/robots.txt: -------------------------------------------------------------------------------- 1 | User-agent: * 2 | Disallow: 3 | -------------------------------------------------------------------------------- /examples/thinkphp/public/router.php: -------------------------------------------------------------------------------- 1 | 10 | // +---------------------------------------------------------------------- 11 | // $Id$ 12 | 13 | if (is_file($_SERVER["DOCUMENT_ROOT"] . $_SERVER["SCRIPT_NAME"])) { 14 | return false; 15 | } else { 16 | $_SERVER["SCRIPT_FILENAME"] = __DIR__ . '/index.php'; 17 | 18 | require __DIR__ . "/index.php"; 19 | } 20 | -------------------------------------------------------------------------------- /examples/thinkphp/public/static/.gitignore: -------------------------------------------------------------------------------- 1 | * 2 | !.gitignore -------------------------------------------------------------------------------- /examples/thinkphp/route/app.php: -------------------------------------------------------------------------------- 1 | 10 | // +---------------------------------------------------------------------- 11 | use think\facade\Route; 12 | 13 | Route::get('/', 'index/index'); 14 | 15 | Route::get('event', 'index/event'); 16 | 17 | Route::get('hello/:name', 'index/hello'); 18 | 19 | Route::get('posts', 'index/getPosts'); 20 | 21 | Route::post('posts', 'index/createPost'); 22 | 23 | Route::post('upload', 'index/upload'); 24 | -------------------------------------------------------------------------------- /examples/thinkphp/runtime/.gitignore: -------------------------------------------------------------------------------- 1 | * 2 | !.gitignore -------------------------------------------------------------------------------- /examples/thinkphp/serverless.yml: -------------------------------------------------------------------------------- 1 | app: appDemo 2 | stage: dev 3 | component: thinkphp 4 | name: thinkphpDemo 5 | inputs: 6 | src: ./ 7 | region: ap-guangzhou 8 | functionConf: 9 | name: ${name} 10 | runtime: Php7 11 | environments: 12 | variables: 13 | APP_ENV: production 14 | apigatewayConf: 15 | protocols: 16 | - http 17 | - https 18 | environment: release 19 | isBase64Encoded: true 20 | -------------------------------------------------------------------------------- /examples/thinkphp/think: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env php 2 | console->run(); -------------------------------------------------------------------------------- /examples/thinkphp/view/README.md: -------------------------------------------------------------------------------- 1 | 如果不使用模板,可以删除该目录 -------------------------------------------------------------------------------- /examples/thinkphp/view/index/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | Serverless - ThinkPHP 9 | 16 | 17 | 18 |

19 | 欢迎访问 ThinkPHP 应用 20 |
21 | 22 | 腾讯云 Serverless 23 | 24 | 为您提供服务 25 |

26 | 27 | 28 | -------------------------------------------------------------------------------- /jest.config.js: -------------------------------------------------------------------------------- 1 | const { join } = require('path'); 2 | require('dotenv').config({ path: join(__dirname, '.env.test') }); 3 | 4 | const config = { 5 | verbose: true, 6 | silent: false, 7 | transform: { 8 | '^.+\\.tsx?$': 'ts-jest', 9 | }, 10 | testTimeout: 600000, 11 | testEnvironment: 'node', 12 | testRegex: '/__tests__/.*\\.(test|spec)\\.(js|ts)$', 13 | testPathIgnorePatterns: ['/node_modules/', '/__tests__/lib/', '/examples/'], 14 | moduleFileExtensions: ['ts', 'tsx', 'js', 'jsx', 'json', 'node'], 15 | }; 16 | 17 | module.exports = config; 18 | -------------------------------------------------------------------------------- /prettier.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | arrowParens: 'always', 3 | printWidth: 100, 4 | semi: true, 5 | trailingComma: 'all', 6 | singleQuote: true, 7 | tabWidth: 2, 8 | }; 9 | -------------------------------------------------------------------------------- /release.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | verifyConditions: [ 3 | '@semantic-release/changelog', 4 | '@semantic-release/git', 5 | '@semantic-release/github', 6 | ], 7 | plugins: [ 8 | [ 9 | '@semantic-release/commit-analyzer', 10 | { 11 | preset: 'angular', 12 | parserOpts: { 13 | noteKeywords: ['BREAKING CHANGE', 'BREAKING CHANGES', 'BREAKING'], 14 | }, 15 | }, 16 | ], 17 | [ 18 | '@semantic-release/release-notes-generator', 19 | { 20 | preset: 'angular', 21 | parserOpts: { 22 | noteKeywords: ['BREAKING CHANGE', 'BREAKING CHANGES', 'BREAKING'], 23 | }, 24 | writerOpts: { 25 | commitsSort: ['subject', 'scope'], 26 | }, 27 | }, 28 | ], 29 | [ 30 | '@semantic-release/changelog', 31 | { 32 | changelogFile: 'CHANGELOG.md', 33 | }, 34 | ], 35 | [ 36 | '@semantic-release/git', 37 | { 38 | assets: ['package.json', 'src/**', 'CHANGELOG.md'], 39 | message: 'chore(release): version ${nextRelease.version} \n\n${nextRelease.notes}', 40 | }, 41 | ], 42 | [ 43 | '@semantic-release/github', 44 | { 45 | assets: ['!.env'], 46 | }, 47 | ], 48 | ], 49 | }; 50 | -------------------------------------------------------------------------------- /scripts/bootstrap.ts: -------------------------------------------------------------------------------- 1 | import { join } from 'path'; 2 | import { spawnSync } from 'child_process'; 3 | 4 | const rootDir = join(__dirname, '..'); 5 | 6 | async function installDependencies(dir: string) { 7 | spawnSync('yarn', ['install'], { 8 | cwd: dir, 9 | }); 10 | } 11 | 12 | async function installShimDeps() { 13 | const needInstallFrameworks = ['express', 'koa', 'egg', 'nextjs', 'nuxtjs', 'nestjs']; 14 | const shimPath = join(rootDir, `src/_shims/`); 15 | for (let i = 0; i < needInstallFrameworks.length; i++) { 16 | const current = needInstallFrameworks[i]; 17 | console.log(`[${current}] Install dependencies`); 18 | await installDependencies(join(shimPath, current)); 19 | } 20 | } 21 | 22 | /* eslint-disable no-console*/ 23 | async function bootstrap() { 24 | console.log('[root] Install dependencies'); 25 | await installDependencies(rootDir); 26 | 27 | console.log('[src] Install dependencies'); 28 | await installDependencies(join(rootDir, 'src')); 29 | 30 | await installShimDeps(); 31 | } 32 | 33 | bootstrap(); 34 | 35 | process.on('unhandledRejection', (e) => { 36 | throw e; 37 | }); 38 | -------------------------------------------------------------------------------- /scripts/config.ts: -------------------------------------------------------------------------------- 1 | import { join } from 'path'; 2 | import { Framework } from '../typings'; 3 | 4 | export const FRAMEWORKS: Framework[] = [ 5 | 'express', 6 | 'koa', 7 | 'egg', 8 | 'nextjs', 9 | 'nuxtjs', 10 | 'nestjs', 11 | 'flask', 12 | 'django', 13 | 'laravel', 14 | 'thinkphp', 15 | ]; 16 | 17 | export const VERSION_YAML_PATH = join(__dirname, '..', 'version.yml'); 18 | 19 | export const COMPONENT_CODE_PATH = join(__dirname, '..', 'build'); 20 | -------------------------------------------------------------------------------- /scripts/logger.ts: -------------------------------------------------------------------------------- 1 | import * as chalk from 'chalk'; 2 | 3 | export const Logger = { 4 | info(msg: string) { 5 | console.log(chalk.bgWhite(chalk.black('[ INFO ] ')), msg); 6 | }, 7 | warn(msg: string) { 8 | console.log(chalk.bgYellow(chalk.black('[ WARNING ] ')), msg); 9 | }, 10 | error(msg: string) { 11 | console.log(chalk.bgRed(chalk.black('[ ERROR ] ')), msg); 12 | }, 13 | success(msg: string) { 14 | console.log(chalk.bgGreen(chalk.black('[ SUCCESS ] ')), msg); 15 | }, 16 | }; 17 | -------------------------------------------------------------------------------- /scripts/version.ts: -------------------------------------------------------------------------------- 1 | // import { join } from 'path'; 2 | import * as ora from 'ora'; 3 | import { program } from 'commander'; 4 | import { prompt } from 'inquirer'; 5 | import { inc as semverInc, ReleaseType } from 'semver'; 6 | 7 | import { Framework } from '../typings'; 8 | import { VERSION_YAML_PATH, FRAMEWORKS } from './config'; 9 | import { parseYaml, generateYaml, isSupportFramework } from './utils'; 10 | 11 | interface Options { 12 | ver: string; 13 | dev: string; 14 | framework: string; 15 | all: boolean; 16 | type: ReleaseType; 17 | } 18 | 19 | async function start(frameworks: Framework[], options: Options) { 20 | const spinner = ora().start(`Start changing...\n`); 21 | 22 | const versions = parseYaml(VERSION_YAML_PATH) as Record; 23 | 24 | let versionType: ReleaseType | undefined = undefined; 25 | let version = ''; 26 | if (options.dev) { 27 | version = 'dev'; 28 | } else if (options.ver) { 29 | version = options.ver; 30 | } else { 31 | if (!options.type) { 32 | spinner.info('No version is specified'); 33 | const { type } = await prompt([ 34 | { 35 | type: 'list', 36 | name: 'type', 37 | message: 'Please select version type ?', 38 | choices: ['patch', 'minor', 'major'], 39 | }, 40 | ]); 41 | versionType = type; 42 | } else { 43 | versionType = options.type; 44 | } 45 | } 46 | 47 | for (let i = 0; i < frameworks.length; i++) { 48 | const curFramework = frameworks[i]; 49 | const curVersion = versions[curFramework]; 50 | if (versionType) { 51 | version = semverInc(curVersion, versionType) as string; 52 | } 53 | versions[curFramework] = version; 54 | await generateYaml(VERSION_YAML_PATH, versions); 55 | } 56 | 57 | spinner.stop(); 58 | } 59 | 60 | async function change(options: Options) { 61 | let frameworks: Framework[]; 62 | if (options.framework) { 63 | const { framework } = options; 64 | if (!isSupportFramework(framework)) { 65 | console.error(`[ERROR] Unsupport framework ${framework}`); 66 | return; 67 | } 68 | frameworks = [framework] as Framework[]; 69 | 70 | // await deployComponent(framework as Framework, options, spinner); 71 | } else if (options.all) { 72 | frameworks = FRAMEWORKS; 73 | } else { 74 | // ask to select framework 75 | const anwsers = await prompt([ 76 | { 77 | type: 'checkbox', 78 | name: 'frameworks', 79 | message: 'Please select framework to be deploy?', 80 | choices: FRAMEWORKS, 81 | }, 82 | ]); 83 | frameworks = anwsers.frameworks as Framework[]; 84 | } 85 | 86 | await start(frameworks, options); 87 | } 88 | 89 | async function run() { 90 | program 91 | .description('Change component version') 92 | .option('-f, --framework [framework]', 'specify framework to be deploy') 93 | .option('-t, --type [type]', 'chagne version type') 94 | .option('-a, --all [all]', 'specify all frameworks to be deploy') 95 | .option('-v, --ver [ver]', 'specify version for component') 96 | .option('-d, --dev [dev]', 'deploy dev version component') 97 | .action((options) => { 98 | change(options); 99 | }); 100 | 101 | program.parse(process.argv); 102 | } 103 | 104 | run(); 105 | -------------------------------------------------------------------------------- /src/_fixtures/public/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/serverless-components/tencent-framework-components/97c001520604ea54a3ee8e78c177dc421942dc8c/src/_fixtures/public/.gitkeep -------------------------------------------------------------------------------- /src/_shims/django/sl_handler.py: -------------------------------------------------------------------------------- 1 | import serverless_wsgi 2 | import {{django_project}}.wsgi 3 | 4 | def handler(event, context): 5 | return serverless_wsgi.handle_request({{django_project}}.wsgi.application, event, context) 6 | -------------------------------------------------------------------------------- /src/_shims/egg/handler.js: -------------------------------------------------------------------------------- 1 | const path = require('path'); 2 | const fs = require('fs'); 3 | const { createServer, proxy } = require('tencent-serverless-http'); 4 | 5 | let app; 6 | let server; 7 | 8 | module.exports.handler = async (event, context) => { 9 | if (!app) { 10 | const userSls = path.join(__dirname, '..', process.env.SLS_ENTRY_FILE); 11 | if (fs.existsSync(userSls)) { 12 | // eslint-disable-next-line 13 | console.log(`Using user custom entry file ${process.env.SLS_ENTRY_FILE}`); 14 | app = require(userSls); 15 | } else { 16 | app = require('./sls'); 17 | } 18 | 19 | // provide sls intialize hooks 20 | if (app.slsInitialize && typeof app.slsInitialize === 'function') { 21 | await app.slsInitialize() 22 | } 23 | } 24 | 25 | // attach event and context to request 26 | try { 27 | app.request.__SLS_EVENT__ = event 28 | app.request.__SLS_CONTEXT__ = context 29 | } catch (e) { 30 | // no op 31 | } 32 | 33 | // do not cache server, so we can pass latest event to server 34 | server = createServer(app.callback(), null, app.binaryTypes || []); 35 | 36 | context.callbackWaitsForEmptyEventLoop = app.callbackWaitsForEmptyEventLoop === true; 37 | 38 | const result = await proxy(server, event, context, 'PROMISE'); 39 | return result.promise; 40 | }; 41 | -------------------------------------------------------------------------------- /src/_shims/egg/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "dependencies": { 3 | "tencent-serverless-http": "^1.3.1" 4 | } 5 | } 6 | -------------------------------------------------------------------------------- /src/_shims/egg/sls.js: -------------------------------------------------------------------------------- 1 | const { Application } = require('egg') 2 | 3 | Object.defineProperty(Application.prototype, Symbol.for('egg#eggPath'), { 4 | value: '/opt' 5 | }) 6 | 7 | const app = new Application({ 8 | mode: 'single', 9 | env: 'prod' 10 | }) 11 | 12 | app.binaryTypes = ['*/*'] 13 | 14 | module.exports = app 15 | -------------------------------------------------------------------------------- /src/_shims/express/handler.js: -------------------------------------------------------------------------------- 1 | try { 2 | require('tencent-component-monitor') 3 | } catch (e) { 4 | console.log(e) 5 | } 6 | const fs = require('fs') 7 | const path = require('path') 8 | const { createServer, proxy } = require('tencent-serverless-http') 9 | 10 | let server 11 | let app 12 | 13 | module.exports.handler = async (event, context) => { 14 | if (!app) { 15 | const userSls = path.join(__dirname, '..', process.env.SLS_ENTRY_FILE) 16 | if (fs.existsSync(userSls)) { 17 | // eslint-disable-next-line 18 | console.log(`Using user custom entry file ${process.env.SLS_ENTRY_FILE}`) 19 | app = require(userSls) 20 | } else { 21 | app = require('./sls.js') 22 | } 23 | // provide sls intialize hooks 24 | if (app.slsInitialize && typeof app.slsInitialize === 'function') { 25 | await app.slsInitialize() 26 | } 27 | } 28 | 29 | // attach event and context to request 30 | try { 31 | app.request.__SLS_EVENT__ = event 32 | app.request.__SLS_CONTEXT__ = context 33 | } catch (e) { 34 | // no op 35 | } 36 | 37 | // do not cache server, so we can pass latest event to server 38 | server = createServer(app, null, app.binaryTypes || []) 39 | 40 | context.callbackWaitsForEmptyEventLoop = app.callbackWaitsForEmptyEventLoop === true 41 | 42 | const result = await proxy(server, event, context, 'PROMISE') 43 | return result.promise 44 | } 45 | -------------------------------------------------------------------------------- /src/_shims/express/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "dependencies": { 3 | "tencent-component-monitor": "^1.1.0", 4 | "tencent-serverless-http": "^1.3.1" 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /src/_shims/express/sls.js: -------------------------------------------------------------------------------- 1 | const express = require('express') 2 | const app = express() 3 | 4 | // Routes 5 | app.get(`/`, (req, res) => { 6 | res.send({ 7 | msg: `Serverless Express Application, Request received: ${req.method} - ${req.path}` 8 | }) 9 | }) 10 | 11 | // Error handler 12 | // eslint-disable-next-line 13 | app.use(function(err, req, res, next) { 14 | console.error(err) 15 | res.status(500).send('Internal Serverless Error') 16 | }) 17 | 18 | module.exports = app 19 | -------------------------------------------------------------------------------- /src/_shims/flask/sl_handler.py: -------------------------------------------------------------------------------- 1 | import app # Replace with your actual application 2 | import serverless_wsgi 3 | 4 | # If you need to send additional content types as text, add then directly 5 | # to the whitelist: 6 | # 7 | # serverless_wsgi.TEXT_MIME_TYPES.append("application/custom+json") 8 | 9 | def handler(event, context): 10 | return serverless_wsgi.handle_request(app.app, event, context) 11 | -------------------------------------------------------------------------------- /src/_shims/koa/handler.js: -------------------------------------------------------------------------------- 1 | const fs = require('fs') 2 | const path = require('path') 3 | const { createServer, proxy } = require('tencent-serverless-http') 4 | 5 | let server 6 | let app 7 | 8 | exports.handler = async (event, context) => { 9 | if (!app) { 10 | const userSls = path.join(__dirname, '..', process.env.SLS_ENTRY_FILE) 11 | if (fs.existsSync(userSls)) { 12 | // eslint-disable-next-line 13 | console.log(`Using user custom entry file ${process.env.SLS_ENTRY_FILE}`) 14 | app = require(userSls) 15 | } else { 16 | app = require('./sls.js') 17 | } 18 | 19 | // provide sls intialize hooks 20 | if (app.slsInitialize && typeof app.slsInitialize === 'function') { 21 | await app.slsInitialize() 22 | } 23 | } 24 | 25 | // attach event and context to request 26 | try { 27 | app.request.__SLS_EVENT__ = event 28 | app.request.__SLS_CONTEXT__ = context 29 | } catch (e) { 30 | // no op 31 | } 32 | 33 | // do not cache server, so we can pass latest event to server 34 | server = createServer(app.callback(), null, app.binaryTypes || []) 35 | 36 | context.callbackWaitsForEmptyEventLoop = app.callbackWaitsForEmptyEventLoop === true 37 | 38 | const result = await proxy(server, event, context, 'PROMISE') 39 | return result.promise 40 | } 41 | -------------------------------------------------------------------------------- /src/_shims/koa/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "dependencies": { 3 | "tencent-serverless-http": "^1.3.1" 4 | } 5 | } 6 | -------------------------------------------------------------------------------- /src/_shims/koa/sls.js: -------------------------------------------------------------------------------- 1 | const Koa = require('koa') 2 | 3 | const app = new Koa() 4 | 5 | app.use(async (ctx, next) => { 6 | if (ctx.path !== '/') { 7 | return next() 8 | } 9 | ctx.body = { 10 | msg: `Serverless Express Application, Request received: ${ctx.req.method} - ${ctx.req.path}` 11 | } 12 | }) 13 | 14 | // don't forget to export! 15 | module.exports = app 16 | -------------------------------------------------------------------------------- /src/_shims/nestjs/handler.js: -------------------------------------------------------------------------------- 1 | const path = require('path') 2 | const { createServer, proxy } = require('tencent-serverless-http') 3 | const userSls = path.join(__dirname, '..', 'sls.js') 4 | const getApp = require(userSls) 5 | 6 | let app 7 | let server 8 | 9 | exports.handler = async (event, context) => { 10 | // cache nestjs application 11 | if (!app) { 12 | const nestApp = await getApp() 13 | await nestApp.init() 14 | app = nestApp.getHttpAdapter().getInstance() 15 | 16 | // provide sls intialize hooks 17 | if (app.slsInitialize && typeof app.slsInitialize === 'function') { 18 | await app.slsInitialize() 19 | } 20 | } 21 | 22 | // attach event and context to request 23 | try { 24 | app.request.__SLS_EVENT__ = event 25 | app.request.__SLS_CONTEXT__ = context 26 | } catch (e) { 27 | // no op 28 | } 29 | 30 | // do not cache server, so we can pass latest event to server 31 | server = createServer( 32 | app.callback && typeof app.callback === 'function' ? app.callback() : app, 33 | null, 34 | app.binaryTypes || [] 35 | ) 36 | 37 | context.callbackWaitsForEmptyEventLoop = app.callbackWaitsForEmptyEventLoop === true 38 | 39 | const { promise } = await proxy(server, event, context, 'PROMISE') 40 | return promise 41 | } 42 | -------------------------------------------------------------------------------- /src/_shims/nestjs/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "dependencies": { 3 | "tencent-serverless-http": "^1.3.1" 4 | } 5 | } 6 | -------------------------------------------------------------------------------- /src/_shims/nextjs/handler.js: -------------------------------------------------------------------------------- 1 | try { 2 | require('tencent-component-monitor') 3 | } catch (e) { 4 | console.log(e) 5 | } 6 | const fs = require('fs') 7 | const path = require('path') 8 | const { createServer, proxy } = require('tencent-serverless-http') 9 | 10 | let server 11 | let app 12 | 13 | module.exports.handler = async (event, context) => { 14 | if (!app) { 15 | const userSls = path.join(__dirname, '..', process.env.SLS_ENTRY_FILE) 16 | if (fs.existsSync(userSls)) { 17 | // eslint-disable-next-line 18 | console.log(`Using user custom entry file ${process.env.SLS_ENTRY_FILE}`) 19 | app = await require(userSls)(true) 20 | } else { 21 | app = await require('./sls')(false) 22 | } 23 | 24 | // provide sls intialize hooks 25 | if (app.slsInitialize && typeof app.slsInitialize === 'function') { 26 | await app.slsInitialize() 27 | } 28 | } 29 | 30 | // attach event and context to request 31 | try { 32 | app.request.__SLS_EVENT__ = event 33 | app.request.__SLS_CONTEXT__ = context 34 | } catch (e) { 35 | // no op 36 | } 37 | 38 | // do not cache server, so we can pass latest event to server 39 | server = createServer( 40 | app.callback && typeof app.callback === 'function' ? app.callback() : app, 41 | null, 42 | app.binaryTypes || [] 43 | ) 44 | 45 | context.callbackWaitsForEmptyEventLoop = app.callbackWaitsForEmptyEventLoop === true 46 | 47 | const { promise } = await proxy(server, event, context, 'PROMISE') 48 | return promise 49 | } 50 | -------------------------------------------------------------------------------- /src/_shims/nextjs/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "dependencies": { 3 | "express": "^4.17.1", 4 | "tencent-component-monitor": "^1.1.0", 5 | "tencent-serverless-http": "^1.3.1" 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /src/_shims/nextjs/sls.js: -------------------------------------------------------------------------------- 1 | const express = require('express') 2 | const next = require('next') 3 | 4 | async function createServer() { 5 | const app = next({ dev: false }) 6 | const handle = app.getRequestHandler() 7 | 8 | // not report route for custom monitor 9 | const noReportRoutes = ['/_next', '/favicon.ico'] 10 | 11 | await app.prepare() 12 | const server = express() 13 | 14 | server.all('*', (req, res) => { 15 | noReportRoutes.forEach((route) => { 16 | if (req.path.indexOf(route) === 0) { 17 | req.__SLS_NO_REPORT__ = true 18 | } 19 | }) 20 | return handle(req, res) 21 | }) 22 | 23 | // define binary type for response 24 | // if includes, will return base64 encoded, very useful for images 25 | server.binaryTypes = ['*/*'] 26 | 27 | // 返回 server 28 | return server 29 | } 30 | 31 | module.exports = createServer 32 | -------------------------------------------------------------------------------- /src/_shims/nuxtjs/handler.js: -------------------------------------------------------------------------------- 1 | try { 2 | require('tencent-component-monitor') 3 | } catch (e) { 4 | console.log(e) 5 | } 6 | const fs = require('fs') 7 | const path = require('path') 8 | const { createServer, proxy } = require('tencent-serverless-http') 9 | 10 | let app 11 | let server 12 | 13 | module.exports.handler = async (event, context) => { 14 | if (!app) { 15 | const userSls = path.join(__dirname, '..', process.env.SLS_ENTRY_FILE) 16 | if (fs.existsSync(userSls)) { 17 | // eslint-disable-next-line 18 | console.log(`Using user custom entry file ${process.env.SLS_ENTRY_FILE}`) 19 | app = await require(userSls)(true) 20 | } else { 21 | app = await require('./sls')(false) 22 | } 23 | 24 | 25 | // provide sls intialize hooks 26 | if (app.slsInitialize && typeof app.slsInitialize === 'function') { 27 | await app.slsInitialize() 28 | } 29 | } 30 | 31 | // attach event and context to request 32 | try { 33 | app.request.__SLS_EVENT__ = event 34 | app.request.__SLS_CONTEXT__ = context 35 | } catch (e) { 36 | // no op 37 | } 38 | 39 | // do not cache server, so we can pass latest event to server 40 | server = createServer( 41 | app.callback && typeof app.callback === 'function' ? app.callback() : app, 42 | null, 43 | app.binaryTypes || [] 44 | ) 45 | 46 | context.callbackWaitsForEmptyEventLoop = app.callbackWaitsForEmptyEventLoop === true 47 | 48 | const { promise } = await proxy(server, event, context, 'PROMISE') 49 | return promise 50 | } 51 | -------------------------------------------------------------------------------- /src/_shims/nuxtjs/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "dependencies": { 3 | "express": "^4.17.1", 4 | "tencent-component-monitor": "^1.1.0", 5 | "tencent-serverless-http": "^1.3.1" 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /src/_shims/nuxtjs/sls.js: -------------------------------------------------------------------------------- 1 | const express = require('express') 2 | const { loadNuxt } = require('nuxt') 3 | 4 | async function createServer() { 5 | // not report route for custom monitor 6 | const noReportRoutes = ['/_nuxt', '/static', '/favicon.ico'] 7 | 8 | const server = express() 9 | const nuxt = await loadNuxt('start') 10 | 11 | server.all('*', (req, res, next) => { 12 | noReportRoutes.forEach((route) => { 13 | if (req.path.indexOf(route) === 0) { 14 | req.__SLS_NO_REPORT__ = true 15 | } 16 | }) 17 | return nuxt.render(req, res, next) 18 | }) 19 | 20 | // define binary type for response 21 | // if includes, will return base64 encoded, very useful for images 22 | server.binaryTypes = ['*/*'] 23 | 24 | // 返回 server 25 | return server 26 | } 27 | 28 | module.exports = createServer 29 | -------------------------------------------------------------------------------- /src/interface/index.ts: -------------------------------------------------------------------------------- 1 | export * from './inputs'; 2 | export * from './outputs'; 3 | export * from './state'; 4 | export type Framework = 5 | | 'express' 6 | | 'koa' 7 | | 'egg' 8 | | 'nextjs' 9 | | 'nuxtjs' 10 | | 'nestjs' 11 | | 'flask' 12 | | 'django' 13 | | 'laravel' 14 | | 'thinkphp'; 15 | -------------------------------------------------------------------------------- /src/interface/outputs.ts: -------------------------------------------------------------------------------- 1 | import { ApigwBindCustomDomainOutputs } from 'tencent-component-toolkit/lib/modules/apigw/interface'; 2 | 3 | export interface ScfOutputs { 4 | configTrafficVersion?: string; 5 | lastVersion?: string; 6 | functionName: string; 7 | runtime: string; 8 | namespace: string; 9 | traffic?: number; 10 | } 11 | export type ApigwOutputs = { 12 | serviceId: string; 13 | subDomain: string | string[]; 14 | environment: 'prepub' | 'test' | 'release'; 15 | url: string; 16 | customDomains?: ApigwBindCustomDomainOutputs[]; 17 | }; 18 | 19 | export interface StaticCosOutput { 20 | region: string; 21 | cosOrigin: string; 22 | bucket?: string; 23 | url?: string; 24 | } 25 | 26 | export interface StaticOutput { 27 | cos: StaticCosOutput; 28 | cdn?: any; 29 | } 30 | 31 | export interface Outputs { 32 | templateUrl?: string; 33 | region?: string; 34 | scf?: ScfOutputs; 35 | apigw?: ApigwOutputs; 36 | staticConf?: StaticOutput; 37 | } 38 | -------------------------------------------------------------------------------- /src/interface/state.ts: -------------------------------------------------------------------------------- 1 | import { 2 | ApiEndpoint, 3 | ApigwBindCustomDomainOutputs, 4 | } from 'tencent-component-toolkit/lib/modules/apigw/interface'; 5 | import { StaticOutput } from './outputs'; 6 | 7 | export type State = { 8 | zipPath?: string; 9 | region?: string; 10 | regionList?: string[]; 11 | lambdaArn?: string; 12 | 13 | configTrafficVersion?: string; 14 | lastVersion?: string; 15 | traffic?: number; 16 | apigwDisabled?: boolean; 17 | bucket?: string; 18 | object?: string; 19 | staticConf?: StaticOutput; 20 | static?: StaticOutput; 21 | 22 | functionName?: string; 23 | runtime?: string; 24 | namespace?: string; 25 | environment: 'prepub' | 'test' | 'release'; 26 | 27 | created: boolean; 28 | serviceId: string; 29 | 30 | apiList: ApiEndpoint[]; 31 | customDomains: ApigwBindCustomDomainOutputs[]; 32 | } & Record; 33 | -------------------------------------------------------------------------------- /src/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "dependencies": { 3 | "adm-zip": "^0.4.16", 4 | "download": "^8.0.0", 5 | "fs-extra": "^9.1.0", 6 | "js-yaml": "^4.0.0", 7 | "tencent-component-toolkit": "^2.14.0" 8 | }, 9 | "devDependencies": { 10 | "@types/adm-zip": "^0.4.33", 11 | "@types/download": "^6.2.4", 12 | "@types/fs-extra": "^9.0.6", 13 | "@types/js-yaml": "^4.0.0" 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /src/serverless-core.d.ts: -------------------------------------------------------------------------------- 1 | declare module '@serverless/core' { 2 | declare class Component { 3 | state: S; 4 | credentials: { 5 | tencent: { 6 | tmpSecrets: { 7 | TmpSecretId: string; 8 | TmpSecretKey: string; 9 | Token: string; 10 | appId: string; 11 | }; 12 | }; 13 | }; 14 | 15 | save(); 16 | 17 | codeInjected: boolean; 18 | 19 | uploadSourceZipToCOS(zipPath: string, uploadUrl: string, optionsA: {}, optionsB: {}); 20 | getSDKEntries(entry: string): {}; 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /src/serverless.ts: -------------------------------------------------------------------------------- 1 | import { ServerlessComponent } from './index'; 2 | 3 | export = ServerlessComponent; 4 | -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "target": "es2017", 4 | "module": "commonjs", 5 | "strict": true, 6 | "moduleResolution": "node", 7 | "noImplicitAny": true, 8 | "rootDir": "./src", 9 | "outDir": "./build", 10 | "skipLibCheck": true, 11 | "allowJs": true, 12 | "lib": ["es2015"], 13 | "sourceMap": false, 14 | "declaration": true, 15 | "forceConsistentCasingInFileNames": true 16 | }, 17 | "include": ["./src", "./src/typings"], 18 | "exclude": ["./build", "./src/_shims/", "./src/_fixtures/"] 19 | } 20 | -------------------------------------------------------------------------------- /typings/index.ts: -------------------------------------------------------------------------------- 1 | export type Framework = 2 | | 'express' 3 | | 'koa' 4 | | 'egg' 5 | | 'nextjs' 6 | | 'nuxtjs' 7 | | 'nestjs' 8 | | 'flask' 9 | | 'django' 10 | | 'laravel' 11 | | 'thinkphp'; 12 | 13 | export interface ComponentConfig { 14 | type: string; 15 | name: string; 16 | version: string; 17 | author: string; 18 | org: string; 19 | description: string; 20 | keywords: string; 21 | repo: string; 22 | readme: string; 23 | license: string; 24 | webDeployable: boolean; 25 | src: string; 26 | } 27 | 28 | export interface SrcObject { 29 | src?: string; 30 | dist?: string; 31 | hook?: string; 32 | exclude?: string[]; 33 | targetDir?: string; 34 | bucket?: string; 35 | object?: string; 36 | } 37 | 38 | export type InputsSrc = string | SrcObject; 39 | 40 | export interface ServerlessConfig { 41 | org?: string; 42 | app?: string; 43 | stage?: string; 44 | 45 | component: string; 46 | name: string; 47 | 48 | inputs: { src?: InputsSrc } & Record; 49 | } 50 | -------------------------------------------------------------------------------- /version.yml: -------------------------------------------------------------------------------- 1 | express: 1.0.11 2 | koa: 1.0.11 3 | egg: 1.0.11 4 | nextjs: 1.0.11 5 | nuxtjs: 1.0.11 6 | nestjs: 1.0.11 7 | flask: 1.0.12 8 | django: 1.0.12 9 | laravel: 1.0.12 10 | thinkphp: 1.0.11 11 | --------------------------------------------------------------------------------