├── .editorconfig ├── .eslintignore ├── .eslintrc.js ├── .gitattributes ├── .github └── workflows │ ├── test.yml │ └── validate.yml ├── .gitignore ├── .npmignore ├── .npmrc ├── .prettierignore ├── LICENSE ├── README.md ├── __tests__ ├── express.test.ts └── lib │ └── utils.ts ├── commitlint.config.js ├── component.yml ├── deploy.md ├── docs ├── advance.md ├── configure.md ├── faq.md ├── output.md └── upload │ ├── express.md │ ├── koa.md │ ├── next.md │ └── nuxt.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 │ ├── .travis.yml │ ├── 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 ├── express │ ├── app.js │ ├── index.html │ ├── package.json │ └── serverless.yml ├── flask │ ├── .gitignore │ ├── app.py │ ├── requirements.txt │ ├── serverless.yml │ └── templates │ │ └── index.html ├── koa │ ├── app.js │ ├── index.html │ ├── package.json │ └── serverless.yml ├── laravel │ ├── .editorconfig │ ├── .env.example │ ├── .env.production │ ├── .gitattributes │ ├── .gitignore │ ├── .styleci.yml │ ├── 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 │ ├── storage │ │ └── framework │ │ │ └── views │ │ │ ├── 5974a20b5097c79d9b6e2ca48080a376f85e3940.php │ │ │ ├── 641ce7419f4834c1fb5522e743e2c36b19fafca1.php │ │ │ └── e8b4bb9e9045b5e4d42d503b4ce315a579ab90fc.php │ └── webpack.mix.js ├── nestjs │ ├── .eslintrc.js │ ├── .gitignore │ ├── .prettierrc │ ├── README.md │ ├── nest-cli.json │ ├── package.json │ ├── serverless.yml │ ├── 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 │ │ ├── global.css │ │ └── index.module.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 │ ├── 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 ├── template.ts ├── utils.ts └── version.ts ├── serverless.component.yml ├── src ├── _fixtures │ └── public │ │ └── .gitkeep ├── _shims │ ├── django │ │ └── scf_bootstrap │ ├── egg │ │ └── scf_bootstrap │ ├── express │ │ └── scf_bootstrap │ ├── flask │ │ └── scf_bootstrap │ ├── koa │ │ └── scf_bootstrap │ ├── laravel │ │ └── scf_bootstrap │ ├── nestjs │ │ └── scf_bootstrap │ ├── nextjs │ │ └── scf_bootstrap │ ├── nuxtjs │ │ └── scf_bootstrap │ └── thinkphp │ │ └── scf_bootstrap ├── config.ts ├── formatter.ts ├── index.ts ├── interface │ ├── index.ts │ ├── inputs.ts │ ├── outputs.ts │ └── state.ts ├── package.json ├── serverless.ts ├── typings │ └── serverless-core.d.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 | -------------------------------------------------------------------------------- /.eslintrc.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | root: true, 3 | extends: ['prettier', 'eslint:recommended', 'plugin:@typescript-eslint/recommended'], 4 | parser: '@typescript-eslint/parser', 5 | plugins: ['import', 'prettier', '@typescript-eslint'], 6 | env: { 7 | es6: true, 8 | jest: true, 9 | node: true, 10 | }, 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': 'off', 52 | '@typescript-eslint/no-unused-vars': ['error'], 53 | '@typescript-eslint/no-var-requires': 'off', 54 | '@typescript-eslint/no-var-requires': 'off', 55 | '@typescript-eslint/no-explicit-any': 'off', 56 | '@typescript-eslint/explicit-module-boundary-types': 'off', 57 | '@typescript-eslint/no-non-null-assertion': 'off', 58 | 59 | 'no-use-before-define': 'error', 60 | 'no-useless-constructor': 'error', 61 | 'object-curly-newline': 'off', 62 | 'object-shorthand': 'off', 63 | 'prefer-const': 'error', 64 | 'prefer-destructuring': ['error', { object: true, array: false }], 65 | quotes: [ 66 | 'error', 67 | 'single', 68 | { 69 | allowTemplateLiterals: true, 70 | avoidEscape: true, 71 | }, 72 | ], 73 | semi: ['error', 'always'], 74 | 'comma-dangle': ['error', 'always-multiline'], 75 | 'spaced-comment': 'error', 76 | strict: ['error', 'global'], 77 | 'prettier/prettier': 'error', 78 | }, 79 | }; 80 | -------------------------------------------------------------------------------- /.gitattributes: -------------------------------------------------------------------------------- 1 | src/_fixtures/** linguist-vendored 2 | examples/** linguist-vendored 3 | -------------------------------------------------------------------------------- /.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 { join } from 'path'; 2 | import { generateId, getServerlessSdk } from './lib/utils'; 3 | import { execSync } from 'child_process'; 4 | import axios from 'axios'; 5 | import { Inputs } from '../src/interface'; 6 | 7 | interface YamlConfig { 8 | org: string; 9 | app: string; 10 | component: string; 11 | name: string; 12 | stage: string; 13 | inputs: Inputs; 14 | } 15 | 16 | const cmd = encodeURIComponent('#!/usr/bin/env bash\n\n/var/lang/node12/bin/node app.js'); 17 | const instanceYaml: YamlConfig = { 18 | org: 'orgDemo', 19 | app: 'appDemo', 20 | component: 'http@dev', 21 | name: `http-integration-tests-${generateId()}`, 22 | stage: 'dev', 23 | inputs: { 24 | faas: { 25 | framework: 'express', 26 | name: `express-intergration-test-${generateId()}`, 27 | bootstrap: { cmd }, 28 | }, 29 | apigw: { 30 | protocols: ['http', 'https'], 31 | }, 32 | }, 33 | }; 34 | 35 | const credentials = { 36 | tencent: { 37 | SecretId: process.env.TENCENT_SECRET_ID, 38 | SecretKey: process.env.TENCENT_SECRET_KEY, 39 | }, 40 | }; 41 | 42 | describe('Express', () => { 43 | const sdk = getServerlessSdk(instanceYaml.org, process.env.TENCENT_APP_ID as string); 44 | 45 | it('deploy', async () => { 46 | const instance = await sdk.deploy(instanceYaml, credentials); 47 | 48 | expect(instance).toBeDefined(); 49 | expect(instance.instanceName).toEqual(instanceYaml.name); 50 | expect(instance.outputs.templateUrl).toBeDefined(); 51 | expect(instance.outputs.region).toEqual('ap-guangzhou'); 52 | expect(instance.outputs.apigw).toBeDefined(); 53 | expect(instance.outputs.apigw.environment).toEqual('release'); 54 | expect(instance.outputs.faas).toBeDefined(); 55 | expect(instance.outputs.faas.runtime).toEqual('Nodejs12.16'); 56 | expect(instance.inputs.faas.bootstrap).toBeDefined(); 57 | expect(instance.inputs.faas.bootstrap.cmd).toEqual(cmd); 58 | }); 59 | 60 | it('update source code', async () => { 61 | const srcPath = join(__dirname, '..', 'examples/express'); 62 | execSync('npm install', { cwd: srcPath }); 63 | 64 | instanceYaml.inputs.src = srcPath; 65 | 66 | const instance = await sdk.deploy(instanceYaml, credentials); 67 | const response = await axios.get(instance.outputs.apigw.url); 68 | 69 | expect(response.data.includes('Serverless')).toBeTruthy(); 70 | expect(instance.outputs.templateUrl).not.toBeDefined(); 71 | }); 72 | 73 | it('remove', async () => { 74 | await sdk.remove(instanceYaml, credentials); 75 | const result = await sdk.getInstance( 76 | instanceYaml.org, 77 | instanceYaml.stage, 78 | instanceYaml.app, 79 | instanceYaml.name, 80 | ); 81 | 82 | expect(result.instance.instanceStatus).toEqual('inactive'); 83 | }); 84 | }); 85 | -------------------------------------------------------------------------------- /__tests__/lib/utils.ts: -------------------------------------------------------------------------------- 1 | const { ServerlessSDK } = require('@serverless/platform-client-china'); 2 | 3 | const generateId = () => 4 | Math.random() 5 | .toString(36) 6 | .substring(6); 7 | 8 | const getServerlessSdk = (orgName: string, orgUid: string) => { 9 | const sdk = new ServerlessSDK({ 10 | context: { 11 | orgUid, 12 | orgName, 13 | }, 14 | }); 15 | return sdk; 16 | }; 17 | 18 | export { generateId, getServerlessSdk }; 19 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /deploy.md: -------------------------------------------------------------------------------- 1 | ## 发布文档 2 | 3 | 修改代码后,只需要执行如下命令部署: 4 | 5 | ```bash 6 | $ npm run deploy 7 | ``` 8 | 9 | 部署的组件版本将依赖项目根目录 `version.yml` 中的 `version` 字段。 10 | 11 | 也可以通过命令行指定版本: 12 | 13 | ```bash 14 | $ npm run deploy --version=1.0.0 15 | ``` 16 | -------------------------------------------------------------------------------- /docs/advance.md: -------------------------------------------------------------------------------- 1 | ## 高级配置 2 | 3 | 组件在部署 `Web` 框架应用时,默认会自动注入 `scf_bootstrap` 文件到项目中,给个框架的默认 `scf_bootstrap` 内容如下: 4 | 5 | - express - [scf_bootstrap](../src/_shims//express/scf_bootstrap) 6 | - koa - [scf_bootstrap](../src/_shims//koa/scf_bootstrap) 7 | - egg - [scf_bootstrap](../src/_shims//egg/scf_bootstrap) 8 | - nextjs - [scf_bootstrap](../src/_shims//nextjs/scf_bootstrap) 9 | - nuxtjs - [scf_bootstrap](../src/_shims//nuxtjs/scf_bootstrap) 10 | - nestjs - [scf_bootstrap](../src/_shims//nestjs/scf_bootstrap) 11 | - flask - [scf_bootstrap](../src/_shims//flask/scf_bootstrap) 12 | - django - [scf_bootstrap](../src/_shims//django/scf_bootstrap) 13 | - laravel - [scf_bootstrap](../src/_shims//laravel/scf_bootstrap) 14 | 15 | 如果需要自定义入口文件,用户可自己在项目下编写自定义的启动命令文件 `scf_bootstrap`,自定义前请注意一下几点: 16 | 17 | 1. scf_bootstrap 文件需要可执行权限 18 | 2. 监听端口必须是 `9000` 19 | 3. 云函数的不同语言的可执行命令是定制化的,必须清楚的知道该语言的可执行文件路径,否则会导致启动失败 20 | 21 | 以下为各个语言可执行文件在云函数环境的绝对路径: 22 | 23 | ```text 24 | Nodejs12.16 - /var/lang/node12/bin/node 25 | Nodejs10.15 - /var/lang/node10/bin/node 26 | 27 | Python3.6 - /var/lang/python3/bin/python3 28 | Python2.7 - /var/lang/python2/bin/python 29 | 30 | Php7 - /var/lang/php7/bin/php 31 | Php5 - /var/lang/php5/bin/php 32 | 33 | Java8 - /var/lang/java8/bin/java 34 | ``` 35 | -------------------------------------------------------------------------------- /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 | | assets | [AssetsOutput](#AssetsOutput) | 静态资源输出信息 | 14 | 15 | ## FunctionOutput 16 | 17 | 云函数输出 18 | 19 | | 名称 | 类型 | 描述 | 20 | | :-------- | :----: | :------------- | 21 | | name | string | 云函数名称 | 22 | | runtime | string | 云运行环境 | 23 | | namespace | string | 云函数名称空间 | 24 | 25 | ## ApigwOutput 26 | 27 | API 网关输出 28 | 29 | | 名称 | 类型 | 描述 | 30 | | :------------ | :-----------------------------: | :------------------------- | 31 | | id | string | API 网关 ID | 32 | | subDomain | string | API 网关子域名 | 33 | | enviroment | `"release" | "prepub" | "test"` | API 网关 | 34 | | url | string | API 网关对外的完整 URL | 35 | | traffic | number (0~1) | 将多少流量导向该云函数 | 36 | | customDomains | [CustomDomain](#CustomDomain)[] | API 网关自定义域名输出列表 | 37 | 38 | ### CustomDomain 39 | 40 | API 网关自定义域名输出 41 | 42 | | 名称 | 类型 | 描述 | 43 | | :-------- | :----: | :------------------------------ | 44 | | url | string | 自定义域名访问链接 | 45 | | subDomain | string | 自定义域名 | 46 | | cname | string | 自定义域名需要配置的 cname 记录 | 47 | 48 | ## AssetsOutput 49 | 50 | 静态资源输出 51 | 52 | | 名称 | 类型 | 描述 | 53 | | :--- | :---------: | :--------- | 54 | | cos | [Cos](#Cos) | 云函数名称 | 55 | | cdn | [Cdn](#Cdn) | 云运行环境 | 56 | 57 | ### Cos 58 | 59 | COS 配置输出 60 | 61 | | 名称 | 类型 | 描述 | 62 | | :-------- | :----: | :--------------- | 63 | | region | string | 地域 | 64 | | bucket | string | COS 桶名称 | 65 | | cosOrigin | string | COS 资源访问域名 | 66 | 67 | ### Cdn 68 | 69 | Cdn 配置输出 70 | 71 | | 名称 | 类型 | 描述 | 72 | | :----- | :----: | :----------- | 73 | | domain | string | CDN 域名 | 74 | | url | string | CDN 访问链接 | 75 | -------------------------------------------------------------------------------- /docs/upload/express.md: -------------------------------------------------------------------------------- 1 | ## 文件上传说明 2 | 3 | 由于 API 网关是将文件请求直接转发给 Web 函数,所以针对文件上传,不在需要进行 `Base64` 编码了,直接把文件内容作为参数传入即可。 4 | 5 | > 注意:当前 API 网关支持上传最大文件大小为 `2M`,如果文件过大,请修改为前端直传对象存储方案。 6 | 7 | ## 代码示例 8 | 9 | 入口文件 `app.js` 如下: 10 | 11 | ```js 12 | const multer = require('multer'); 13 | const express = require('express'); 14 | const path = require('path'); 15 | 16 | const app = express(); 17 | 18 | // Serverless 场景只能读写 /tmp 目录,所以这里需要指定上传文件的目录为 /tmp/upload 19 | const upload = multer({ dest: '/tmp/upload' }); 20 | 21 | // Routes 22 | app.post('/upload', upload.single('file'), (req, res) => { 23 | res.send({ 24 | success: true, 25 | data: req.file, 26 | }); 27 | }); 28 | // ... 29 | 30 | app.listen(9000, () => { 31 | console.log(`Server start on http://localhost:9000`); 32 | }); 33 | ``` 34 | 35 | 实例代码实现了文件上传接口 `POST /upload`,如果要支持文件上传,需要安装 `multer` 包。 36 | -------------------------------------------------------------------------------- /docs/upload/koa.md: -------------------------------------------------------------------------------- 1 | ## 文件上传说明 2 | 3 | 由于 API 网关是将文件请求直接转发给 Web 函数,所以针对文件上传,不在需要进行 Base64 编码了,直接把文件内容作为参数传入即可。 4 | 5 | > 注意:当前 API 网关支持上传最大文件大小为 `2M`,如果文件过大,请修改为前端直传对象存储方案。 6 | 7 | ## 代码 z 示例 8 | 9 | 入口文件 `app.js` 如下: 10 | 11 | ```js 12 | const Koa = require('koa'); 13 | const KoaRouter = require('@koa/router'); 14 | const multer = require('@koa/multer'); 15 | 16 | const app = new Koa(); 17 | const router = new KoaRouter(); 18 | const upload = multer({ dest: '/tmp/upload' }); 19 | 20 | router.post('/upload', upload.single('file'), (ctx) => { 21 | ctx.body = { 22 | success: true, 23 | data: ctx.file, 24 | }; 25 | }); 26 | 27 | app.use(router.routes()).use(router.allowedMethods()); 28 | 29 | app.listen(9000, () => { 30 | console.log(`Server start on http://localhost:9000`); 31 | }); 32 | ``` 33 | 34 | 示例代码实现了文件上传接口 `POST /upload`,如果要支持文件上传,需要安装 `@koajs/multer` 和 `multer` 包。 35 | -------------------------------------------------------------------------------- /docs/upload/next.md: -------------------------------------------------------------------------------- 1 | ## 文件上传说明 2 | 3 | 由于 API 网关是将文件请求直接转发给 Web 函数,所以针对文件上传,不在需要进行 `Base64` 编码了,直接把文件内容作为参数传入即可。 4 | 5 | > 注意:当前 API 网关支持上传最大文件大小为 `2M`,如果文件过大,请修改为前端直传对象存储方案。 6 | 7 | ## 代码示例 8 | 9 | 自定义服务为 Express: 10 | 11 | ```js 12 | const multer = require('multer'); 13 | const express = require('express'); 14 | const next = require('next'); 15 | 16 | const isServerless = process.env.SERVERLESS; 17 | 18 | const upload = multer({ dest: isServerless ? '/tmp/upload' : './upload' }); 19 | 20 | const server = express(); 21 | const app = next({ dev: false }); 22 | const handle = app.getRequestHandler(); 23 | 24 | server.post('/upload', upload.single('file'), (req, res) => { 25 | res.send({ 26 | success: true, 27 | data: req.file, 28 | }); 29 | }); 30 | 31 | server.all('*', (req, res, next) => { 32 | return handle(req, res); 33 | }); 34 | 35 | server.listen(9000, () => { 36 | console.log(`Server start on http://localhost:9000`); 37 | }); 38 | ``` 39 | 40 | 自定义服务为 Koa: 41 | 42 | ```js 43 | const Koa = require('koa'); 44 | const Router = require('@koa/router'); 45 | const multer = require('@koa/multer'); 46 | const next = require('next'); 47 | 48 | const isServerless = process.env.SERVERLESS; 49 | 50 | const server = new Koa(); 51 | const router = new Router(); 52 | const upload = multer({ dest: isServerless ? '/tmp/upload' : './upload' }); 53 | const app = next({ dev: false }); 54 | const handle = app.getRequestHandler(); 55 | 56 | router.post('/upload', upload.single('file'), (ctx) => { 57 | ctx.body = { 58 | success: true, 59 | data: ctx.file, 60 | }; 61 | }); 62 | 63 | server.use(router.routes()).use(router.allowedMethods()); 64 | 65 | server.use((ctx) => { 66 | ctx.status = 200; 67 | ctx.respond = false; 68 | ctx.req.ctx = ctx; 69 | 70 | return handle(ctx.req, ctx.res); 71 | }); 72 | 73 | server.listen(9000, () => { 74 | console.log(`Server start on http://localhost:9000`); 75 | }); 76 | ``` 77 | 78 | 开发者可根据个人项目需要参考修改。 79 | 80 | 上述代码中实现了文件上传接口 `POST /upload`。使用 Koa 的项目,如果要支持文件上传,需要安装 `@koajs/multer` 和 `multer` 包。使用 Express 的项目,如果要支持文件上传,需要安装 `multer` 包。 81 | -------------------------------------------------------------------------------- /docs/upload/nuxt.md: -------------------------------------------------------------------------------- 1 | ## 文件上传说明 2 | 3 | 由于 API 网关是将文件请求直接转发给 Web 函数,所以针对文件上传,不在需要进行 `Base64` 编码了,直接把文件内容作为参数传入即可。 4 | 5 | > 注意:当前 API 网关支持上传最大文件大小为 `2M`,如果文件过大,请修改为前端直传对象存储方案。 6 | 7 | ## 代码示例 8 | 9 | 自定义服务为 Express: 10 | 11 | ```js 12 | const multer = require('multer'); 13 | const express = require('express'); 14 | const { loadNuxt } = require('nuxt'); 15 | 16 | const isServerless = process.env.SERVERLESS; 17 | 18 | const upload = multer({ dest: isServerless ? '/tmp/upload' : './upload' }); 19 | 20 | const server = express(); 21 | const nuxt = await loadNuxt('start'); 22 | 23 | server.post('/upload', upload.single('file'), (req, res) => { 24 | res.send({ 25 | success: true, 26 | data: req.file, 27 | }); 28 | }); 29 | 30 | server.all('*', (req, res, next) => { 31 | return nuxt.render(req, res, next); 32 | }); 33 | 34 | server.listen(9000, () => { 35 | console.log(`Server start on http://localhost:9000`); 36 | }); 37 | ``` 38 | 39 | 自定义服务为 Koa: 40 | 41 | ```js 42 | const Koa = require('koa'); 43 | const Router = require('@koa/router'); 44 | const multer = require('@koa/multer'); 45 | 46 | const { loadNuxt } = require('nuxt'); 47 | 48 | const isServerless = process.env.SERVERLESS; 49 | 50 | const server = new Koa(); 51 | const router = new Router(); 52 | const upload = multer({ dest: isServerless ? '/tmp/upload' : './upload' }); 53 | const nuxt = await loadNuxt('start'); 54 | 55 | router.post('/upload', upload.single('file'), (ctx) => { 56 | ctx.body = { 57 | success: true, 58 | data: ctx.file, 59 | }; 60 | }); 61 | 62 | server.use(router.routes()).use(router.allowedMethods()); 63 | 64 | server.use((ctx) => { 65 | ctx.status = 200; 66 | ctx.respond = false; 67 | ctx.req.ctx = ctx; 68 | 69 | nuxt.render(ctx.req, ctx.res); 70 | }); 71 | 72 | server.listen(9000, () => { 73 | console.log(`Server start on http://localhost:9000`); 74 | }); 75 | ``` 76 | 77 | 开发者可根据个人项目需要参考修改。 78 | 79 | 上述代码中实现了文件上传接口 `POST /upload`。使用 Koa 的项目,如果要支持文件上传,需要安装 `@koajs/multer` 和 `multer` 包。使用 Express 的项目,如果要支持文件上传,需要安装 `multer` 包。 80 | -------------------------------------------------------------------------------- /examples/django/.gitignore: -------------------------------------------------------------------------------- 1 | requirements 2 | asgiref 3 | asgiref-3.3.1.dist-info 4 | asgiref-3.4.1.dist-info 5 | bin 6 | django 7 | Django-3.1.3.dist-info 8 | pytz 9 | pytz-2020.4.dist-info 10 | pytz-2021.1.dist-info 11 | sqlparse 12 | sqlparse-0.4.1.dist-info 13 | typing_extensions-3.10.0.0.dist-info 14 | typing_extensions.py 15 | -------------------------------------------------------------------------------- /examples/django/djangodemo/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/serverless-components/tencent-http/456dab08b82d9719314d7e3a6e2099dba93a752b/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/settings.py: -------------------------------------------------------------------------------- 1 | """ 2 | Django settings for djangodemo project. 3 | 4 | Generated by 'django-admin startproject' using Django 3.1.3. 5 | 6 | For more information on this file, see 7 | https://docs.djangoproject.com/en/3.1/topics/settings/ 8 | 9 | For the full list of settings and their values, see 10 | https://docs.djangoproject.com/en/3.1/ref/settings/ 11 | """ 12 | 13 | from pathlib import Path 14 | 15 | # Build paths inside the project like this: BASE_DIR / 'subdir'. 16 | BASE_DIR = Path(__file__).resolve().parent.parent 17 | 18 | 19 | # Quick-start development settings - unsuitable for production 20 | # See https://docs.djangoproject.com/en/3.1/howto/deployment/checklist/ 21 | 22 | # SECURITY WARNING: keep the secret key used in production secret! 23 | SECRET_KEY = 'tr%ez&(i@2$l#i9u)xv1kxdh#ufk^dm_vjvwa1pqwk&xc*pd*e' 24 | 25 | # SECURITY WARNING: don't run with debug turned on in production! 26 | DEBUG = True 27 | 28 | ALLOWED_HOSTS = ["*"] 29 | 30 | 31 | # Application definition 32 | 33 | INSTALLED_APPS = [ 34 | 'django.contrib.admin', 35 | 'django.contrib.auth', 36 | 'django.contrib.contenttypes', 37 | 'django.contrib.sessions', 38 | 'django.contrib.messages', 39 | 'django.contrib.staticfiles', 40 | ] 41 | 42 | MIDDLEWARE = [ 43 | 'django.middleware.security.SecurityMiddleware', 44 | 'django.contrib.sessions.middleware.SessionMiddleware', 45 | 'django.middleware.common.CommonMiddleware', 46 | 'django.middleware.csrf.CsrfViewMiddleware', 47 | 'django.contrib.auth.middleware.AuthenticationMiddleware', 48 | 'django.contrib.messages.middleware.MessageMiddleware', 49 | 'django.middleware.clickjacking.XFrameOptionsMiddleware', 50 | ] 51 | 52 | ROOT_URLCONF = 'djangodemo.urls' 53 | 54 | TEMPLATES = [ 55 | { 56 | 'BACKEND': 'django.template.backends.django.DjangoTemplates', 57 | 'DIRS': [BASE_DIR / 'templates'], 58 | 'APP_DIRS': True, 59 | 'OPTIONS': { 60 | 'context_processors': [ 61 | 'django.template.context_processors.debug', 62 | 'django.template.context_processors.request', 63 | 'django.contrib.auth.context_processors.auth', 64 | 'django.contrib.messages.context_processors.messages', 65 | ], 66 | }, 67 | }, 68 | ] 69 | 70 | WSGI_APPLICATION = 'djangodemo.wsgi.application' 71 | 72 | 73 | # Database 74 | # https://docs.djangoproject.com/en/3.1/ref/settings/#databases 75 | 76 | # DATABASES = { 77 | # 'default': { 78 | # 'ENGINE': 'django.db.backends.sqlite3', 79 | # 'NAME': BASE_DIR / 'db.sqlite3', 80 | # } 81 | # } 82 | 83 | 84 | # Password validation 85 | # https://docs.djangoproject.com/en/3.1/ref/settings/#auth-password-validators 86 | 87 | AUTH_PASSWORD_VALIDATORS = [ 88 | { 89 | 'NAME': 'django.contrib.auth.password_validation.UserAttributeSimilarityValidator', 90 | }, 91 | { 92 | 'NAME': 'django.contrib.auth.password_validation.MinimumLengthValidator', 93 | }, 94 | { 95 | 'NAME': 'django.contrib.auth.password_validation.CommonPasswordValidator', 96 | }, 97 | { 98 | 'NAME': 'django.contrib.auth.password_validation.NumericPasswordValidator', 99 | }, 100 | ] 101 | 102 | 103 | # Internationalization 104 | # https://docs.djangoproject.com/en/3.1/topics/i18n/ 105 | 106 | LANGUAGE_CODE = 'en-us' 107 | 108 | TIME_ZONE = 'UTC' 109 | 110 | USE_I18N = True 111 | 112 | USE_L10N = True 113 | 114 | USE_TZ = True 115 | 116 | 117 | # Static files (CSS, JavaScript, Images) 118 | # https://docs.djangoproject.com/en/3.1/howto/static-files/ 119 | 120 | STATIC_URL = '/static/' 121 | -------------------------------------------------------------------------------- /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 19 | 20 | 21 | urlpatterns = [ 22 | path('', index), 23 | path('admin/', admin.site.urls), 24 | ] 25 | -------------------------------------------------------------------------------- /examples/django/djangodemo/views.py: -------------------------------------------------------------------------------- 1 | from django.shortcuts import render 2 | from django.http import HttpResponse 3 | 4 | # Create your views here. 5 | 6 | def index(request): 7 | return render(request, 'index.html', context={'hello': 'world'}) 8 | 9 | def author(request): 10 | print(request) 11 | return HttpResponse("Tencent Cloud Serverless Team") 12 | -------------------------------------------------------------------------------- /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 | component: http 2 | name: djangoDemo 3 | 4 | inputs: 5 | src: 6 | # 这里会自动帮你安装依赖到当前项目根目录 7 | hook: 'pip3 install -r requirements.txt -t ./' 8 | dist: ./ 9 | exclude: 10 | - .env 11 | - '__pycache__/**' 12 | region: ap-guangzhou 13 | faas: 14 | framework: django 15 | name: ${name} 16 | runtime: Python3.6 17 | memorySize: 512 18 | apigw: 19 | protocols: 20 | - http 21 | - https 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/.travis.yml: -------------------------------------------------------------------------------- 1 | 2 | language: node_js 3 | node_js: 4 | - '10' 5 | before_install: 6 | - npm i npminstall -g 7 | install: 8 | - npminstall 9 | script: 10 | - npm run ci 11 | after_script: 12 | - npminstall codecov && codecov 13 | -------------------------------------------------------------------------------- /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": "test", 3 | "version": "1.0.0", 4 | "description": "", 5 | "private": true, 6 | "egg": { 7 | "declarations": true 8 | }, 9 | "dependencies": { 10 | "egg": "^2.15.1", 11 | "egg-scripts": "^2.11.0", 12 | "egg-view-nunjucks": "^2.3.0" 13 | }, 14 | "devDependencies": { 15 | "autod": "^3.0.1", 16 | "autod-egg": "^1.1.0", 17 | "egg-bin": "^4.11.0", 18 | "egg-ci": "^1.11.0", 19 | "egg-mock": "^3.21.0", 20 | "eslint": "^5.13.0", 21 | "eslint-config-egg": "^7.1.0" 22 | }, 23 | "engines": { 24 | "node": ">=10.0.0" 25 | }, 26 | "scripts": { 27 | "start": "egg-scripts start --title=egg-server --port=9000", 28 | "stop": "egg-scripts stop --title=egg-server-test", 29 | "dev": "egg-bin dev", 30 | "debug": "egg-bin debug", 31 | "test": "npm run lint -- --fix && npm run test-local", 32 | "test-local": "egg-bin test", 33 | "cov": "egg-bin cov", 34 | "lint": "eslint .", 35 | "ci": "npm run lint && npm run cov", 36 | "autod": "autod" 37 | }, 38 | "ci": { 39 | "version": "10" 40 | }, 41 | "repository": { 42 | "type": "git", 43 | "url": "" 44 | }, 45 | "author": "", 46 | "license": "MIT" 47 | } 48 | -------------------------------------------------------------------------------- /examples/egg/serverless.yml: -------------------------------------------------------------------------------- 1 | component: http 2 | name: eggDemo 3 | 4 | inputs: 5 | src: 6 | src: ./ 7 | exclude: 8 | - .env 9 | faas: 10 | runtime: Nodejs12.16 11 | framework: egg 12 | name: ${name} 13 | apigw: 14 | protocols: 15 | - http 16 | - https 17 | -------------------------------------------------------------------------------- /examples/express/app.js: -------------------------------------------------------------------------------- 1 | const express = require('express') 2 | const multer = require('multer'); 3 | const path = require('path') 4 | 5 | const app = express() 6 | 7 | // Serverless 场景只能读写 /tmp 目录,所以这里需要指定上传文件的目录为 /tmp/upload 8 | const upload = multer({ dest: '/tmp/upload' }); 9 | 10 | // Routes 11 | app.get(`/`, (req, res) => { 12 | res.sendFile(path.join(__dirname, 'index.html')) 13 | }) 14 | 15 | app.get('/user', (req, res) => { 16 | res.send([ 17 | { 18 | title: 'serverless framework', 19 | link: 'https://serverless.com' 20 | } 21 | ]) 22 | }) 23 | 24 | app.get('/user/:id', (req, res) => { 25 | const id = req.params.id 26 | res.send({ 27 | id: id, 28 | title: 'serverless framework', 29 | link: 'https://serverless.com' 30 | }) 31 | }) 32 | 33 | app.get('/404', (req, res) => { 34 | res.status(404).send('Not found') 35 | }) 36 | 37 | app.get('/500', (req, res) => { 38 | res.status(500).send('Server Error') 39 | }) 40 | 41 | app.post('/upload', upload.single('file'), (req, res) => { 42 | res.send({ 43 | success: true, 44 | data: req.file, 45 | }); 46 | }); 47 | 48 | // Error handler 49 | app.use(function(err, req, res, next) { 50 | console.error(err) 51 | res.status(500).send('Internal Serverless Error') 52 | }) 53 | 54 | app.listen(9000, () => { 55 | console.log(`Server start on http://localhost:9000`); 56 | }) 57 | -------------------------------------------------------------------------------- /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/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "express-demo", 3 | "version": "1.0.0", 4 | "description": "", 5 | "main": "sls.js", 6 | "scripts": { 7 | "dev": "NODE_ENV=development node app.js" 8 | }, 9 | "author": "yugasun", 10 | "license": "MIT", 11 | "dependencies": { 12 | "express": "^4.17.1", 13 | "multer": "^1.4.2" 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /examples/express/serverless.yml: -------------------------------------------------------------------------------- 1 | component: http 2 | name: expressDemo 3 | 4 | inputs: 5 | src: 6 | src: ./ 7 | exclude: 8 | - .env 9 | faas: 10 | runtime: Nodejs12.16 11 | framework: express 12 | name: ${name} 13 | apigw: 14 | protocols: 15 | - http 16 | - https 17 | -------------------------------------------------------------------------------- /examples/flask/.gitignore: -------------------------------------------------------------------------------- 1 | requirements 2 | bin 3 | click 4 | click* 5 | flask 6 | Flask* 7 | itsdangerous* 8 | importlib_metadata* 9 | jinja2 10 | Jinja2* 11 | markupsafe 12 | MarkupSafe* 13 | werkzeug 14 | Werkzeug* 15 | Misc* 16 | typing_extensions* 17 | zipp* 18 | -------------------------------------------------------------------------------- /examples/flask/app.py: -------------------------------------------------------------------------------- 1 | from flask import Flask, jsonify, render_template 2 | app = Flask(__name__) 3 | 4 | 5 | @app.route("/") 6 | def index(): 7 | return render_template('index.html') 8 | 9 | 10 | @app.route("/users") 11 | def users(): 12 | users = [{'name': 'test1'}, {'name': 'test2'}] 13 | return jsonify(data=users) 14 | 15 | 16 | @app.route("/users/") 17 | def user(id): 18 | return jsonify(data={'name': 'test1'}) 19 | 20 | # HTTP 直通函数由于是基于 docker 镜像运行,所以必须监听地址为 0.0.0.0,并且端口为 9000 21 | app.run(host = '0.0.0.0', port = 9000) 22 | -------------------------------------------------------------------------------- /examples/flask/requirements.txt: -------------------------------------------------------------------------------- 1 | Flask==1.0.2 2 | # TODO: 由于云函数运行环境 Python3.6 版本太低,werkzeug 只能使用低版本 3 | werkzeug==1.0.1 4 | -------------------------------------------------------------------------------- /examples/flask/serverless.yml: -------------------------------------------------------------------------------- 1 | component: http 2 | name: flaskDemo 3 | 4 | inputs: 5 | src: 6 | # TODO: 安装python项目依赖到项目当前目录 7 | hook: 'pip3 install -r requirements.txt -t ./' 8 | dist: ./ 9 | exclude: 10 | - .env 11 | - 'requirements/**' 12 | - '__pycache__/**' 13 | region: ap-guangzhou 14 | faas: 15 | framework: flask 16 | name: ${name} 17 | runtime: Python3.6 18 | apigw: 19 | protocols: 20 | - http 21 | - https 22 | -------------------------------------------------------------------------------- /examples/flask/templates/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | Serverless Flask 7 | 14 | 15 | 16 |

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

