├── .editorconfig
├── .gitignore
├── .prettierrc
├── LICENSE
├── README.md
├── clients
├── app-shell
│ ├── index.html
│ ├── package.json
│ ├── pnpm-lock.yaml
│ ├── src
│ │ ├── App.vue
│ │ └── main.ts
│ ├── tsconfig.json
│ └── vite.config.ts
└── sub-foo
│ ├── index.html
│ ├── package.json
│ ├── pnpm-lock.yaml
│ ├── src
│ ├── App.vue
│ └── main.ts
│ ├── tsconfig.json
│ └── vite.config.ts
├── iac
├── Pulumi.yaml
├── README.md
├── package.json
├── pnpm-lock.yaml
├── src
│ ├── index.ts
│ └── serving.ts
└── tsconfig.json
├── infra
└── .gitkeep
├── mbe
├── README.md
├── app-assemblies
│ ├── README.md
│ ├── jest.config.js
│ ├── package.json
│ ├── rollup.config.js
│ ├── src
│ │ └── libm
│ │ │ ├── libm.spec.js
│ │ │ └── libm.ts
│ └── tsconfig.json
├── app-gateway
│ ├── Caddyfile
│ ├── README.md
│ └── package.json
├── ecosystem.config.js
├── lerna.json
├── mod-express
│ ├── Dockerfile
│ ├── babel.config.js
│ ├── docker-compose.yml
│ ├── package.json
│ └── src
│ │ ├── core
│ │ └── router.js
│ │ ├── hello-world
│ │ └── index.js
│ │ └── index.js
├── mod-fastify
│ ├── Dockerfile
│ ├── babel.config.js
│ ├── docker-compose.yml
│ ├── package.json
│ └── src
│ │ ├── core
│ │ └── router.js
│ │ ├── hello-world
│ │ └── index.js
│ │ └── index.js
├── mod-koa
│ ├── Dockerfile
│ ├── README.md
│ ├── babel.config.js
│ ├── docker-compose.yml
│ ├── ecosystem.config.js
│ ├── package.json
│ └── src
│ │ ├── core
│ │ └── router.js
│ │ ├── hello
│ │ └── index.js
│ │ └── index.js
├── mod-nest
│ ├── .eslintrc.js
│ ├── README.md
│ ├── jest.config.js
│ ├── nest-cli.json
│ ├── package.json
│ ├── src
│ │ ├── __tests__
│ │ │ └── app.controller.spec.ts
│ │ ├── app.controller.ts
│ │ ├── app.module.ts
│ │ ├── app.service.ts
│ │ ├── hello-world
│ │ │ ├── hello-world.controller.ts
│ │ │ ├── hello-world.module.ts
│ │ │ └── hello-world.service.ts
│ │ └── main.ts
│ ├── test
│ │ ├── app.e2e-spec.ts
│ │ └── jest-e2e.json
│ ├── tsconfig.build.json
│ └── tsconfig.json
└── package.json
├── mfe
├── Caddyfile
├── Dockerfile
├── README.md
├── app-components
│ ├── .eslintrc
│ ├── .gitignore
│ ├── .prettierrc
│ ├── Dockerfile
│ ├── README.md
│ ├── babel.config.js
│ ├── docker-compose.yml
│ ├── package.json
│ ├── rollup.config.js
│ └── src
│ │ ├── footer
│ │ └── Footer.svelte
│ │ └── header
│ │ └── Header.svelte
├── app-shell
│ ├── .env
│ ├── Caddyfile
│ ├── Dockerfile
│ ├── README.md
│ ├── docker-compose.yml
│ ├── index.js
│ ├── index.pug
│ └── package.json
├── docker-compose.yml
├── lerna.json
├── list.yml
├── mod-angular
│ ├── .browserslistrc
│ ├── .editorconfig
│ ├── .gitignore
│ ├── Dockerfile
│ ├── README.md
│ ├── angular.json
│ ├── e2e
│ │ ├── protractor.conf.js
│ │ ├── src
│ │ │ ├── app.e2e-spec.ts
│ │ │ └── app.po.ts
│ │ └── tsconfig.json
│ ├── extra-webpack.config.js
│ ├── karma.conf.js
│ ├── package.json
│ ├── src
│ │ ├── app
│ │ │ ├── app-routing.module.ts
│ │ │ ├── app.component.css
│ │ │ ├── app.component.html
│ │ │ ├── app.component.spec.ts
│ │ │ ├── app.component.ts
│ │ │ ├── app.module.ts
│ │ │ └── evt.directive.ts
│ │ ├── assets
│ │ │ └── .gitkeep
│ │ ├── environments
│ │ │ ├── environment.prod.ts
│ │ │ └── environment.ts
│ │ ├── favicon.ico
│ │ ├── index.html
│ │ ├── main.ts
│ │ ├── polyfills.ts
│ │ ├── single-spa
│ │ │ ├── asset-url.ts
│ │ │ └── single-spa-props.ts
│ │ ├── styles.css
│ │ └── test.ts
│ ├── tsconfig.app.json
│ ├── tsconfig.base.json
│ ├── tsconfig.json
│ ├── tsconfig.spec.json
│ └── tslint.json
├── mod-react
│ ├── .env
│ ├── .rescriptsrc.js
│ ├── Dockerfile
│ ├── README.md
│ ├── package.json
│ ├── public
│ │ ├── favicon.ico
│ │ ├── index.html
│ │ ├── logo192.png
│ │ ├── logo512.png
│ │ ├── manifest.json
│ │ └── robots.txt
│ └── src
│ │ ├── App.css
│ │ ├── App.js
│ │ ├── App.test.js
│ │ ├── components
│ │ ├── HelloModal.js
│ │ └── LibVersion.js
│ │ ├── index.js
│ │ ├── logo.svg
│ │ ├── pages
│ │ ├── About.js
│ │ └── Home.js
│ │ └── serviceWorker.js
├── mod-svelte
│ ├── Dockerfile
│ ├── README.md
│ ├── babel.config.js
│ ├── env.js
│ ├── package.json
│ ├── src
│ │ ├── App.svelte
│ │ ├── core
│ │ │ └── RouterOutlet.svelte
│ │ ├── index.html
│ │ ├── landings
│ │ │ ├── About.svelte
│ │ │ └── Home.svelte
│ │ └── main.js
│ └── webpack.config.js
├── mod-vue
│ ├── .browserslistrc
│ ├── .eslintrc
│ ├── .gitignore
│ ├── Caddyfile
│ ├── Dockerfile
│ ├── README.md
│ ├── babel.config.js
│ ├── docker-compose.yml
│ ├── jest.config.js
│ ├── package.json
│ ├── public
│ │ ├── favicon.ico
│ │ └── index.html
│ ├── src
│ │ ├── App.vue
│ │ ├── assets
│ │ │ └── logo.png
│ │ ├── components
│ │ │ └── HelloWorld.vue
│ │ ├── main.js
│ │ ├── router
│ │ │ └── index.js
│ │ └── views
│ │ │ ├── About.vue
│ │ │ ├── Home.vue
│ │ │ └── NotFound.vue
│ └── vue.config.js
└── package.json
└── servers
└── .gitkeep
/.editorconfig:
--------------------------------------------------------------------------------
1 | root = true
2 |
3 | [*]
4 | charset = utf-8
5 | end_of_line = lf
6 | indent_size = 2
7 | indent_style = space
8 | insert_final_newline = true
9 | trim_trailing_whitespace = true
10 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | .DS_Store
2 | .cache
3 | node_modules
4 | dist
5 | coverage
6 | *.log
7 |
--------------------------------------------------------------------------------
/.prettierrc:
--------------------------------------------------------------------------------
1 | {
2 | "printWidth": 100,
3 | "singleQuote": true
4 | }
5 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | The MIT License (MIT)
2 |
3 | Copyright (c) Shyam Chen
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 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Micro Fullstack
2 |
3 | :maple_leaf: **JavaScript Microservices Development**: Build, test, deploy, and scale microservices in TypeScript.
4 |
5 | Here's how to make microservices development quick and easy:
6 |
7 | - Develop microservice applications using [TypeScript][typescript]
8 | - Integrate multiple single-page applications on a single page with [Garfish][garfish]
9 | - Develop multiple micro-frontend service applications using [Vue][vue]
10 | - Design a service gateway and registry with [Caddy][caddy]
11 | - Develop multiple micro-backend service applications using [Fastify][fastify]
12 | - Containerize microservice-based applications with [Docker][docker]
13 | - Automate cloud infrastructure management with [Pulumi][pulumi]
14 |
15 | [typescript]: https://www.typescriptlang.org/
16 | [garfish]: https://www.garfishjs.org/
17 | [vue]: https://vuejs.org/
18 | [caddy]: https://caddyserver.com/
19 | [fastify]: https://fastify.dev/
20 | [docker]: https://www.docker.com/
21 | [pulumi]: https://www.pulumi.com/
22 |
23 | | Micro Frontends | Micro Backends | Infrastructure as Code |
24 | | --------------------------- | --------------------------- | ----------------------- |
25 | | See [./clients](./clients). | See [./servers](./servers). | See [./infra](./infra). |
26 |
27 | ---
28 |
29 | #### Archive
30 |
31 | | Micro Frontends | Micro Backends | Infrastructure as Code |
32 | | ------------------- | ------------------- | ---------------------- |
33 | | See [./mfe](./mfe). | See [./mbe](./mbe). | See [./iac](./iac). |
34 |
--------------------------------------------------------------------------------
/clients/app-shell/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 | App Shell
8 |
9 |
10 |
11 |
12 |
13 |
14 |
--------------------------------------------------------------------------------
/clients/app-shell/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "private": true,
3 | "type": "module",
4 | "scripts": {
5 | "dev": "vite",
6 | "build": "vite build",
7 | "preview": "vite preview"
8 | },
9 | "dependencies": {
10 | "@garfish/css-scope": "^1.19.3",
11 | "@garfish/es-module": "^1.19.3",
12 | "garfish": "1.19.3",
13 | "vue": "3.5.13",
14 | "vue-storer": "0.6.0"
15 | },
16 | "devDependencies": {
17 | "@vitejs/plugin-vue": "5.2.1",
18 | "process-envify": "2.0.0",
19 | "typescript": "5.7.3",
20 | "vite": "6.1.0",
21 | "vue-tsc": "2.2.0"
22 | }
23 | }
24 |
--------------------------------------------------------------------------------
/clients/app-shell/src/App.vue:
--------------------------------------------------------------------------------
1 |
39 |
40 |
41 | App Shell
42 |
43 |
47 |
48 |
49 |
50 |
--------------------------------------------------------------------------------
/clients/app-shell/src/main.ts:
--------------------------------------------------------------------------------
1 | import { createApp } from 'vue';
2 |
3 | import App from './App.vue';
4 |
5 | const app = createApp(App);
6 |
7 | app.mount('#root');
8 |
--------------------------------------------------------------------------------
/clients/app-shell/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "compilerOptions": {
3 | "noUnusedLocals": true,
4 | "strict": true,
5 | "strictNullChecks": true,
6 |
7 | "allowImportingTsExtensions": true,
8 | "baseUrl": ".",
9 | "module": "esnext",
10 | "moduleResolution": "bundler",
11 | "paths": {
12 | "~/*": ["src/*"]
13 | },
14 | "resolveJsonModule": true,
15 | "types": ["vite/client", "vitest/globals"],
16 |
17 | "noEmit": true,
18 |
19 | "allowJs": true,
20 |
21 | "esModuleInterop": true,
22 | "forceConsistentCasingInFileNames": true,
23 | "isolatedModules": true,
24 |
25 | "jsx": "preserve",
26 | "lib": ["ESNext", "DOM"],
27 | "target": "esnext",
28 |
29 | "skipLibCheck": true
30 | },
31 | "include": ["src", "vite.config.ts"],
32 | "exclude": ["node_modules", "dist", "coverage"]
33 | }
34 |
--------------------------------------------------------------------------------
/clients/app-shell/vite.config.ts:
--------------------------------------------------------------------------------
1 | import { defineConfig } from 'vite';
2 | import vue from '@vitejs/plugin-vue';
3 |
4 | const port = 8000;
5 |
6 | export default defineConfig({
7 | base: `http://localhost:${port}`,
8 | server: {
9 | port,
10 | cors: true,
11 | origin: `http://localhost:${port}`,
12 | },
13 | plugins: [vue()],
14 | });
15 |
--------------------------------------------------------------------------------
/clients/sub-foo/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 | App Shell
8 |
9 |
10 |
11 |
12 |
13 |
14 |
--------------------------------------------------------------------------------
/clients/sub-foo/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "private": true,
3 | "type": "module",
4 | "scripts": {
5 | "dev": "vite",
6 | "build": "vite build",
7 | "preview": "vite preview"
8 | },
9 | "dependencies": {
10 | "@garfish/bridge-vue-v3": "1.19.3",
11 | "vue": "3.5.13"
12 | },
13 | "devDependencies": {
14 | "@vitejs/plugin-vue": "5.2.1",
15 | "process-envify": "^2.0.0",
16 | "typescript": "^5.7.3",
17 | "vite": "6.1.0",
18 | "vue-tsc": "^2.2.0"
19 | }
20 | }
21 |
--------------------------------------------------------------------------------
/clients/sub-foo/pnpm-lock.yaml:
--------------------------------------------------------------------------------
1 | lockfileVersion: '9.0'
2 |
3 | settings:
4 | autoInstallPeers: true
5 | excludeLinksFromLockfile: false
6 |
7 | importers:
8 |
9 | .:
10 | dependencies:
11 | '@garfish/bridge-vue-v3':
12 | specifier: 1.19.3
13 | version: 1.19.3(vue@3.5.13(typescript@5.7.3))
14 | vue:
15 | specifier: 3.5.13
16 | version: 3.5.13(typescript@5.7.3)
17 | devDependencies:
18 | '@vitejs/plugin-vue':
19 | specifier: 5.2.1
20 | version: 5.2.1(vite@6.1.0)(vue@3.5.13(typescript@5.7.3))
21 | process-envify:
22 | specifier: ^2.0.0
23 | version: 2.0.0
24 | typescript:
25 | specifier: ^5.7.3
26 | version: 5.7.3
27 | vite:
28 | specifier: 6.1.0
29 | version: 6.1.0
30 | vue-tsc:
31 | specifier: ^2.2.0
32 | version: 2.2.0(typescript@5.7.3)
33 |
34 | packages:
35 |
36 | '@babel/helper-string-parser@7.25.9':
37 | resolution: {integrity: sha512-4A/SCr/2KLd5jrtOMFzaKjVtAei3+2r/NChoBNoZ3EyP/+GlhoaEGoWOZUmFmoITP7zOJyHIMm+DYRd8o3PvHA==}
38 | engines: {node: '>=6.9.0'}
39 |
40 | '@babel/helper-validator-identifier@7.25.9':
41 | resolution: {integrity: sha512-Ed61U6XJc3CVRfkERJWDz4dJwKe7iLmmJsbOGu9wSloNSFttHV0I8g6UAgb7qnK5ly5bGLPd4oXZlxCdANBOWQ==}
42 | engines: {node: '>=6.9.0'}
43 |
44 | '@babel/parser@7.26.7':
45 | resolution: {integrity: sha512-kEvgGGgEjRUutvdVvZhbn/BxVt+5VSpwXz1j3WYXQbXDo8KzFOPNG2GQbdAiNq8g6wn1yKk7C/qrke03a84V+w==}
46 | engines: {node: '>=6.0.0'}
47 | hasBin: true
48 |
49 | '@babel/types@7.26.7':
50 | resolution: {integrity: sha512-t8kDRGrKXyp6+tjUh7hw2RLyclsW4TRoRvRHtSyAX9Bb5ldlFh+90YAYY6awRXrlB4G5G2izNeGySpATlFzmOg==}
51 | engines: {node: '>=6.9.0'}
52 |
53 | '@esbuild/aix-ppc64@0.24.2':
54 | resolution: {integrity: sha512-thpVCb/rhxE/BnMLQ7GReQLLN8q9qbHmI55F4489/ByVg2aQaQ6kbcLb6FHkocZzQhxc4gx0sCk0tJkKBFzDhA==}
55 | engines: {node: '>=18'}
56 | cpu: [ppc64]
57 | os: [aix]
58 |
59 | '@esbuild/android-arm64@0.24.2':
60 | resolution: {integrity: sha512-cNLgeqCqV8WxfcTIOeL4OAtSmL8JjcN6m09XIgro1Wi7cF4t/THaWEa7eL5CMoMBdjoHOTh/vwTO/o2TRXIyzg==}
61 | engines: {node: '>=18'}
62 | cpu: [arm64]
63 | os: [android]
64 |
65 | '@esbuild/android-arm@0.24.2':
66 | resolution: {integrity: sha512-tmwl4hJkCfNHwFB3nBa8z1Uy3ypZpxqxfTQOcHX+xRByyYgunVbZ9MzUUfb0RxaHIMnbHagwAxuTL+tnNM+1/Q==}
67 | engines: {node: '>=18'}
68 | cpu: [arm]
69 | os: [android]
70 |
71 | '@esbuild/android-x64@0.24.2':
72 | resolution: {integrity: sha512-B6Q0YQDqMx9D7rvIcsXfmJfvUYLoP722bgfBlO5cGvNVb5V/+Y7nhBE3mHV9OpxBf4eAS2S68KZztiPaWq4XYw==}
73 | engines: {node: '>=18'}
74 | cpu: [x64]
75 | os: [android]
76 |
77 | '@esbuild/darwin-arm64@0.24.2':
78 | resolution: {integrity: sha512-kj3AnYWc+CekmZnS5IPu9D+HWtUI49hbnyqk0FLEJDbzCIQt7hg7ucF1SQAilhtYpIujfaHr6O0UHlzzSPdOeA==}
79 | engines: {node: '>=18'}
80 | cpu: [arm64]
81 | os: [darwin]
82 |
83 | '@esbuild/darwin-x64@0.24.2':
84 | resolution: {integrity: sha512-WeSrmwwHaPkNR5H3yYfowhZcbriGqooyu3zI/3GGpF8AyUdsrrP0X6KumITGA9WOyiJavnGZUwPGvxvwfWPHIA==}
85 | engines: {node: '>=18'}
86 | cpu: [x64]
87 | os: [darwin]
88 |
89 | '@esbuild/freebsd-arm64@0.24.2':
90 | resolution: {integrity: sha512-UN8HXjtJ0k/Mj6a9+5u6+2eZ2ERD7Edt1Q9IZiB5UZAIdPnVKDoG7mdTVGhHJIeEml60JteamR3qhsr1r8gXvg==}
91 | engines: {node: '>=18'}
92 | cpu: [arm64]
93 | os: [freebsd]
94 |
95 | '@esbuild/freebsd-x64@0.24.2':
96 | resolution: {integrity: sha512-TvW7wE/89PYW+IevEJXZ5sF6gJRDY/14hyIGFXdIucxCsbRmLUcjseQu1SyTko+2idmCw94TgyaEZi9HUSOe3Q==}
97 | engines: {node: '>=18'}
98 | cpu: [x64]
99 | os: [freebsd]
100 |
101 | '@esbuild/linux-arm64@0.24.2':
102 | resolution: {integrity: sha512-7HnAD6074BW43YvvUmE/35Id9/NB7BeX5EoNkK9obndmZBUk8xmJJeU7DwmUeN7tkysslb2eSl6CTrYz6oEMQg==}
103 | engines: {node: '>=18'}
104 | cpu: [arm64]
105 | os: [linux]
106 |
107 | '@esbuild/linux-arm@0.24.2':
108 | resolution: {integrity: sha512-n0WRM/gWIdU29J57hJyUdIsk0WarGd6To0s+Y+LwvlC55wt+GT/OgkwoXCXvIue1i1sSNWblHEig00GBWiJgfA==}
109 | engines: {node: '>=18'}
110 | cpu: [arm]
111 | os: [linux]
112 |
113 | '@esbuild/linux-ia32@0.24.2':
114 | resolution: {integrity: sha512-sfv0tGPQhcZOgTKO3oBE9xpHuUqguHvSo4jl+wjnKwFpapx+vUDcawbwPNuBIAYdRAvIDBfZVvXprIj3HA+Ugw==}
115 | engines: {node: '>=18'}
116 | cpu: [ia32]
117 | os: [linux]
118 |
119 | '@esbuild/linux-loong64@0.24.2':
120 | resolution: {integrity: sha512-CN9AZr8kEndGooS35ntToZLTQLHEjtVB5n7dl8ZcTZMonJ7CCfStrYhrzF97eAecqVbVJ7APOEe18RPI4KLhwQ==}
121 | engines: {node: '>=18'}
122 | cpu: [loong64]
123 | os: [linux]
124 |
125 | '@esbuild/linux-mips64el@0.24.2':
126 | resolution: {integrity: sha512-iMkk7qr/wl3exJATwkISxI7kTcmHKE+BlymIAbHO8xanq/TjHaaVThFF6ipWzPHryoFsesNQJPE/3wFJw4+huw==}
127 | engines: {node: '>=18'}
128 | cpu: [mips64el]
129 | os: [linux]
130 |
131 | '@esbuild/linux-ppc64@0.24.2':
132 | resolution: {integrity: sha512-shsVrgCZ57Vr2L8mm39kO5PPIb+843FStGt7sGGoqiiWYconSxwTiuswC1VJZLCjNiMLAMh34jg4VSEQb+iEbw==}
133 | engines: {node: '>=18'}
134 | cpu: [ppc64]
135 | os: [linux]
136 |
137 | '@esbuild/linux-riscv64@0.24.2':
138 | resolution: {integrity: sha512-4eSFWnU9Hhd68fW16GD0TINewo1L6dRrB+oLNNbYyMUAeOD2yCK5KXGK1GH4qD/kT+bTEXjsyTCiJGHPZ3eM9Q==}
139 | engines: {node: '>=18'}
140 | cpu: [riscv64]
141 | os: [linux]
142 |
143 | '@esbuild/linux-s390x@0.24.2':
144 | resolution: {integrity: sha512-S0Bh0A53b0YHL2XEXC20bHLuGMOhFDO6GN4b3YjRLK//Ep3ql3erpNcPlEFed93hsQAjAQDNsvcK+hV90FubSw==}
145 | engines: {node: '>=18'}
146 | cpu: [s390x]
147 | os: [linux]
148 |
149 | '@esbuild/linux-x64@0.24.2':
150 | resolution: {integrity: sha512-8Qi4nQcCTbLnK9WoMjdC9NiTG6/E38RNICU6sUNqK0QFxCYgoARqVqxdFmWkdonVsvGqWhmm7MO0jyTqLqwj0Q==}
151 | engines: {node: '>=18'}
152 | cpu: [x64]
153 | os: [linux]
154 |
155 | '@esbuild/netbsd-arm64@0.24.2':
156 | resolution: {integrity: sha512-wuLK/VztRRpMt9zyHSazyCVdCXlpHkKm34WUyinD2lzK07FAHTq0KQvZZlXikNWkDGoT6x3TD51jKQ7gMVpopw==}
157 | engines: {node: '>=18'}
158 | cpu: [arm64]
159 | os: [netbsd]
160 |
161 | '@esbuild/netbsd-x64@0.24.2':
162 | resolution: {integrity: sha512-VefFaQUc4FMmJuAxmIHgUmfNiLXY438XrL4GDNV1Y1H/RW3qow68xTwjZKfj/+Plp9NANmzbH5R40Meudu8mmw==}
163 | engines: {node: '>=18'}
164 | cpu: [x64]
165 | os: [netbsd]
166 |
167 | '@esbuild/openbsd-arm64@0.24.2':
168 | resolution: {integrity: sha512-YQbi46SBct6iKnszhSvdluqDmxCJA+Pu280Av9WICNwQmMxV7nLRHZfjQzwbPs3jeWnuAhE9Jy0NrnJ12Oz+0A==}
169 | engines: {node: '>=18'}
170 | cpu: [arm64]
171 | os: [openbsd]
172 |
173 | '@esbuild/openbsd-x64@0.24.2':
174 | resolution: {integrity: sha512-+iDS6zpNM6EnJyWv0bMGLWSWeXGN/HTaF/LXHXHwejGsVi+ooqDfMCCTerNFxEkM3wYVcExkeGXNqshc9iMaOA==}
175 | engines: {node: '>=18'}
176 | cpu: [x64]
177 | os: [openbsd]
178 |
179 | '@esbuild/sunos-x64@0.24.2':
180 | resolution: {integrity: sha512-hTdsW27jcktEvpwNHJU4ZwWFGkz2zRJUz8pvddmXPtXDzVKTTINmlmga3ZzwcuMpUvLw7JkLy9QLKyGpD2Yxig==}
181 | engines: {node: '>=18'}
182 | cpu: [x64]
183 | os: [sunos]
184 |
185 | '@esbuild/win32-arm64@0.24.2':
186 | resolution: {integrity: sha512-LihEQ2BBKVFLOC9ZItT9iFprsE9tqjDjnbulhHoFxYQtQfai7qfluVODIYxt1PgdoyQkz23+01rzwNwYfutxUQ==}
187 | engines: {node: '>=18'}
188 | cpu: [arm64]
189 | os: [win32]
190 |
191 | '@esbuild/win32-ia32@0.24.2':
192 | resolution: {integrity: sha512-q+iGUwfs8tncmFC9pcnD5IvRHAzmbwQ3GPS5/ceCyHdjXubwQWI12MKWSNSMYLJMq23/IUCvJMS76PDqXe1fxA==}
193 | engines: {node: '>=18'}
194 | cpu: [ia32]
195 | os: [win32]
196 |
197 | '@esbuild/win32-x64@0.24.2':
198 | resolution: {integrity: sha512-7VTgWzgMGvup6aSqDPLiW5zHaxYJGTO4OokMjIlrCtf+VpEL+cXKtCvg723iguPYI5oaUNdS+/V7OU2gvXVWEg==}
199 | engines: {node: '>=18'}
200 | cpu: [x64]
201 | os: [win32]
202 |
203 | '@garfish/bridge-vue-v3@1.19.3':
204 | resolution: {integrity: sha512-0vvbB0y6NgiG2anG9VQSezb09ldAzuVLPYpcIE9JU7SmueP80qxwsbZiBMVWspCyIRCMWfpqLoo8mhIAbdwhrg==}
205 | peerDependencies:
206 | vue: '=3'
207 |
208 | '@jridgewell/sourcemap-codec@1.5.0':
209 | resolution: {integrity: sha512-gv3ZRaISU3fjPAgNsriBRqGWQL6quFx04YMPW/zD8XMLsU32mhCCbfbO6KZFLjvYpCZ8zyDEgqsgf+PwPaM7GQ==}
210 |
211 | '@rollup/rollup-android-arm-eabi@4.34.5':
212 | resolution: {integrity: sha512-JXmmQcKQtpf3Z6lvA8akkrHDZ5AEfgc2hLMix1/X5BhQbezBQ0AP5GYLdU8jsQRme8qr2sscCe3wizp7UT0L9g==}
213 | cpu: [arm]
214 | os: [android]
215 |
216 | '@rollup/rollup-android-arm64@4.34.5':
217 | resolution: {integrity: sha512-9/A8/ZBOprUjkrJoP9BBEq2vdSud6BPd3LChw09bJQiEZH5oN4kWIkHu90cA0Cj0cSF5cIaD76+0lA+d5KHmpQ==}
218 | cpu: [arm64]
219 | os: [android]
220 |
221 | '@rollup/rollup-darwin-arm64@4.34.5':
222 | resolution: {integrity: sha512-b9oCfgHKfc1AJEQ5sEpE8Kf6s7aeygj5bZAsl1hTpZc1V9cfZASFSXzzNj7o/BQNPbjmVkVxpCCLRhBfLXhJ5g==}
223 | cpu: [arm64]
224 | os: [darwin]
225 |
226 | '@rollup/rollup-darwin-x64@4.34.5':
227 | resolution: {integrity: sha512-Gz42gKBQPoFdMYdsVqkcpttYOO/0aP7f+1CgMaeZEz0gss7dop1TsO3hT77Iroz/TV7PdPUG/RYlj9EA39L4dw==}
228 | cpu: [x64]
229 | os: [darwin]
230 |
231 | '@rollup/rollup-freebsd-arm64@4.34.5':
232 | resolution: {integrity: sha512-JPkafjkOFaupd8VQYsXfGFKC2pfMr7hwSYGkVGNwhbW0k0lHHyIdhCSNBendJ4O7YlT4yRyKXoms1TL7saO7SQ==}
233 | cpu: [arm64]
234 | os: [freebsd]
235 |
236 | '@rollup/rollup-freebsd-x64@4.34.5':
237 | resolution: {integrity: sha512-j6Q8VFqyI8hZM33h1JC6DZK2w8ejkXqEMozTrtIEGfRVMpVZL3GrLOOYEUkAgUSpJ9sb2w+FEpjGj7IHRcQfdw==}
238 | cpu: [x64]
239 | os: [freebsd]
240 |
241 | '@rollup/rollup-linux-arm-gnueabihf@4.34.5':
242 | resolution: {integrity: sha512-6jyiXKF9Xq6x9yQjct5xrRT0VghJk5VzAfed3o0hgncwacZkzOdR0TXLRNjexsEXWN8tG7jWWwsVk7WeFi//gw==}
243 | cpu: [arm]
244 | os: [linux]
245 |
246 | '@rollup/rollup-linux-arm-musleabihf@4.34.5':
247 | resolution: {integrity: sha512-cOTYe5tLcGAvGztRLIqx87LE7j/qjaAqFrrHsPFlnuhhhFO5LSr2AzvdQYuxomJMzMBrXkMRNl9bQEpDZ5bjLQ==}
248 | cpu: [arm]
249 | os: [linux]
250 |
251 | '@rollup/rollup-linux-arm64-gnu@4.34.5':
252 | resolution: {integrity: sha512-KHlrd+YqmS7rriW+LBb1kQNYmd5w1sAIG3z7HEpnQOrg/skeYYv9DAcclGL9gpFdpnzmiAEkzsTT74kZWUtChQ==}
253 | cpu: [arm64]
254 | os: [linux]
255 |
256 | '@rollup/rollup-linux-arm64-musl@4.34.5':
257 | resolution: {integrity: sha512-uOb6hzDqym4Sw+qw3+svS3SmwQGVUhyTdPKyHDdlYg1Z0aHjdNmjwRY7zw/90/UfBe/yD7Mv2mYKhQpOfy4RYA==}
258 | cpu: [arm64]
259 | os: [linux]
260 |
261 | '@rollup/rollup-linux-loongarch64-gnu@4.34.5':
262 | resolution: {integrity: sha512-pARu8ZKANZH4wINLdHLKG69EPwJswM6A+Ox1a9LpiclRQoyjacFFTtXN3akKQ2ufJXDasO/pWvxKN9ZfCgEoFA==}
263 | cpu: [loong64]
264 | os: [linux]
265 |
266 | '@rollup/rollup-linux-powerpc64le-gnu@4.34.5':
267 | resolution: {integrity: sha512-crUWn12NRmCdao2YwS1GvlPCVypMBMJlexTaantaP2+dAMd2eZBErFcKG8hZYEHjSbbk2UoH1aTlyeA4iKLqSA==}
268 | cpu: [ppc64]
269 | os: [linux]
270 |
271 | '@rollup/rollup-linux-riscv64-gnu@4.34.5':
272 | resolution: {integrity: sha512-XtD/oMhCdixi3x8rCNyDRMUsLo1Z+1UQcK+oR7AsjglGov9ETiT3TNFhUPzaGC1jH+uaMtPhxrVRUub+pnAKTg==}
273 | cpu: [riscv64]
274 | os: [linux]
275 |
276 | '@rollup/rollup-linux-s390x-gnu@4.34.5':
277 | resolution: {integrity: sha512-V3+BvgyHb21aF7lw0sc78Tv0+xLp4lm2OM7CKFVrBuppsMvtl/9O5y2OX4tdDT0EhIsDP/ObJPqDuEg1ZoTwSQ==}
278 | cpu: [s390x]
279 | os: [linux]
280 |
281 | '@rollup/rollup-linux-x64-gnu@4.34.5':
282 | resolution: {integrity: sha512-SkCIXLGk42yldTcH8UXh++m0snVxp9DLf4meb1mWm0lC8jzxjFBwSLGtUSeLgQDsC05iBaIhyjNX46DlByrApQ==}
283 | cpu: [x64]
284 | os: [linux]
285 |
286 | '@rollup/rollup-linux-x64-musl@4.34.5':
287 | resolution: {integrity: sha512-iUcH3FBtBN2/Ce0rI84suRhD0+bB5BVEffqOwsGaX5py5TuYLOQa7S7oVBP0NKtB5rub3i9IvZtMXiD96l5v0A==}
288 | cpu: [x64]
289 | os: [linux]
290 |
291 | '@rollup/rollup-win32-arm64-msvc@4.34.5':
292 | resolution: {integrity: sha512-PUbWd+h/h6rUowalDYIdc9S9LJXbQDMcJe0BjABl3oT3efYRgZ8aUe8ZZDSie7y+fz6Z+rueNfdorIbkWv5Eqg==}
293 | cpu: [arm64]
294 | os: [win32]
295 |
296 | '@rollup/rollup-win32-ia32-msvc@4.34.5':
297 | resolution: {integrity: sha512-3vncGhOJiAUR85fnAXJyvSp2GaDWYByIQmW68ZAr+e8kIxgvJ1VaZbfHD5BO5X6hwRQdY6Um/XfA3l5c2lV+OQ==}
298 | cpu: [ia32]
299 | os: [win32]
300 |
301 | '@rollup/rollup-win32-x64-msvc@4.34.5':
302 | resolution: {integrity: sha512-Mi8yVUlQOoeBpY72n75VLATptPGvj2lHa47rQdK9kZ4MoG5Ve86aVIU+PO3tBklTCBtILtdRfXS0EvIbXgmCAg==}
303 | cpu: [x64]
304 | os: [win32]
305 |
306 | '@types/estree@1.0.6':
307 | resolution: {integrity: sha512-AYnb1nQyY49te+VRAVgmzfcgjYS91mY5P0TKUDCLEM+gNnA+3T6rWITXRLYCpahpqSQbN5cE+gHpnPyXjHWxcw==}
308 |
309 | '@vitejs/plugin-vue@5.2.1':
310 | resolution: {integrity: sha512-cxh314tzaWwOLqVes2gnnCtvBDcM1UMdn+iFR+UjAn411dPT3tOmqrJjbMd7koZpMAmBM/GqeV4n9ge7JSiJJQ==}
311 | engines: {node: ^18.0.0 || >=20.0.0}
312 | peerDependencies:
313 | vite: ^5.0.0 || ^6.0.0
314 | vue: ^3.2.25
315 |
316 | '@volar/language-core@2.4.11':
317 | resolution: {integrity: sha512-lN2C1+ByfW9/JRPpqScuZt/4OrUUse57GLI6TbLgTIqBVemdl1wNcZ1qYGEo2+Gw8coYLgCy7SuKqn6IrQcQgg==}
318 |
319 | '@volar/source-map@2.4.11':
320 | resolution: {integrity: sha512-ZQpmafIGvaZMn/8iuvCFGrW3smeqkq/IIh9F1SdSx9aUl0J4Iurzd6/FhmjNO5g2ejF3rT45dKskgXWiofqlZQ==}
321 |
322 | '@volar/typescript@2.4.11':
323 | resolution: {integrity: sha512-2DT+Tdh88Spp5PyPbqhyoYavYCPDsqbHLFwcUI9K1NlY1YgUJvujGdrqUp0zWxnW7KWNTr3xSpMuv2WnaTKDAw==}
324 |
325 | '@vue/compiler-core@3.5.13':
326 | resolution: {integrity: sha512-oOdAkwqUfW1WqpwSYJce06wvt6HljgY3fGeM9NcVA1HaYOij3mZG9Rkysn0OHuyUAGMbEbARIpsG+LPVlBJ5/Q==}
327 |
328 | '@vue/compiler-dom@3.5.13':
329 | resolution: {integrity: sha512-ZOJ46sMOKUjO3e94wPdCzQ6P1Lx/vhp2RSvfaab88Ajexs0AHeV0uasYhi99WPaogmBlRHNRuly8xV75cNTMDA==}
330 |
331 | '@vue/compiler-sfc@3.5.13':
332 | resolution: {integrity: sha512-6VdaljMpD82w6c2749Zhf5T9u5uLBWKnVue6XWxprDobftnletJ8+oel7sexFfM3qIxNmVE7LSFGTpv6obNyaQ==}
333 |
334 | '@vue/compiler-ssr@3.5.13':
335 | resolution: {integrity: sha512-wMH6vrYHxQl/IybKJagqbquvxpWCuVYpoUJfCqFZwa/JY1GdATAQ+TgVtgrwwMZ0D07QhA99rs/EAAWfvG6KpA==}
336 |
337 | '@vue/compiler-vue2@2.7.16':
338 | resolution: {integrity: sha512-qYC3Psj9S/mfu9uVi5WvNZIzq+xnXMhOwbTFKKDD7b1lhpnn71jXSFdTQ+WsIEk0ONCd7VV2IMm7ONl6tbQ86A==}
339 |
340 | '@vue/language-core@2.2.0':
341 | resolution: {integrity: sha512-O1ZZFaaBGkKbsRfnVH1ifOK1/1BUkyK+3SQsfnh6PmMmD4qJcTU8godCeA96jjDRTL6zgnK7YzCHfaUlH2r0Mw==}
342 | peerDependencies:
343 | typescript: '*'
344 | peerDependenciesMeta:
345 | typescript:
346 | optional: true
347 |
348 | '@vue/reactivity@3.5.13':
349 | resolution: {integrity: sha512-NaCwtw8o48B9I6L1zl2p41OHo/2Z4wqYGGIK1Khu5T7yxrn+ATOixn/Udn2m+6kZKB/J7cuT9DbWWhRxqixACg==}
350 |
351 | '@vue/runtime-core@3.5.13':
352 | resolution: {integrity: sha512-Fj4YRQ3Az0WTZw1sFe+QDb0aXCerigEpw418pw1HBUKFtnQHWzwojaukAs2X/c9DQz4MQ4bsXTGlcpGxU/RCIw==}
353 |
354 | '@vue/runtime-dom@3.5.13':
355 | resolution: {integrity: sha512-dLaj94s93NYLqjLiyFzVs9X6dWhTdAlEAciC3Moq7gzAc13VJUdCnjjRurNM6uTLFATRHexHCTu/Xp3eW6yoog==}
356 |
357 | '@vue/server-renderer@3.5.13':
358 | resolution: {integrity: sha512-wAi4IRJV/2SAW3htkTlB+dHeRmpTiVIK1OGLWV1yeStVSebSQQOwGwIq0D3ZIoBj2C2qpgz5+vX9iEBkTdk5YA==}
359 | peerDependencies:
360 | vue: 3.5.13
361 |
362 | '@vue/shared@3.5.13':
363 | resolution: {integrity: sha512-/hnE/qP5ZoGpol0a5mDi45bOd7t3tjYJBjsgCsivow7D48cJeV5l05RD82lPqi7gRiphZM37rnhW1l6ZoCNNnQ==}
364 |
365 | alien-signals@0.4.14:
366 | resolution: {integrity: sha512-itUAVzhczTmP2U5yX67xVpsbbOiquusbWVyA9N+sy6+r6YVbFkahXvNCeEPWEOMhwDYwbVbGHFkVL03N9I5g+Q==}
367 |
368 | balanced-match@1.0.2:
369 | resolution: {integrity: sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==}
370 |
371 | brace-expansion@2.0.1:
372 | resolution: {integrity: sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==}
373 |
374 | csstype@3.1.3:
375 | resolution: {integrity: sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw==}
376 |
377 | de-indent@1.0.2:
378 | resolution: {integrity: sha512-e/1zu3xH5MQryN2zdVaF0OrdNLUbvWxzMbi+iNA6Bky7l1RoP8a2fIbRocyHclXt/arDrrR6lL3TqFD9pMQTsg==}
379 |
380 | entities@4.5.0:
381 | resolution: {integrity: sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==}
382 | engines: {node: '>=0.12'}
383 |
384 | esbuild@0.24.2:
385 | resolution: {integrity: sha512-+9egpBW8I3CD5XPe0n6BfT5fxLzxrlDzqydF3aviG+9ni1lDC/OvMHcxqEFV0+LANZG5R1bFMWfUrjVsdwxJvA==}
386 | engines: {node: '>=18'}
387 | hasBin: true
388 |
389 | estree-walker@2.0.2:
390 | resolution: {integrity: sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w==}
391 |
392 | fsevents@2.3.3:
393 | resolution: {integrity: sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==}
394 | engines: {node: ^8.16.0 || ^10.6.0 || >=11.0.0}
395 | os: [darwin]
396 |
397 | he@1.2.0:
398 | resolution: {integrity: sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==}
399 | hasBin: true
400 |
401 | magic-string@0.30.17:
402 | resolution: {integrity: sha512-sNPKHvyjVf7gyjwS4xGTaW/mCnF8wnjtifKBEhxfZ7E/S8tQ0rssrwGNn6q8JH/ohItJfSQp9mBtQYuTlH5QnA==}
403 |
404 | minimatch@9.0.5:
405 | resolution: {integrity: sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==}
406 | engines: {node: '>=16 || 14 >=14.17'}
407 |
408 | muggle-string@0.4.1:
409 | resolution: {integrity: sha512-VNTrAak/KhO2i8dqqnqnAHOa3cYBwXEZe9h+D5h/1ZqFSTEFHdM65lR7RoIqq3tBBYavsOXV84NoHXZ0AkPyqQ==}
410 |
411 | nanoid@3.3.8:
412 | resolution: {integrity: sha512-WNLf5Sd8oZxOm+TzppcYk8gVOgP+l58xNy58D0nbUnOxOWRWvlcCV4kUF7ltmI6PsrLl/BgKEyS4mqsGChFN0w==}
413 | engines: {node: ^10 || ^12 || ^13.7 || ^14 || >=15.0.1}
414 | hasBin: true
415 |
416 | path-browserify@1.0.1:
417 | resolution: {integrity: sha512-b7uo2UCUOYZcnF/3ID0lulOJi/bafxa1xPe7ZPsammBSpjSWQkjNxlt635YGS2MiR9GjvuXCtz2emr3jbsz98g==}
418 |
419 | picocolors@1.1.1:
420 | resolution: {integrity: sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==}
421 |
422 | postcss@8.5.1:
423 | resolution: {integrity: sha512-6oz2beyjc5VMn/KV1pPw8fliQkhBXrVn1Z3TVyqZxU8kZpzEKhBdmCFqI6ZbmGtamQvQGuU1sgPTk8ZrXDD7jQ==}
424 | engines: {node: ^10 || ^12 || >=14}
425 |
426 | process-envify@2.0.0:
427 | resolution: {integrity: sha512-bxlWH2iGWrlYvQSN8U3awIp0MUzZUXpHGFW2vpe4f/0F2MNOGsT10H/ILQXcTwfUpnfAFsUb7/ozwpoHMPuEVg==}
428 |
429 | rollup@4.34.5:
430 | resolution: {integrity: sha512-GyVCmpo9z/HYqFD8QWoBUnz1Q9xC22t8tPAZm/AvAcUg2U2/+DkboEvSioMwv042zE4I9N3FEhx7fiCT2YHzKQ==}
431 | engines: {node: '>=18.0.0', npm: '>=8.0.0'}
432 | hasBin: true
433 |
434 | source-map-js@1.2.1:
435 | resolution: {integrity: sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==}
436 | engines: {node: '>=0.10.0'}
437 |
438 | typescript@5.7.3:
439 | resolution: {integrity: sha512-84MVSjMEHP+FQRPy3pX9sTVV/INIex71s9TL2Gm5FG/WG1SqXeKyZ0k7/blY/4FdOzI12CBy1vGc4og/eus0fw==}
440 | engines: {node: '>=14.17'}
441 | hasBin: true
442 |
443 | vite@6.1.0:
444 | resolution: {integrity: sha512-RjjMipCKVoR4hVfPY6GQTgveinjNuyLw+qruksLDvA5ktI1150VmcMBKmQaEWJhg/j6Uaf6dNCNA0AfdzUb/hQ==}
445 | engines: {node: ^18.0.0 || ^20.0.0 || >=22.0.0}
446 | hasBin: true
447 | peerDependencies:
448 | '@types/node': ^18.0.0 || ^20.0.0 || >=22.0.0
449 | jiti: '>=1.21.0'
450 | less: '*'
451 | lightningcss: ^1.21.0
452 | sass: '*'
453 | sass-embedded: '*'
454 | stylus: '*'
455 | sugarss: '*'
456 | terser: ^5.16.0
457 | tsx: ^4.8.1
458 | yaml: ^2.4.2
459 | peerDependenciesMeta:
460 | '@types/node':
461 | optional: true
462 | jiti:
463 | optional: true
464 | less:
465 | optional: true
466 | lightningcss:
467 | optional: true
468 | sass:
469 | optional: true
470 | sass-embedded:
471 | optional: true
472 | stylus:
473 | optional: true
474 | sugarss:
475 | optional: true
476 | terser:
477 | optional: true
478 | tsx:
479 | optional: true
480 | yaml:
481 | optional: true
482 |
483 | vscode-uri@3.1.0:
484 | resolution: {integrity: sha512-/BpdSx+yCQGnCvecbyXdxHDkuk55/G3xwnC0GqY4gmQ3j+A+g8kzzgB4Nk/SINjqn6+waqw3EgbVF2QKExkRxQ==}
485 |
486 | vue-tsc@2.2.0:
487 | resolution: {integrity: sha512-gtmM1sUuJ8aSb0KoAFmK9yMxb8TxjewmxqTJ1aKphD5Cbu0rULFY6+UQT51zW7SpUcenfPUuflKyVwyx9Qdnxg==}
488 | hasBin: true
489 | peerDependencies:
490 | typescript: '>=5.0.0'
491 |
492 | vue@3.5.13:
493 | resolution: {integrity: sha512-wmeiSMxkZCSc+PM2w2VRsOYAZC8GdipNFRTsLSfodVqI9mbejKeXEGr8SckuLnrQPGe3oJN5c3K0vpoU9q/wCQ==}
494 | peerDependencies:
495 | typescript: '*'
496 | peerDependenciesMeta:
497 | typescript:
498 | optional: true
499 |
500 | snapshots:
501 |
502 | '@babel/helper-string-parser@7.25.9': {}
503 |
504 | '@babel/helper-validator-identifier@7.25.9': {}
505 |
506 | '@babel/parser@7.26.7':
507 | dependencies:
508 | '@babel/types': 7.26.7
509 |
510 | '@babel/types@7.26.7':
511 | dependencies:
512 | '@babel/helper-string-parser': 7.25.9
513 | '@babel/helper-validator-identifier': 7.25.9
514 |
515 | '@esbuild/aix-ppc64@0.24.2':
516 | optional: true
517 |
518 | '@esbuild/android-arm64@0.24.2':
519 | optional: true
520 |
521 | '@esbuild/android-arm@0.24.2':
522 | optional: true
523 |
524 | '@esbuild/android-x64@0.24.2':
525 | optional: true
526 |
527 | '@esbuild/darwin-arm64@0.24.2':
528 | optional: true
529 |
530 | '@esbuild/darwin-x64@0.24.2':
531 | optional: true
532 |
533 | '@esbuild/freebsd-arm64@0.24.2':
534 | optional: true
535 |
536 | '@esbuild/freebsd-x64@0.24.2':
537 | optional: true
538 |
539 | '@esbuild/linux-arm64@0.24.2':
540 | optional: true
541 |
542 | '@esbuild/linux-arm@0.24.2':
543 | optional: true
544 |
545 | '@esbuild/linux-ia32@0.24.2':
546 | optional: true
547 |
548 | '@esbuild/linux-loong64@0.24.2':
549 | optional: true
550 |
551 | '@esbuild/linux-mips64el@0.24.2':
552 | optional: true
553 |
554 | '@esbuild/linux-ppc64@0.24.2':
555 | optional: true
556 |
557 | '@esbuild/linux-riscv64@0.24.2':
558 | optional: true
559 |
560 | '@esbuild/linux-s390x@0.24.2':
561 | optional: true
562 |
563 | '@esbuild/linux-x64@0.24.2':
564 | optional: true
565 |
566 | '@esbuild/netbsd-arm64@0.24.2':
567 | optional: true
568 |
569 | '@esbuild/netbsd-x64@0.24.2':
570 | optional: true
571 |
572 | '@esbuild/openbsd-arm64@0.24.2':
573 | optional: true
574 |
575 | '@esbuild/openbsd-x64@0.24.2':
576 | optional: true
577 |
578 | '@esbuild/sunos-x64@0.24.2':
579 | optional: true
580 |
581 | '@esbuild/win32-arm64@0.24.2':
582 | optional: true
583 |
584 | '@esbuild/win32-ia32@0.24.2':
585 | optional: true
586 |
587 | '@esbuild/win32-x64@0.24.2':
588 | optional: true
589 |
590 | '@garfish/bridge-vue-v3@1.19.3(vue@3.5.13(typescript@5.7.3))':
591 | dependencies:
592 | vue: 3.5.13(typescript@5.7.3)
593 |
594 | '@jridgewell/sourcemap-codec@1.5.0': {}
595 |
596 | '@rollup/rollup-android-arm-eabi@4.34.5':
597 | optional: true
598 |
599 | '@rollup/rollup-android-arm64@4.34.5':
600 | optional: true
601 |
602 | '@rollup/rollup-darwin-arm64@4.34.5':
603 | optional: true
604 |
605 | '@rollup/rollup-darwin-x64@4.34.5':
606 | optional: true
607 |
608 | '@rollup/rollup-freebsd-arm64@4.34.5':
609 | optional: true
610 |
611 | '@rollup/rollup-freebsd-x64@4.34.5':
612 | optional: true
613 |
614 | '@rollup/rollup-linux-arm-gnueabihf@4.34.5':
615 | optional: true
616 |
617 | '@rollup/rollup-linux-arm-musleabihf@4.34.5':
618 | optional: true
619 |
620 | '@rollup/rollup-linux-arm64-gnu@4.34.5':
621 | optional: true
622 |
623 | '@rollup/rollup-linux-arm64-musl@4.34.5':
624 | optional: true
625 |
626 | '@rollup/rollup-linux-loongarch64-gnu@4.34.5':
627 | optional: true
628 |
629 | '@rollup/rollup-linux-powerpc64le-gnu@4.34.5':
630 | optional: true
631 |
632 | '@rollup/rollup-linux-riscv64-gnu@4.34.5':
633 | optional: true
634 |
635 | '@rollup/rollup-linux-s390x-gnu@4.34.5':
636 | optional: true
637 |
638 | '@rollup/rollup-linux-x64-gnu@4.34.5':
639 | optional: true
640 |
641 | '@rollup/rollup-linux-x64-musl@4.34.5':
642 | optional: true
643 |
644 | '@rollup/rollup-win32-arm64-msvc@4.34.5':
645 | optional: true
646 |
647 | '@rollup/rollup-win32-ia32-msvc@4.34.5':
648 | optional: true
649 |
650 | '@rollup/rollup-win32-x64-msvc@4.34.5':
651 | optional: true
652 |
653 | '@types/estree@1.0.6': {}
654 |
655 | '@vitejs/plugin-vue@5.2.1(vite@6.1.0)(vue@3.5.13(typescript@5.7.3))':
656 | dependencies:
657 | vite: 6.1.0
658 | vue: 3.5.13(typescript@5.7.3)
659 |
660 | '@volar/language-core@2.4.11':
661 | dependencies:
662 | '@volar/source-map': 2.4.11
663 |
664 | '@volar/source-map@2.4.11': {}
665 |
666 | '@volar/typescript@2.4.11':
667 | dependencies:
668 | '@volar/language-core': 2.4.11
669 | path-browserify: 1.0.1
670 | vscode-uri: 3.1.0
671 |
672 | '@vue/compiler-core@3.5.13':
673 | dependencies:
674 | '@babel/parser': 7.26.7
675 | '@vue/shared': 3.5.13
676 | entities: 4.5.0
677 | estree-walker: 2.0.2
678 | source-map-js: 1.2.1
679 |
680 | '@vue/compiler-dom@3.5.13':
681 | dependencies:
682 | '@vue/compiler-core': 3.5.13
683 | '@vue/shared': 3.5.13
684 |
685 | '@vue/compiler-sfc@3.5.13':
686 | dependencies:
687 | '@babel/parser': 7.26.7
688 | '@vue/compiler-core': 3.5.13
689 | '@vue/compiler-dom': 3.5.13
690 | '@vue/compiler-ssr': 3.5.13
691 | '@vue/shared': 3.5.13
692 | estree-walker: 2.0.2
693 | magic-string: 0.30.17
694 | postcss: 8.5.1
695 | source-map-js: 1.2.1
696 |
697 | '@vue/compiler-ssr@3.5.13':
698 | dependencies:
699 | '@vue/compiler-dom': 3.5.13
700 | '@vue/shared': 3.5.13
701 |
702 | '@vue/compiler-vue2@2.7.16':
703 | dependencies:
704 | de-indent: 1.0.2
705 | he: 1.2.0
706 |
707 | '@vue/language-core@2.2.0(typescript@5.7.3)':
708 | dependencies:
709 | '@volar/language-core': 2.4.11
710 | '@vue/compiler-dom': 3.5.13
711 | '@vue/compiler-vue2': 2.7.16
712 | '@vue/shared': 3.5.13
713 | alien-signals: 0.4.14
714 | minimatch: 9.0.5
715 | muggle-string: 0.4.1
716 | path-browserify: 1.0.1
717 | optionalDependencies:
718 | typescript: 5.7.3
719 |
720 | '@vue/reactivity@3.5.13':
721 | dependencies:
722 | '@vue/shared': 3.5.13
723 |
724 | '@vue/runtime-core@3.5.13':
725 | dependencies:
726 | '@vue/reactivity': 3.5.13
727 | '@vue/shared': 3.5.13
728 |
729 | '@vue/runtime-dom@3.5.13':
730 | dependencies:
731 | '@vue/reactivity': 3.5.13
732 | '@vue/runtime-core': 3.5.13
733 | '@vue/shared': 3.5.13
734 | csstype: 3.1.3
735 |
736 | '@vue/server-renderer@3.5.13(vue@3.5.13(typescript@5.7.3))':
737 | dependencies:
738 | '@vue/compiler-ssr': 3.5.13
739 | '@vue/shared': 3.5.13
740 | vue: 3.5.13(typescript@5.7.3)
741 |
742 | '@vue/shared@3.5.13': {}
743 |
744 | alien-signals@0.4.14: {}
745 |
746 | balanced-match@1.0.2: {}
747 |
748 | brace-expansion@2.0.1:
749 | dependencies:
750 | balanced-match: 1.0.2
751 |
752 | csstype@3.1.3: {}
753 |
754 | de-indent@1.0.2: {}
755 |
756 | entities@4.5.0: {}
757 |
758 | esbuild@0.24.2:
759 | optionalDependencies:
760 | '@esbuild/aix-ppc64': 0.24.2
761 | '@esbuild/android-arm': 0.24.2
762 | '@esbuild/android-arm64': 0.24.2
763 | '@esbuild/android-x64': 0.24.2
764 | '@esbuild/darwin-arm64': 0.24.2
765 | '@esbuild/darwin-x64': 0.24.2
766 | '@esbuild/freebsd-arm64': 0.24.2
767 | '@esbuild/freebsd-x64': 0.24.2
768 | '@esbuild/linux-arm': 0.24.2
769 | '@esbuild/linux-arm64': 0.24.2
770 | '@esbuild/linux-ia32': 0.24.2
771 | '@esbuild/linux-loong64': 0.24.2
772 | '@esbuild/linux-mips64el': 0.24.2
773 | '@esbuild/linux-ppc64': 0.24.2
774 | '@esbuild/linux-riscv64': 0.24.2
775 | '@esbuild/linux-s390x': 0.24.2
776 | '@esbuild/linux-x64': 0.24.2
777 | '@esbuild/netbsd-arm64': 0.24.2
778 | '@esbuild/netbsd-x64': 0.24.2
779 | '@esbuild/openbsd-arm64': 0.24.2
780 | '@esbuild/openbsd-x64': 0.24.2
781 | '@esbuild/sunos-x64': 0.24.2
782 | '@esbuild/win32-arm64': 0.24.2
783 | '@esbuild/win32-ia32': 0.24.2
784 | '@esbuild/win32-x64': 0.24.2
785 |
786 | estree-walker@2.0.2: {}
787 |
788 | fsevents@2.3.3:
789 | optional: true
790 |
791 | he@1.2.0: {}
792 |
793 | magic-string@0.30.17:
794 | dependencies:
795 | '@jridgewell/sourcemap-codec': 1.5.0
796 |
797 | minimatch@9.0.5:
798 | dependencies:
799 | brace-expansion: 2.0.1
800 |
801 | muggle-string@0.4.1: {}
802 |
803 | nanoid@3.3.8: {}
804 |
805 | path-browserify@1.0.1: {}
806 |
807 | picocolors@1.1.1: {}
808 |
809 | postcss@8.5.1:
810 | dependencies:
811 | nanoid: 3.3.8
812 | picocolors: 1.1.1
813 | source-map-js: 1.2.1
814 |
815 | process-envify@2.0.0: {}
816 |
817 | rollup@4.34.5:
818 | dependencies:
819 | '@types/estree': 1.0.6
820 | optionalDependencies:
821 | '@rollup/rollup-android-arm-eabi': 4.34.5
822 | '@rollup/rollup-android-arm64': 4.34.5
823 | '@rollup/rollup-darwin-arm64': 4.34.5
824 | '@rollup/rollup-darwin-x64': 4.34.5
825 | '@rollup/rollup-freebsd-arm64': 4.34.5
826 | '@rollup/rollup-freebsd-x64': 4.34.5
827 | '@rollup/rollup-linux-arm-gnueabihf': 4.34.5
828 | '@rollup/rollup-linux-arm-musleabihf': 4.34.5
829 | '@rollup/rollup-linux-arm64-gnu': 4.34.5
830 | '@rollup/rollup-linux-arm64-musl': 4.34.5
831 | '@rollup/rollup-linux-loongarch64-gnu': 4.34.5
832 | '@rollup/rollup-linux-powerpc64le-gnu': 4.34.5
833 | '@rollup/rollup-linux-riscv64-gnu': 4.34.5
834 | '@rollup/rollup-linux-s390x-gnu': 4.34.5
835 | '@rollup/rollup-linux-x64-gnu': 4.34.5
836 | '@rollup/rollup-linux-x64-musl': 4.34.5
837 | '@rollup/rollup-win32-arm64-msvc': 4.34.5
838 | '@rollup/rollup-win32-ia32-msvc': 4.34.5
839 | '@rollup/rollup-win32-x64-msvc': 4.34.5
840 | fsevents: 2.3.3
841 |
842 | source-map-js@1.2.1: {}
843 |
844 | typescript@5.7.3: {}
845 |
846 | vite@6.1.0:
847 | dependencies:
848 | esbuild: 0.24.2
849 | postcss: 8.5.1
850 | rollup: 4.34.5
851 | optionalDependencies:
852 | fsevents: 2.3.3
853 |
854 | vscode-uri@3.1.0: {}
855 |
856 | vue-tsc@2.2.0(typescript@5.7.3):
857 | dependencies:
858 | '@volar/typescript': 2.4.11
859 | '@vue/language-core': 2.2.0(typescript@5.7.3)
860 | typescript: 5.7.3
861 |
862 | vue@3.5.13(typescript@5.7.3):
863 | dependencies:
864 | '@vue/compiler-dom': 3.5.13
865 | '@vue/compiler-sfc': 3.5.13
866 | '@vue/runtime-dom': 3.5.13
867 | '@vue/server-renderer': 3.5.13(vue@3.5.13(typescript@5.7.3))
868 | '@vue/shared': 3.5.13
869 | optionalDependencies:
870 | typescript: 5.7.3
871 |
--------------------------------------------------------------------------------
/clients/sub-foo/src/App.vue:
--------------------------------------------------------------------------------
1 |
2 | sub-foo
3 |
4 |
--------------------------------------------------------------------------------
/clients/sub-foo/src/main.ts:
--------------------------------------------------------------------------------
1 | import { h, createApp } from 'vue';
2 | import { vueBridge } from '@garfish/bridge-vue-v3';
3 |
4 | import App from './App.vue';
5 |
6 | export const provider = vueBridge({
7 | rootComponent: App,
8 | appOptions: () => ({
9 | el: '#app',
10 | render: () => h(App),
11 | }),
12 | });
13 |
14 | if (!window.__GARFISH__) {
15 | const app = createApp(App);
16 | app.mount('#app');
17 | }
18 |
--------------------------------------------------------------------------------
/clients/sub-foo/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "compilerOptions": {
3 | "noUnusedLocals": true,
4 | "strict": true,
5 | "strictNullChecks": true,
6 |
7 | "allowImportingTsExtensions": true,
8 | "baseUrl": ".",
9 | "module": "esnext",
10 | "moduleResolution": "bundler",
11 | "paths": {
12 | "~/*": ["src/*"]
13 | },
14 | "resolveJsonModule": true,
15 | "types": ["vite/client", "vitest/globals"],
16 |
17 | "noEmit": true,
18 |
19 | "allowJs": true,
20 |
21 | "esModuleInterop": true,
22 | "forceConsistentCasingInFileNames": true,
23 | "isolatedModules": true,
24 |
25 | "jsx": "preserve",
26 | "lib": ["ESNext", "DOM"],
27 | "target": "esnext",
28 |
29 | "skipLibCheck": true
30 | },
31 | "include": ["src", "vite.config.ts"],
32 | "exclude": ["node_modules", "dist", "coverage"]
33 | }
34 |
--------------------------------------------------------------------------------
/clients/sub-foo/vite.config.ts:
--------------------------------------------------------------------------------
1 | import { defineConfig } from 'vite';
2 | import vue from '@vitejs/plugin-vue';
3 |
4 | const port = 8001;
5 |
6 | export default defineConfig({
7 | base: `http://localhost:${port}`,
8 | server: {
9 | port,
10 | cors: true,
11 | origin: `http://localhost:${port}`,
12 | },
13 | plugins: [vue()],
14 | });
15 |
--------------------------------------------------------------------------------
/iac/Pulumi.yaml:
--------------------------------------------------------------------------------
1 | name: infra
2 | runtime: nodejs
3 | description: A minimal Kubernetes TypeScript Pulumi program
4 |
--------------------------------------------------------------------------------
/iac/README.md:
--------------------------------------------------------------------------------
1 | # Infrastructure as Code
2 |
3 | - git `git --version`
4 | - node `node -v`
5 | - pnpm `pnpm -v`
6 | - pm2 `pm2 -v`
7 | - caddy `caddy version`
8 | - docker `docker -v`
9 | - docker-compose `docker-compose -v`
10 | - minikube `minikube version`
11 | - kubectl `kubectl version --client --short`
12 | - httpie `http --version`
13 | - watch `watch -v`
14 |
15 | ```sh
16 | $ minikube start
17 | $ kubectl version --short
18 | ```
19 |
20 | ```sh
21 | # Install Knative Serving
22 | $ kubectl apply -f https://github.com/knative/serving/releases/download/v0.17.0/serving-crds.yaml
23 | $ kubectl apply -f https://github.com/knative/serving/releases/download/v0.17.0/serving-core.yaml
24 | ```
25 |
26 | ```sh
27 | # Install Kourier
28 | $ kubectl apply -f https://github.com/knative/net-kourier/releases/download/v0.17.0/kourier.yaml
29 | ```
30 |
31 | ```sh
32 | # Configure Knative Serving
33 | $ kubectl patch configmap/config-network \
34 | -n knative-serving \
35 | --type merge \
36 | -p '{"data":{"ingress.class":"kourier.ingress.networking.knative.dev"}}'
37 | ```
38 |
39 | ```sh
40 | # Knative Serving pods
41 | $ watch "kubectl get pods -n knative-serving"
42 | ```
43 |
44 | ```sh
45 | $ pulumi config set isMinikube true
46 | $ pulumi up
47 | ```
48 |
--------------------------------------------------------------------------------
/iac/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "iac",
3 | "version": "1.0.0",
4 | "private": true,
5 | "scripts": {
6 | "up": "pulumi up src -C"
7 | },
8 | "dependencies": {
9 | "@pulumi/pulumi": "^2.0.0",
10 | "@pulumi/kubernetes": "^2.0.0"
11 | },
12 | "devDependencies": {
13 | "@types/node": "^10.0.0"
14 | }
15 | }
16 |
--------------------------------------------------------------------------------
/iac/pnpm-lock.yaml:
--------------------------------------------------------------------------------
1 | dependencies:
2 | '@pulumi/kubernetes': 2.7.7
3 | '@pulumi/pulumi': 2.18.2
4 | devDependencies:
5 | '@types/node': 10.17.51
6 | lockfileVersion: 5.2
7 | packages:
8 | /@grpc/grpc-js/0.6.18:
9 | dependencies:
10 | semver: 6.3.0
11 | dev: false
12 | engines:
13 | node: ^8.13.0 || >=10.10.0
14 | resolution:
15 | integrity: sha512-uAzv/tM8qpbf1vpx1xPMfcUMzbfdqJtdCYAqY/LsLeQQlnTb4vApylojr+wlCyr7bZeg3AFfHvtihnNOQQt/nA==
16 | /@protobufjs/aspromise/1.1.2:
17 | dev: false
18 | resolution:
19 | integrity: sha1-m4sMxmPWaafY9vXQiToU00jzD78=
20 | /@protobufjs/base64/1.1.2:
21 | dev: false
22 | resolution:
23 | integrity: sha512-AZkcAA5vnN/v4PDqKyMR5lx7hZttPDgClv83E//FMNhR2TMcLUhfRUBHCmSl0oi9zMgDDqRUJkSxO3wm85+XLg==
24 | /@protobufjs/codegen/2.0.4:
25 | dev: false
26 | resolution:
27 | integrity: sha512-YyFaikqM5sH0ziFZCN3xDC7zeGaB/d0IUb9CATugHWbd1FRFwWwt4ld4OYMPWu5a3Xe01mGAULCdqhMlPl29Jg==
28 | /@protobufjs/eventemitter/1.1.0:
29 | dev: false
30 | resolution:
31 | integrity: sha1-NVy8mLr61ZePntCV85diHx0Ga3A=
32 | /@protobufjs/fetch/1.1.0:
33 | dependencies:
34 | '@protobufjs/aspromise': 1.1.2
35 | '@protobufjs/inquire': 1.1.0
36 | dev: false
37 | resolution:
38 | integrity: sha1-upn7WYYUr2VwDBYZ/wbUVLDYTEU=
39 | /@protobufjs/float/1.0.2:
40 | dev: false
41 | resolution:
42 | integrity: sha1-Xp4avctz/Ap8uLKR33jIy9l7h9E=
43 | /@protobufjs/inquire/1.1.0:
44 | dev: false
45 | resolution:
46 | integrity: sha1-/yAOPnzyQp4tyvwRQIKOjMY48Ik=
47 | /@protobufjs/path/1.1.2:
48 | dev: false
49 | resolution:
50 | integrity: sha1-bMKyDFya1q0NzP0hynZz2Nf79o0=
51 | /@protobufjs/pool/1.1.0:
52 | dev: false
53 | resolution:
54 | integrity: sha1-Cf0V8tbTq/qbZbw2ZQbWrXhG/1Q=
55 | /@protobufjs/utf8/1.1.0:
56 | dev: false
57 | resolution:
58 | integrity: sha1-p3c2C1s5oaLlEG+OhY8v0tBgxXA=
59 | /@pulumi/kubernetes/2.7.7:
60 | dependencies:
61 | '@pulumi/pulumi': 2.18.2
62 | '@types/glob': 5.0.36
63 | '@types/node-fetch': 2.5.8
64 | '@types/tmp': 0.0.33
65 | glob: 7.1.6
66 | node-fetch: 2.6.1
67 | shell-quote: 1.7.2
68 | tmp: 0.0.33
69 | dev: false
70 | requiresBuild: true
71 | resolution:
72 | integrity: sha512-wi1qHiSX0z3tc2mdLY6TPH/EZ8I1+CNM0jXLHiwOj1ukx3FOqOLLWItuN6mnuBL2BRP1dWud1N9jEiOb8SpD0Q==
73 | /@pulumi/pulumi/2.18.2:
74 | dependencies:
75 | '@grpc/grpc-js': 0.6.18
76 | '@pulumi/query': 0.3.0
77 | google-protobuf: 3.14.0
78 | js-yaml: 3.14.1
79 | minimist: 1.2.5
80 | normalize-package-data: 2.5.0
81 | protobufjs: 6.10.2
82 | read-package-tree: 5.3.1
83 | require-from-string: 2.0.2
84 | semver: 6.3.0
85 | source-map-support: 0.4.18
86 | ts-node: 7.0.1
87 | typescript: 3.7.5
88 | upath: 1.2.0
89 | dev: false
90 | engines:
91 | node: '>=8.13.0 || >=10.10.0'
92 | resolution:
93 | integrity: sha512-t4b7AfH3c5aJcU3G4vUU6IeGilSkxjr2zurpW0SOgMxisYpNZ0x40kridJpApZ2sKLPYWLPy2U0zfBXRvY5t/A==
94 | /@pulumi/query/0.3.0:
95 | dev: false
96 | resolution:
97 | integrity: sha512-xfo+yLRM2zVjVEA4p23IjQWzyWl1ZhWOGobsBqRpIarzLvwNH/RAGaoehdxlhx4X92302DrpdIFgTICMN4P38w==
98 | /@types/events/3.0.0:
99 | dev: false
100 | resolution:
101 | integrity: sha512-EaObqwIvayI5a8dCzhFrjKzVwKLxjoG9T6Ppd5CEo07LRKfQ8Yokw54r5+Wq7FaBQ+yXRvQAYPrHwya1/UFt9g==
102 | /@types/glob/5.0.36:
103 | dependencies:
104 | '@types/events': 3.0.0
105 | '@types/minimatch': 3.0.3
106 | '@types/node': 10.17.51
107 | dev: false
108 | resolution:
109 | integrity: sha512-KEzSKuP2+3oOjYYjujue6Z3Yqis5HKA1BsIC+jZ1v3lrRNdsqyNNtX0rQf6LSuI4DJJ2z5UV//zBZCcvM0xikg==
110 | /@types/long/4.0.1:
111 | dev: false
112 | resolution:
113 | integrity: sha512-5tXH6Bx/kNGd3MgffdmP4dy2Z+G4eaXw0SE81Tq3BNadtnMR5/ySMzX4SLEzHJzSmPNn4HIdpQsBvXMUykr58w==
114 | /@types/minimatch/3.0.3:
115 | dev: false
116 | resolution:
117 | integrity: sha512-tHq6qdbT9U1IRSGf14CL0pUlULksvY9OZ+5eEgl1N7t+OA3tGvNpxJCzuKQlsNgCVwbAs670L1vcVQi8j9HjnA==
118 | /@types/node-fetch/2.5.8:
119 | dependencies:
120 | '@types/node': 10.17.51
121 | form-data: 3.0.0
122 | dev: false
123 | resolution:
124 | integrity: sha512-fbjI6ja0N5ZA8TV53RUqzsKNkl9fv8Oj3T7zxW7FGv1GSH7gwJaNF8dzCjrqKaxKeUpTz4yT1DaJFq/omNpGfw==
125 | /@types/node/10.17.51:
126 | resolution:
127 | integrity: sha512-KANw+MkL626tq90l++hGelbl67irOJzGhUJk6a1Bt8QHOeh9tztJx+L0AqttraWKinmZn7Qi5lJZJzx45Gq0dg==
128 | /@types/node/13.13.40:
129 | dev: false
130 | resolution:
131 | integrity: sha512-eKaRo87lu1yAXrzEJl0zcJxfUMDT5/mZalFyOkT44rnQps41eS2pfWzbaulSPpQLFNy29bFqn+Y5lOTL8ATlEQ==
132 | /@types/tmp/0.0.33:
133 | dev: false
134 | resolution:
135 | integrity: sha1-EHPEvIJHVK49EM+riKsCN7qWTk0=
136 | /argparse/1.0.10:
137 | dependencies:
138 | sprintf-js: 1.0.3
139 | dev: false
140 | resolution:
141 | integrity: sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==
142 | /arrify/1.0.1:
143 | dev: false
144 | engines:
145 | node: '>=0.10.0'
146 | resolution:
147 | integrity: sha1-iYUI2iIm84DfkEcoRWhJwVAaSw0=
148 | /asap/2.0.6:
149 | dev: false
150 | resolution:
151 | integrity: sha1-5QNHYR1+aQlDIIu9r+vLwvuGbUY=
152 | /asynckit/0.4.0:
153 | dev: false
154 | resolution:
155 | integrity: sha1-x57Zf380y48robyXkLzDZkdLS3k=
156 | /balanced-match/1.0.0:
157 | dev: false
158 | resolution:
159 | integrity: sha1-ibTRmasr7kneFk6gK4nORi1xt2c=
160 | /brace-expansion/1.1.11:
161 | dependencies:
162 | balanced-match: 1.0.0
163 | concat-map: 0.0.1
164 | dev: false
165 | resolution:
166 | integrity: sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==
167 | /buffer-from/1.1.1:
168 | dev: false
169 | resolution:
170 | integrity: sha512-MQcXEUbCKtEo7bhqEs6560Hyd4XaovZlO/k9V3hjVUF/zwW7KBVdSK4gIt/bzwS9MbR5qob+F5jusZsb0YQK2A==
171 | /call-bind/1.0.2:
172 | dependencies:
173 | function-bind: 1.1.1
174 | get-intrinsic: 1.1.0
175 | dev: false
176 | resolution:
177 | integrity: sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA==
178 | /combined-stream/1.0.8:
179 | dependencies:
180 | delayed-stream: 1.0.0
181 | dev: false
182 | engines:
183 | node: '>= 0.8'
184 | resolution:
185 | integrity: sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==
186 | /concat-map/0.0.1:
187 | dev: false
188 | resolution:
189 | integrity: sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=
190 | /debuglog/1.0.1:
191 | dev: false
192 | resolution:
193 | integrity: sha1-qiT/uaw9+aI1GDfPstJ5NgzXhJI=
194 | /define-properties/1.1.3:
195 | dependencies:
196 | object-keys: 1.1.1
197 | dev: false
198 | engines:
199 | node: '>= 0.4'
200 | resolution:
201 | integrity: sha512-3MqfYKj2lLzdMSf8ZIZE/V+Zuy+BgD6f164e8K2w7dgnpKArBDerGYpM46IYYcjnkdPNMjPk9A6VFB8+3SKlXQ==
202 | /delayed-stream/1.0.0:
203 | dev: false
204 | engines:
205 | node: '>=0.4.0'
206 | resolution:
207 | integrity: sha1-3zrhmayt+31ECqrgsp4icrJOxhk=
208 | /dezalgo/1.0.3:
209 | dependencies:
210 | asap: 2.0.6
211 | wrappy: 1.0.2
212 | dev: false
213 | resolution:
214 | integrity: sha1-f3Qt4Gb8dIvI24IFad3c5Jvw1FY=
215 | /diff/3.5.0:
216 | dev: false
217 | engines:
218 | node: '>=0.3.1'
219 | resolution:
220 | integrity: sha512-A46qtFgd+g7pDZinpnwiRJtxbC1hpgf0uzP3iG89scHk0AUC7A1TGxf5OiiOUv/JMZR8GOt8hL900hV0bOy5xA==
221 | /es-abstract/1.18.0-next.2:
222 | dependencies:
223 | call-bind: 1.0.2
224 | es-to-primitive: 1.2.1
225 | function-bind: 1.1.1
226 | get-intrinsic: 1.1.0
227 | has: 1.0.3
228 | has-symbols: 1.0.1
229 | is-callable: 1.2.2
230 | is-negative-zero: 2.0.1
231 | is-regex: 1.1.1
232 | object-inspect: 1.9.0
233 | object-keys: 1.1.1
234 | object.assign: 4.1.2
235 | string.prototype.trimend: 1.0.3
236 | string.prototype.trimstart: 1.0.3
237 | dev: false
238 | engines:
239 | node: '>= 0.4'
240 | resolution:
241 | integrity: sha512-Ih4ZMFHEtZupnUh6497zEL4y2+w8+1ljnCyaTa+adcoafI1GOvMwFlDjBLfWR7y9VLfrjRJe9ocuHY1PSR9jjw==
242 | /es-to-primitive/1.2.1:
243 | dependencies:
244 | is-callable: 1.2.2
245 | is-date-object: 1.0.2
246 | is-symbol: 1.0.3
247 | dev: false
248 | engines:
249 | node: '>= 0.4'
250 | resolution:
251 | integrity: sha512-QCOllgZJtaUo9miYBcLChTUaHNjJF3PYs1VidD7AwiEj1kYxKeQTctLAezAOH5ZKRH0g2IgPn6KwB4IT8iRpvA==
252 | /esprima/4.0.1:
253 | dev: false
254 | engines:
255 | node: '>=4'
256 | hasBin: true
257 | resolution:
258 | integrity: sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==
259 | /form-data/3.0.0:
260 | dependencies:
261 | asynckit: 0.4.0
262 | combined-stream: 1.0.8
263 | mime-types: 2.1.28
264 | dev: false
265 | engines:
266 | node: '>= 6'
267 | resolution:
268 | integrity: sha512-CKMFDglpbMi6PyN+brwB9Q/GOw0eAnsrEZDgcsH5Krhz5Od/haKHAX0NmQfha2zPPz0JpWzA7GJHGSnvCRLWsg==
269 | /fs.realpath/1.0.0:
270 | dev: false
271 | resolution:
272 | integrity: sha1-FQStJSMVjKpA20onh8sBQRmU6k8=
273 | /function-bind/1.1.1:
274 | dev: false
275 | resolution:
276 | integrity: sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==
277 | /get-intrinsic/1.1.0:
278 | dependencies:
279 | function-bind: 1.1.1
280 | has: 1.0.3
281 | has-symbols: 1.0.1
282 | dev: false
283 | resolution:
284 | integrity: sha512-M11rgtQp5GZMZzDL7jLTNxbDfurpzuau5uqRWDPvlHjfvg3TdScAZo96GLvhMjImrmR8uAt0FS2RLoMrfWGKlg==
285 | /glob/7.1.6:
286 | dependencies:
287 | fs.realpath: 1.0.0
288 | inflight: 1.0.6
289 | inherits: 2.0.4
290 | minimatch: 3.0.4
291 | once: 1.4.0
292 | path-is-absolute: 1.0.1
293 | dev: false
294 | resolution:
295 | integrity: sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA==
296 | /google-protobuf/3.14.0:
297 | dev: false
298 | resolution:
299 | integrity: sha512-bwa8dBuMpOxg7COyqkW6muQuvNnWgVN8TX/epDRGW5m0jcrmq2QJyCyiV8ZE2/6LaIIqJtiv9bYokFhfpy/o6w==
300 | /graceful-fs/4.2.4:
301 | dev: false
302 | resolution:
303 | integrity: sha512-WjKPNJF79dtJAVniUlGGWHYGz2jWxT6VhN/4m1NdkbZ2nOsEF+cI1Edgql5zCRhs/VsQYRvrXctxktVXZUkixw==
304 | /has-symbols/1.0.1:
305 | dev: false
306 | engines:
307 | node: '>= 0.4'
308 | resolution:
309 | integrity: sha512-PLcsoqu++dmEIZB+6totNFKq/7Do+Z0u4oT0zKOJNl3lYK6vGwwu2hjHs+68OEZbTjiUE9bgOABXbP/GvrS0Kg==
310 | /has/1.0.3:
311 | dependencies:
312 | function-bind: 1.1.1
313 | dev: false
314 | engines:
315 | node: '>= 0.4.0'
316 | resolution:
317 | integrity: sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==
318 | /hosted-git-info/2.8.8:
319 | dev: false
320 | resolution:
321 | integrity: sha512-f/wzC2QaWBs7t9IYqB4T3sR1xviIViXJRJTWBlx2Gf3g0Xi5vI7Yy4koXQ1c9OYDGHN9sBy1DQ2AB8fqZBWhUg==
322 | /inflight/1.0.6:
323 | dependencies:
324 | once: 1.4.0
325 | wrappy: 1.0.2
326 | dev: false
327 | resolution:
328 | integrity: sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=
329 | /inherits/2.0.4:
330 | dev: false
331 | resolution:
332 | integrity: sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==
333 | /is-callable/1.2.2:
334 | dev: false
335 | engines:
336 | node: '>= 0.4'
337 | resolution:
338 | integrity: sha512-dnMqspv5nU3LoewK2N/y7KLtxtakvTuaCsU9FU50/QDmdbHNy/4/JuRtMHqRU22o3q+W89YQndQEeCVwK+3qrA==
339 | /is-core-module/2.2.0:
340 | dependencies:
341 | has: 1.0.3
342 | dev: false
343 | resolution:
344 | integrity: sha512-XRAfAdyyY5F5cOXn7hYQDqh2Xmii+DEfIcQGxK/uNwMHhIkPWO0g8msXcbzLe+MpGoR951MlqM/2iIlU4vKDdQ==
345 | /is-date-object/1.0.2:
346 | dev: false
347 | engines:
348 | node: '>= 0.4'
349 | resolution:
350 | integrity: sha512-USlDT524woQ08aoZFzh3/Z6ch9Y/EWXEHQ/AaRN0SkKq4t2Jw2R2339tSXmwuVoY7LLlBCbOIlx2myP/L5zk0g==
351 | /is-negative-zero/2.0.1:
352 | dev: false
353 | engines:
354 | node: '>= 0.4'
355 | resolution:
356 | integrity: sha512-2z6JzQvZRa9A2Y7xC6dQQm4FSTSTNWjKIYYTt4246eMTJmIo0Q+ZyOsU66X8lxK1AbB92dFeglPLrhwpeRKO6w==
357 | /is-regex/1.1.1:
358 | dependencies:
359 | has-symbols: 1.0.1
360 | dev: false
361 | engines:
362 | node: '>= 0.4'
363 | resolution:
364 | integrity: sha512-1+QkEcxiLlB7VEyFtyBg94e08OAsvq7FUBgApTq/w2ymCLyKJgDPsybBENVtA7XCQEgEXxKPonG+mvYRxh/LIg==
365 | /is-symbol/1.0.3:
366 | dependencies:
367 | has-symbols: 1.0.1
368 | dev: false
369 | engines:
370 | node: '>= 0.4'
371 | resolution:
372 | integrity: sha512-OwijhaRSgqvhm/0ZdAcXNZt9lYdKFpcRDT5ULUuYXPoT794UNOdU+gpT6Rzo7b4V2HUl/op6GqY894AZwv9faQ==
373 | /js-yaml/3.14.1:
374 | dependencies:
375 | argparse: 1.0.10
376 | esprima: 4.0.1
377 | dev: false
378 | hasBin: true
379 | resolution:
380 | integrity: sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g==
381 | /json-parse-even-better-errors/2.3.1:
382 | dev: false
383 | resolution:
384 | integrity: sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==
385 | /long/4.0.0:
386 | dev: false
387 | resolution:
388 | integrity: sha512-XsP+KhQif4bjX1kbuSiySJFNAehNxgLb6hPRGJ9QsUr8ajHkuXGdrHmFUTUUXhDwVX2R5bY4JNZEwbUiMhV+MA==
389 | /make-error/1.3.6:
390 | dev: false
391 | resolution:
392 | integrity: sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw==
393 | /mime-db/1.45.0:
394 | dev: false
395 | engines:
396 | node: '>= 0.6'
397 | resolution:
398 | integrity: sha512-CkqLUxUk15hofLoLyljJSrukZi8mAtgd+yE5uO4tqRZsdsAJKv0O+rFMhVDRJgozy+yG6md5KwuXhD4ocIoP+w==
399 | /mime-types/2.1.28:
400 | dependencies:
401 | mime-db: 1.45.0
402 | dev: false
403 | engines:
404 | node: '>= 0.6'
405 | resolution:
406 | integrity: sha512-0TO2yJ5YHYr7M2zzT7gDU1tbwHxEUWBCLt0lscSNpcdAfFyJOVEpRYNS7EXVcTLNj/25QO8gulHC5JtTzSE2UQ==
407 | /minimatch/3.0.4:
408 | dependencies:
409 | brace-expansion: 1.1.11
410 | dev: false
411 | resolution:
412 | integrity: sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==
413 | /minimist/1.2.5:
414 | dev: false
415 | resolution:
416 | integrity: sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw==
417 | /mkdirp/0.5.5:
418 | dependencies:
419 | minimist: 1.2.5
420 | dev: false
421 | hasBin: true
422 | resolution:
423 | integrity: sha512-NKmAlESf6jMGym1++R0Ra7wvhV+wFW63FaSOFPwRahvea0gMUcGUhVeAg/0BC0wiv9ih5NYPB1Wn1UEI1/L+xQ==
424 | /node-fetch/2.6.1:
425 | dev: false
426 | engines:
427 | node: 4.x || >=6.0.0
428 | resolution:
429 | integrity: sha512-V4aYg89jEoVRxRb2fJdAg8FHvI7cEyYdVAh94HH0UIK8oJxUfkjlDQN9RbMx+bEjP7+ggMiFRprSti032Oipxw==
430 | /normalize-package-data/2.5.0:
431 | dependencies:
432 | hosted-git-info: 2.8.8
433 | resolve: 1.19.0
434 | semver: 5.7.1
435 | validate-npm-package-license: 3.0.4
436 | dev: false
437 | resolution:
438 | integrity: sha512-/5CMN3T0R4XTj4DcGaexo+roZSdSFW/0AOOTROrjxzCG1wrWXEsGbRKevjlIL+ZDE4sZlJr5ED4YW0yqmkK+eA==
439 | /npm-normalize-package-bin/1.0.1:
440 | dev: false
441 | resolution:
442 | integrity: sha512-EPfafl6JL5/rU+ot6P3gRSCpPDW5VmIzX959Ob1+ySFUuuYHWHekXpwdUZcKP5C+DS4GEtdJluwBjnsNDl+fSA==
443 | /object-inspect/1.9.0:
444 | dev: false
445 | resolution:
446 | integrity: sha512-i3Bp9iTqwhaLZBxGkRfo5ZbE07BQRT7MGu8+nNgwW9ItGp1TzCTw2DLEoWwjClxBjOFI/hWljTAmYGCEwmtnOw==
447 | /object-keys/1.1.1:
448 | dev: false
449 | engines:
450 | node: '>= 0.4'
451 | resolution:
452 | integrity: sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==
453 | /object.assign/4.1.2:
454 | dependencies:
455 | call-bind: 1.0.2
456 | define-properties: 1.1.3
457 | has-symbols: 1.0.1
458 | object-keys: 1.1.1
459 | dev: false
460 | engines:
461 | node: '>= 0.4'
462 | resolution:
463 | integrity: sha512-ixT2L5THXsApyiUPYKmW+2EHpXXe5Ii3M+f4e+aJFAHao5amFRW6J0OO6c/LU8Be47utCx2GL89hxGB6XSmKuQ==
464 | /object.getownpropertydescriptors/2.1.1:
465 | dependencies:
466 | call-bind: 1.0.2
467 | define-properties: 1.1.3
468 | es-abstract: 1.18.0-next.2
469 | dev: false
470 | engines:
471 | node: '>= 0.8'
472 | resolution:
473 | integrity: sha512-6DtXgZ/lIZ9hqx4GtZETobXLR/ZLaa0aqV0kzbn80Rf8Z2e/XFnhA0I7p07N2wH8bBBltr2xQPi6sbKWAY2Eng==
474 | /once/1.4.0:
475 | dependencies:
476 | wrappy: 1.0.2
477 | dev: false
478 | resolution:
479 | integrity: sha1-WDsap3WWHUsROsF9nFC6753Xa9E=
480 | /os-tmpdir/1.0.2:
481 | dev: false
482 | engines:
483 | node: '>=0.10.0'
484 | resolution:
485 | integrity: sha1-u+Z0BseaqFxc/sdm/lc0VV36EnQ=
486 | /path-is-absolute/1.0.1:
487 | dev: false
488 | engines:
489 | node: '>=0.10.0'
490 | resolution:
491 | integrity: sha1-F0uSaHNVNP+8es5r9TpanhtcX18=
492 | /path-parse/1.0.6:
493 | dev: false
494 | resolution:
495 | integrity: sha512-GSmOT2EbHrINBf9SR7CDELwlJ8AENk3Qn7OikK4nFYAu3Ote2+JYNVvkpAEQm3/TLNEJFD/xZJjzyxg3KBWOzw==
496 | /protobufjs/6.10.2:
497 | dependencies:
498 | '@protobufjs/aspromise': 1.1.2
499 | '@protobufjs/base64': 1.1.2
500 | '@protobufjs/codegen': 2.0.4
501 | '@protobufjs/eventemitter': 1.1.0
502 | '@protobufjs/fetch': 1.1.0
503 | '@protobufjs/float': 1.0.2
504 | '@protobufjs/inquire': 1.1.0
505 | '@protobufjs/path': 1.1.2
506 | '@protobufjs/pool': 1.1.0
507 | '@protobufjs/utf8': 1.1.0
508 | '@types/long': 4.0.1
509 | '@types/node': 13.13.40
510 | long: 4.0.0
511 | dev: false
512 | hasBin: true
513 | requiresBuild: true
514 | resolution:
515 | integrity: sha512-27yj+04uF6ya9l+qfpH187aqEzfCF4+Uit0I9ZBQVqK09hk/SQzKa2MUqUpXaVa7LOFRg1TSSr3lVxGOk6c0SQ==
516 | /read-package-json/2.1.2:
517 | dependencies:
518 | glob: 7.1.6
519 | json-parse-even-better-errors: 2.3.1
520 | normalize-package-data: 2.5.0
521 | npm-normalize-package-bin: 1.0.1
522 | dev: false
523 | resolution:
524 | integrity: sha512-D1KmuLQr6ZSJS0tW8hf3WGpRlwszJOXZ3E8Yd/DNRaM5d+1wVRZdHlpGBLAuovjr28LbWvjpWkBHMxpRGGjzNA==
525 | /read-package-tree/5.3.1:
526 | dependencies:
527 | read-package-json: 2.1.2
528 | readdir-scoped-modules: 1.1.0
529 | util-promisify: 2.1.0
530 | dev: false
531 | resolution:
532 | integrity: sha512-mLUDsD5JVtlZxjSlPPx1RETkNjjvQYuweKwNVt1Sn8kP5Jh44pvYuUHCp6xSVDZWbNxVxG5lyZJ921aJH61sTw==
533 | /readdir-scoped-modules/1.1.0:
534 | dependencies:
535 | debuglog: 1.0.1
536 | dezalgo: 1.0.3
537 | graceful-fs: 4.2.4
538 | once: 1.4.0
539 | dev: false
540 | resolution:
541 | integrity: sha512-asaikDeqAQg7JifRsZn1NJZXo9E+VwlyCfbkZhwyISinqk5zNS6266HS5kah6P0SaQKGF6SkNnZVHUzHFYxYDw==
542 | /require-from-string/2.0.2:
543 | dev: false
544 | engines:
545 | node: '>=0.10.0'
546 | resolution:
547 | integrity: sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==
548 | /resolve/1.19.0:
549 | dependencies:
550 | is-core-module: 2.2.0
551 | path-parse: 1.0.6
552 | dev: false
553 | resolution:
554 | integrity: sha512-rArEXAgsBG4UgRGcynxWIWKFvh/XZCcS8UJdHhwy91zwAvCZIbcs+vAbflgBnNjYMs/i/i+/Ux6IZhML1yPvxg==
555 | /semver/5.7.1:
556 | dev: false
557 | hasBin: true
558 | resolution:
559 | integrity: sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==
560 | /semver/6.3.0:
561 | dev: false
562 | hasBin: true
563 | resolution:
564 | integrity: sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==
565 | /shell-quote/1.7.2:
566 | dev: false
567 | resolution:
568 | integrity: sha512-mRz/m/JVscCrkMyPqHc/bczi3OQHkLTqXHEFu0zDhK/qfv3UcOA4SVmRCLmos4bhjr9ekVQubj/R7waKapmiQg==
569 | /source-map-support/0.4.18:
570 | dependencies:
571 | source-map: 0.5.7
572 | dev: false
573 | resolution:
574 | integrity: sha512-try0/JqxPLF9nOjvSta7tVondkP5dwgyLDjVoyMDlmjugT2lRZ1OfsrYTkCd2hkDnJTKRbO/Rl3orm8vlsUzbA==
575 | /source-map-support/0.5.19:
576 | dependencies:
577 | buffer-from: 1.1.1
578 | source-map: 0.6.1
579 | dev: false
580 | resolution:
581 | integrity: sha512-Wonm7zOCIJzBGQdB+thsPar0kYuCIzYvxZwlBa87yi/Mdjv7Tip2cyVbLj5o0cFPN4EVkuTwb3GDDyUx2DGnGw==
582 | /source-map/0.5.7:
583 | dev: false
584 | engines:
585 | node: '>=0.10.0'
586 | resolution:
587 | integrity: sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=
588 | /source-map/0.6.1:
589 | dev: false
590 | engines:
591 | node: '>=0.10.0'
592 | resolution:
593 | integrity: sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==
594 | /spdx-correct/3.1.1:
595 | dependencies:
596 | spdx-expression-parse: 3.0.1
597 | spdx-license-ids: 3.0.7
598 | dev: false
599 | resolution:
600 | integrity: sha512-cOYcUWwhCuHCXi49RhFRCyJEK3iPj1Ziz9DpViV3tbZOwXD49QzIN3MpOLJNxh2qwq2lJJZaKMVw9qNi4jTC0w==
601 | /spdx-exceptions/2.3.0:
602 | dev: false
603 | resolution:
604 | integrity: sha512-/tTrYOC7PPI1nUAgx34hUpqXuyJG+DTHJTnIULG4rDygi4xu/tfgmq1e1cIRwRzwZgo4NLySi+ricLkZkw4i5A==
605 | /spdx-expression-parse/3.0.1:
606 | dependencies:
607 | spdx-exceptions: 2.3.0
608 | spdx-license-ids: 3.0.7
609 | dev: false
610 | resolution:
611 | integrity: sha512-cbqHunsQWnJNE6KhVSMsMeH5H/L9EpymbzqTQ3uLwNCLZ1Q481oWaofqH7nO6V07xlXwY6PhQdQ2IedWx/ZK4Q==
612 | /spdx-license-ids/3.0.7:
613 | dev: false
614 | resolution:
615 | integrity: sha512-U+MTEOO0AiDzxwFvoa4JVnMV6mZlJKk2sBLt90s7G0Gd0Mlknc7kxEn3nuDPNZRta7O2uy8oLcZLVT+4sqNZHQ==
616 | /sprintf-js/1.0.3:
617 | dev: false
618 | resolution:
619 | integrity: sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw=
620 | /string.prototype.trimend/1.0.3:
621 | dependencies:
622 | call-bind: 1.0.2
623 | define-properties: 1.1.3
624 | dev: false
625 | resolution:
626 | integrity: sha512-ayH0pB+uf0U28CtjlLvL7NaohvR1amUvVZk+y3DYb0Ey2PUV5zPkkKy9+U1ndVEIXO8hNg18eIv9Jntbii+dKw==
627 | /string.prototype.trimstart/1.0.3:
628 | dependencies:
629 | call-bind: 1.0.2
630 | define-properties: 1.1.3
631 | dev: false
632 | resolution:
633 | integrity: sha512-oBIBUy5lea5tt0ovtOFiEQaBkoBBkyJhZXzJYrSmDo5IUUqbOPvVezuRs/agBIdZ2p2Eo1FD6bD9USyBLfl3xg==
634 | /tmp/0.0.33:
635 | dependencies:
636 | os-tmpdir: 1.0.2
637 | dev: false
638 | engines:
639 | node: '>=0.6.0'
640 | resolution:
641 | integrity: sha512-jRCJlojKnZ3addtTOjdIqoRuPEKBvNXcGYqzO6zWZX8KfKEpnGY5jfggJQ3EjKuu8D4bJRr0y+cYJFmYbImXGw==
642 | /ts-node/7.0.1:
643 | dependencies:
644 | arrify: 1.0.1
645 | buffer-from: 1.1.1
646 | diff: 3.5.0
647 | make-error: 1.3.6
648 | minimist: 1.2.5
649 | mkdirp: 0.5.5
650 | source-map-support: 0.5.19
651 | yn: 2.0.0
652 | dev: false
653 | engines:
654 | node: '>=4.2.0'
655 | hasBin: true
656 | resolution:
657 | integrity: sha512-BVwVbPJRspzNh2yfslyT1PSbl5uIk03EZlb493RKHN4qej/D06n1cEhjlOJG69oFsE7OT8XjpTUcYf6pKTLMhw==
658 | /typescript/3.7.5:
659 | dev: false
660 | engines:
661 | node: '>=4.2.0'
662 | hasBin: true
663 | resolution:
664 | integrity: sha512-/P5lkRXkWHNAbcJIiHPfRoKqyd7bsyCma1hZNUGfn20qm64T6ZBlrzprymeu918H+mB/0rIg2gGK/BXkhhYgBw==
665 | /upath/1.2.0:
666 | dev: false
667 | engines:
668 | node: '>=4'
669 | resolution:
670 | integrity: sha512-aZwGpamFO61g3OlfT7OQCHqhGnW43ieH9WZeP7QxN/G/jS4jfqUkZxoryvJgVPEcrl5NL/ggHsSmLMHuH64Lhg==
671 | /util-promisify/2.1.0:
672 | dependencies:
673 | object.getownpropertydescriptors: 2.1.1
674 | dev: false
675 | resolution:
676 | integrity: sha1-PCI2R2xNMsX/PEcAKt18E7moKlM=
677 | /validate-npm-package-license/3.0.4:
678 | dependencies:
679 | spdx-correct: 3.1.1
680 | spdx-expression-parse: 3.0.1
681 | dev: false
682 | resolution:
683 | integrity: sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew==
684 | /wrappy/1.0.2:
685 | dev: false
686 | resolution:
687 | integrity: sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=
688 | /yn/2.0.0:
689 | dev: false
690 | engines:
691 | node: '>=4'
692 | resolution:
693 | integrity: sha1-5a2ryKz0CPY4X8dklWhMiOavaJo=
694 | specifiers:
695 | '@pulumi/kubernetes': ^2.0.0
696 | '@pulumi/pulumi': ^2.0.0
697 | '@types/node': ^10.0.0
698 |
--------------------------------------------------------------------------------
/iac/src/index.ts:
--------------------------------------------------------------------------------
1 | import * as k8s from '@pulumi/kubernetes';
2 |
3 | // import * as serving from './serving';
4 |
5 | const appLabels = { app: 'nginx' };
6 |
7 | const deployment = new k8s.apps.v1.Deployment('nginx', {
8 | spec: {
9 | selector: { matchLabels: appLabels },
10 | replicas: 1,
11 | template: {
12 | metadata: { labels: appLabels },
13 | spec: { containers: [{ name: 'nginx', image: 'nginx' }] },
14 | },
15 | },
16 | });
17 |
18 | // new serving.Instance();
19 |
20 | export const name = deployment.metadata.name;
21 |
--------------------------------------------------------------------------------
/iac/src/serving.ts:
--------------------------------------------------------------------------------
1 | import * as pulumi from '@pulumi/pulumi';
2 | import * as k8s from '@pulumi/kubernetes';
3 |
4 | export interface ServingArgs {
5 | name: string;
6 | namespace: string;
7 | containers: Containers[];
8 | }
9 |
10 | export interface Containers {
11 | image: string;
12 | env: Object[];
13 | }
14 |
15 | export class Instance extends pulumi.CustomResource {
16 | constructor(args: ServingArgs, opts?: pulumi.ResourceOptions) {
17 | super('serving:serving:Instance', args.name, args, opts);
18 |
19 | new k8s.apiextensions.CustomResource(`${args.name}-cr`, {
20 | apiVersion: 'serving.knative.dev/v1',
21 | kind: 'Service',
22 | metadata: {
23 | name: args.name,
24 | namespace: args.namespace,
25 | },
26 | spec: {
27 | template: {
28 | spec: {
29 | containers: args.containers,
30 | },
31 | },
32 | },
33 | });
34 | }
35 | }
36 |
--------------------------------------------------------------------------------
/iac/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "compilerOptions": {
3 | "strict": true,
4 | "outDir": "bin",
5 | "target": "es2016",
6 | "module": "commonjs",
7 | "moduleResolution": "node",
8 | "sourceMap": true,
9 | "experimentalDecorators": true,
10 | "pretty": true,
11 | "noFallthroughCasesInSwitch": true,
12 | "noImplicitReturns": true,
13 | "forceConsistentCasingInFileNames": true
14 | },
15 | "files": ["src/index.ts"]
16 | }
17 |
--------------------------------------------------------------------------------
/infra/.gitkeep:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Shyam-Chen/Micro-Fullstack/72ff7b703784cf8f7ac9edcdb44e532bbecbeca8/infra/.gitkeep
--------------------------------------------------------------------------------
/mbe/README.md:
--------------------------------------------------------------------------------
1 | # Micro Backends
2 |
3 | ### Table of Contents
4 |
5 | - [Getting Started](#getting-started)
6 | - [Directory Structure](#directory-structure)
7 | - [Application Testing](#application-testing)
8 | - [Previewing Locally](#previewing-locally)
9 | - [Application Containerization](#application-containerization)
10 | - [Production Ready](#production-ready)
11 |
12 | ---
13 |
14 | ## Getting Started
15 |
16 | ```sh
17 | $ git clone https://github.com/Shyam-Chen/Micro-Fullstack
18 | $ cd Micro-Fullstack
19 |
20 | $ cd server
21 | $ yarn install
22 | $ yarn bootstrap
23 |
24 | $ yarn serve
25 | ```
26 |
27 | `app-gateway` is listening on port 3000.
28 | `mod-koa` is listening on port 3001.
29 | `mod-express` is listening on port 3002.
30 | `mod-nest` is listening on port 3003.
31 | `mod-fastify` is listening on port 3004.
32 |
33 | ```sh
34 | $ http :3000
35 | # app-gateway
36 |
37 | $ http :3000 'Host: localhost:3001'
38 | # mod-koa
39 |
40 | $ http :3000 'Host: localhost:3002'
41 | # mod-express
42 |
43 | $ http :3000 'Host: localhost:3003'
44 | # mod-nest
45 |
46 | $ http :3000 'Host: localhost:3004'
47 | # mod-fastify
48 | ```
49 |
50 | ## Directory Structure
51 |
52 | ```sh
53 | # core
54 | app-gateway
55 |
56 | # shared
57 | app-assemblies
58 |
59 | # modules
60 | mod-koa
61 | mod-express
62 | mod-nest
63 | mod-fastify
64 | ```
65 |
66 | ## Application Testing
67 |
68 | jest
69 |
70 | ```sh
71 | $ yarn test
72 | ```
73 |
74 | ## Previewing Locally
75 |
76 | caddy
77 |
78 | ```sh
79 | $ yarn build
80 | $ caddy run -config ./app-gateway/Caddyfile
81 | $ pm2 start ecosystem.config.js
82 | ```
83 |
84 | ## Application Containerization
85 |
86 | docker
87 |
88 | ```sh
89 | $
90 | ```
91 |
92 | ## Production Ready
93 |
94 | knative
95 |
96 | ```sh
97 | $
98 | ```
99 |
--------------------------------------------------------------------------------
/mbe/app-assemblies/README.md:
--------------------------------------------------------------------------------
1 | # App Assemblies
2 |
3 | ```sh
4 | $ yarn install
5 | ```
6 |
7 | ```sh
8 | $ yarn serve
9 | ```
10 |
11 | ```sh
12 | $ yarn build
13 | ```
14 |
15 | ```sh
16 | $ yarn test
17 | ```
18 |
--------------------------------------------------------------------------------
/mbe/app-assemblies/jest.config.js:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Shyam-Chen/Micro-Fullstack/72ff7b703784cf8f7ac9edcdb44e532bbecbeca8/mbe/app-assemblies/jest.config.js
--------------------------------------------------------------------------------
/mbe/app-assemblies/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "app-assemblies",
3 | "version": "1.0.0",
4 | "main": "index.js",
5 | "license": "MIT",
6 | "dependencies": {
7 | "@assemblyscript/loader": "^0.17.4"
8 | },
9 | "devDependencies": {
10 | "@rollup/plugin-commonjs": "^16.0.0",
11 | "@rollup/plugin-node-resolve": "^10.0.0",
12 | "assemblyscript": "^0.17.2",
13 | "babel-jest": "^26.6.3",
14 | "jest": "^26.6.3",
15 | "rollup": "^2.33.1",
16 | "rollup-plugin-asc": "^0.1.0"
17 | },
18 | "scripts": {
19 | "serve": "rollup -c -w",
20 | "build": "rollup -c",
21 | "lint": "echo \"Error: no lint specified\" && exit 1",
22 | "test": "echo \"Error: no test specified\" && exit 1"
23 | }
24 | }
25 |
--------------------------------------------------------------------------------
/mbe/app-assemblies/rollup.config.js:
--------------------------------------------------------------------------------
1 | import path from 'path';
2 | import resolve from '@rollup/plugin-node-resolve';
3 | import commonjs from '@rollup/plugin-commonjs';
4 | import asc from 'rollup-plugin-asc';
5 |
6 | const config = (file, mod) => ({
7 | input: path.join(__dirname, 'src', file),
8 | output: {
9 | file: path.join(__dirname, 'dist', file.substring(file.lastIndexOf('.'), 0) + '.js'),
10 | format: 'cjs',
11 | exports: 'auto',
12 | },
13 | external: ['fs', 'path', '@assemblyscript/loader', '@assemblyscript/loader/umd'],
14 | plugins: [
15 | resolve(),
16 | commonjs(),
17 | asc({
18 | output: path.join(__dirname, 'dist', mod),
19 | }),
20 | ],
21 | watch: {
22 | clearScreen: false,
23 | },
24 | });
25 |
26 | export default [
27 | { ...config('./libm/libm.ts', 'libm') },
28 | // ...
29 | ];
30 |
--------------------------------------------------------------------------------
/mbe/app-assemblies/src/libm/libm.spec.js:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Shyam-Chen/Micro-Fullstack/72ff7b703784cf8f7ac9edcdb44e532bbecbeca8/mbe/app-assemblies/src/libm/libm.spec.js
--------------------------------------------------------------------------------
/mbe/app-assemblies/src/libm/libm.ts:
--------------------------------------------------------------------------------
1 |
2 | export const E = Math.E;
3 | export const LN10 = Math.LN10;
4 | export const LN2 = Math.LN2;
5 | export const LOG10E = Math.LOG10E;
6 | export const LOG2E = Math.LOG2E;
7 | export const PI = Math.PI;
8 | export const SQRT1_2 = Math.SQRT1_2;
9 | export const SQRT2 = Math.SQRT2;
10 |
11 | export function abs(x: f64): f64 {
12 | return Math.abs(x);
13 | }
14 |
15 | export function acos(x: f64): f64 {
16 | return Math.acos(x);
17 | }
18 |
19 | export function acosh(x: f64): f64 {
20 | return Math.acosh(x);
21 | }
22 |
23 | export function asin(x: f64): f64 {
24 | return Math.asin(x);
25 | }
26 |
27 | export function asinh(x: f64): f64 {
28 | return Math.asinh(x);
29 | }
30 |
31 | export function atan(x: f64): f64 {
32 | return Math.atan(x);
33 | }
34 |
35 | export function atanh(x: f64): f64 {
36 | return Math.atanh(x);
37 | }
38 |
39 | export function atan2(y: f64, x: f64): f64 {
40 | return Math.atan2(y, x);
41 | }
42 |
43 | export function cbrt(x: f64): f64 {
44 | return Math.cbrt(x);
45 | }
46 |
47 | export function ceil(x: f64): f64 {
48 | return Math.ceil(x);
49 | }
50 |
51 | export function clz32(x: f64): f64 {
52 | return Math.clz32(x);
53 | }
54 |
55 | export function cos(x: f64): f64 {
56 | return Math.cos(x);
57 | }
58 |
59 | export function cosh(x: f64): f64 {
60 | return Math.cosh(x);
61 | }
62 |
63 | export function exp(x: f64): f64 {
64 | return Math.exp(x);
65 | }
66 |
67 | export function expm1(x: f64): f64 {
68 | return Math.expm1(x);
69 | }
70 |
71 | export function floor(x: f64): f64 {
72 | return Math.floor(x);
73 | }
74 |
75 | export function fround(x: f64): f64 {
76 | return Math.fround(x);
77 | }
78 |
79 | export function hypot(a: f64, b: f64): f64 {
80 | return Math.hypot(a, b);
81 | }
82 |
83 | export function imul(a: f64, b: f64): f64 {
84 | return Math.imul(a, b);
85 | }
86 |
87 | export function log(x: f64): f64 {
88 | return Math.log(x);
89 | }
90 |
91 | export function log10(x: f64): f64 {
92 | return Math.log10(x);
93 | }
94 |
95 | export function log1p(x: f64): f64 {
96 | return Math.log1p(x);
97 | }
98 |
99 | export function log2(x: f64): f64 {
100 | return Math.log2(x);
101 | }
102 |
103 | export function max(a: f64, b: f64): f64 {
104 | return Math.max(a, b);
105 | }
106 |
107 | export function min(a: f64, b: f64): f64 {
108 | return Math.min(a, b);
109 | }
110 |
111 | export function pow(x: f64, y: f64): f64 {
112 | return Math.pow(x, y);
113 | }
114 |
115 | export function round(x: f64): f64 {
116 | return Math.round(x);
117 | }
118 |
119 | export function sign(x: f64): f64 {
120 | return Math.sign(x);
121 | }
122 |
123 | export function sin(x: f64): f64 {
124 | return Math.sin(x);
125 | }
126 |
127 | export function sinh(x: f64): f64 {
128 | return Math.sinh(x);
129 | }
130 |
131 | export function sqrt(x: f64): f64 {
132 | return Math.sqrt(x);
133 | }
134 |
135 | export function tan(x: f64): f64 {
136 | return Math.tan(x);
137 | }
138 |
139 | export function tanh(x: f64): f64 {
140 | return Math.tanh(x);
141 | }
142 |
143 | export function trunc(x: f64): f64 {
144 | return Math.trunc(x);
145 | }
146 |
--------------------------------------------------------------------------------
/mbe/app-assemblies/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "extends": "./node_modules/assemblyscript/std/assembly.json",
3 | "include": [
4 | "./src/**/*.ts"
5 | ]
6 | }
7 |
--------------------------------------------------------------------------------
/mbe/app-gateway/Caddyfile:
--------------------------------------------------------------------------------
1 | :3000 {
2 | @koa {
3 | header Host localhost:3001
4 | }
5 |
6 | @express {
7 | header Host localhost:3002
8 | }
9 |
10 | @nest {
11 | header Host localhost:3003
12 | }
13 |
14 | @fastify {
15 | header Host localhost:3004
16 | }
17 |
18 | route {
19 | reverse_proxy @koa localhost:3001
20 | reverse_proxy @express localhost:3002
21 | reverse_proxy @nest localhost:3003
22 | reverse_proxy @fastify localhost:3004
23 | respond "app-gateway"
24 | }
25 | }
26 |
--------------------------------------------------------------------------------
/mbe/app-gateway/README.md:
--------------------------------------------------------------------------------
1 | # App Gateway
2 |
3 | ```sh
4 | $ yarn serve
5 | ```
6 |
7 | ```sh
8 | $ ps aux | grep node
9 | $ kill -9
10 | ```
11 |
--------------------------------------------------------------------------------
/mbe/app-gateway/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "app-gateway",
3 | "version": "1.0.0",
4 | "scripts": {
5 | "serve": "caddy run"
6 | },
7 | "license": "MIT"
8 | }
9 |
--------------------------------------------------------------------------------
/mbe/ecosystem.config.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | apps: [
3 | {
4 | name: 'mod-koa',
5 | script: './mod-koa/dist/index.js',
6 | instances: 1,
7 | exec_mode: 'cluster',
8 | env: {
9 | NODE_ENV: 'production',
10 | },
11 | log_date_format: 'YYYY-MM-DD HH:mm Z',
12 | },
13 | {
14 | name: 'mod-express',
15 | script: './mod-express/dist/index.js',
16 | instances: 1,
17 | exec_mode: 'cluster',
18 | env: {
19 | NODE_ENV: 'production',
20 | },
21 | log_date_format: 'YYYY-MM-DD HH:mm Z',
22 | },
23 | {
24 | name: 'mod-nest',
25 | script: './mod-nest/dist/main.js',
26 | instances: 1,
27 | exec_mode: 'cluster',
28 | env: {
29 | NODE_ENV: 'production',
30 | },
31 | log_date_format: 'YYYY-MM-DD HH:mm Z',
32 | },
33 | {
34 | name: 'mod-fastify',
35 | script: './mod-fastify/dist/index.js',
36 | instances: 1,
37 | exec_mode: 'cluster',
38 | env: {
39 | NODE_ENV: 'production',
40 | },
41 | log_date_format: 'YYYY-MM-DD HH:mm Z',
42 | },
43 | ],
44 | };
45 |
--------------------------------------------------------------------------------
/mbe/lerna.json:
--------------------------------------------------------------------------------
1 | {
2 | "version": "0.0.0",
3 | "npmClient": "yarn",
4 | "packages": ["./*"]
5 | }
6 |
--------------------------------------------------------------------------------
/mbe/mod-express/Dockerfile:
--------------------------------------------------------------------------------
1 | FROM node:14-alpine
2 |
--------------------------------------------------------------------------------
/mbe/mod-express/babel.config.js:
--------------------------------------------------------------------------------
1 | module.exports = (api) => {
2 | api.cache(true);
3 |
4 | return {
5 | presets: [
6 | [
7 | '@babel/preset-env',
8 | {
9 | targets: {
10 | node: 'current',
11 | },
12 | },
13 | ],
14 | ],
15 | plugins: [
16 | [
17 | 'babel-plugin-root-import',
18 | {
19 | paths: [{ rootPathPrefix: '~', rootPathSuffix: 'src' }],
20 | },
21 | ],
22 | ],
23 | };
24 | };
25 |
--------------------------------------------------------------------------------
/mbe/mod-express/docker-compose.yml:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Shyam-Chen/Micro-Fullstack/72ff7b703784cf8f7ac9edcdb44e532bbecbeca8/mbe/mod-express/docker-compose.yml
--------------------------------------------------------------------------------
/mbe/mod-express/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "mod-express",
3 | "version": "1.0.0",
4 | "scripts": {
5 | "serve": "nodemon src/index.js --exec babel-node",
6 | "build": "babel src -d dist --ignore **/__tests__/**,**/__mocks__/**",
7 | "lint": "echo \"Error: no lint specified\" && exit 1",
8 | "test": "echo \"Error: no test specified\" && exit 1"
9 | },
10 | "main": "index.js",
11 | "license": "MIT",
12 | "dependencies": {
13 | "@assemblyscript/loader": "^0.14.3",
14 | "cors": "^2.8.5",
15 | "express": "^4.17.1"
16 | },
17 | "devDependencies": {
18 | "@babel/cli": "^7.10.5",
19 | "@babel/core": "^7.10.5",
20 | "@babel/node": "^7.10.5",
21 | "@babel/preset-env": "^7.10.4",
22 | "babel-plugin-root-import": "^6.5.0",
23 | "nodemon": "^2.0.4"
24 | }
25 | }
26 |
--------------------------------------------------------------------------------
/mbe/mod-express/src/core/router.js:
--------------------------------------------------------------------------------
1 | import { Router } from 'express';
2 |
3 | import helloWorld from '~/hello-world';
4 |
5 | const router = Router();
6 |
7 | router.get('/', (req, res) => {
8 | res.send('mod-express');
9 | });
10 |
11 | router.use('/hello-world', helloWorld);
12 |
13 | export default router;
14 |
--------------------------------------------------------------------------------
/mbe/mod-express/src/hello-world/index.js:
--------------------------------------------------------------------------------
1 | import fs from 'fs';
2 | import path from 'path';
3 | import { Router } from 'express';
4 | import loader from '@assemblyscript/loader';
5 |
6 | const router = Router();
7 |
8 | const wasmFile = fs.readFileSync(path.join(__dirname, '../../../app-assemblies/dist/as-api.wasm'));
9 | const assemblies = loader.instantiateSync(wasmFile, {}).exports;
10 |
11 | router.get('/', (req, res) => {
12 | res.json({ data: 'Hello, World!' });
13 | });
14 |
15 | router.get('/add', (req, res) => {
16 | res.json({ data: assemblies.add(1, 2) });
17 | });
18 |
19 | export default router;
20 |
--------------------------------------------------------------------------------
/mbe/mod-express/src/index.js:
--------------------------------------------------------------------------------
1 | import http from 'http';
2 | import express from 'express';
3 | import cors from 'cors';
4 |
5 | import router from '~/core/router';
6 |
7 | const app = express();
8 |
9 | app.use(cors());
10 | app.use(express.json());
11 | app.use(express.urlencoded({ extended: true }));
12 |
13 | app.use('/', router);
14 |
15 | const server = http.Server(app);
16 |
17 | server.listen(3002, 'localhost', () => {
18 | console.log('🚀 App: Bootstrap Succeeded');
19 | console.log(`🚀 Host: http://${'localhost'}:${'3002'}`);
20 | });
21 |
22 | process.on('SIGINT', () => process.exit(0));
23 |
--------------------------------------------------------------------------------
/mbe/mod-fastify/Dockerfile:
--------------------------------------------------------------------------------
1 | FROM node:14-alpine
2 |
--------------------------------------------------------------------------------
/mbe/mod-fastify/babel.config.js:
--------------------------------------------------------------------------------
1 | module.exports = (api) => {
2 | api.cache(true);
3 |
4 | return {
5 | presets: [
6 | [
7 | '@babel/preset-env',
8 | {
9 | targets: {
10 | node: 'current',
11 | },
12 | },
13 | ],
14 | ],
15 | plugins: [
16 | [
17 | 'babel-plugin-root-import',
18 | {
19 | paths: [{ rootPathPrefix: '~', rootPathSuffix: 'src' }],
20 | },
21 | ],
22 | ],
23 | };
24 | };
25 |
--------------------------------------------------------------------------------
/mbe/mod-fastify/docker-compose.yml:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Shyam-Chen/Micro-Fullstack/72ff7b703784cf8f7ac9edcdb44e532bbecbeca8/mbe/mod-fastify/docker-compose.yml
--------------------------------------------------------------------------------
/mbe/mod-fastify/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "mod-fastify",
3 | "version": "1.0.0",
4 | "scripts": {
5 | "serve": "nodemon src/index.js --exec babel-node",
6 | "build": "babel src -d dist --ignore **/__tests__/**,**/__mocks__/**",
7 | "lint": "echo \"Error: no lint specified\" && exit 1",
8 | "test": "echo \"Error: no test specified\" && exit 1"
9 | },
10 | "main": "index.js",
11 | "license": "MIT",
12 | "dependencies": {
13 | "@assemblyscript/loader": "^0.14.3",
14 | "fastify": "^3.1.1",
15 | "fastify-cors": "^4.1.0"
16 | },
17 | "devDependencies": {
18 | "@babel/cli": "^7.10.5",
19 | "@babel/core": "^7.10.5",
20 | "@babel/node": "^7.10.5",
21 | "@babel/preset-env": "^7.10.4",
22 | "babel-plugin-root-import": "^6.5.0",
23 | "nodemon": "^2.0.4"
24 | }
25 | }
26 |
--------------------------------------------------------------------------------
/mbe/mod-fastify/src/core/router.js:
--------------------------------------------------------------------------------
1 | import helloWorld from '~/hello-world';
2 |
3 | export default (fastify, opts, next) => {
4 | fastify.get('/', async () => 'mod-fastify');
5 | fastify.register(helloWorld, { prefix: '/hello-world' });
6 |
7 | next();
8 | };
9 |
--------------------------------------------------------------------------------
/mbe/mod-fastify/src/hello-world/index.js:
--------------------------------------------------------------------------------
1 | import fs from 'fs';
2 | import path from 'path';
3 | import loader from '@assemblyscript/loader';
4 |
5 | const wasmFile = fs.readFileSync(path.join(__dirname, '../../../app-assemblies/dist/as-api.wasm'));
6 | const assemblies = loader.instantiateSync(wasmFile, {}).exports;
7 |
8 | export default (fastify, opts, next) => {
9 | fastify.get('/', async () => {
10 | return { data: 'Hello, World!' };
11 | });
12 |
13 | fastify.get('/add', async () => {
14 | return { data: assemblies.add(1, 2) };
15 | });
16 |
17 | next();
18 | };
19 |
--------------------------------------------------------------------------------
/mbe/mod-fastify/src/index.js:
--------------------------------------------------------------------------------
1 | import Fastify from 'fastify';
2 | import cors from 'fastify-cors';
3 |
4 | import router from '~/core/router';
5 |
6 | const fastify = Fastify();
7 |
8 | fastify.register(cors);
9 |
10 | fastify.register(router, { prefix: '/' });
11 |
12 | fastify.listen(3004, 'localhost', (err, address) => {
13 | if (err) throw err;
14 | console.log('🚀 App: Bootstrap Succeeded');
15 | console.log(`🚀 Host: ${address}`);
16 | });
17 |
18 | process.on('SIGINT', () => process.exit(0));
19 |
--------------------------------------------------------------------------------
/mbe/mod-koa/Dockerfile:
--------------------------------------------------------------------------------
1 | FROM keymetrics/pm2:14-alpine
2 |
3 | COPY /dist .
4 | COPY package.json .
5 | COPY ecosystem.config.js .
6 |
7 | RUN yarn install --production
8 |
9 | EXPOSE 3001
10 |
11 | CMD [ "pm2-runtime", "start", "ecosystem.config.js" ]
12 |
--------------------------------------------------------------------------------
/mbe/mod-koa/README.md:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Shyam-Chen/Micro-Fullstack/72ff7b703784cf8f7ac9edcdb44e532bbecbeca8/mbe/mod-koa/README.md
--------------------------------------------------------------------------------
/mbe/mod-koa/babel.config.js:
--------------------------------------------------------------------------------
1 | module.exports = (api) => {
2 | api.cache(true);
3 |
4 | return {
5 | presets: [
6 | [
7 | '@babel/preset-env',
8 | {
9 | targets: {
10 | node: 'current',
11 | },
12 | },
13 | ],
14 | ],
15 | plugins: [
16 | [
17 | 'babel-plugin-root-import',
18 | {
19 | paths: [{ rootPathPrefix: '~', rootPathSuffix: 'src' }],
20 | },
21 | ],
22 | ],
23 | };
24 | };
25 |
--------------------------------------------------------------------------------
/mbe/mod-koa/docker-compose.yml:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Shyam-Chen/Micro-Fullstack/72ff7b703784cf8f7ac9edcdb44e532bbecbeca8/mbe/mod-koa/docker-compose.yml
--------------------------------------------------------------------------------
/mbe/mod-koa/ecosystem.config.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | apps: [
3 | {
4 | name: 'mod-koa',
5 | script: './dist/index.js',
6 | instances: 2,
7 | exec_mode: 'cluster',
8 | env: {
9 | NODE_ENV: 'production',
10 | },
11 | log_date_format: 'YYYY-MM-DD HH:mm Z',
12 | },
13 | ],
14 | };
15 |
--------------------------------------------------------------------------------
/mbe/mod-koa/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "mod-koa",
3 | "version": "1.0.0",
4 | "scripts": {
5 | "serve": "nodemon src/index.js --exec babel-node",
6 | "build": "babel src -d dist --ignore **/__tests__/**,**/__mocks__/**",
7 | "lint": "echo \"Error: no lint specified\" && exit 1",
8 | "test": "echo \"Error: no test specified\" && exit 1"
9 | },
10 | "main": "index.js",
11 | "license": "MIT",
12 | "dependencies": {
13 | "@assemblyscript/loader": "^0.14.3",
14 | "@koa/cors": "^3.1.0",
15 | "@koa/router": "^9.3.1",
16 | "koa": "^2.13.0",
17 | "koa-bodyparser": "^4.3.0"
18 | },
19 | "devDependencies": {
20 | "@babel/cli": "^7.10.4",
21 | "@babel/core": "^7.10.4",
22 | "@babel/node": "^7.10.4",
23 | "@babel/preset-env": "^7.10.4",
24 | "babel-plugin-root-import": "^6.5.0",
25 | "nodemon": "^2.0.4"
26 | }
27 | }
28 |
--------------------------------------------------------------------------------
/mbe/mod-koa/src/core/router.js:
--------------------------------------------------------------------------------
1 | import Router from '@koa/router';
2 |
3 | import hello from '~/hello';
4 |
5 | const router = new Router();
6 |
7 | router.get('/', async (ctx) => {
8 | ctx.body = 'mod-koa';
9 | });
10 |
11 | router.use('/hello', hello.routes(), hello.allowedMethods());
12 |
13 | export default router;
14 |
--------------------------------------------------------------------------------
/mbe/mod-koa/src/hello/index.js:
--------------------------------------------------------------------------------
1 | import fs from 'fs';
2 | import path from 'path';
3 | import Router from '@koa/router';
4 | import loader from '@assemblyscript/loader';
5 |
6 | const router = new Router();
7 |
8 | const wasmFile = fs.readFileSync(path.join(__dirname, '../../../app-assemblies/dist/as-api.wasm'));
9 | const assemblies = loader.instantiateSync(wasmFile, {}).exports;
10 |
11 | router.get('/', async (ctx) => {
12 | ctx.body = { data: 'Hello, World!' };
13 | });
14 |
15 | router.get('/add', async (ctx) => {
16 | ctx.body = { data: assemblies.add(1, 2) };
17 | });
18 |
19 | export default router;
20 |
--------------------------------------------------------------------------------
/mbe/mod-koa/src/index.js:
--------------------------------------------------------------------------------
1 | import http from 'http';
2 | import Koa from 'koa';
3 | import cors from '@koa/cors';
4 | import bodyParser from 'koa-bodyparser';
5 |
6 | import router from '~/core/router';
7 |
8 | const app = new Koa();
9 |
10 | app.use(cors());
11 | app.use(bodyParser());
12 |
13 | app.use(router.routes());
14 | app.use(router.allowedMethods());
15 |
16 | const server = http.createServer(app.callback());
17 |
18 | server.listen(3001, 'localhost', () => {
19 | console.log('🚀 App: Bootstrap Succeeded');
20 | console.log(`🚀 Host: http://${'localhost'}:${'3001'}`);
21 | });
22 |
23 | process.on('SIGINT', () => process.exit(0));
24 |
--------------------------------------------------------------------------------
/mbe/mod-nest/.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/eslint-recommended',
10 | 'plugin:@typescript-eslint/recommended',
11 | 'prettier',
12 | 'prettier/@typescript-eslint',
13 | ],
14 | root: true,
15 | env: {
16 | node: true,
17 | jest: true,
18 | },
19 | rules: {
20 | '@typescript-eslint/interface-name-prefix': 'off',
21 | '@typescript-eslint/explicit-function-return-type': 'off',
22 | '@typescript-eslint/no-explicit-any': 'off',
23 | },
24 | };
25 |
--------------------------------------------------------------------------------
/mbe/mod-nest/README.md:
--------------------------------------------------------------------------------
1 | # Mod Nest
2 |
3 | ```sh
4 | $ yarn serve
5 | ```
6 |
--------------------------------------------------------------------------------
/mbe/mod-nest/jest.config.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | moduleFileExtensions: ['js', 'json', 'ts'],
3 | rootDir: 'src',
4 | testRegex: '.spec.ts$',
5 | transform: {
6 | '^.+\\.(t|j)s$': 'ts-jest',
7 | },
8 | collectCoverageFrom: ['**/*.(t|j)s'],
9 | coverageDirectory: '../coverage',
10 | testEnvironment: 'node',
11 | };
12 |
--------------------------------------------------------------------------------
/mbe/mod-nest/nest-cli.json:
--------------------------------------------------------------------------------
1 | {
2 | "collection": "@nestjs/schematics",
3 | "sourceRoot": "src"
4 | }
5 |
--------------------------------------------------------------------------------
/mbe/mod-nest/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "mod-nest",
3 | "private": true,
4 | "version": "1.0.0",
5 | "description": "Nest TypeScript starter repository",
6 | "license": "MIT",
7 | "scripts": {
8 | "serve": "nest start --watch",
9 | "build": "nest build",
10 | "lint": "eslint \"{src,apps,libs,test}/**/*.ts\" --fix",
11 | "test": "jest --coverage"
12 | },
13 | "dependencies": {
14 | "@assemblyscript/loader": "^0.14.3",
15 | "@nestjs/common": "^7.1.1",
16 | "@nestjs/core": "^7.1.1",
17 | "@nestjs/platform-express": "^7.1.1",
18 | "reflect-metadata": "^0.1.13",
19 | "rimraf": "^3.0.2",
20 | "rxjs": "^6.5.5"
21 | },
22 | "devDependencies": {
23 | "@nestjs/cli": "^7.2.0",
24 | "@nestjs/schematics": "^7.0.0",
25 | "@nestjs/testing": "^7.1.1",
26 | "@types/express": "^4.17.6",
27 | "@types/jest": "^25.2.3",
28 | "@types/node": "^14.0.6",
29 | "@types/supertest": "^2.0.9",
30 | "@typescript-eslint/eslint-plugin": "^3.0.2",
31 | "@typescript-eslint/parser": "^3.0.2",
32 | "eslint": "^7.1.0",
33 | "eslint-config-prettier": "^6.11.0",
34 | "eslint-plugin-import": "^2.20.2",
35 | "jest": "^26.0.1",
36 | "prettier": "^2.0.5",
37 | "supertest": "^4.0.2",
38 | "ts-jest": "^26.1.0",
39 | "ts-loader": "^7.0.5",
40 | "ts-node": "^8.10.2",
41 | "tsconfig-paths": "^3.9.0",
42 | "typescript": "^3.9.3"
43 | }
44 | }
45 |
--------------------------------------------------------------------------------
/mbe/mod-nest/src/__tests__/app.controller.spec.ts:
--------------------------------------------------------------------------------
1 | import { Test, TestingModule } from '@nestjs/testing';
2 |
3 | import { AppController } from '../app.controller';
4 | import { AppService } from '../app.service';
5 |
6 | describe('AppController', () => {
7 | let app: TestingModule;
8 |
9 | beforeAll(async () => {
10 | app = await Test.createTestingModule({
11 | controllers: [AppController],
12 | providers: [AppService],
13 | }).compile();
14 | });
15 |
16 | describe('getHello', () => {
17 | it('should return "Hello World!"', () => {
18 | const appController = app.get(AppController);
19 | expect(appController.getHello()).toBe('Hello World!');
20 | });
21 | });
22 | });
23 |
--------------------------------------------------------------------------------
/mbe/mod-nest/src/app.controller.ts:
--------------------------------------------------------------------------------
1 | import { Controller, Get } from '@nestjs/common';
2 |
3 | import { AppService } from './app.service';
4 |
5 | @Controller()
6 | export class AppController {
7 | constructor(private readonly appService: AppService) {}
8 |
9 | @Get()
10 | appRoot(): string {
11 | return this.appService.appRoot();
12 | }
13 | }
14 |
--------------------------------------------------------------------------------
/mbe/mod-nest/src/app.module.ts:
--------------------------------------------------------------------------------
1 | import { Module } from '@nestjs/common';
2 |
3 | import { HelloWorldModule } from '~/hello-world/hello-world.module';
4 |
5 | import { AppController } from './app.controller';
6 | import { AppService } from './app.service';
7 |
8 | @Module({
9 | imports: [HelloWorldModule],
10 | controllers: [AppController],
11 | providers: [AppService],
12 | })
13 | export class AppModule {}
14 |
--------------------------------------------------------------------------------
/mbe/mod-nest/src/app.service.ts:
--------------------------------------------------------------------------------
1 | import { Injectable } from '@nestjs/common';
2 |
3 | @Injectable()
4 | export class AppService {
5 | appRoot(): string {
6 | return 'mod-nest';
7 | }
8 | }
9 |
--------------------------------------------------------------------------------
/mbe/mod-nest/src/hello-world/hello-world.controller.ts:
--------------------------------------------------------------------------------
1 | import fs from 'fs';
2 | import path from 'path';
3 | import { Controller, Get } from '@nestjs/common';
4 | import loader from '@assemblyscript/loader';
5 |
6 | import { HelloWorldService } from './hello-world.service';
7 |
8 | const wasmFile = fs.readFileSync(path.join(__dirname, '../../../app-assemblies/dist/as-api.wasm'));
9 | const assemblies: any = loader.instantiateSync(wasmFile, {}).exports;
10 |
11 | @Controller('hello-world')
12 | export class HelloWorldController {
13 | constructor(private readonly helloWorldService: HelloWorldService) {}
14 |
15 | @Get()
16 | getHello(): string {
17 | return this.helloWorldService.getHello();
18 | }
19 |
20 | @Get('add')
21 | add(): any {
22 | return assemblies.add(1, 2);
23 | }
24 | }
25 |
--------------------------------------------------------------------------------
/mbe/mod-nest/src/hello-world/hello-world.module.ts:
--------------------------------------------------------------------------------
1 | import { Module } from '@nestjs/common';
2 |
3 | import { HelloWorldController } from './hello-world.controller';
4 | import { HelloWorldService } from './hello-world.service';
5 |
6 | @Module({
7 | imports: [],
8 | controllers: [HelloWorldController],
9 | providers: [HelloWorldService],
10 | })
11 | export class HelloWorldModule {}
12 |
--------------------------------------------------------------------------------
/mbe/mod-nest/src/hello-world/hello-world.service.ts:
--------------------------------------------------------------------------------
1 | import { Injectable } from '@nestjs/common';
2 |
3 | @Injectable()
4 | export class HelloWorldService {
5 | getHello(): string {
6 | return 'HelloWorld';
7 | }
8 | }
9 |
--------------------------------------------------------------------------------
/mbe/mod-nest/src/main.ts:
--------------------------------------------------------------------------------
1 | import { NestFactory } from '@nestjs/core';
2 |
3 | import { AppModule } from './app.module';
4 |
5 | async function bootstrap() {
6 | const app = await NestFactory.create(AppModule, { cors: true });
7 |
8 | await app.listen(3003, () => {
9 | console.log('🚀 App: Bootstrap Succeeded');
10 | console.log(`🚀 Host: http://${'localhost'}:${'3003'}`);
11 | });
12 | }
13 |
14 | bootstrap();
15 |
--------------------------------------------------------------------------------
/mbe/mod-nest/test/app.e2e-spec.ts:
--------------------------------------------------------------------------------
1 | import * as request from 'supertest';
2 | import { Test } from '@nestjs/testing';
3 | import { AppModule } from './../src/app.module';
4 | import { INestApplication } from '@nestjs/common';
5 |
6 | describe('AppController (e2e)', () => {
7 | let app: INestApplication;
8 |
9 | beforeAll(async () => {
10 | const moduleFixture = await Test.createTestingModule({
11 | imports: [AppModule],
12 | }).compile();
13 |
14 | app = moduleFixture.createNestApplication();
15 | await app.init();
16 | });
17 |
18 | it('/ (GET)', () => {
19 | return request(app.getHttpServer())
20 | .get('/')
21 | .expect(200)
22 | .expect('Hello World!');
23 | });
24 | });
25 |
--------------------------------------------------------------------------------
/mbe/mod-nest/test/jest-e2e.json:
--------------------------------------------------------------------------------
1 | {
2 | "moduleFileExtensions": ["js", "json", "ts"],
3 | "rootDir": ".",
4 | "testEnvironment": "node",
5 | "testRegex": ".e2e-spec.ts$",
6 | "transform": {
7 | "^.+\\.(t|j)s$": "ts-jest"
8 | }
9 | }
10 |
--------------------------------------------------------------------------------
/mbe/mod-nest/tsconfig.build.json:
--------------------------------------------------------------------------------
1 | {
2 | "extends": "./tsconfig.json",
3 | "exclude": ["node_modules", "dist", "test", "**/*spec.ts"]
4 | }
5 |
--------------------------------------------------------------------------------
/mbe/mod-nest/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "compilerOptions": {
3 | "module": "commonjs",
4 | "declaration": true,
5 | "removeComments": true,
6 | "emitDecoratorMetadata": true,
7 | "experimentalDecorators": true,
8 | "allowSyntheticDefaultImports": true,
9 | "allowJs": true,
10 | "moduleResolution": "node",
11 | "esModuleInterop": true,
12 | "target": "es2017",
13 | "sourceMap": true,
14 | "outDir": "./dist",
15 | "baseUrl": ".",
16 | "paths": {
17 | "~/*": ["./src/*"]
18 | },
19 | "incremental": true
20 | }
21 | }
22 |
--------------------------------------------------------------------------------
/mbe/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "mbe",
3 | "version": "1.0.0",
4 | "scripts": {
5 | "bootstrap": "lerna bootstrap",
6 | "serve": "lerna run --parallel serve",
7 | "build": "lerna run --parallel build",
8 | "lint": "echo \"Error: no lint specified\" && exit 1",
9 | "test": "echo \"Error: no test specified\" && exit 1"
10 | },
11 | "license": "MIT",
12 | "devDependencies": {
13 | "lerna": "^3.22.1"
14 | }
15 | }
16 |
--------------------------------------------------------------------------------
/mfe/Caddyfile:
--------------------------------------------------------------------------------
1 | localhost:8000 {
2 | encode gzip
3 | root * ./app-shell/dist
4 | try_files {path} /index.html
5 | file_server browse
6 |
7 | header {
8 | Strict-Transport-Security max-age=31536000
9 | X-Content-Type-Options nosniff
10 | X-Frame-Options DENY
11 | Referrer-Policy no-referrer-when-downgrade
12 | }
13 | }
14 |
15 | localhost:8001 {
16 | encode gzip
17 | root * ./mod-vue/dist
18 | try_files {path} /index.html
19 | file_server browse
20 |
21 | header {
22 | Access-Control-Allow-Origin https://localhost:8000
23 | Strict-Transport-Security max-age=31536000
24 | X-Content-Type-Options nosniff
25 | X-Frame-Options DENY
26 | Referrer-Policy no-referrer-when-downgrade
27 | }
28 | }
29 |
30 | localhost:8002 {
31 | encode gzip
32 | root * ./mod-react/dist
33 | try_files {path} /index.html
34 | file_server browse
35 |
36 | header {
37 | Access-Control-Allow-Origin https://localhost:8000
38 | Strict-Transport-Security max-age=31536000
39 | X-Content-Type-Options nosniff
40 | X-Frame-Options DENY
41 | Referrer-Policy no-referrer-when-downgrade
42 | }
43 | }
44 |
45 | localhost:8003 {
46 | encode gzip
47 | root * ./mod-angular/dist
48 | try_files {path} /index.html
49 | file_server browse
50 |
51 | header {
52 | Access-Control-Allow-Origin https://localhost:8000
53 | Strict-Transport-Security max-age=31536000
54 | X-Content-Type-Options nosniff
55 | X-Frame-Options DENY
56 | Referrer-Policy no-referrer-when-downgrade
57 | }
58 | }
59 |
--------------------------------------------------------------------------------
/mfe/Dockerfile:
--------------------------------------------------------------------------------
1 | FROM caddy:2-alpine
2 |
3 | COPY source dest
4 |
--------------------------------------------------------------------------------
/mfe/README.md:
--------------------------------------------------------------------------------
1 | # Micro Frontends
2 |
3 | ### Table of Contents
4 |
5 | - [Getting Started](#getting-started)
6 | - [Directory Structure](#directory-structure)
7 | - [Application Testing](#application-testing)
8 | - [Previewing Locally](#previewing-locally)
9 | - [Application Containerization](#application-containerization)
10 | - [Production Ready](#production-ready)
11 |
12 | ---
13 |
14 | ## Getting Started
15 |
16 | ```sh
17 | $ git clone https://github.com/Shyam-Chen/Micro-Fullstack
18 | $ cd Micro-Fullstack
19 |
20 | $ cd client
21 | $ yarn install
22 | $ yarn bootstrap
23 |
24 | $ yarn serve
25 | ```
26 |
27 | Visit [http://localhost:8000](http://localhost:8000).
28 |
29 | `app-shell` is listening on port 8000.
30 | `mod-vue` is listening on port 8001.
31 | `mod-react` is listening on port 8002.
32 | `mod-angular` is listening on port 8003.
33 | `mod-svelte` is listening on port 8004.
34 |
35 | ## Directory Structure
36 |
37 | ```sh
38 | # core
39 | app-shell
40 |
41 | # shared
42 | app-components
43 |
44 | # modules
45 | mod-vue
46 | mod-react
47 | mod-angular
48 | mod-svelte
49 | ```
50 |
51 | ## Application Testing
52 |
53 | jest
54 |
55 | ```sh
56 | $ yarn test
57 | ```
58 |
59 | ## Previewing Locally
60 |
61 | caddy
62 |
63 | ```sh
64 | # /Micro-Fullstack/client
65 | $ yarn build
66 | $ caddy run
67 | ```
68 |
69 | Visit [https://localhost:8000](https://localhost:8000).
70 |
71 | ## Application Containerization
72 |
73 | docker
74 |
75 | TODO: Push images to Docker Hub
76 |
77 | ```sh
78 | $ docker login
79 | ```
80 |
81 | ```sh
82 | $ yarn build
83 | $ docker-compose build
84 | $ docker-compose push
85 | ```
86 |
87 | ## Production Ready
88 |
89 | knative
90 |
91 | TODO: Pull images from Docker Hub
92 |
93 | ```sh
94 | $ minikube start
95 | $
96 | ```
97 |
98 | ## Domain name
99 |
100 | For example:
101 |
102 | - `example.com` (`app-shell`, `setDefaultMountApp('/app')`)
103 | - `example.com/app` (`mod-vue`, App)
104 | - `example.com/auth` (`mod-react`, Auth)
105 | - `example.com/account` (`mod-angular`, Account)
106 | - `example.com/product` (`mod-svelte`, Product)
107 | - `app.example.com` (`mod-vue`, App)
108 | - `auth.example.com` (`mod-react`, Auth)
109 | - `account.example.com` (`mod-angular`, Account)
110 | - `product.example.com` (`mod-svelte`, Product)
111 | - (`app-components`, Common)
112 |
113 | TODO: Without `setDefaultMountApp('/app')`:
114 |
115 | - `example.com` (`app-shell`, Render in Vue)
116 | - `example.com/auth` (`mod-vue`, Auth)
117 | - `example.com/account` (`mod-react`, Account)
118 | - `example.com/product` (`mod-angular`, Product)
119 | - `example.com/payment` (`mod-svelte`, Payment)
120 | - `auth.example.com` (`mod-vue`, Auth)
121 | - `account.example.com` (`mod-react`, Account)
122 | - `product.example.com` (`mod-angular`, Product)
123 | - `payment.example.com` (`mod-svelte`, Payment)
124 | - (`app-components`, Common)
125 |
--------------------------------------------------------------------------------
/mfe/app-components/.eslintrc:
--------------------------------------------------------------------------------
1 | {
2 | "plugins": ["svelte3"],
3 | "overrides": [
4 | {
5 | "files": ["*.svelte"],
6 | "processor": "svelte3/svelte3"
7 | }
8 | ],
9 | "env": {
10 | "browser": true,
11 | "node": true,
12 | "commonjs": true,
13 | "es6": true,
14 | "jest": true
15 | },
16 | "globals": {},
17 | "extends": ["eslint:recommended"],
18 | "parser": "babel-eslint",
19 | "parserOptions": {
20 | "ecmaVersion": 2019,
21 | "sourceType": "module"
22 | }
23 | }
24 |
--------------------------------------------------------------------------------
/mfe/app-components/.gitignore:
--------------------------------------------------------------------------------
1 | /node_modules/
2 | /public/build/
3 |
4 | .DS_Store
5 |
--------------------------------------------------------------------------------
/mfe/app-components/.prettierrc:
--------------------------------------------------------------------------------
1 | {
2 | "printWidth": 100,
3 | "singleQuote": true,
4 | "trailingComma": "all"
5 | }
6 |
--------------------------------------------------------------------------------
/mfe/app-components/Dockerfile:
--------------------------------------------------------------------------------
1 | FROM node:14-alpine
2 |
--------------------------------------------------------------------------------
/mfe/app-components/README.md:
--------------------------------------------------------------------------------
1 | # App Components
2 |
--------------------------------------------------------------------------------
/mfe/app-components/babel.config.js:
--------------------------------------------------------------------------------
1 | module.exports = (api) => {
2 | api.cache(true);
3 |
4 | return {
5 | presets: [
6 | [
7 | '@babel/preset-env'
8 | ],
9 | ],
10 | plugins: [
11 | '@babel/plugin-transform-runtime',
12 | '@babel/plugin-syntax-optional-chaining'
13 | ],
14 | };
15 | };
16 |
--------------------------------------------------------------------------------
/mfe/app-components/docker-compose.yml:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Shyam-Chen/Micro-Fullstack/72ff7b703784cf8f7ac9edcdb44e532bbecbeca8/mfe/app-components/docker-compose.yml
--------------------------------------------------------------------------------
/mfe/app-components/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "app-components",
3 | "version": "1.0.0",
4 | "scripts": {
5 | "serve": "rollup -c -w",
6 | "build": "rollup -c",
7 | "lint": "eslint 'src/**/*.{js,svelte}'",
8 | "test": "echo \"Error: no test specified\" && exit 1"
9 | },
10 | "license": "MIT",
11 | "dependencies": {
12 | "@babel/runtime": "^7.9.6"
13 | },
14 | "devDependencies": {
15 | "@babel/core": "^7.9.6",
16 | "@babel/plugin-syntax-optional-chaining": "^7.8.3",
17 | "@babel/plugin-transform-runtime": "^7.9.6",
18 | "@babel/preset-env": "^7.9.6",
19 | "@rollup/plugin-babel": "^5.0.2",
20 | "@rollup/plugin-commonjs": "^12.0.0",
21 | "@rollup/plugin-node-resolve": "^8.0.0",
22 | "babel-eslint": "^10.1.0",
23 | "eslint": "^7.7.0",
24 | "eslint-plugin-svelte3": "^2.7.3",
25 | "rollup": "^2.3.4",
26 | "rollup-plugin-eslint": "^7.0.0",
27 | "rollup-plugin-svelte": "^5.0.3",
28 | "rollup-plugin-terser": "^5.1.2",
29 | "svelte": "^3.0.0"
30 | }
31 | }
32 |
--------------------------------------------------------------------------------
/mfe/app-components/rollup.config.js:
--------------------------------------------------------------------------------
1 | import path from 'path';
2 | import { eslint } from 'rollup-plugin-eslint';
3 | import svelte from 'rollup-plugin-svelte';
4 | import { getBabelOutputPlugin } from '@rollup/plugin-babel';
5 | import resolve from '@rollup/plugin-node-resolve';
6 | import commonjs from '@rollup/plugin-commonjs';
7 | import { terser } from 'rollup-plugin-terser';
8 |
9 | const production = !process.env.ROLLUP_WATCH;
10 |
11 | const cpnConfig = (file) => ({
12 | input: path.join(__dirname, 'src', file),
13 | output: {
14 | file: path.join(__dirname, 'dist', file.substring(file.lastIndexOf('.'), 0) + '.js'),
15 | format: 'esm',
16 | sourcemap: true,
17 | },
18 | plugins: [
19 | eslint(),
20 | svelte({
21 | customElement: true,
22 | tag: null,
23 | dev: !production,
24 | }),
25 | getBabelOutputPlugin({
26 | configFile: path.resolve(__dirname, 'babel.config.js'),
27 | }),
28 | resolve({
29 | browser: true,
30 | dedupe: ['svelte'],
31 | }),
32 | commonjs(),
33 | production && terser(),
34 | ],
35 | watch: {
36 | clearScreen: false,
37 | },
38 | });
39 |
40 | export default [
41 | { ...cpnConfig('./header/Header.svelte') },
42 | { ...cpnConfig('./footer/Footer.svelte') },
43 | // { ...cpnConfig('') },
44 | ];
45 |
--------------------------------------------------------------------------------
/mfe/app-components/src/footer/Footer.svelte:
--------------------------------------------------------------------------------
1 |
19 |
20 |
26 |
27 | {title}
28 |
29 |
--------------------------------------------------------------------------------
/mfe/app-components/src/header/Header.svelte:
--------------------------------------------------------------------------------
1 |
12 |
13 |
19 |
20 | {title}
21 |
22 |
--------------------------------------------------------------------------------
/mfe/app-shell/.env:
--------------------------------------------------------------------------------
1 | APP_NAME="Micro Fullstack"
2 |
3 | ENTRY_VUE="//localhost:8001"
4 | ENTRY_REACT="//localhost:8002"
5 | ENTRY_ANGULAR="//localhost:8003"
6 | ENTRY_SVELTE="//localhost:8004"
7 |
--------------------------------------------------------------------------------
/mfe/app-shell/Caddyfile:
--------------------------------------------------------------------------------
1 | localhost:8000 {
2 | encode gzip
3 | root * ./dist
4 | try_files {path} /index.html
5 | file_server browse
6 |
7 | header {
8 | Strict-Transport-Security max-age=31536000
9 | X-Content-Type-Options nosniff
10 | X-Frame-Options DENY
11 | Referrer-Policy no-referrer-when-downgrade
12 | }
13 | }
14 |
--------------------------------------------------------------------------------
/mfe/app-shell/Dockerfile:
--------------------------------------------------------------------------------
1 | FROM caddy:2-alpine
2 |
3 | COPY Caddyfile /etc/caddy/Caddyfile
4 | COPY /dist /usr/share/caddy/dist
5 |
--------------------------------------------------------------------------------
/mfe/app-shell/README.md:
--------------------------------------------------------------------------------
1 | # App Shell
2 |
3 | ## Usage
4 |
5 | ```sh
6 | $ yarn install
7 | ```
8 |
9 | ```sh
10 | $ yarn serve
11 | ```
12 |
13 | ```sh
14 | $ yarn build
15 | ```
16 |
17 | ## Environments
18 |
19 | `.env`
20 |
--------------------------------------------------------------------------------
/mfe/app-shell/docker-compose.yml:
--------------------------------------------------------------------------------
1 | version: '3'
2 |
3 | services:
4 |
5 | caddy:
6 | image: caddy
7 | ports:
8 | - "80:8000"
9 | - "443:443"
10 |
--------------------------------------------------------------------------------
/mfe/app-shell/index.js:
--------------------------------------------------------------------------------
1 | import 'zone.js';
2 | import { registerMicroApps, setDefaultMountApp, start } from 'qiankun';
3 |
4 | registerMicroApps([
5 | {
6 | name: 'mod-vue',
7 | entry: process.env.ENTRY_VUE,
8 | container: '#app-root',
9 | activeRule: '/vue',
10 | },
11 | {
12 | name: 'mod-react',
13 | entry: process.env.ENTRY_REACT,
14 | container: '#app-root',
15 | activeRule: '/react',
16 | },
17 | {
18 | name: 'mod-angular',
19 | entry: process.env.ENTRY_ANGULAR,
20 | container: '#app-root',
21 | activeRule: '/angular',
22 | },
23 | {
24 | name: 'mod-svelte',
25 | entry: process.env.ENTRY_SVELTE,
26 | container: '#app-root',
27 | activeRule: '/svelte',
28 | },
29 | ]);
30 |
31 | setDefaultMountApp('/vue');
32 |
33 | start();
34 |
--------------------------------------------------------------------------------
/mfe/app-shell/index.pug:
--------------------------------------------------------------------------------
1 | doctype html
2 | html(lang='en')
3 | head
4 | meta(charset='UTF-8')
5 | meta(name='viewport', content='width=device-width, initial-scale=1.0')
6 | title= process.env.APP_NAME
7 |
8 | body
9 | #app-root
10 | script(src='./index.js')
11 |
--------------------------------------------------------------------------------
/mfe/app-shell/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "app-shell",
3 | "version": "1.0.0",
4 | "scripts": {
5 | "serve": "parcel index.pug --port 8000",
6 | "build": "parcel build index.pug"
7 | },
8 | "license": "MIT",
9 | "dependencies": {
10 | "qiankun": "^2.0.16",
11 | "zone.js": "^0.10.3"
12 | },
13 | "devDependencies": {
14 | "parcel-bundler": "^1.12.4",
15 | "pug": "^3.0.0"
16 | }
17 | }
18 |
--------------------------------------------------------------------------------
/mfe/docker-compose.yml:
--------------------------------------------------------------------------------
1 | version: '3.8'
2 |
3 | services:
4 | shell:
5 | image: /shell:
6 | build:
7 | context: ./app-shell
8 | dockerfile: Dockerfile
9 |
10 | vue:
11 | image: /vue:
12 | build:
13 | context: ./mod-vue
14 | dockerfile: Dockerfile
15 |
16 | react:
17 | image: /react:
18 | build:
19 | context: ./mod-react
20 | dockerfile: Dockerfile
21 |
22 | angular:
23 | image: /angular:
24 | build:
25 | context: ./mod-angular
26 | dockerfile: Dockerfile
27 |
28 | svelte:
29 | image: /svelte:
30 | build:
31 | context: ./mod-svelte
32 | dockerfile: Dockerfile
33 |
--------------------------------------------------------------------------------
/mfe/lerna.json:
--------------------------------------------------------------------------------
1 | {
2 | "version": "0.0.0",
3 | "npmClient": "yarn",
4 | "packages": ["./*"]
5 | }
6 |
--------------------------------------------------------------------------------
/mfe/list.yml:
--------------------------------------------------------------------------------
1 | apiVersion: v1
2 | kind: List
3 | items:
4 | - apiVersion: serving.knative.dev/v1
5 | kind: Service
6 | metadata:
7 | name: shell
8 | namespace: micro
9 | spec:
10 | template:
11 | metadata:
12 | name: app-shell
13 | annotations:
14 | autoscaling.knative.dev/minScale: '1'
15 | autoscaling.knative.dev/maxScale: '5'
16 | spec:
17 | containers:
18 | - image: docker.io//shell:
19 | - apiVersion: serving.knative.dev/v1
20 | kind: Service
21 | metadata:
22 | name: vue
23 | namespace: micro
24 | spec:
25 | template:
26 | metadata:
27 | name: mod-vue
28 | annotations:
29 | autoscaling.knative.dev/minScale: '1'
30 | autoscaling.knative.dev/maxScale: '5'
31 | spec:
32 | containers:
33 | - image: docker.io//vue:
34 | - apiVersion: serving.knative.dev/v1
35 | kind: Service
36 | metadata:
37 | name: react
38 | namespace: micro
39 | spec:
40 | template:
41 | metadata:
42 | name: mod-react
43 | annotations:
44 | autoscaling.knative.dev/minScale: '1'
45 | autoscaling.knative.dev/maxScale: '5'
46 | spec:
47 | containers:
48 | - image: docker.io//react:
49 | - apiVersion: serving.knative.dev/v1
50 | kind: Service
51 | metadata:
52 | name: angular
53 | namespace: micro
54 | spec:
55 | template:
56 | metadata:
57 | name: mod-angular
58 | annotations:
59 | autoscaling.knative.dev/minScale: '1'
60 | autoscaling.knative.dev/maxScale: '5'
61 | spec:
62 | containers:
63 | - image: docker.io//angular:
64 | - apiVersion: serving.knative.dev/v1
65 | kind: Service
66 | metadata:
67 | name: svelte
68 | namespace: micro
69 | spec:
70 | template:
71 | metadata:
72 | name: mod-svelte
73 | annotations:
74 | autoscaling.knative.dev/minScale: '1'
75 | autoscaling.knative.dev/maxScale: '5'
76 | spec:
77 | containers:
78 | - image: docker.io//svelte:
79 |
--------------------------------------------------------------------------------
/mfe/mod-angular/.browserslistrc:
--------------------------------------------------------------------------------
1 | # This file is used by the build system to adjust CSS and JS output to support the specified browsers below.
2 | # For additional information regarding the format and rule options, please see:
3 | # https://github.com/browserslist/browserslist#queries
4 |
5 | # You can see what browsers were selected by your queries by running:
6 | # npx browserslist
7 |
8 | > 0.5%
9 | last 2 versions
10 | Firefox ESR
11 | not dead
12 | not IE 9-11 # For IE 9-11 support, remove 'not'.
--------------------------------------------------------------------------------
/mfe/mod-angular/.editorconfig:
--------------------------------------------------------------------------------
1 | # Editor configuration, see https://editorconfig.org
2 | root = true
3 |
4 | [*]
5 | charset = utf-8
6 | indent_style = space
7 | indent_size = 2
8 | insert_final_newline = true
9 | trim_trailing_whitespace = true
10 |
11 | [*.md]
12 | max_line_length = off
13 | trim_trailing_whitespace = false
14 |
--------------------------------------------------------------------------------
/mfe/mod-angular/.gitignore:
--------------------------------------------------------------------------------
1 | # See http://help.github.com/ignore-files/ for more about ignoring files.
2 |
3 | # compiled output
4 | /dist
5 | /tmp
6 | /out-tsc
7 | # Only exists if Bazel was run
8 | /bazel-out
9 |
10 | # dependencies
11 | /node_modules
12 |
13 | # profiling files
14 | chrome-profiler-events*.json
15 | speed-measure-plugin*.json
16 |
17 | # IDEs and editors
18 | /.idea
19 | .project
20 | .classpath
21 | .c9/
22 | *.launch
23 | .settings/
24 | *.sublime-workspace
25 |
26 | # IDE - VSCode
27 | .vscode/*
28 | !.vscode/settings.json
29 | !.vscode/tasks.json
30 | !.vscode/launch.json
31 | !.vscode/extensions.json
32 | .history/*
33 |
34 | # misc
35 | /.sass-cache
36 | /connect.lock
37 | /coverage
38 | /libpeerconnection.log
39 | npm-debug.log
40 | yarn-error.log
41 | testem.log
42 | /typings
43 |
44 | # System Files
45 | .DS_Store
46 | Thumbs.db
47 |
--------------------------------------------------------------------------------
/mfe/mod-angular/Dockerfile:
--------------------------------------------------------------------------------
1 | FROM caddy:2-alpine
2 |
3 | COPY Caddyfile /etc/caddy/Caddyfile
4 | COPY /dist /usr/share/caddy/dist
5 |
--------------------------------------------------------------------------------
/mfe/mod-angular/README.md:
--------------------------------------------------------------------------------
1 | # Mod Angular
2 |
--------------------------------------------------------------------------------
/mfe/mod-angular/angular.json:
--------------------------------------------------------------------------------
1 | {
2 | "$schema": "./node_modules/@angular/cli/lib/config/schema.json",
3 | "version": 1,
4 | "cli": {
5 | "packageManager": "yarn"
6 | },
7 | "newProjectRoot": "projects",
8 | "projects": {
9 | "angular9": {
10 | "projectType": "application",
11 | "schematics": {},
12 | "root": "",
13 | "sourceRoot": "src",
14 | "prefix": "angular9",
15 | "architect": {
16 | "build": {
17 | "builder": "@angular-builders/custom-webpack:browser",
18 | "options": {
19 | "outputPath": "dist",
20 | "index": "src/index.html",
21 | "main": "src/main.ts",
22 | "polyfills": "src/polyfills.ts",
23 | "tsConfig": "tsconfig.app.json",
24 | "aot": true,
25 | "assets": ["src/favicon.ico", "src/assets"],
26 | "styles": ["src/styles.css"],
27 | "scripts": [],
28 | "customWebpackConfig": {
29 | "path": "./extra-webpack.config.js"
30 | }
31 | },
32 | "configurations": {
33 | "production": {
34 | "fileReplacements": [
35 | {
36 | "replace": "src/environments/environment.ts",
37 | "with": "src/environments/environment.prod.ts"
38 | }
39 | ],
40 | "optimization": true,
41 | "outputHashing": "all",
42 | "sourceMap": false,
43 | "extractCss": true,
44 | "namedChunks": false,
45 | "extractLicenses": true,
46 | "vendorChunk": false,
47 | "buildOptimizer": true,
48 | "budgets": [
49 | {
50 | "type": "initial",
51 | "maximumWarning": "2mb",
52 | "maximumError": "5mb"
53 | },
54 | {
55 | "type": "anyComponentStyle",
56 | "maximumWarning": "6kb",
57 | "maximumError": "10kb"
58 | }
59 | ]
60 | }
61 | }
62 | },
63 | "serve": {
64 | "builder": "@angular-builders/custom-webpack:dev-server",
65 | "options": {
66 | "browserTarget": "angular9:build"
67 | },
68 | "configurations": {
69 | "production": {
70 | "browserTarget": "angular9:build:production"
71 | }
72 | }
73 | },
74 | "extract-i18n": {
75 | "builder": "@angular-devkit/build-angular:extract-i18n",
76 | "options": {
77 | "browserTarget": "angular9:build"
78 | }
79 | },
80 | "test": {
81 | "builder": "@angular-devkit/build-angular:karma",
82 | "options": {
83 | "main": "src/test.ts",
84 | "polyfills": "src/polyfills.ts",
85 | "tsConfig": "tsconfig.spec.json",
86 | "karmaConfig": "karma.conf.js",
87 | "assets": ["src/favicon.ico", "src/assets"],
88 | "styles": ["src/styles.css"],
89 | "scripts": []
90 | }
91 | },
92 | "lint": {
93 | "builder": "@angular-devkit/build-angular:tslint",
94 | "options": {
95 | "tsConfig": ["tsconfig.app.json", "tsconfig.spec.json", "e2e/tsconfig.json"],
96 | "exclude": ["**/node_modules/**"]
97 | }
98 | },
99 | "e2e": {
100 | "builder": "@angular-devkit/build-angular:protractor",
101 | "options": {
102 | "protractorConfig": "e2e/protractor.conf.js",
103 | "devServerTarget": "angular9:serve"
104 | },
105 | "configurations": {
106 | "production": {
107 | "devServerTarget": "angular9:serve:production"
108 | }
109 | }
110 | }
111 | }
112 | }
113 | },
114 | "defaultProject": "angular9"
115 | }
116 |
--------------------------------------------------------------------------------
/mfe/mod-angular/e2e/protractor.conf.js:
--------------------------------------------------------------------------------
1 | // @ts-check
2 | // Protractor configuration file, see link for more information
3 | // https://github.com/angular/protractor/blob/master/lib/config.ts
4 |
5 | const { SpecReporter } = require('jasmine-spec-reporter');
6 |
7 | /**
8 | * @type { import("protractor").Config }
9 | */
10 | exports.config = {
11 | allScriptsTimeout: 11000,
12 | specs: ['./src/**/*.e2e-spec.ts'],
13 | capabilities: {
14 | browserName: 'chrome',
15 | },
16 | directConnect: true,
17 | baseUrl: 'http://localhost:7103/',
18 | framework: 'jasmine',
19 | jasmineNodeOpts: {
20 | showColors: true,
21 | defaultTimeoutInterval: 30000,
22 | print: function() {},
23 | },
24 | onPrepare() {
25 | require('ts-node').register({
26 | project: require('path').join(__dirname, './tsconfig.json'),
27 | });
28 | jasmine.getEnv().addReporter(new SpecReporter({ spec: { displayStacktrace: true } }));
29 | },
30 | };
31 |
--------------------------------------------------------------------------------
/mfe/mod-angular/e2e/src/app.e2e-spec.ts:
--------------------------------------------------------------------------------
1 | import { AppPage } from './app.po';
2 | import { browser, logging } from 'protractor';
3 |
4 | describe('workspace-project App', () => {
5 | let page: AppPage;
6 |
7 | beforeEach(() => {
8 | page = new AppPage();
9 | });
10 |
11 | it('should display welcome message', () => {
12 | page.navigateTo();
13 | expect(page.getTitleText()).toEqual('angular9 app is running!');
14 | });
15 |
16 | afterEach(async () => {
17 | // Assert that there are no errors emitted from the browser
18 | const logs = await browser
19 | .manage()
20 | .logs()
21 | .get(logging.Type.BROWSER);
22 | expect(logs).not.toContain(
23 | jasmine.objectContaining({
24 | level: logging.Level.SEVERE,
25 | } as logging.Entry),
26 | );
27 | });
28 | });
29 |
--------------------------------------------------------------------------------
/mfe/mod-angular/e2e/src/app.po.ts:
--------------------------------------------------------------------------------
1 | import { browser, by, element } from 'protractor';
2 |
3 | export class AppPage {
4 | navigateTo(): Promise {
5 | return browser.get(browser.baseUrl) as Promise;
6 | }
7 |
8 | getTitleText(): Promise {
9 | return element(by.css('app-root .content span')).getText() as Promise;
10 | }
11 | }
12 |
--------------------------------------------------------------------------------
/mfe/mod-angular/e2e/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "extends": "../tsconfig.base.json",
3 | "compilerOptions": {
4 | "outDir": "../out-tsc/e2e",
5 | "module": "commonjs",
6 | "target": "es2018",
7 | "types": ["jasmine", "jasminewd2", "node"]
8 | }
9 | }
10 |
--------------------------------------------------------------------------------
/mfe/mod-angular/extra-webpack.config.js:
--------------------------------------------------------------------------------
1 | const singleSpaAngularWebpack = require('single-spa-angular/lib/webpack').default;
2 | const webpackMerge = require('webpack-merge');
3 | const { name } = require('./package');
4 |
5 | module.exports = (angularWebpackConfig, options) => {
6 | const singleSpaWebpackConfig = singleSpaAngularWebpack(angularWebpackConfig, options);
7 |
8 | const singleSpaConfig = {
9 | output: {
10 | library: `${name}-[name]`,
11 | libraryTarget: 'umd',
12 | },
13 | externals: {
14 | 'zone.js': 'Zone',
15 | },
16 | };
17 | const mergedConfig = webpackMerge.smart(singleSpaWebpackConfig, singleSpaConfig);
18 | return mergedConfig;
19 | };
20 |
--------------------------------------------------------------------------------
/mfe/mod-angular/karma.conf.js:
--------------------------------------------------------------------------------
1 | // Karma configuration file, see link for more information
2 | // https://karma-runner.github.io/1.0/config/configuration-file.html
3 |
4 | module.exports = function(config) {
5 | config.set({
6 | basePath: '',
7 | frameworks: ['jasmine', '@angular-devkit/build-angular'],
8 | plugins: [
9 | require('karma-jasmine'),
10 | require('karma-chrome-launcher'),
11 | require('karma-jasmine-html-reporter'),
12 | require('karma-coverage-istanbul-reporter'),
13 | require('@angular-devkit/build-angular/plugins/karma'),
14 | ],
15 | client: {
16 | clearContext: false, // leave Jasmine Spec Runner output visible in browser
17 | },
18 | coverageIstanbulReporter: {
19 | dir: require('path').join(__dirname, './coverage/angular9'),
20 | reports: ['html', 'lcovonly', 'text-summary'],
21 | fixWebpackSourcePaths: true,
22 | },
23 | reporters: ['progress', 'kjhtml'],
24 | port: 9876,
25 | colors: true,
26 | logLevel: config.LOG_INFO,
27 | autoWatch: true,
28 | browsers: ['Chrome'],
29 | singleRun: false,
30 | restartOnFileChange: true,
31 | });
32 | };
33 |
--------------------------------------------------------------------------------
/mfe/mod-angular/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "mod-angular",
3 | "version": "0.0.0",
4 | "scripts": {
5 | "serve": "ng serve --disable-host-check --port 8003 --live-reload false",
6 | "build": "ng build",
7 | "lint": "echo \"Error: no lint specified\" && exit 1",
8 | "test": "echo \"Error: no test specified\" && exit 1"
9 | },
10 | "private": true,
11 | "dependencies": {
12 | "@angular-builders/custom-webpack": "^8",
13 | "@angular/animations": "~10.0.5",
14 | "@angular/common": "~10.0.5",
15 | "@angular/compiler": "~10.0.5",
16 | "@angular/core": "~10.0.5",
17 | "@angular/forms": "~10.0.5",
18 | "@angular/platform-browser": "~10.0.5",
19 | "@angular/platform-browser-dynamic": "~10.0.5",
20 | "@angular/router": "~10.0.5",
21 | "rxjs": "~6.5.4",
22 | "single-spa": "^5.5.4",
23 | "single-spa-angular": "^4.3.1",
24 | "tslib": "^2.0.0",
25 | "zone.js": "~0.10.2"
26 | },
27 | "devDependencies": {
28 | "@angular-devkit/build-angular": "~0.1000.4",
29 | "@angular/cli": "~10.0.4",
30 | "@angular/compiler-cli": "~10.0.5",
31 | "@angular/language-service": "~10.0.5",
32 | "@types/jasmine": "~3.5.0",
33 | "@types/jasminewd2": "~2.0.3",
34 | "@types/node": "^12.11.1",
35 | "codelyzer": "^6.0.0",
36 | "jasmine-core": "~3.5.0",
37 | "jasmine-spec-reporter": "~5.0.0",
38 | "karma": "~5.0.0",
39 | "karma-chrome-launcher": "~3.1.0",
40 | "karma-coverage-istanbul-reporter": "~3.0.2",
41 | "karma-jasmine": "~3.3.0",
42 | "karma-jasmine-html-reporter": "^1.5.0",
43 | "protractor": "~7.0.0",
44 | "ts-node": "~8.3.0",
45 | "tslint": "~6.1.0",
46 | "typescript": "~3.9.7"
47 | }
48 | }
49 |
--------------------------------------------------------------------------------
/mfe/mod-angular/src/app/app-routing.module.ts:
--------------------------------------------------------------------------------
1 | declare const window: any;
2 | import { NgModule } from '@angular/core';
3 | import { Location, APP_BASE_HREF, LocationStrategy, PathLocationStrategy } from '@angular/common';
4 | import { Routes, RouterModule } from '@angular/router';
5 |
6 | const routes: Routes = [];
7 |
8 | @NgModule({
9 | imports: [RouterModule.forRoot(routes)],
10 | providers: [
11 | Location,
12 | { provide: APP_BASE_HREF, useValue: window.__POWERED_BY_QIANKUN__ ? '/angular' : '/' },
13 | { provide: LocationStrategy, useClass: PathLocationStrategy },
14 | ],
15 | exports: [RouterModule],
16 | })
17 | export class AppRoutingModule {}
18 |
--------------------------------------------------------------------------------
/mfe/mod-angular/src/app/app.component.css:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Shyam-Chen/Micro-Fullstack/72ff7b703784cf8f7ac9edcdb44e532bbecbeca8/mfe/mod-angular/src/app/app.component.css
--------------------------------------------------------------------------------
/mfe/mod-angular/src/app/app.component.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
15 |
16 |
{{ title }} app is running!
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
--------------------------------------------------------------------------------
/mfe/mod-angular/src/app/app.component.spec.ts:
--------------------------------------------------------------------------------
1 | import { TestBed, async } from '@angular/core/testing';
2 | import { RouterTestingModule } from '@angular/router/testing';
3 | import { AppComponent } from './app.component';
4 |
5 | describe('AppComponent', () => {
6 | beforeEach(async(() => {
7 | TestBed.configureTestingModule({
8 | imports: [RouterTestingModule],
9 | declarations: [AppComponent],
10 | }).compileComponents();
11 | }));
12 |
13 | it('should create the app', () => {
14 | const fixture = TestBed.createComponent(AppComponent);
15 | const app = fixture.componentInstance;
16 | expect(app).toBeTruthy();
17 | });
18 |
19 | it(`should have as title 'angular9'`, () => {
20 | const fixture = TestBed.createComponent(AppComponent);
21 | const app = fixture.componentInstance;
22 | expect(app.title).toEqual('angular9');
23 | });
24 |
25 | it('should render title', () => {
26 | const fixture = TestBed.createComponent(AppComponent);
27 | fixture.detectChanges();
28 | const compiled = fixture.nativeElement;
29 | expect(compiled.querySelector('.content span').textContent).toContain('angular9 app is running!');
30 | });
31 | });
32 |
--------------------------------------------------------------------------------
/mfe/mod-angular/src/app/app.component.ts:
--------------------------------------------------------------------------------
1 | import Header from '../../../app-components/dist/header/Header';
2 | import Footer from '../../../app-components/dist/footer/Footer';
3 |
4 | customElements.get('app-header') || customElements.define('app-header', (Header as any));
5 | customElements.get('app-footer') || customElements.define('app-footer', (Footer as any));
6 |
7 | import { Component } from '@angular/core';
8 |
9 | @Component({
10 | selector: 'app-root',
11 | templateUrl: './app.component.html',
12 | styleUrls: ['./app.component.css'],
13 | })
14 | export class AppComponent {
15 | title = 'angular9';
16 |
17 | onMessage(evt: any): void {
18 | console.log(evt.detail.text);
19 | }
20 |
21 | onGood(evt: any): void {
22 | console.log(evt.detail.text);
23 | }
24 | }
25 |
--------------------------------------------------------------------------------
/mfe/mod-angular/src/app/app.module.ts:
--------------------------------------------------------------------------------
1 | import { BrowserModule } from '@angular/platform-browser';
2 | import { NgModule, CUSTOM_ELEMENTS_SCHEMA } from '@angular/core';
3 |
4 | import { AppRoutingModule } from './app-routing.module';
5 | import { AppComponent } from './app.component';
6 | import { EvtDirective } from './evt.directive';
7 |
8 | @NgModule({
9 | declarations: [AppComponent, EvtDirective],
10 | imports: [BrowserModule, AppRoutingModule],
11 | providers: [],
12 | schemas: [CUSTOM_ELEMENTS_SCHEMA],
13 | bootstrap: [AppComponent],
14 | })
15 | export class AppModule {}
16 |
--------------------------------------------------------------------------------
/mfe/mod-angular/src/app/evt.directive.ts:
--------------------------------------------------------------------------------
1 | import { Directive, ElementRef, Input, AfterViewInit } from '@angular/core';
2 |
3 | @Directive({ selector: '[elEvt]' })
4 | export class EvtDirective implements AfterViewInit {
5 | @Input('elEvt') elEvt: any;
6 |
7 | constructor(private el: ElementRef) {}
8 |
9 | ngAfterViewInit() {
10 | const key = Object.keys(this.elEvt)[0];
11 | this.el.nativeElement.$on(key, this.elEvt[key]);
12 | }
13 | }
14 |
--------------------------------------------------------------------------------
/mfe/mod-angular/src/assets/.gitkeep:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Shyam-Chen/Micro-Fullstack/72ff7b703784cf8f7ac9edcdb44e532bbecbeca8/mfe/mod-angular/src/assets/.gitkeep
--------------------------------------------------------------------------------
/mfe/mod-angular/src/environments/environment.prod.ts:
--------------------------------------------------------------------------------
1 | export const environment = {
2 | production: true,
3 | };
4 |
--------------------------------------------------------------------------------
/mfe/mod-angular/src/environments/environment.ts:
--------------------------------------------------------------------------------
1 | // This file can be replaced during build by using the `fileReplacements` array.
2 | // `ng build --prod` replaces `environment.ts` with `environment.prod.ts`.
3 | // The list of file replacements can be found in `angular.json`.
4 |
5 | export const environment = {
6 | production: false,
7 | };
8 |
9 | /*
10 | * For easier debugging in development mode, you can import the following file
11 | * to ignore zone related error stack frames such as `zone.run`, `zoneDelegate.invokeTask`.
12 | *
13 | * This import should be commented out in production mode because it will have a negative impact
14 | * on performance if an error is thrown.
15 | */
16 | // import 'zone.js/dist/zone-error'; // Included with Angular CLI.
17 |
--------------------------------------------------------------------------------
/mfe/mod-angular/src/favicon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Shyam-Chen/Micro-Fullstack/72ff7b703784cf8f7ac9edcdb44e532bbecbeca8/mfe/mod-angular/src/favicon.ico
--------------------------------------------------------------------------------
/mfe/mod-angular/src/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Angular
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
--------------------------------------------------------------------------------
/mfe/mod-angular/src/main.ts:
--------------------------------------------------------------------------------
1 | declare const window: any;
2 | declare var __webpack_public_path__: string;
3 |
4 | import 'zone.js/dist/zone';
5 | import { enableProdMode, NgZone } from '@angular/core';
6 |
7 | import { platformBrowserDynamic } from '@angular/platform-browser-dynamic';
8 | import { Router } from '@angular/router';
9 | import { AppModule } from './app/app.module';
10 | import { environment } from './environments/environment';
11 | import { singleSpaAngular, getSingleSpaExtraProviders } from 'single-spa-angular';
12 | import { singleSpaPropsSubject } from './single-spa/single-spa-props';
13 |
14 | if (environment.production) {
15 | enableProdMode();
16 | }
17 |
18 | if (window.__POWERED_BY_QIANKUN__) {
19 | __webpack_public_path__ = window.__INJECTED_PUBLIC_PATH_BY_QIANKUN__;
20 | }
21 |
22 | if (!window.__POWERED_BY_QIANKUN__) {
23 | platformBrowserDynamic()
24 | .bootstrapModule(AppModule)
25 | .catch((err) => console.error(err));
26 | }
27 |
28 | const { bootstrap, mount, unmount } = singleSpaAngular({
29 | bootstrapFunction: (singleSpaProps) => {
30 | singleSpaPropsSubject.next(singleSpaProps);
31 | return platformBrowserDynamic(getSingleSpaExtraProviders()).bootstrapModule(AppModule);
32 | },
33 | template: '',
34 | Router,
35 | NgZone,
36 | });
37 |
38 | export { bootstrap, mount, unmount };
39 |
--------------------------------------------------------------------------------
/mfe/mod-angular/src/polyfills.ts:
--------------------------------------------------------------------------------
1 | /**
2 | * This file includes polyfills needed by Angular and is loaded before the app.
3 | * You can add your own extra polyfills to this file.
4 | *
5 | * This file is divided into 2 sections:
6 | * 1. Browser polyfills. These are applied before loading ZoneJS and are sorted by browsers.
7 | * 2. Application imports. Files imported after ZoneJS that should be loaded before your main
8 | * file.
9 | *
10 | * The current setup is for so-called "evergreen" browsers; the last versions of browsers that
11 | * automatically update themselves. This includes Safari >= 10, Chrome >= 55 (including Opera),
12 | * Edge >= 13 on the desktop, and iOS 10 and Chrome on mobile.
13 | *
14 | * Learn more in https://angular.io/guide/browser-support
15 | */
16 |
17 | /***************************************************************************************************
18 | * BROWSER POLYFILLS
19 | */
20 |
21 | /** IE10 and IE11 requires the following for NgClass support on SVG elements */
22 | // import 'classlist.js'; // Run `npm install --save classlist.js`.
23 |
24 | /**
25 | * Web Animations `@angular/platform-browser/animations`
26 | * Only required if AnimationBuilder is used within the application and using IE/Edge or Safari.
27 | * Standard animation support in Angular DOES NOT require any polyfills (as of Angular 6.0).
28 | */
29 | // import 'web-animations-js'; // Run `npm install --save web-animations-js`.
30 |
31 | /**
32 | * By default, zone.js will patch all possible macroTask and DomEvents
33 | * user can disable parts of macroTask/DomEvents patch by setting following flags
34 | * because those flags need to be set before `zone.js` being loaded, and webpack
35 | * will put import in the top of bundle, so user need to create a separate file
36 | * in this directory (for example: zone-flags.ts), and put the following flags
37 | * into that file, and then add the following code before importing zone.js.
38 | * import './zone-flags';
39 | *
40 | * The flags allowed in zone-flags.ts are listed here.
41 | *
42 | * The following flags will work for all browsers.
43 | *
44 | * (window as any).__Zone_disable_requestAnimationFrame = true; // disable patch requestAnimationFrame
45 | * (window as any).__Zone_disable_on_property = true; // disable patch onProperty such as onclick
46 | * (window as any).__zone_symbol__UNPATCHED_EVENTS = ['scroll', 'mousemove']; // disable patch specified eventNames
47 | *
48 | * in IE/Edge developer tools, the addEventListener will also be wrapped by zone.js
49 | * with the following flag, it will bypass `zone.js` patch for IE/Edge
50 | *
51 | * (window as any).__Zone_enable_cross_context_check = true;
52 | *
53 | */
54 |
55 | /***************************************************************************************************
56 | * Zone JS is required by default for Angular itself.
57 | */
58 | import 'zone.js/dist/zone'; // Included with Angular CLI.
59 |
60 | /***************************************************************************************************
61 | * APPLICATION IMPORTS
62 | */
63 |
--------------------------------------------------------------------------------
/mfe/mod-angular/src/single-spa/asset-url.ts:
--------------------------------------------------------------------------------
1 | // In single-spa, the assets need to be loaded from a dynamic location,
2 | // instead of hard coded to `/assets`. We use webpack public path for this.
3 | // See https://webpack.js.org/guides/public-path/#root
4 |
5 | export function assetUrl(url: string): string {
6 | // @ts-ignore
7 | const publicPath = __webpack_public_path__;
8 | const publicPathSuffix = publicPath.endsWith('/') ? '' : '/';
9 | const urlPrefix = url.startsWith('/') ? '' : '/';
10 |
11 | return `${publicPath}${publicPathSuffix}assets${urlPrefix}${url}`;
12 | }
13 |
--------------------------------------------------------------------------------
/mfe/mod-angular/src/single-spa/single-spa-props.ts:
--------------------------------------------------------------------------------
1 | import { ReplaySubject } from 'rxjs';
2 | import { AppProps } from 'single-spa';
3 |
4 | export const singleSpaPropsSubject = new ReplaySubject(1);
5 |
6 | // Add any custom single-spa props you have to this type def
7 | // https://single-spa.js.org/docs/building-applications.html#custom-props
8 | export type SingleSpaProps = AppProps & {};
9 |
--------------------------------------------------------------------------------
/mfe/mod-angular/src/styles.css:
--------------------------------------------------------------------------------
1 | /* You can add global styles to this file, and also import other style files */
2 |
--------------------------------------------------------------------------------
/mfe/mod-angular/src/test.ts:
--------------------------------------------------------------------------------
1 | // This file is required by karma.conf.js and loads recursively all the .spec and framework files
2 |
3 | import 'zone.js/dist/zone-testing';
4 | import { getTestBed } from '@angular/core/testing';
5 | import { BrowserDynamicTestingModule, platformBrowserDynamicTesting } from '@angular/platform-browser-dynamic/testing';
6 |
7 | declare const require: {
8 | context(
9 | path: string,
10 | deep?: boolean,
11 | filter?: RegExp,
12 | ): {
13 | keys(): string[];
14 | (id: string): T;
15 | };
16 | };
17 |
18 | // First, initialize the Angular testing environment.
19 | getTestBed().initTestEnvironment(BrowserDynamicTestingModule, platformBrowserDynamicTesting());
20 | // Then we find all the tests.
21 | const context = require.context('./', true, /\.spec\.ts$/);
22 | // And load the modules.
23 | context.keys().map(context);
24 |
--------------------------------------------------------------------------------
/mfe/mod-angular/tsconfig.app.json:
--------------------------------------------------------------------------------
1 | {
2 | "extends": "./tsconfig.base.json",
3 | "compilerOptions": {
4 | "outDir": "./out-tsc/app",
5 | "types": []
6 | },
7 | "files": ["src/main.ts", "src/polyfills.ts"],
8 | "include": ["src/**/*.d.ts"]
9 | }
10 |
--------------------------------------------------------------------------------
/mfe/mod-angular/tsconfig.base.json:
--------------------------------------------------------------------------------
1 | {
2 | "compileOnSave": false,
3 | "compilerOptions": {
4 | "baseUrl": "./",
5 | "outDir": "./dist/out-tsc",
6 | "sourceMap": true,
7 | "declaration": false,
8 | "downlevelIteration": true,
9 | "experimentalDecorators": true,
10 | "module": "es2020",
11 | "moduleResolution": "node",
12 | "importHelpers": true,
13 | "target": "es2015",
14 | "typeRoots": ["node_modules/@types"],
15 | "lib": ["es2018", "dom"],
16 | "allowJs": true
17 | },
18 | "angularCompilerOptions": {
19 | "fullTemplateTypeCheck": true,
20 | "strictInjectionParameters": true
21 | }
22 | }
23 |
--------------------------------------------------------------------------------
/mfe/mod-angular/tsconfig.json:
--------------------------------------------------------------------------------
1 | /*
2 | This is a "Solution Style" tsconfig.json file, and is used by editors and TypeScript’s language server to improve development experience.
3 | It is not intended to be used to perform a compilation.
4 |
5 | To learn more about this file see: https://angular.io/config/solution-tsconfig.
6 | */
7 | {
8 | "files": [],
9 | "references": [
10 | {
11 | "path": "./tsconfig.app.json"
12 | },
13 | {
14 | "path": "./tsconfig.spec.json"
15 | }
16 | ]
17 | }
--------------------------------------------------------------------------------
/mfe/mod-angular/tsconfig.spec.json:
--------------------------------------------------------------------------------
1 | {
2 | "extends": "./tsconfig.base.json",
3 | "compilerOptions": {
4 | "outDir": "./out-tsc/spec",
5 | "types": ["jasmine", "node"]
6 | },
7 | "files": ["src/test.ts", "src/polyfills.ts"],
8 | "include": ["src/**/*.spec.ts", "src/**/*.d.ts"]
9 | }
10 |
--------------------------------------------------------------------------------
/mfe/mod-angular/tslint.json:
--------------------------------------------------------------------------------
1 | {
2 | "extends": "tslint:recommended",
3 | "rules": {
4 | "align": {
5 | "options": [
6 | "parameters",
7 | "statements"
8 | ]
9 | },
10 | "array-type": false,
11 | "arrow-parens": false,
12 | "arrow-return-shorthand": true,
13 | "curly": true,
14 | "deprecation": {
15 | "severity": "warning"
16 | },
17 | "component-class-suffix": true,
18 | "contextual-lifecycle": true,
19 | "directive-class-suffix": true,
20 | "directive-selector": [true, "attribute", "angular9", "camelCase"],
21 | "component-selector": [true, "element", "angular9", "kebab-case"],
22 | "eofline": true,
23 | "import-blacklist": [true, "rxjs/Rx"],
24 | "import-spacing": true,
25 | "indent": {
26 | "options": [
27 | "spaces"
28 | ]
29 | },
30 | "interface-name": false,
31 | "max-classes-per-file": false,
32 | "max-line-length": [true, 140],
33 | "member-access": false,
34 | "member-ordering": [
35 | true,
36 | {
37 | "order": ["static-field", "instance-field", "static-method", "instance-method"]
38 | }
39 | ],
40 | "no-consecutive-blank-lines": false,
41 | "no-console": [true, "debug", "info", "time", "timeEnd", "trace"],
42 | "no-empty": false,
43 | "no-inferrable-types": [true, "ignore-params"],
44 | "no-non-null-assertion": true,
45 | "no-redundant-jsdoc": true,
46 | "no-switch-case-fall-through": true,
47 | "no-var-requires": false,
48 | "object-literal-key-quotes": [true, "as-needed"],
49 | "object-literal-sort-keys": false,
50 | "ordered-imports": false,
51 | "quotemark": [true, "single"],
52 | "semicolon": {
53 | "options": [
54 | "always"
55 | ]
56 | },
57 | "space-before-function-paren": {
58 | "options": {
59 | "anonymous": "never",
60 | "asyncArrow": "always",
61 | "constructor": "never",
62 | "method": "never",
63 | "named": "never"
64 | }
65 | },
66 | "trailing-comma": false,
67 | "no-conflicting-lifecycle": true,
68 | "no-host-metadata-property": true,
69 | "no-input-rename": true,
70 | "no-inputs-metadata-property": true,
71 | "no-output-native": true,
72 | "no-output-on-prefix": true,
73 | "no-output-rename": true,
74 | "no-outputs-metadata-property": true,
75 | "template-banana-in-box": true,
76 | "template-no-negated-async": true,
77 | "typedef-whitespace": {
78 | "options": [
79 | {
80 | "call-signature": "nospace",
81 | "index-signature": "nospace",
82 | "parameter": "nospace",
83 | "property-declaration": "nospace",
84 | "variable-declaration": "nospace"
85 | },
86 | {
87 | "call-signature": "onespace",
88 | "index-signature": "onespace",
89 | "parameter": "onespace",
90 | "property-declaration": "onespace",
91 | "variable-declaration": "onespace"
92 | }
93 | ]
94 | },
95 | "use-lifecycle-interface": true,
96 | "use-pipe-transform-interface": true
97 | , "variable-name": {
98 | "options": [
99 | "ban-keywords",
100 | "check-format",
101 | "allow-pascal-case"
102 | ]
103 | },
104 | "whitespace": {
105 | "options": [
106 | "check-branch",
107 | "check-decl",
108 | "check-operator",
109 | "check-separator",
110 | "check-type",
111 | "check-typecast"
112 | ]
113 | }
114 | },
115 | "rulesDirectory": ["codelyzer"]
116 | }
117 |
--------------------------------------------------------------------------------
/mfe/mod-react/.env:
--------------------------------------------------------------------------------
1 | SKIP_PREFLIGHT_CHECK=true
2 | BROWSER=none
3 | PORT=8002
4 | WDS_SOCKET_PORT=8002
5 |
--------------------------------------------------------------------------------
/mfe/mod-react/.rescriptsrc.js:
--------------------------------------------------------------------------------
1 | const webpack = require('webpack');
2 | const ModuleScopePlugin = require('react-dev-utils/ModuleScopePlugin');
3 |
4 | const { name } = require('./package');
5 |
6 | module.exports = {
7 | webpack: (config) => {
8 | config.entry = config.entry.filter((e) => !e.includes('webpackHotDevClient'));
9 |
10 | config.output.library = `${name}-[name]`;
11 | config.output.libraryTarget = 'umd';
12 | config.output.jsonpFunction = `webpackJsonp_${name}`;
13 | config.output.globalObject = 'window';
14 |
15 | config.plugins = config.plugins.filter(
16 | (plugin) => !(plugin instanceof webpack.HotModuleReplacementPlugin),
17 | );
18 |
19 | config.resolve.plugins = config.resolve.plugins.filter(
20 | (plugin) => !(plugin instanceof ModuleScopePlugin),
21 | );
22 |
23 | config.resolve.alias = {
24 | ...config.resolve.alias,
25 | react: 'preact/compat',
26 | 'react-dom': 'preact/compat',
27 | };
28 |
29 | return config;
30 | },
31 |
32 | devServer: (_) => {
33 | const config = {};
34 |
35 | config.port = '8002';
36 | config.headers = {
37 | 'Access-Control-Allow-Origin': '*',
38 | };
39 | config.historyApiFallback = true;
40 |
41 | config.hot = false;
42 | config.watchContentBase = false;
43 | config.liveReload = false;
44 |
45 | return config;
46 | },
47 | };
48 |
--------------------------------------------------------------------------------
/mfe/mod-react/Dockerfile:
--------------------------------------------------------------------------------
1 | FROM caddy:2-alpine
2 |
3 | COPY Caddyfile /etc/caddy/Caddyfile
4 | COPY /dist /usr/share/caddy/dist
5 |
--------------------------------------------------------------------------------
/mfe/mod-react/README.md:
--------------------------------------------------------------------------------
1 | # Mod React
2 |
--------------------------------------------------------------------------------
/mfe/mod-react/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "mod-react",
3 | "version": "0.1.0",
4 | "private": true,
5 | "dependencies": {
6 | "preact": "^10.4.8",
7 | "react": "^16.12.0",
8 | "react-dom": "^16.12.0",
9 | "react-router-dom": "^5.1.2",
10 | "single-spa-react": "^3.0.1"
11 | },
12 | "scripts": {
13 | "serve": "rescripts start",
14 | "build": "rescripts build && mv build dist",
15 | "lint": "echo \"Error: no lint specified\" && exit 1",
16 | "test": "echo \"Error: no test specified\" && exit 1"
17 | },
18 | "browserslist": {
19 | "production": [
20 | ">0.2%",
21 | "not dead",
22 | "not op_mini all"
23 | ],
24 | "development": [
25 | "last 1 chrome version",
26 | "last 1 firefox version",
27 | "last 1 safari version"
28 | ]
29 | },
30 | "devDependencies": {
31 | "@rescripts/cli": "^0.0.14",
32 | "react-scripts": "3.4.0"
33 | }
34 | }
35 |
--------------------------------------------------------------------------------
/mfe/mod-react/public/favicon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Shyam-Chen/Micro-Fullstack/72ff7b703784cf8f7ac9edcdb44e532bbecbeca8/mfe/mod-react/public/favicon.ico
--------------------------------------------------------------------------------
/mfe/mod-react/public/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
12 |
13 |
17 |
18 |
27 | React App
28 |
29 |
30 |
31 |
32 |
42 |
43 |
44 |
--------------------------------------------------------------------------------
/mfe/mod-react/public/logo192.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Shyam-Chen/Micro-Fullstack/72ff7b703784cf8f7ac9edcdb44e532bbecbeca8/mfe/mod-react/public/logo192.png
--------------------------------------------------------------------------------
/mfe/mod-react/public/logo512.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Shyam-Chen/Micro-Fullstack/72ff7b703784cf8f7ac9edcdb44e532bbecbeca8/mfe/mod-react/public/logo512.png
--------------------------------------------------------------------------------
/mfe/mod-react/public/manifest.json:
--------------------------------------------------------------------------------
1 | {
2 | "short_name": "React App",
3 | "name": "Create React App Sample",
4 | "icons": [
5 | {
6 | "src": "favicon.ico",
7 | "sizes": "64x64 32x32 24x24 16x16",
8 | "type": "image/x-icon"
9 | },
10 | {
11 | "src": "logo192.png",
12 | "type": "image/png",
13 | "sizes": "192x192"
14 | },
15 | {
16 | "src": "logo512.png",
17 | "type": "image/png",
18 | "sizes": "512x512"
19 | }
20 | ],
21 | "start_url": ".",
22 | "display": "standalone",
23 | "theme_color": "#000000",
24 | "background_color": "#ffffff"
25 | }
26 |
--------------------------------------------------------------------------------
/mfe/mod-react/public/robots.txt:
--------------------------------------------------------------------------------
1 | # https://www.robotstxt.org/robotstxt.html
2 | User-agent: *
3 |
--------------------------------------------------------------------------------
/mfe/mod-react/src/App.css:
--------------------------------------------------------------------------------
1 | .app-main {
2 | display: flex;
3 | flex-direction: column;
4 | align-items: center;
5 | }
6 |
7 | .app-title {
8 | font-size: 30px;
9 | margin: 0;
10 | margin-bottom: 32px;
11 | }
12 |
13 | .app-lib {
14 | font-size: 16px;
15 | color: #2c3e50;
16 | }
17 |
18 | .app-nav-item {
19 | margin-top: 16px;
20 | padding: 12px 24px;
21 | border: 2px solid #2c3e50;
22 | }
23 |
--------------------------------------------------------------------------------
/mfe/mod-react/src/App.js:
--------------------------------------------------------------------------------
1 | import React, { lazy, Suspense } from 'react';
2 | import { BrowserRouter as Router, Link, Route, Switch } from 'react-router-dom';
3 |
4 | import './App.css';
5 |
6 | import Home from './pages/Home';
7 |
8 | const About = lazy(() => import('./pages/About'));
9 |
10 | const RouteExample = () => {
11 | return (
12 |
13 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 | );
27 | };
28 |
29 | export default function App() {
30 | return (
31 |
32 |
33 |
34 | );
35 | }
36 |
--------------------------------------------------------------------------------
/mfe/mod-react/src/App.test.js:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import ReactDOM from 'react-dom';
3 | import App from './App';
4 |
5 | it('renders without crashing', () => {
6 | const div = document.createElement('div');
7 | ReactDOM.render(, div);
8 | ReactDOM.unmountComponentAtNode(div);
9 | });
10 |
--------------------------------------------------------------------------------
/mfe/mod-react/src/components/HelloModal.js:
--------------------------------------------------------------------------------
1 | import React, { useState, useEffect } from 'react';
2 | import { Button, Modal } from 'antd';
3 |
4 | const dispatchUIEvent = () => {
5 | const $a = document.createElement('a');
6 | $a.onclick = () => {
7 | console.log('log from UIEvent');
8 | };
9 | const evt = new MouseEvent('click', {
10 | view: window,
11 | bubbles: true,
12 | cancelable: false,
13 | });
14 | $a.dispatchEvent(evt);
15 | };
16 |
17 | export default function() {
18 | const [visible, setVisible] = useState(false);
19 | useEffect(() => {
20 | dispatchUIEvent();
21 | }, []);
22 | return (
23 | <>
24 |
25 | setVisible(false)} onCancel={() => setVisible(false)} title="qiankun">
26 | Probably the most complete micro-frontends solution you ever met
27 |
28 | >
29 | );
30 | }
31 |
--------------------------------------------------------------------------------
/mfe/mod-react/src/components/LibVersion.js:
--------------------------------------------------------------------------------
1 | import React, { version as reactVersion } from 'react';
2 | import { version as antdVersion } from 'antd';
3 |
4 | export default function() {
5 | return (
6 | <>
7 | React Demo
8 |
9 | React version: {reactVersion}, AntD version: {antdVersion}
10 |
11 | >
12 | );
13 | }
14 |
--------------------------------------------------------------------------------
/mfe/mod-react/src/index.js:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import ReactDOM from 'react-dom';
3 | import singleSpaReact from 'single-spa-react';
4 |
5 | import App from './App';
6 | import * as serviceWorker from './serviceWorker';
7 |
8 | if (window.__POWERED_BY_QIANKUN__) {
9 | // eslint-disable-next-line no-undef
10 | __webpack_public_path__ = window.__INJECTED_PUBLIC_PATH_BY_QIANKUN__;
11 | }
12 |
13 | if (!window.__POWERED_BY_QIANKUN__) {
14 | ReactDOM.render(, document.querySelector('#root'));
15 | }
16 |
17 | const { bootstrap, mount, unmount } = singleSpaReact({
18 | React,
19 | ReactDOM,
20 | rootComponent: () => ,
21 | domElementGetter: () => document.querySelector('#root'),
22 | });
23 |
24 | export { bootstrap, mount, unmount };
25 |
26 | // If you want your app to work offline and load faster, you can change
27 | // unregister() to register() below. Note this comes with some pitfalls.
28 | // Learn more about service workers: https://bit.ly/CRA-PWA
29 | serviceWorker.unregister();
30 |
--------------------------------------------------------------------------------
/mfe/mod-react/src/logo.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/mfe/mod-react/src/pages/About.js:
--------------------------------------------------------------------------------
1 | import React, { useRef, useEffect } from 'react';
2 |
3 | import Footer from '../../../app-components/dist/footer/Footer';
4 |
5 | customElements.get('app-footer') || customElements.define('app-footer', Footer);
6 |
7 | const useEvt = (evtName, evtFunc) => {
8 | const evtRef = useRef(null);
9 |
10 | useEffect(() => {
11 | if (!evtRef.current) return null;
12 | evtRef.current.addEventListener(evtName, evtFunc);
13 | }, [evtName, evtFunc, evtRef]);
14 |
15 | return evtRef;
16 | };
17 |
18 | export default function () {
19 | const onGood = useEvt('good', evt => { console.log(evt.detail.text); });
20 |
21 | return (
22 | <>
23 |
24 | About
25 |
26 |
27 | >
28 | );
29 | }
30 |
--------------------------------------------------------------------------------
/mfe/mod-react/src/pages/Home.js:
--------------------------------------------------------------------------------
1 | import React, { useRef, useEffect } from 'react';
2 |
3 | import Header from '../../../app-components/dist/header/Header';
4 |
5 | customElements.get('app-header') || customElements.define('app-header', Header);
6 |
7 | const useEvt = (evtName, evtFunc) => {
8 | const evtRef = useRef(null);
9 |
10 | useEffect(() => {
11 | if (!evtRef.current) return null;
12 | evtRef.current.$on(evtName, evtFunc);
13 | }, [evtName, evtFunc, evtRef]);
14 |
15 | return evtRef;
16 | };
17 |
18 | export default function () {
19 | const onMessage = useEvt('message', evt => { console.log(evt.detail.text); });
20 |
21 | return (
22 |
23 | Home
24 |
25 |
26 |
27 | );
28 | }
29 |
--------------------------------------------------------------------------------
/mfe/mod-react/src/serviceWorker.js:
--------------------------------------------------------------------------------
1 | // This optional code is used to register a service worker.
2 | // register() is not called by default.
3 |
4 | // This lets the app load faster on subsequent visits in production, and gives
5 | // it offline capabilities. However, it also means that developers (and users)
6 | // will only see deployed updates on subsequent visits to a page, after all the
7 | // existing tabs open on the page have been closed, since previously cached
8 | // resources are updated in the background.
9 |
10 | // To learn more about the benefits of this model and instructions on how to
11 | // opt-in, read https://bit.ly/CRA-PWA
12 |
13 | const isLocalhost = Boolean(
14 | window.location.hostname === 'localhost' ||
15 | // [::1] is the IPv6 localhost address.
16 | window.location.hostname === '[::1]' ||
17 | // 127.0.0.1/8 is considered localhost for IPv4.
18 | window.location.hostname.match(/^127(?:\.(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)){3}$/),
19 | );
20 |
21 | export function register(config) {
22 | if (process.env.NODE_ENV === 'production' && 'serviceWorker' in navigator) {
23 | // The URL constructor is available in all browsers that support SW.
24 | const publicUrl = new URL(process.env.PUBLIC_URL, window.location.href);
25 | if (publicUrl.origin !== window.location.origin) {
26 | // Our service worker won't work if PUBLIC_URL is on a different origin
27 | // from what our page is served on. This might happen if a CDN is used to
28 | // serve assets; see https://github.com/facebook/create-react-app/issues/2374
29 | return;
30 | }
31 |
32 | window.addEventListener('load', () => {
33 | const swUrl = `${process.env.PUBLIC_URL}/service-worker.js`;
34 |
35 | if (isLocalhost) {
36 | // This is running on localhost. Let's check if a service worker still exists or not.
37 | checkValidServiceWorker(swUrl, config);
38 |
39 | // Add some additional logging to localhost, pointing developers to the
40 | // service worker/PWA documentation.
41 | navigator.serviceWorker.ready.then(() => {
42 | console.log(
43 | 'This web app is being served cache-first by a service ' +
44 | 'worker. To learn more, visit https://bit.ly/CRA-PWA',
45 | );
46 | });
47 | } else {
48 | // Is not localhost. Just register service worker
49 | registerValidSW(swUrl, config);
50 | }
51 | });
52 | }
53 | }
54 |
55 | function registerValidSW(swUrl, config) {
56 | navigator.serviceWorker
57 | .register(swUrl)
58 | .then(registration => {
59 | registration.onupdatefound = () => {
60 | const installingWorker = registration.installing;
61 | if (installingWorker == null) {
62 | return;
63 | }
64 | installingWorker.onstatechange = () => {
65 | if (installingWorker.state === 'installed') {
66 | if (navigator.serviceWorker.controller) {
67 | // At this point, the updated precached content has been fetched,
68 | // but the previous service worker will still serve the older
69 | // content until all client tabs are closed.
70 | console.log(
71 | 'New content is available and will be used when all ' +
72 | 'tabs for this page are closed. See https://bit.ly/CRA-PWA.',
73 | );
74 |
75 | // Execute callback
76 | if (config && config.onUpdate) {
77 | config.onUpdate(registration);
78 | }
79 | } else {
80 | // At this point, everything has been precached.
81 | // It's the perfect time to display a
82 | // "Content is cached for offline use." message.
83 | console.log('Content is cached for offline use.');
84 |
85 | // Execute callback
86 | if (config && config.onSuccess) {
87 | config.onSuccess(registration);
88 | }
89 | }
90 | }
91 | };
92 | };
93 | })
94 | .catch(error => {
95 | console.error('Error during service worker registration:', error);
96 | });
97 | }
98 |
99 | function checkValidServiceWorker(swUrl, config) {
100 | // Check if the service worker can be found. If it can't reload the page.
101 | fetch(swUrl)
102 | .then(response => {
103 | // Ensure service worker exists, and that we really are getting a JS file.
104 | const contentType = response.headers.get('content-type');
105 | if (response.status === 404 || (contentType != null && contentType.indexOf('javascript') === -1)) {
106 | // No service worker found. Probably a different app. Reload the page.
107 | navigator.serviceWorker.ready.then(registration => {
108 | registration.unregister().then(() => {
109 | window.location.reload();
110 | });
111 | });
112 | } else {
113 | // Service worker found. Proceed as normal.
114 | registerValidSW(swUrl, config);
115 | }
116 | })
117 | .catch(() => {
118 | console.log('No internet connection found. App is running in offline mode.');
119 | });
120 | }
121 |
122 | export function unregister() {
123 | if ('serviceWorker' in navigator) {
124 | navigator.serviceWorker.ready.then(registration => {
125 | registration.unregister();
126 | });
127 | }
128 | }
129 |
--------------------------------------------------------------------------------
/mfe/mod-svelte/Dockerfile:
--------------------------------------------------------------------------------
1 | FROM caddy:2-alpine
2 |
3 | COPY Caddyfile /etc/caddy/Caddyfile
4 | COPY /dist /usr/share/caddy/dist
5 |
--------------------------------------------------------------------------------
/mfe/mod-svelte/README.md:
--------------------------------------------------------------------------------
1 | # Mod Svelte
2 |
--------------------------------------------------------------------------------
/mfe/mod-svelte/babel.config.js:
--------------------------------------------------------------------------------
1 | module.exports = (api) => {
2 | api.cache(true);
3 |
4 | return {
5 | presets: [
6 | [
7 | '@babel/preset-env',
8 | {
9 | useBuiltIns: 'entry',
10 | corejs: '3',
11 | shippedProposals: true,
12 | targets: 'defaults',
13 | },
14 | ],
15 | ],
16 | plugins: ['@babel/plugin-transform-runtime'],
17 | };
18 | };
19 |
--------------------------------------------------------------------------------
/mfe/mod-svelte/env.js:
--------------------------------------------------------------------------------
1 | function Environments() {
2 | this.NODE_ENV = process.env.NODE_ENV || 'development';
3 |
4 | this.APP_NAME = process.env.APP_NAME || 'Mod Svelte';
5 | this.APP_DESCRIPTION = process.env.APP_DESCRIPTION || '';
6 |
7 | this.HOST_NAME = process.env.HOST_NAME || '0.0.0.0';
8 | this.SITE_PORT = process.env.SITE_PORT || 8004;
9 | this.SITE_URL = process.env.SITE_URL || `http://${this.HOST_NAME}:${this.SITE_PORT}`;
10 | this.APP_BASE = process.env.APP_BASE || '/';
11 | }
12 |
13 | module.exports = new Environments();
14 |
--------------------------------------------------------------------------------
/mfe/mod-svelte/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "mod-svelte",
3 | "version": "1.0.0",
4 | "main": "index.js",
5 | "scripts": {
6 | "serve": "webpack-dev-server",
7 | "build": "webpack --env.prod",
8 | "lint": "echo \"Error: no lint specified\" && exit 1",
9 | "test": "echo \"Error: no test specified\" && exit 1"
10 | },
11 | "license": "MIT",
12 | "dependencies": {
13 | "@babel/runtime": "^7.10.5",
14 | "core-js": "^3.6.5",
15 | "single-spa-svelte": "^2.0.0",
16 | "svelte": "^3.24.0",
17 | "svelte-routing": "^1.4.2"
18 | },
19 | "devDependencies": {
20 | "@babel/core": "^7.10.5",
21 | "@babel/plugin-transform-runtime": "^7.10.5",
22 | "@babel/preset-env": "^7.10.4",
23 | "babel-loader": "^8.1.0",
24 | "cache-loader": "^4.1.0",
25 | "copy-webpack-plugin": "^6.0.3",
26 | "css-loader": "^4.0.0",
27 | "file-loader": "^6.0.0",
28 | "html-webpack-plugin": "^4.3.0",
29 | "postcss-loader": "^3.0.0",
30 | "process-envify": "^0.1.3",
31 | "script-ext-html-webpack-plugin": "^2.1.4",
32 | "style-loader": "^1.2.1",
33 | "svelte-loader": "^2.13.6",
34 | "url-loader": "^4.1.0",
35 | "webpack": "^4.44.0",
36 | "webpack-cli": "^3.3.12",
37 | "webpack-dev-server": "^3.11.0"
38 | }
39 | }
40 |
--------------------------------------------------------------------------------
/mfe/mod-svelte/src/App.svelte:
--------------------------------------------------------------------------------
1 |
8 |
9 |
10 |
14 |
15 |
16 |
17 |
--------------------------------------------------------------------------------
/mfe/mod-svelte/src/core/RouterOutlet.svelte:
--------------------------------------------------------------------------------
1 |
7 |
8 |
9 |
10 |
--------------------------------------------------------------------------------
/mfe/mod-svelte/src/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 | Mod Svelte
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
--------------------------------------------------------------------------------
/mfe/mod-svelte/src/landings/About.svelte:
--------------------------------------------------------------------------------
1 | About Page
2 |
--------------------------------------------------------------------------------
/mfe/mod-svelte/src/landings/Home.svelte:
--------------------------------------------------------------------------------
1 | Home Page
2 |
--------------------------------------------------------------------------------
/mfe/mod-svelte/src/main.js:
--------------------------------------------------------------------------------
1 | import singleSpaSvelte from 'single-spa-svelte';
2 |
3 | import App from './App';
4 |
5 | if (window.__POWERED_BY_QIANKUN__) {
6 | __webpack_public_path__ = window.__INJECTED_PUBLIC_PATH_BY_QIANKUN__;
7 | }
8 |
9 | if (!window.__POWERED_BY_QIANKUN__) {
10 | new App({ target: document.querySelector('#app-root') });
11 | }
12 |
13 | const { bootstrap, mount, unmount } = singleSpaSvelte({
14 | component: App,
15 | domElementGetter: () => document.querySelector('#app-root'),
16 | });
17 |
18 | export { bootstrap, mount, unmount };
19 |
--------------------------------------------------------------------------------
/mfe/mod-svelte/webpack.config.js:
--------------------------------------------------------------------------------
1 | const path = require('path');
2 | const webpack = require('webpack');
3 | const HtmlPlugin = require('html-webpack-plugin');
4 | const ScriptExtHtmlPlugin = require('script-ext-html-webpack-plugin');
5 | const CopyPlugin = require('copy-webpack-plugin');
6 | const envify = require('process-envify');
7 |
8 | const env = require('./env');
9 | const pkg = require('./package');
10 |
11 | const SOURCE_ROOT = path.join(__dirname, 'src');
12 | const DISTRIBUTION_ROOT = path.join(__dirname, 'dist');
13 |
14 | module.exports = ({ prod = false } = {}) => ({
15 | mode: prod ? 'production' : 'development',
16 | context: SOURCE_ROOT,
17 | entry: './main.js',
18 | output: {
19 | path: DISTRIBUTION_ROOT,
20 | filename: prod ? '[name].[hash].js' : '[name].js',
21 | chunkFilename: prod ? '[id].[chunkhash].js' : '[name].js',
22 | publicPath: '/',
23 | library: `${pkg.name}-[name]`,
24 | libraryTarget: 'umd',
25 | jsonpFunction: `webpackJsonp_${pkg.name}`,
26 | },
27 | module: {
28 | rules: [
29 | {
30 | test: /\.svelte$/,
31 | use: [{ loader: 'svelte-loader' }],
32 | },
33 | {
34 | test: /\.m?jsx?$/,
35 | exclude: /node_modules/,
36 | use: [{ loader: 'cache-loader' }, { loader: 'babel-loader' }],
37 | },
38 | // {
39 | // test: /\.css$/,
40 | // use: [
41 | // 'style-loader',
42 | // { loader: 'css-loader', options: { importLoaders: 1 } },
43 | // { loader: 'postcss-loader', options: { sourceMap: true } },
44 | // ],
45 | // },
46 | {
47 | test: /\.(png|jpe?g|gif|webp)(\?.*)?$/,
48 | use: [
49 | {
50 | loader: 'url-loader',
51 | options: {
52 | limit: 4096,
53 | fallback: {
54 | loader: 'file-loader',
55 | options: { name: path.posix.join('assets', 'images/[name].[hash:8].[ext]') },
56 | },
57 | },
58 | },
59 | ],
60 | },
61 | {
62 | test: /\.(svg)(\?.*)?$/,
63 | use: [
64 | {
65 | loader: 'file-loader',
66 | options: { name: path.posix.join('assets', 'images/[name].[hash:8].[ext]') },
67 | },
68 | ],
69 | },
70 | {
71 | test: /\.(mp4|webm|ogg|mp3|wav|flac|aac)(\?.*)?$/,
72 | use: [
73 | {
74 | loader: 'url-loader',
75 | options: {
76 | limit: 4096,
77 | fallback: {
78 | loader: 'file-loader',
79 | options: { name: path.posix.join('assets', 'medias/[name].[hash:8].[ext]') },
80 | },
81 | },
82 | },
83 | ],
84 | },
85 | {
86 | test: /\.(woff2?|eot|ttf|otf)(\?.*)?$/i,
87 | use: [
88 | {
89 | loader: 'url-loader',
90 | options: {
91 | limit: 4096,
92 | fallback: {
93 | loader: 'file-loader',
94 | options: { name: path.posix.join('assets', 'fonts/[name].[hash:8].[ext]') },
95 | },
96 | },
97 | },
98 | ],
99 | },
100 | ].filter(Boolean),
101 | },
102 | resolve: {
103 | extensions: ['.mjs', '.js', '.svelte'],
104 | mainFields: ['svelte', 'browser', 'module', 'main'],
105 | alias: {
106 | svelte: path.resolve('node_modules', 'svelte'),
107 | '~': SOURCE_ROOT,
108 | },
109 | },
110 | plugins: [
111 | new webpack.DefinePlugin(envify(env)),
112 | new HtmlPlugin({
113 | template: 'index.html',
114 | minify: prod && {
115 | removeComments: true,
116 | collapseWhitespace: true,
117 | removeAttributeQuotes: true,
118 | },
119 | chunksSortMode: prod ? 'manual' : 'auto',
120 | }),
121 | new ScriptExtHtmlPlugin({
122 | defaultAttribute: 'defer',
123 | preload: {
124 | test: /\.js$/,
125 | chunks: 'initial',
126 | },
127 | prefetch: {
128 | test: /\.js$/,
129 | chunks: 'all',
130 | },
131 | }),
132 | // new CopyPlugin([
133 | // {
134 | // from: 'assets/**/*',
135 | // to: DISTRIBUTION_ROOT,
136 | // ignore: ['assets/styles/**/*'],
137 | // },
138 | // ]),
139 | !prod && new webpack.HotModuleReplacementPlugin(),
140 | prod && new webpack.optimize.AggressiveSplittingPlugin(),
141 | ].filter(Boolean),
142 | optimization: {
143 | runtimeChunk: 'single',
144 | splitChunks: {
145 | chunks: 'all',
146 | maxInitialRequests: Infinity,
147 | minSize: 0,
148 | cacheGroups: {
149 | vendor: {
150 | test: /[\\/]node_modules[\\/]/,
151 | },
152 | },
153 | },
154 | },
155 | devServer: {
156 | headers: {
157 | 'Access-Control-Allow-Origin': '*',
158 | },
159 | contentBase: DISTRIBUTION_ROOT,
160 | historyApiFallback: true,
161 | host: env.HOST_NAME,
162 | hot: true,
163 | inline: true,
164 | overlay: true,
165 | port: env.SITE_PORT,
166 | },
167 | devtool: prod ? 'hidden-source-map' : 'cheap-module-eval-source-map',
168 | });
169 |
--------------------------------------------------------------------------------
/mfe/mod-vue/.browserslistrc:
--------------------------------------------------------------------------------
1 | > 1%
2 | last 2 versions
3 |
--------------------------------------------------------------------------------
/mfe/mod-vue/.eslintrc:
--------------------------------------------------------------------------------
1 | {
2 | "plugins": [],
3 | "root": true,
4 | "env": {
5 | "node": true
6 | },
7 | "globals": {
8 | "__webpack_public_path__": true
9 | },
10 | "extends": [
11 | "plugin:vue/essential",
12 | "eslint:recommended"
13 | ],
14 | "parserOptions": {
15 | "parser": "babel-eslint"
16 | },
17 | "rules": {},
18 | "overrides": [
19 | {
20 | "files": [
21 | "**/__tests__/*.{j,t}s?(x)",
22 | "**/tests/unit/**/*.spec.{j,t}s?(x)"
23 | ],
24 | "env": {
25 | "jest": true
26 | }
27 | }
28 | ]
29 | }
30 |
--------------------------------------------------------------------------------
/mfe/mod-vue/.gitignore:
--------------------------------------------------------------------------------
1 | .DS_Store
2 | node_modules
3 | /dist
4 |
5 | # local env files
6 | .env.local
7 | .env.*.local
8 |
9 | # Log files
10 | npm-debug.log*
11 | yarn-debug.log*
12 | yarn-error.log*
13 |
14 | # Editor directories and files
15 | .idea
16 | .vscode
17 | *.suo
18 | *.ntvs*
19 | *.njsproj
20 | *.sln
21 | *.sw?
22 |
--------------------------------------------------------------------------------
/mfe/mod-vue/Caddyfile:
--------------------------------------------------------------------------------
1 | :8001 {
2 | encode gzip
3 | root * /usr/share/caddy/dist
4 | try_files {path} /index.html
5 | file_server browse
6 |
7 | header {
8 | Access-Control-Allow-Origin http://localhost:8000
9 | Strict-Transport-Security max-age=31536000
10 | X-Content-Type-Options nosniff
11 | X-Frame-Options DENY
12 | Referrer-Policy no-referrer-when-downgrade
13 | }
14 | }
15 |
--------------------------------------------------------------------------------
/mfe/mod-vue/Dockerfile:
--------------------------------------------------------------------------------
1 | FROM caddy:2-alpine
2 |
3 | COPY Caddyfile /etc/caddy/Caddyfile
4 | COPY /dist /usr/share/caddy/dist
5 |
--------------------------------------------------------------------------------
/mfe/mod-vue/README.md:
--------------------------------------------------------------------------------
1 | # Mod Vue
2 |
3 | ## Usage
4 |
5 | ```sh
6 | $ yarn install
7 | ```
8 |
9 | ```sh
10 | $ yarn serve
11 | ```
12 |
13 | ```sh
14 | $ yarn build
15 | ```
16 |
17 | ```sh
18 | $ yarn lint
19 | ```
20 |
21 | ```sh
22 | $ yarn test
23 | ```
24 |
25 | ## Dockerization
26 |
27 | ```sh
28 | $ yarn build
29 | $ docker-compose up
30 | ```
31 |
32 | Visit [http://localhost:8001](http://localhost:8001).
33 |
--------------------------------------------------------------------------------
/mfe/mod-vue/babel.config.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | presets: ['@vue/cli-plugin-babel/preset'],
3 | };
4 |
--------------------------------------------------------------------------------
/mfe/mod-vue/docker-compose.yml:
--------------------------------------------------------------------------------
1 | version: '3.8'
2 |
3 | services:
4 | serve:
5 | image: serve-mod-vue
6 | build:
7 | context: .
8 | dockerfile: Dockerfile
9 | ports:
10 | - '80:80'
11 | - '443:443'
12 | - '8001:8001'
13 | volumes:
14 | - caddy_data:/data
15 | - caddy_config:/config
16 | networks:
17 | - micro
18 |
19 | volumes:
20 | caddy_data:
21 | caddy_config:
22 |
23 | networks:
24 | micro:
25 | driver: bridge
26 |
--------------------------------------------------------------------------------
/mfe/mod-vue/jest.config.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | preset: '@vue/cli-plugin-unit-jest',
3 | };
4 |
--------------------------------------------------------------------------------
/mfe/mod-vue/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "mod-vue",
3 | "version": "0.1.0",
4 | "private": true,
5 | "scripts": {
6 | "serve": "vue-cli-service serve",
7 | "build": "vue-cli-service build",
8 | "lint": "vue-cli-service lint",
9 | "test": "vue-cli-service test:unit"
10 | },
11 | "dependencies": {
12 | "core-js": "^3.6.4",
13 | "single-spa-vue": "^1.8.2",
14 | "vue": "^2.6.11",
15 | "vue-router": "^3.1.6"
16 | },
17 | "devDependencies": {
18 | "@vue/cli-plugin-babel": "~4.2.0",
19 | "@vue/cli-plugin-eslint": "~4.2.0",
20 | "@vue/cli-plugin-unit-jest": "~4.5.0",
21 | "@vue/cli-service": "~4.2.0",
22 | "@vue/test-utils": "^1.0.3",
23 | "babel-eslint": "^10.0.3",
24 | "eslint": "^6.7.2",
25 | "eslint-plugin-vue": "^6.1.2",
26 | "vue-template-compiler": "^2.6.11"
27 | }
28 | }
29 |
--------------------------------------------------------------------------------
/mfe/mod-vue/public/favicon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Shyam-Chen/Micro-Fullstack/72ff7b703784cf8f7ac9edcdb44e532bbecbeca8/mfe/mod-vue/public/favicon.ico
--------------------------------------------------------------------------------
/mfe/mod-vue/public/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 | <%= htmlWebpackPlugin.options.title %>
9 |
10 |
11 |
14 |
15 |
16 |
17 |
18 |
--------------------------------------------------------------------------------
/mfe/mod-vue/src/App.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
11 |
12 |
13 | Home~
14 | |
15 | About~
16 |
17 |
18 |
19 |
20 |

21 |
22 |
23 |
24 |
25 |
40 |
41 |
46 |
--------------------------------------------------------------------------------
/mfe/mod-vue/src/assets/logo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Shyam-Chen/Micro-Fullstack/72ff7b703784cf8f7ac9edcdb44e532bbecbeca8/mfe/mod-vue/src/assets/logo.png
--------------------------------------------------------------------------------
/mfe/mod-vue/src/components/HelloWorld.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
{{ msg }}
4 |
5 | For a guide and recipes on how to configure / customize this project,
6 | check out the
7 | vue-cli documentation.
8 |
9 |
Installed CLI Plugins
10 |
30 |
Essential Links
31 |
38 |
Ecosystem
39 |
54 |
55 |
56 |
57 |
65 |
66 |
82 |
--------------------------------------------------------------------------------
/mfe/mod-vue/src/main.js:
--------------------------------------------------------------------------------
1 | import Vue from 'vue';
2 | import singleSpaVue from 'single-spa-vue';
3 |
4 | import App from './App.vue';
5 | import router from './router';
6 |
7 | if (window.__POWERED_BY_QIANKUN__) {
8 | __webpack_public_path__ = window.__INJECTED_PUBLIC_PATH_BY_QIANKUN__;
9 | }
10 |
11 | if (!window.__POWERED_BY_QIANKUN__) {
12 | new Vue({
13 | router,
14 | render: h => h(App),
15 | }).$mount('#app');
16 | }
17 |
18 | const { bootstrap, mount, unmount } = singleSpaVue({
19 | Vue,
20 | appOptions: {
21 | el: '#app',
22 | router,
23 | render: h => h(App),
24 | },
25 | });
26 |
27 | export { bootstrap, mount, unmount };
28 |
--------------------------------------------------------------------------------
/mfe/mod-vue/src/router/index.js:
--------------------------------------------------------------------------------
1 | import Vue from 'vue';
2 | import VueRouter from 'vue-router';
3 |
4 | import Home from '@/views/Home.vue';
5 | import NotFound from '@/views/NotFound.vue';
6 |
7 | Vue.use(VueRouter);
8 |
9 | const routes = [
10 | {
11 | path: '/',
12 | name: 'home',
13 | component: Home,
14 | },
15 | {
16 | path: '/about',
17 | name: 'about',
18 | // route level code-splitting
19 | // this generates a separate chunk (about.[hash].js) for this route
20 | // which is lazy-loaded when the route is visited.
21 | component: () => import(/* webpackChunkName: "about" */ '../views/About.vue'),
22 | },
23 | { path: '*', component: NotFound },
24 | ];
25 |
26 | const router = new VueRouter({
27 | base: window.__POWERED_BY_QIANKUN__ ? '/vue' : '/',
28 | mode: 'history',
29 | routes,
30 | });
31 |
32 | export default router;
33 |
--------------------------------------------------------------------------------
/mfe/mod-vue/src/views/About.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
This is an about page
4 |
dynamic span color
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
20 |
21 |
51 |
--------------------------------------------------------------------------------
/mfe/mod-vue/src/views/Home.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |

4 |
5 |
6 |
7 |
12 |
--------------------------------------------------------------------------------
/mfe/mod-vue/src/views/NotFound.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 | 404
4 |
5 |
6 |
7 |
12 |
--------------------------------------------------------------------------------
/mfe/mod-vue/vue.config.js:
--------------------------------------------------------------------------------
1 | const path = require('path');
2 |
3 | const pkg = require('./package');
4 |
5 | module.exports = {
6 | configureWebpack: {
7 | output: {
8 | jsonpFunction: `webpackJsonp_${pkg.name}`,
9 | library: `${pkg.name}-[name]`,
10 | libraryTarget: 'umd',
11 | },
12 | resolve: {
13 | alias: {
14 | '@': path.join(__dirname, 'src'),
15 | '~': path.join(__dirname, '../app-components/dist'),
16 | },
17 | },
18 | },
19 | chainWebpack(config) {
20 | config.module.rules.delete('eslint');
21 | },
22 | devServer: {
23 | disableHostCheck: true,
24 | headers: {
25 | 'Access-Control-Allow-Origin': '*',
26 | },
27 | hot: true,
28 | overlay: {
29 | warnings: false,
30 | errors: true,
31 | },
32 | port: 8001,
33 | progress: false,
34 | },
35 | };
36 |
--------------------------------------------------------------------------------
/mfe/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "mfe",
3 | "version": "1.0.0",
4 | "scripts": {
5 | "bootstrap": "lerna bootstrap",
6 | "serve": "lerna run --parallel serve",
7 | "build": "lerna run --parallel build",
8 | "lint": "echo \"Error: no lint specified\" && exit 1",
9 | "test": "echo \"Error: no test specified\" && exit 1"
10 | },
11 | "license": "MIT",
12 | "devDependencies": {
13 | "lerna": "^3.22.1"
14 | }
15 | }
16 |
--------------------------------------------------------------------------------
/servers/.gitkeep:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Shyam-Chen/Micro-Fullstack/72ff7b703784cf8f7ac9edcdb44e532bbecbeca8/servers/.gitkeep
--------------------------------------------------------------------------------