25 | 26 | 27 | -------------------------------------------------------------------------------- /examples/koa/app.js: -------------------------------------------------------------------------------- 1 | const Koa = require('koa') 2 | const KoaRouter = require('koa-router') 3 | const sendFile = require('koa-sendfile') 4 | const path = require('path') 5 | const multer = require('@koa/multer'); 6 | 7 | const app = new Koa() 8 | const router = new KoaRouter() 9 | 10 | // Serverless 场景只能读写 /tmp 目录,所以这里需要指定上传文件的目录为 /tmp/upload 11 | const upload = multer({ dest: '/tmp/upload' }); 12 | 13 | // Routes 14 | router.get(`/`, async (ctx) => { 15 | await sendFile(ctx, path.join(__dirname, 'index.html')) 16 | }) 17 | 18 | router.post('/upload', upload.single('file'), (ctx) => { 19 | ctx.body = { 20 | success: true, 21 | data: ctx.file, 22 | }; 23 | }); 24 | 25 | app.use(router.allowedMethods()).use(router.routes()) 26 | 27 | app.listen(9000, () => { 28 | console.log(`Server start on http://localhost:9000`); 29 | }) 30 | 31 | -------------------------------------------------------------------------------- /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/multer": "^3.0.0", 13 | "koa": "^2.11.0", 14 | "koa-router": "^8.0.8", 15 | "koa-sendfile": "^2.0.1", 16 | "multer": "^1.4.2" 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /examples/koa/serverless.yml: -------------------------------------------------------------------------------- 1 | component: http 2 | name: koaDemo 3 | 4 | inputs: 5 | src: 6 | src: ./ 7 | exclude: 8 | - .env 9 | faas: 10 | runtime: Nodejs12.16 11 | framework: koa 12 | name: ${name} 13 | apigw: 14 | ignoreUpdate: true 15 | protocols: 16 | - http 17 | - https 18 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /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/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.5", 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/mail.php: -------------------------------------------------------------------------------- 1 | env('MAIL_MAILER', 'smtp'), 17 | 18 | /* 19 | |-------------------------------------------------------------------------- 20 | | Mailer Configurations 21 | |-------------------------------------------------------------------------- 22 | | 23 | | Here you may configure all of the mailers used by your application plus 24 | | their respective settings. Several examples have been configured for 25 | | you and you are free to add your own as your application requires. 26 | | 27 | | Laravel supports a variety of mail "transport" drivers to be used while 28 | | sending an e-mail. You will specify which one you are using for your 29 | | mailers below. You are free to add additional mailers as required. 30 | | 31 | | Supported: "smtp", "sendmail", "mailgun", "ses", 32 | | "postmark", "log", "array" 33 | | 34 | */ 35 | 36 | 'mailers' => [ 37 | 'smtp' => [ 38 | 'transport' => 'smtp', 39 | 'host' => env('MAIL_HOST', 'smtp.mailgun.org'), 40 | 'port' => env('MAIL_PORT', 587), 41 | 'encryption' => env('MAIL_ENCRYPTION', 'tls'), 42 | 'username' => env('MAIL_USERNAME'), 43 | 'password' => env('MAIL_PASSWORD'), 44 | 'timeout' => null, 45 | 'auth_mode' => null, 46 | ], 47 | 48 | 'ses' => [ 49 | 'transport' => 'ses', 50 | ], 51 | 52 | 'mailgun' => [ 53 | 'transport' => 'mailgun', 54 | ], 55 | 56 | 'postmark' => [ 57 | 'transport' => 'postmark', 58 | ], 59 | 60 | 'sendmail' => [ 61 | 'transport' => 'sendmail', 62 | 'path' => '/usr/sbin/sendmail -bs', 63 | ], 64 | 65 | 'log' => [ 66 | 'transport' => 'log', 67 | 'channel' => env('MAIL_LOG_CHANNEL'), 68 | ], 69 | 70 | 'array' => [ 71 | 'transport' => 'array', 72 | ], 73 | ], 74 | 75 | /* 76 | |-------------------------------------------------------------------------- 77 | | Global "From" Address 78 | |-------------------------------------------------------------------------- 79 | | 80 | | You may wish for all e-mails sent by your application to be sent from 81 | | the same address. Here, you may specify a name and address that is 82 | | used globally for all e-mails that are sent by your application. 83 | | 84 | */ 85 | 86 | 'from' => [ 87 | 'address' => env('MAIL_FROM_ADDRESS', 'hello@example.com'), 88 | 'name' => env('MAIL_FROM_NAME', 'Example'), 89 | ], 90 | 91 | /* 92 | |-------------------------------------------------------------------------- 93 | | Markdown Mail Settings 94 | |-------------------------------------------------------------------------- 95 | | 96 | | If you are using Markdown based email rendering, you may configure your 97 | | theme and component paths here, allowing you to customize the design 98 | | of the emails. Or, you may simply stick with the Laravel defaults! 99 | | 100 | */ 101 | 102 | 'markdown' => [ 103 | 'theme' => 'default', 104 | 105 | 'paths' => [ 106 | resource_path('views/vendor/mail'), 107 | ], 108 | ], 109 | 110 | ]; 111 | -------------------------------------------------------------------------------- /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-http/456dab08b82d9719314d7e3a6e2099dba93a752b/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 | -------------------------------------------------------------------------------- /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 | component: http 2 | name: laravelDemo 3 | 4 | inputs: 5 | src: 6 | src: ./ 7 | exclude: 8 | - .env 9 | region: ap-guangzhou 10 | faas: 11 | name: ${name} 12 | framework: laravel 13 | runtime: Php7 14 | environments: 15 | - key: APP_ENV 16 | value: production 17 | apigw: 18 | protocols: 19 | - http 20 | - https 21 | -------------------------------------------------------------------------------- /examples/laravel/storage/framework/views/5974a20b5097c79d9b6e2ca48080a376f85e3940.php: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | <?php echo $__env->yieldContent('title'); ?> 8 | 9 | 10 | 11 | 12 | 13 | 14 | 50 | 51 | 52 |
53 |
54 | yieldContent('code'); ?> 55 |
56 | 57 |
58 | yieldContent('message'); ?> 59 |
60 |
61 | 62 | 63 | -------------------------------------------------------------------------------- /examples/laravel/storage/framework/views/641ce7419f4834c1fb5522e743e2c36b19fafca1.php: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | Laravel 8 | 9 | 10 | 11 | 12 | 13 | 65 | 66 | 67 |
68 | 69 | 80 | 81 | 82 |
83 |
84 | Laravel 85 |
86 | 87 | 97 |
98 |
99 | 100 | 101 | -------------------------------------------------------------------------------- /examples/laravel/storage/framework/views/e8b4bb9e9045b5e4d42d503b4ce315a579ab90fc.php: -------------------------------------------------------------------------------- 1 | startSection('title', __('Server Error')); ?> 2 | startSection('code', '500'); ?> 3 | startSection('message', __('Server Error')); ?> 4 | 5 | make('errors::minimal', \Illuminate\Support\Arr::except(get_defined_vars(), ['__data', '__path']))->render(); ?> -------------------------------------------------------------------------------- /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/.eslintrc.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | parser: '@typescript-eslint/parser', 3 | parserOptions: { 4 | project: 'tsconfig.json', 5 | sourceType: 'module', 6 | }, 7 | plugins: ['@typescript-eslint/eslint-plugin'], 8 | extends: [ 9 | 'plugin:@typescript-eslint/recommended', 10 | 'plugin:prettier/recommended', 11 | ], 12 | root: true, 13 | env: { 14 | node: true, 15 | jest: true, 16 | }, 17 | ignorePatterns: ['.eslintrc.js'], 18 | rules: { 19 | '@typescript-eslint/interface-name-prefix': 'off', 20 | '@typescript-eslint/explicit-function-return-type': 'off', 21 | '@typescript-eslint/explicit-module-boundary-types': 'off', 22 | '@typescript-eslint/no-explicit-any': 'off', 23 | }, 24 | }; 25 | -------------------------------------------------------------------------------- /examples/nestjs/.prettierrc: -------------------------------------------------------------------------------- 1 | { 2 | "singleQuote": true, 3 | "trailingComma": "all" 4 | } -------------------------------------------------------------------------------- /examples/nestjs/README.md: -------------------------------------------------------------------------------- 1 |

2 | Nest Logo 3 |

4 | 5 | [circleci-image]: https://img.shields.io/circleci/build/github/nestjs/nest/master?token=abc123def456 6 | [circleci-url]: https://circleci.com/gh/nestjs/nest 7 | 8 |

A progressive Node.js framework for building efficient and scalable server-side applications.

9 |

10 | NPM Version 11 | Package License 12 | NPM Downloads 13 | CircleCI 14 | Coverage 15 | Discord 16 | Backers on Open Collective 17 | Sponsors on Open Collective 18 | 19 | Support us 20 | 21 |

22 | 24 | 25 | ## Description 26 | 27 | [Nest](https://github.com/nestjs/nest) framework TypeScript starter repository. 28 | 29 | ## Installation 30 | 31 | ```bash 32 | $ npm install 33 | ``` 34 | 35 | ## Running the app 36 | 37 | ```bash 38 | # development 39 | $ npm run start 40 | 41 | # watch mode 42 | $ npm run start:dev 43 | 44 | # production mode 45 | $ npm run start:prod 46 | ``` 47 | 48 | ## Test 49 | 50 | ```bash 51 | # unit tests 52 | $ npm run test 53 | 54 | # e2e tests 55 | $ npm run test:e2e 56 | 57 | # test coverage 58 | $ npm run test:cov 59 | ``` 60 | 61 | ## Support 62 | 63 | Nest is an MIT-licensed open source project. It can grow thanks to the sponsors and support by the amazing backers. If you'd like to join them, please [read more here](https://docs.nestjs.com/support). 64 | 65 | ## Stay in touch 66 | 67 | - Author - [Kamil Myśliwiec](https://twitter.com/kammysliwiec) 68 | - Website - [https://nestjs.com](https://nestjs.com/) 69 | - Twitter - [@nestframework](https://twitter.com/nestframework) 70 | 71 | ## License 72 | 73 | Nest is [MIT licensed](https://github.com/nestjs/nest/blob/master/LICENSE). 74 | -------------------------------------------------------------------------------- /examples/nestjs/nest-cli.json: -------------------------------------------------------------------------------- 1 | { 2 | "collection": "@nestjs/schematics", 3 | "sourceRoot": "src" 4 | } 5 | -------------------------------------------------------------------------------- /examples/nestjs/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "serverless-nestjs", 3 | "private": true, 4 | "version": "1.0.0", 5 | "description": "Nest TypeScript starter repository", 6 | "license": "MIT", 7 | "scripts": { 8 | "prebuild": "rimraf dist", 9 | "build": "nest build", 10 | "format": "prettier --write \"src/**/*.ts\" \"test/**/*.ts\"", 11 | "start": "nest start", 12 | "start:dev": "nest start --watch", 13 | "start:debug": "nest start --debug --watch", 14 | "start:prod": "node dist/main", 15 | "lint": "eslint \"{src,apps,libs,test}/**/*.ts\" --fix", 16 | "test": "jest", 17 | "test:watch": "jest --watch", 18 | "test:cov": "jest --coverage", 19 | "test:debug": "node --inspect-brk -r tsconfig-paths/register -r ts-node/register node_modules/.bin/jest --runInBand", 20 | "test:e2e": "jest --config ./test/jest-e2e.json" 21 | }, 22 | "dependencies": { 23 | "@nestjs/common": "^8.0.0", 24 | "@nestjs/core": "^8.0.0", 25 | "@nestjs/platform-express": "^8.0.0", 26 | "hbs": "^4.1.2", 27 | "reflect-metadata": "^0.1.13", 28 | "rimraf": "^3.0.2", 29 | "rxjs": "^7.2.0" 30 | }, 31 | "devDependencies": { 32 | "@nestjs/cli": "^8.0.0", 33 | "@nestjs/schematics": "^8.0.0", 34 | "@nestjs/testing": "^8.0.0", 35 | "@types/express": "^4.17.13", 36 | "@types/jest": "^26.0.24", 37 | "@types/node": "^16.0.0", 38 | "@types/supertest": "^2.0.11", 39 | "@typescript-eslint/eslint-plugin": "^4.28.2", 40 | "@typescript-eslint/parser": "^4.28.2", 41 | "eslint": "^7.30.0", 42 | "eslint-config-prettier": "^8.3.0", 43 | "eslint-plugin-prettier": "^3.4.0", 44 | "jest": "^27.0.6", 45 | "prettier": "^2.3.2", 46 | "supertest": "^6.1.3", 47 | "ts-jest": "^27.0.3", 48 | "ts-loader": "^9.2.3", 49 | "ts-node": "^10.0.0", 50 | "tsconfig-paths": "^3.10.1", 51 | "typescript": "^4.3.5" 52 | }, 53 | "jest": { 54 | "moduleFileExtensions": [ 55 | "js", 56 | "json", 57 | "ts" 58 | ], 59 | "rootDir": "src", 60 | "testRegex": ".*\\.spec\\.ts$", 61 | "transform": { 62 | "^.+\\.(t|j)s$": "ts-jest" 63 | }, 64 | "collectCoverageFrom": [ 65 | "**/*.(t|j)s" 66 | ], 67 | "coverageDirectory": "../coverage", 68 | "testEnvironment": "node" 69 | } 70 | } 71 | -------------------------------------------------------------------------------- /examples/nestjs/serverless.yml: -------------------------------------------------------------------------------- 1 | component: http 2 | name: nestDemo 3 | 4 | inputs: 5 | src: 6 | dist: ./ 7 | hook: npm run build 8 | exclude: 9 | - .env 10 | faas: 11 | runtime: Nodejs12.16 12 | framework: nestjs 13 | name: ${name} 14 | apigw: 15 | protocols: 16 | - http 17 | - https 18 | -------------------------------------------------------------------------------- /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 app: TestingModule; 7 | 8 | beforeAll(async () => { 9 | app = await Test.createTestingModule({ 10 | controllers: [AppController], 11 | providers: [AppService], 12 | }).compile(); 13 | }); 14 | 15 | describe('getHello', () => { 16 | it('should return "Hello World!"', () => { 17 | const appController = app.get(AppController); 18 | expect(appController.getHello()).toBe('Hello World!'); 19 | }); 20 | }); 21 | }); 22 | -------------------------------------------------------------------------------- /examples/nestjs/src/app.controller.ts: -------------------------------------------------------------------------------- 1 | import { Controller, Get, Render } from '@nestjs/common'; 2 | import { AppService } from './app.service'; 3 | 4 | @Controller() 5 | export class AppController { 6 | constructor(private readonly appService: AppService) {} 7 | 8 | @Get() 9 | @Render('index') 10 | root() { 11 | return { 12 | message: 'Serverless Framework', 13 | }; 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /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 | app.listen(9000, '0.0.0.0', () => { 13 | console.log(`Server start on http://0.0.0.0:9000`); 14 | }); 15 | } 16 | bootstrap(); 17 | -------------------------------------------------------------------------------- /examples/nestjs/tsconfig.build.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "./tsconfig.json", 3 | "exclude": ["node_modules", "dist", "test", "**/*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 | "skipLibCheck": true 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /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 | .env 21 | 22 | # debug 23 | npm-debug.log* 24 | yarn-debug.log* 25 | yarn-error.log* 26 | 27 | .serverless 28 | .next 29 | -------------------------------------------------------------------------------- /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/global.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/index.module.css' 3 | 4 | export default function Index() { 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-http/456dab08b82d9719314d7e3a6e2099dba93a752b/examples/nextjs/public/favicon.ico -------------------------------------------------------------------------------- /examples/nextjs/serverless.yml: -------------------------------------------------------------------------------- 1 | component: http 2 | name: nextDemo 3 | 4 | inputs: 5 | src: 6 | dist: ./ 7 | hook: npm run build 8 | exclude: 9 | - .env 10 | faas: 11 | runtime: Nodejs12.16 12 | framework: nextjs 13 | name: ${name} 14 | apigw: 15 | protocols: 16 | - http 17 | - https 18 | -------------------------------------------------------------------------------- /examples/nextjs/styles/global.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/nextjs/styles/index.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/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 Application Created By Serverless Framework' 27 | } 28 | ], 29 | link: [ 30 | { rel: 'icon', type: 'image/x-icon', href: `${process.env.STATIC_URL || ''}/favicon.ico` } 31 | ] 32 | }, 33 | /* 34 | ** Customize the progress-bar color 35 | */ 36 | loading: { color: '#fff' }, 37 | /* 38 | ** Global CSS 39 | */ 40 | css: [], 41 | /* 42 | ** Plugins to load before mounting the App 43 | */ 44 | plugins: [], 45 | /* 46 | ** Nuxt.js dev-modules 47 | */ 48 | buildModules: [], 49 | /* 50 | ** Nuxt.js modules 51 | */ 52 | modules: [] 53 | } 54 | -------------------------------------------------------------------------------- /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 | component: http 2 | name: nuxtDemo 3 | 4 | inputs: 5 | src: 6 | dist: ./ 7 | hook: npm run build 8 | exclude: 9 | - .env 10 | faas: 11 | runtime: Nodejs12.16 12 | framework: nuxtjs 13 | name: ${name} 14 | apigw: 15 | protocols: 16 | - http 17 | - https 18 | -------------------------------------------------------------------------------- /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-http/456dab08b82d9719314d7e3a6e2099dba93a752b/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 -------------------------------------------------------------------------------- /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/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 | } 50 | -------------------------------------------------------------------------------- /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-http/456dab08b82d9719314d7e3a6e2099dba93a752b/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 | component: http 2 | name: thinkphpDemo 3 | 4 | inputs: 5 | src: 6 | src: ./ 7 | exclude: 8 | - .env 9 | region: ap-guangzhou 10 | faas: 11 | name: ${name} 12 | framework: thinkphp 13 | runtime: Php7 14 | environments: 15 | - key: APP_ENV 16 | value: production 17 | apigw: 18 | protocols: 19 | - http 20 | - https 21 | -------------------------------------------------------------------------------- /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 | /* eslint-disable no-console*/ 13 | async function bootstrap() { 14 | console.log('[root] Install dependencies'); 15 | await installDependencies(rootDir); 16 | 17 | console.log('[src] Install dependencies'); 18 | await installDependencies(join(rootDir, 'src')); 19 | } 20 | 21 | bootstrap(); 22 | 23 | process.on('unhandledRejection', (e) => { 24 | throw e; 25 | }); 26 | -------------------------------------------------------------------------------- /scripts/config.ts: -------------------------------------------------------------------------------- 1 | import { join } from 'path'; 2 | import { Framework } from '../typings'; 3 | 4 | export const COMPONENT_NAME = 'http'; 5 | 6 | export const VERSION_YAML_PATH = join(__dirname, '..', 'version.yml'); 7 | 8 | export const COMPONENT_CODE_PATH = join(__dirname, '..', 'build'); 9 | 10 | export const FRAMEWORKS: Framework[] = [ 11 | 'express', 12 | 'koa', 13 | 'egg', 14 | 'nextjs', 15 | 'nuxtjs', 16 | 'nestjs', 17 | 'flask', 18 | 'django', 19 | 'laravel', 20 | 'thinkphp', 21 | ]; 22 | -------------------------------------------------------------------------------- /scripts/deploy.ts: -------------------------------------------------------------------------------- 1 | import { join } from 'path'; 2 | import * as dotenv from 'dotenv'; 3 | import * as ora from 'ora'; 4 | import { execSync } from 'child_process'; 5 | import { program } from 'commander'; 6 | 7 | dotenv.config({ 8 | path: join(__dirname, '..', '.env'), 9 | }); 10 | 11 | import { COMPONENT_NAME, VERSION_YAML_PATH } from './config'; 12 | import { copySync, rmdirSync, parseYaml, getComponentConfig, publishComponent } from './utils'; 13 | 14 | async function buildProject() { 15 | const buildPath = join(__dirname, '..', 'build'); 16 | rmdirSync(buildPath); 17 | execSync(`tsc -p .`, { 18 | cwd: process.cwd(), 19 | }); 20 | copySync(join(__dirname, '..', 'src/node_modules'), join(__dirname, '..', 'build/node_modules')); 21 | } 22 | 23 | async function copyExtraFiles() { 24 | const shimPath = join(__dirname, '..', `src/_shims`); 25 | const targetShimPath = join(__dirname, '..', 'build/_shims'); 26 | const fixturePath = join(__dirname, '..', 'src/_fixtures'); 27 | const targetFixturePath = join(__dirname, '..', 'build/_fixtures'); 28 | 29 | // 复制前,需要先删除 30 | rmdirSync(targetShimPath); 31 | rmdirSync(targetFixturePath); 32 | 33 | // 复制指定框架的 _shims 文件 34 | copySync(shimPath, targetShimPath); 35 | // 复制 _fixtures 36 | copySync(fixturePath, targetFixturePath); 37 | } 38 | 39 | async function deploy(options: { [propName: string]: any }) { 40 | const stage = options.env || 'dev'; 41 | process.env.SERVERLESS_PLATFORM_STAGE = stage; 42 | 43 | const spinner = ora().start('Start deploying...\n'); 44 | 45 | spinner.info(`[BUILD] Building project...`); 46 | await buildProject(); 47 | spinner.succeed(`[BUILD] Build project success`); 48 | if (options.onlyBuild) { 49 | spinner.stop(); 50 | return true; 51 | } 52 | 53 | spinner.info(`Copying extra files for component...`); 54 | await copyExtraFiles(); 55 | 56 | spinner.info(`Generate config file for compooent ${COMPONENT_NAME}...`); 57 | const { version } = parseYaml(VERSION_YAML_PATH); 58 | const compConfig = getComponentConfig(version); 59 | 60 | if (options.version) { 61 | compConfig.version = options.version; 62 | } 63 | if (options.dev) { 64 | compConfig.version = 'dev'; 65 | } 66 | 67 | try { 68 | spinner.info(`Publishing component ${COMPONENT_NAME}@${compConfig.version}...`); 69 | await publishComponent(compConfig); 70 | spinner.succeed(`Publish compooent ${COMPONENT_NAME}@${compConfig.version} success`); 71 | } catch (e) { 72 | spinner.warn(`Publish compooent ${COMPONENT_NAME}@${compConfig.version} error: ${e.message}`); 73 | } 74 | 75 | spinner.stop(); 76 | 77 | return compConfig; 78 | } 79 | 80 | async function run() { 81 | program 82 | .description('Deploy components') 83 | .option('-d, --dev [dev]', 'deploy dev version component') 84 | .option('-e, --env [env]', 'specify deploy environment: prod,dev', 'dev') 85 | .option('-v, --ver [ver]', 'component version') 86 | .option('-ob, --onlyBuild [onlyBuild]', 'only build project', false) 87 | .action((options) => { 88 | deploy(options); 89 | }); 90 | 91 | program.parse(process.argv); 92 | } 93 | 94 | run(); 95 | -------------------------------------------------------------------------------- /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/template.ts: -------------------------------------------------------------------------------- 1 | import { join } from 'path'; 2 | import * as COS from 'cos-nodejs-sdk-v5'; 3 | import * as dotenv from 'dotenv'; 4 | import * as ora from 'ora'; 5 | import { program } from 'commander'; 6 | import { prompt } from 'inquirer'; 7 | import { Framework } from '../typings'; 8 | import { FRAMEWORKS } from './config'; 9 | 10 | dotenv.config(); 11 | 12 | const { zip } = require('yzip/src'); 13 | 14 | interface Options { 15 | framework: string; 16 | all: boolean; 17 | } 18 | 19 | async function updateTemplate(framework: Framework, spinner: ora.Ora) { 20 | const cos = new COS({ 21 | SecretId: process.env.TENCENT_SECRET_ID, 22 | SecretKey: process.env.TENCENT_SECRET_KEY, 23 | }); 24 | 25 | const filename = `${framework}.zip`; 26 | const input = join(__dirname, '../examples/', framework); 27 | const output = join(__dirname, '../dist/', filename); 28 | // 1. 生成 zip 文件 29 | await zip(input, output); 30 | // 2. 上传 31 | spinner.info(`Uploading ${filename}...`); 32 | await cos.uploadFile({ 33 | Bucket: 'serverless-templates-1300862921', 34 | Region: 'ap-beijing', 35 | Key: `/http/${filename}`, 36 | FilePath: output, 37 | }); 38 | 39 | spinner.succeed(`Upload ${filename} success!`); 40 | } 41 | 42 | async function tempalte(options: Options) { 43 | let frameworks: Framework[]; 44 | if (options.framework) { 45 | const { framework } = options; 46 | frameworks = [framework] as Framework[]; 47 | 48 | // await deployComponent(framework as Framework, options, spinner); 49 | } else if (options.all) { 50 | frameworks = FRAMEWORKS; 51 | } else { 52 | // ask to select framework 53 | const anwsers = await prompt([ 54 | { 55 | type: 'checkbox', 56 | name: 'frameworks', 57 | message: 'Please select framework to be deploy ?', 58 | choices: FRAMEWORKS, 59 | }, 60 | ]); 61 | frameworks = anwsers.frameworks as Framework[]; 62 | } 63 | 64 | const spinner = ora().start(`Start deploying examples...\n`); 65 | 66 | for (let i = 0; i < frameworks.length; i++) { 67 | await updateTemplate(frameworks[i], spinner); 68 | } 69 | 70 | spinner.stop(); 71 | } 72 | 73 | async function run() { 74 | program 75 | .description('Deploy examples') 76 | .option('-f, --framework [framework]', 'specify framework example to be deploy') 77 | .option('-a, --all [all]', 'specify all frameworks examples to be deploy') 78 | .action((options) => { 79 | tempalte(options); 80 | }); 81 | 82 | program.parse(process.argv); 83 | } 84 | 85 | run(); 86 | -------------------------------------------------------------------------------- /scripts/version.ts: -------------------------------------------------------------------------------- 1 | import * as ora from 'ora'; 2 | import { program } from 'commander'; 3 | import { prompt } from 'inquirer'; 4 | import { inc as semverInc, ReleaseType } from 'semver'; 5 | 6 | import { VERSION_YAML_PATH } from './config'; 7 | import { parseYaml, generateYaml } from './utils'; 8 | 9 | interface Options { 10 | ver: string; 11 | dev: string; 12 | framework: string; 13 | all: boolean; 14 | type: ReleaseType; 15 | } 16 | 17 | async function change(options: Options) { 18 | const spinner = ora().start(`Start changing...\n`); 19 | 20 | const versions = parseYaml(VERSION_YAML_PATH); 21 | 22 | let versionType: ReleaseType | undefined = undefined; 23 | let version = ''; 24 | if (options.dev) { 25 | version = 'dev'; 26 | } else if (options.ver) { 27 | version = options.ver; 28 | } else { 29 | if (!options.type) { 30 | spinner.info('No version is specified'); 31 | const { type } = await prompt([ 32 | { 33 | type: 'list', 34 | name: 'type', 35 | message: 'Please select version type ?', 36 | choices: ['patch', 'minor', 'major'], 37 | }, 38 | ]); 39 | versionType = type; 40 | } else { 41 | versionType = options.type; 42 | } 43 | } 44 | 45 | const curVersion = versions.version; 46 | if (versionType) { 47 | version = semverInc(curVersion, versionType) as string; 48 | } 49 | versions.version = version; 50 | await generateYaml(VERSION_YAML_PATH, versions); 51 | 52 | spinner.stop(); 53 | } 54 | 55 | async function run() { 56 | program 57 | .description('Change component version') 58 | .option('-t, --type [type]', 'chagne version type') 59 | .option('-a, --all [all]', 'specify all frameworks to be deploy') 60 | .option('-v, --ver [ver]', 'specify version for component') 61 | .option('-d, --dev [dev]', 'deploy dev version component') 62 | .action((options) => { 63 | change(options); 64 | }); 65 | 66 | program.parse(process.argv); 67 | } 68 | 69 | run(); 70 | -------------------------------------------------------------------------------- /src/_fixtures/public/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/serverless-components/tencent-http/456dab08b82d9719314d7e3a6e2099dba93a752b/src/_fixtures/public/.gitkeep -------------------------------------------------------------------------------- /src/_shims/django/scf_bootstrap: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # HTTP 直通函数由于是基于 docker 镜像运行,所以必须监听地址为 0.0.0.0,并且端口为 9000 4 | /var/lang/python3/bin/python3 manage.py runserver 0.0.0.0:9000 5 | -------------------------------------------------------------------------------- /src/_shims/egg/scf_bootstrap: -------------------------------------------------------------------------------- 1 | #!/var/lang/node12/bin/node 2 | 3 | /** 4 | * docker 中 node 路径:/var/lang/node12/bin/node 5 | * 由于 serverless 函数只有 /tmp 读写权限,所以在启动时需要修改两个环境变量 6 | * NODE_LOG_DIR 是为了改写 egg-scripts 默认 node 写入路径(~/logs)-> /tmp 7 | * EGG_APP_CONFIG 是为了修改 egg 应有的默认当前目录 -> /tmp 8 | */ 9 | 10 | process.env.EGG_SERVER_ENV = 'prod'; 11 | process.env.NODE_ENV = 'production'; 12 | process.env.NODE_LOG_DIR = '/tmp'; 13 | process.env.EGG_APP_CONFIG = '{"rundir":"/tmp","logger":{"dir":"/tmp"}}'; 14 | 15 | const { Application } = require('egg'); 16 | 17 | // 如果通过层部署 node_modules 就需要修改 eggPath 18 | Object.defineProperty(Application.prototype, Symbol.for('egg#eggPath'), { 19 | value: '/opt', 20 | }); 21 | 22 | const app = new Application({ 23 | mode: 'single', 24 | env: 'prod', 25 | }); 26 | 27 | app.listen(9000, '0.0.0.0', () => { 28 | console.log('Server start on http://0.0.0.0:9000'); 29 | }); 30 | -------------------------------------------------------------------------------- /src/_shims/express/scf_bootstrap: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | /var/lang/node12/bin/node app.js 4 | -------------------------------------------------------------------------------- /src/_shims/flask/scf_bootstrap: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # HTTP 直通函数由于是基于 docker 镜像运行,所以必须监听地址为 0.0.0.0,并且端口为 9000 4 | /var/lang/python3/bin/python3 app.py 5 | -------------------------------------------------------------------------------- /src/_shims/koa/scf_bootstrap: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | /var/lang/node12/bin/node app.js 4 | -------------------------------------------------------------------------------- /src/_shims/laravel/scf_bootstrap: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | ####################################### 4 | # 注入 serverless 环境下的环境变量 5 | ####################################### 6 | # 注入 SERVERLESS 标识 7 | export SERVERLESS=1 8 | # 修改模板编译缓存路径,云函数只有 /tmp 目录可读写 9 | export VIEW_COMPILED_PATH=/tmp/storage/framework/views 10 | # 修改 session 以内存方式(数组类型)存储 11 | export SESSION_DRIVER=array 12 | # 日志输出到 stderr 13 | export LOG_CHANNEL=stderr 14 | # 修改应用存储路径 15 | export APP_STORAGE=/tmp/storage 16 | 17 | # 初始化模板缓存目录 18 | mkdir -p /tmp/storage/framework/views 19 | 20 | # HTTP 直通函数由于是基于 docker 镜像运行,所以必须监听地址为 0.0.0.0,并且端口为 9000 21 | # 云端可执行文件路径 /var/lang/php7/bin/php 22 | /var/lang/php7/bin/php artisan serve --host 0.0.0.0 --port 9000 23 | -------------------------------------------------------------------------------- /src/_shims/nestjs/scf_bootstrap: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # SERVERLESS=1 /var/lang/node12/bin/npm run start -- -e /var/lang/node12/bin/node 4 | SERVERLESS=1 /var/lang/node12/bin/node ./dist/main.js 5 | -------------------------------------------------------------------------------- /src/_shims/nextjs/scf_bootstrap: -------------------------------------------------------------------------------- 1 | #!/var/lang/node12/bin/node 2 | 3 | /* 4 | # HTTP 直通函数由于是基于 docker 镜像运行,所以必须监听地址为 0.0.0.0,并且端口为 9000 5 | */ 6 | const { nextStart } = require('next/dist/cli/next-start'); 7 | nextStart(['--port', '9000', '--hostname', '0.0.0.0']); 8 | -------------------------------------------------------------------------------- /src/_shims/nuxtjs/scf_bootstrap: -------------------------------------------------------------------------------- 1 | #!/var/lang/node12/bin/node 2 | 3 | /* 4 | # HTTP 直通函数由于是基于 docker 镜像运行,所以必须监听地址为 0.0.0.0,并且端口为 9000 5 | */ 6 | require('@nuxt/cli') 7 | .run(['start', '--port', '9000', '--hostname', '0.0.0.0']) 8 | .catch((error) => { 9 | require('consola').fatal(error); 10 | require('exit')(2); 11 | }); 12 | -------------------------------------------------------------------------------- /src/_shims/thinkphp/scf_bootstrap: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | export SERVERLESS=1 4 | 5 | # HTTP 直通函数由于是基于 docker 镜像运行,所以必须监听地址为 0.0.0.0,并且端口为 9000 6 | # 云端可执行文件路径 /var/lang/php7/bin/php 7 | export PATH=/var/lang/php7/bin:$PATH 8 | 9 | export VIEW_COMPILED_PATH=/tmp/runtime/view 10 | 11 | mkdir -p /tmp/runtime 12 | 13 | php think run --host 0.0.0.0 --port 9000 -n 14 | -------------------------------------------------------------------------------- /src/config.ts: -------------------------------------------------------------------------------- 1 | import { Framework, FrameworkConfig } from './interface'; 2 | 3 | type DefaultConfig = Partial; 4 | 5 | const TEMPLATE_BASE_URL = 'https://serverless-templates-1300862921.cos.ap-beijing.myqcloud.com'; 6 | 7 | const frameworks: Record = { 8 | express: { 9 | defaultStatics: [{ src: 'public', targetDir: '/' }], 10 | }, 11 | koa: { 12 | defaultStatics: [{ src: 'public', targetDir: '/' }], 13 | }, 14 | egg: { 15 | defaultStatics: [{ src: 'public', targetDir: '/' }], 16 | }, 17 | nestjs: { 18 | defaultStatics: [{ src: 'public', targetDir: '/' }], 19 | }, 20 | nextjs: { 21 | defaultStatics: [ 22 | { src: '.next/static', targetDir: '/_next/static' }, 23 | { src: 'public', targetDir: '/' }, 24 | ], 25 | }, 26 | nuxtjs: { 27 | defaultStatics: [ 28 | { src: '.nuxt/dist/client', targetDir: '/' }, 29 | { src: 'static', targetDir: '/' }, 30 | ], 31 | }, 32 | laravel: {}, 33 | thinkphp: {}, 34 | flask: {}, 35 | django: {}, 36 | gin: {}, 37 | }; 38 | 39 | const CONFIGS: DefaultConfig = { 40 | // support metrics frameworks 41 | region: 'ap-guangzhou', 42 | description: 'Created by Serverless Component', 43 | handler: 'scf_bootstrap', 44 | timeout: 10, 45 | memorySize: 512, 46 | namespace: 'default', 47 | runtime: 'Nodejs12.16', 48 | defaultEnvs: [ 49 | { 50 | key: 'SERVERLESS', 51 | value: '1', 52 | }, 53 | ], 54 | cos: { 55 | lifecycle: [ 56 | { 57 | status: 'Enabled', 58 | id: 'deleteObject', 59 | expiration: { days: '10' }, 60 | abortIncompleteMultipartUpload: { daysAfterInitiation: '10' }, 61 | }, 62 | ], 63 | }, 64 | cdn: { 65 | forceRedirect: { 66 | switch: 'on', 67 | redirectType: 'https', 68 | redirectStatusCode: 301, 69 | }, 70 | https: { 71 | switch: 'on', 72 | http2: 'on', 73 | }, 74 | }, 75 | 76 | defaultCdnConfig: { 77 | forceRedirect: { 78 | switch: 'on', 79 | redirectType: 'https', 80 | redirectStatusCode: 301, 81 | }, 82 | https: { 83 | switch: 'on', 84 | http2: 'on', 85 | }, 86 | }, 87 | acl: { 88 | permissions: 'public-read', 89 | grantRead: '', 90 | grantWrite: '', 91 | grantFullControl: '', 92 | }, 93 | getPolicy(region: string, bucket: string, appid: string) { 94 | return { 95 | Statement: [ 96 | { 97 | Principal: { qcs: ['qcs::cam::anyone:anyone'] }, 98 | Effect: 'Allow', 99 | Action: [ 100 | 'name/cos:HeadBucket', 101 | 'name/cos:ListMultipartUploads', 102 | 'name/cos:ListParts', 103 | 'name/cos:GetObject', 104 | 'name/cos:HeadObject', 105 | 'name/cos:OptionsObject', 106 | ], 107 | Resource: [`qcs::cos:${region}:uid/${appid}:${bucket}-${appid}/*`], 108 | }, 109 | ], 110 | version: '2.0', 111 | }; 112 | }, 113 | }; 114 | 115 | export const getConfig = (framework: Framework): FrameworkConfig => { 116 | const templateUrl = `${TEMPLATE_BASE_URL}/http/${framework}.zip`; 117 | const frameworkConfigs = frameworks[framework]; 118 | return { 119 | framework, 120 | templateUrl, 121 | ...CONFIGS, 122 | ...frameworkConfigs, 123 | } as FrameworkConfig; 124 | }; 125 | -------------------------------------------------------------------------------- /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 | | 'gin'; 16 | 17 | export interface Credential { 18 | SecretId: string; 19 | SecretKey: string; 20 | Token?: string; 21 | } 22 | 23 | export type Policy = { 24 | Statement: [ 25 | { 26 | Principal: { qcs: string[] }; 27 | Effect: string; 28 | Action: string[]; 29 | Resource: string[]; 30 | }, 31 | ]; 32 | version: string; 33 | }; 34 | 35 | export type DefaultCdnConfig = { 36 | forceRedirect: { 37 | switch?: 'on' | 'off'; 38 | redirectStatusCode: number; 39 | redirectType?: 'https'; 40 | }; 41 | https: { 42 | switch: 'on'; 43 | http2: 'on'; 44 | }; 45 | }; 46 | 47 | export type FrameworkConfig = { 48 | region: string; 49 | templateUrl: string; 50 | framework: string; 51 | handler: string; 52 | runtime: string; 53 | timeout: number; 54 | memorySize: number; 55 | namespace: string; 56 | description: string; 57 | defaultStatics: { src: string; targetDir: string }[]; 58 | defaultCdnConfig: DefaultCdnConfig; 59 | acl: { 60 | permissions: string; 61 | grantRead: string; 62 | grantWrite: string; 63 | grantFullControl: string; 64 | }; 65 | // eslint-disable-next-line 66 | getPolicy: (r: string, b: string, a: string) => Policy; 67 | pythonFrameworks?: string[]; 68 | supportMetrics?: string[]; 69 | defaultEnvs: { 70 | key: string; 71 | value: string; 72 | }[]; 73 | cos: { 74 | lifecycle: { 75 | status: string; 76 | id: string; 77 | expiration: { days: string }; 78 | abortIncompleteMultipartUpload: { daysAfterInitiation: string }; 79 | }[]; 80 | }; 81 | cdn: { 82 | forceRedirect?: { 83 | switch?: 'on' | 'off' | undefined; 84 | redirectType?: 'https'; 85 | redirectStatusCode: number; 86 | }; 87 | https?: { switch?: 'on' | 'off' | undefined; http2?: 'on' | 'off' | undefined }; 88 | }; 89 | }; 90 | -------------------------------------------------------------------------------- /src/interface/outputs.ts: -------------------------------------------------------------------------------- 1 | import { 2 | ApiEndpoint, 3 | ApigwBindCustomDomainOutputs, 4 | } from 'tencent-component-toolkit/lib/modules/apigw/interface'; 5 | 6 | export interface FaasOutputs { 7 | name: string; 8 | runtime: string; 9 | namespace: string; 10 | type?: string; 11 | } 12 | export type ApigwOutputs = { 13 | created?: boolean; 14 | isDisabled?: boolean; 15 | id: string; 16 | subDomain: string | string[]; 17 | environment: 'prepub' | 'test' | 'release'; 18 | url: string; 19 | customDomains?: ApigwBindCustomDomainOutputs[]; 20 | apiList: ApiEndpoint[]; 21 | }; 22 | 23 | export interface AssetsCosOutputs { 24 | region: string; 25 | cosOrigin: string; 26 | bucket?: string; 27 | url?: string; 28 | } 29 | 30 | export interface AssetsOutputs { 31 | cos: AssetsCosOutputs; 32 | cdn?: any; 33 | } 34 | 35 | export interface Outputs { 36 | templateUrl?: string; 37 | region?: string; 38 | faas?: FaasOutputs; 39 | apigw?: ApigwOutputs; 40 | assets?: AssetsOutputs; 41 | } 42 | -------------------------------------------------------------------------------- /src/interface/state.ts: -------------------------------------------------------------------------------- 1 | import { FaasOutputs, ApigwOutputs, AssetsOutputs } from './outputs'; 2 | 3 | export type State = { 4 | zipPath?: string; 5 | region?: string; 6 | lambdaArn?: string; 7 | functionName?: string; 8 | faas?: FaasOutputs; 9 | apigw?: ApigwOutputs; 10 | assets?: AssetsOutputs; 11 | }; 12 | -------------------------------------------------------------------------------- /src/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "dependencies": { 3 | "adm-zip": "^0.5.5", 4 | "download": "^8.0.0", 5 | "fs-extra": "^9.1.0", 6 | "js-yaml": "^4.0.0", 7 | "tencent-component-toolkit": "2.23.3", 8 | "type": "^2.1.0" 9 | }, 10 | "devDependencies": { 11 | "@types/adm-zip": "^0.4.34", 12 | "@types/download": "^6.2.4", 13 | "@types/fs-extra": "^9.0.6", 14 | "@types/js-yaml": "^4.0.0" 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /src/serverless.ts: -------------------------------------------------------------------------------- 1 | import { ServerlessComponent } from './index'; 2 | 3 | export = ServerlessComponent; 4 | -------------------------------------------------------------------------------- /src/typings/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( 20 | zipPath: string, 21 | uploadUrl: string, 22 | optionsA: Record, 23 | optionsB: Record, 24 | ); 25 | getSDKEntries(entry: string): Record; 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /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/_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 | | 'gin'; 13 | 14 | export interface ComponentConfig { 15 | type: string; 16 | name: string; 17 | version: string; 18 | author: string; 19 | org: string; 20 | description: string; 21 | keywords: string; 22 | repo: string; 23 | readme: string; 24 | license: string; 25 | webDeployable: boolean; 26 | src: string; 27 | 28 | actions?: Record; 29 | } 30 | 31 | export interface SrcObject { 32 | src?: string; 33 | dist?: string; 34 | hook?: string; 35 | exclude?: string[]; 36 | targetDir?: string; 37 | bucket?: string; 38 | object?: string; 39 | } 40 | 41 | export type InputsSrc = string | SrcObject; 42 | 43 | export interface ServerlessConfig { 44 | org?: string; 45 | app?: string; 46 | stage?: string; 47 | 48 | component: string; 49 | name: string; 50 | 51 | inputs: { src?: InputsSrc } & Record; 52 | } 53 | -------------------------------------------------------------------------------- /version.yml: -------------------------------------------------------------------------------- 1 | version: 0.0.14 2 | --------------------------------------------------------------------------------