Compare commits
	
		
			166 Commits
		
	
	
		
			0.8.0-alph
			...
			dependabot
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
| ![dependabot[bot]](/assets/img/avatar_default.png)  | 5dc8c7b196 | ||
| ![dependabot[bot]](/assets/img/avatar_default.png)  | 0d278f83ab | ||
|   | d91a7a09e3 | ||
|   | bdece853f2 | ||
|   | 416024b32e | ||
|   | 525e19b4ac | ||
| ![dependabot[bot]](/assets/img/avatar_default.png)  | 258f7bc2e0 | ||
| ![dependabot-preview[bot]](/assets/img/avatar_default.png)  | a861685d19 | ||
| ![dependabot-preview[bot]](/assets/img/avatar_default.png)  | 01059aa9d1 | ||
| ![dependabot-preview[bot]](/assets/img/avatar_default.png)  | 5ec875215b | ||
| ![dependabot-preview[bot]](/assets/img/avatar_default.png)  | c8507558d6 | ||
| ![dependabot-preview[bot]](/assets/img/avatar_default.png)  | 4e3649cb93 | ||
| ![dependabot-preview[bot]](/assets/img/avatar_default.png)  | 5f554b4b96 | ||
| ![dependabot-preview[bot]](/assets/img/avatar_default.png)  | 7924f64eed | ||
| ![dependabot-preview[bot]](/assets/img/avatar_default.png)  | 1379ceb74c | ||
| ![dependabot-preview[bot]](/assets/img/avatar_default.png)  | 0527e0f301 | ||
|   | 299e41da36 | ||
|   | 1af66e72c2 | ||
| ![dependabot[bot]](/assets/img/avatar_default.png)  | 5ee7dbe48d | ||
| ![dependabot-preview[bot]](/assets/img/avatar_default.png)  | 0ce73aea36 | ||
| ![dependabot-preview[bot]](/assets/img/avatar_default.png)  | 13d22c7885 | ||
|   | 9582c06a08 | ||
|   | 9e7de8be7a | ||
|   | b668d7c397 | ||
| ![dependabot-preview[bot]](/assets/img/avatar_default.png)  | 6bcc471f4d | ||
| ![dependabot-preview[bot]](/assets/img/avatar_default.png)  | 1e908e1cc1 | ||
| ![dependabot-preview[bot]](/assets/img/avatar_default.png)  | aa6b2511ab | ||
| ![dependabot-preview[bot]](/assets/img/avatar_default.png)  | 2123a0fec4 | ||
|   | 9e9cdeb3ee | ||
|   | c17434703e | ||
|   | 0644eb285a | ||
|   | 0f4120c2c8 | ||
|   | ba43561f40 | ||
|   | 046226b580 | ||
| ![dependabot-preview[bot]](/assets/img/avatar_default.png)  | cd391e63c1 | ||
|   | ed5fc4adaf | ||
|   | eb5a1d4fc5 | ||
|   | 4cd8bde604 | ||
| ![dependabot-preview[bot]](/assets/img/avatar_default.png)  | c73aedb68d | ||
| ![dependabot-preview[bot]](/assets/img/avatar_default.png)  | e9ee8ec1f5 | ||
|   | fd6b1947a5 | ||
| ![dependabot-preview[bot]](/assets/img/avatar_default.png)  | aeb373190a | ||
|   | a74b086219 | ||
|   | 6214581ca8 | ||
|   | 63bc06a993 | ||
|   | 833b7d06a3 | ||
| ![dependabot-preview[bot]](/assets/img/avatar_default.png)  | 1ae68f1076 | ||
|   | 5ce61ef200 | ||
| ![dependabot-preview[bot]](/assets/img/avatar_default.png)  | 3923c3451f | ||
|   | 8741db25b6 | ||
|   | 16d20b23a7 | ||
| ![dependabot-preview[bot]](/assets/img/avatar_default.png)  | 5028ba7694 | ||
| ![dependabot-preview[bot]](/assets/img/avatar_default.png)  | a324fab432 | ||
|   | 275ec78ad0 | ||
|   | 2455eb215e | ||
|   | 3b3503de1e | ||
|   | 7135633b60 | ||
|   | b69cf16250 | ||
| ![dependabot-preview[bot]](/assets/img/avatar_default.png)  | 4527da6251 | ||
| ![dependabot-preview[bot]](/assets/img/avatar_default.png)  | 2a17ea6131 | ||
| ![dependabot-preview[bot]](/assets/img/avatar_default.png)  | 5adca0dd2f | ||
|   | 521a9e64a2 | ||
|   | bfe8dc4249 | ||
|   | b569820d3e | ||
| ![dependabot-preview[bot]](/assets/img/avatar_default.png)  | 99b3696b29 | ||
|   | 779679a809 | ||
|   | ec49f75717 | ||
|   | 23598ce1c6 | ||
|   | 2831949814 | ||
|   | e712e3d0e2 | ||
|   | 7df1c64740 | ||
|   | 91325f9ca3 | ||
|   | 7326325c19 | ||
| ![dependabot-preview[bot]](/assets/img/avatar_default.png)  | 59e195fa94 | ||
| ![dependabot-preview[bot]](/assets/img/avatar_default.png)  | 5ed4f8795a | ||
| ![dependabot-preview[bot]](/assets/img/avatar_default.png)  | a02e7e66af | ||
| ![dependabot-preview[bot]](/assets/img/avatar_default.png)  | 9c1d093bb8 | ||
|   | 302877d4b4 | ||
|   | 871bb29dbe | ||
|   | 3be144f644 | ||
|   | 2560dc23fc | ||
| ![dependabot-preview[bot]](/assets/img/avatar_default.png)  | 3d6c3d10bf | ||
|   | 5f811693f1 | ||
|   | 0068fb92eb | ||
| ![dependabot-preview[bot]](/assets/img/avatar_default.png)  | 71174ead45 | ||
| ![dependabot-preview[bot]](/assets/img/avatar_default.png)  | 43c18caceb | ||
| ![dependabot-preview[bot]](/assets/img/avatar_default.png)  | 7b4c9c3154 | ||
| ![dependabot-preview[bot]](/assets/img/avatar_default.png)  | 9d2649433d | ||
| ![dependabot-preview[bot]](/assets/img/avatar_default.png)  | 6353fa7dd3 | ||
|   | bfa837c88d | ||
|   | bdc454e7e5 | ||
| ![dependabot-preview[bot]](/assets/img/avatar_default.png)  | 9b3e85754c | ||
| ![dependabot-preview[bot]](/assets/img/avatar_default.png)  | af3dcc5f31 | ||
|   | c375fb9eaf | ||
|   | 70c314229f | ||
|   | 66e23ead00 | ||
|   | 2e5666c2b6 | ||
|   | 7675656a54 | ||
|   | 3d7f7b0ad1 | ||
|   | a1ccbd6cab | ||
|   | 33cb4ce63c | ||
|   | aefb4497e2 | ||
|   | 0047e66f10 | ||
|   | 6bae4254af | ||
|   | a9689993b0 | ||
|   | 8c0182b29f | ||
|   | 02d55c7143 | ||
|   | f343b537f1 | ||
|   | a84e7da65f | ||
|   | f3b64387cb | ||
|   | e132435ff8 | ||
|   | fb492fa6f7 | ||
|   | 159714491d | ||
|   | 64cbbc70bb | ||
|   | d0559f627e | ||
|   | 0a6784e270 | ||
|   | b6fd3c7e98 | ||
|   | 1c05534071 | ||
|   | 3627d5bb40 | ||
|   | 1f7714c1e9 | ||
|   | d868ebf4a1 | ||
|   | 4640379b06 | ||
| ![dependabot-preview[bot]](/assets/img/avatar_default.png)  | 922120efbb | ||
|   | 91fec99b00 | ||
|   | 2f89c1fe1f | ||
|   | 2298f39cca | ||
|   | 23d68bc27b | ||
|   | 74c0423f0d | ||
|   | 06f87c4d8e | ||
|   | 35262de828 | ||
| ![dependabot-preview[bot]](/assets/img/avatar_default.png)  | 34a495984c | ||
|   | d7130c4e28 | ||
|   | c9630a53c3 | ||
|   | 0522690472 | ||
|   | a8a0fbed32 | ||
|   | 26ae9585f6 | ||
|   | b69bd699c8 | ||
|   | 650ee5f63a | ||
|   | e3c60cbb77 | ||
|   | 0daca43d10 | ||
|   | d3c239dc54 | ||
|   | 05ac2441da | ||
|   | c0009b1b64 | ||
| ![dependabot-preview[bot]](/assets/img/avatar_default.png)  | 82960824ef | ||
| ![dependabot-preview[bot]](/assets/img/avatar_default.png)  | 64b63cbd0f | ||
|   | 05771fb07f | ||
|   | d1f680dacd | ||
|   | 14c9397b70 | ||
|   | eb5e724899 | ||
|   | 80619bd800 | ||
|   | 8e2cdfc607 | ||
|   | 58f416b7b2 | ||
|   | b6cf39e3e5 | ||
|   | 41bc98ab64 | ||
|   | b007ac315a | ||
|   | 940f6b8f72 | ||
|   | f9690b74a5 | ||
|   | f2c58d545a | ||
|   | 4732426629 | ||
|   | d4af4f67b2 | ||
|   | 6420e8b6c6 | ||
|   | 15c59fa31f | ||
|   | 294131b48f | ||
|   | 48413abaa1 | ||
|   | d36b2b935b | ||
|   | f493749689 | 
| @@ -1,73 +0,0 @@ | ||||
| defaults: &defaults | ||||
|   machine: true | ||||
|   environment: | ||||
|     IMPORT_PATH: "github.com/$CIRCLE_PROJECT_USERNAME/$CIRCLE_PROJECT_REPONAME" | ||||
|     OUTPUT_DIR: "./build" | ||||
|     DIST_DIR: "./dist" | ||||
|  | ||||
| install_golang: &install_golang | ||||
|   run: | ||||
|     name: install Golang 1.11 | ||||
|     command: | | ||||
|       sudo add-apt-repository ppa:gophers/archive | ||||
|       sudo apt-get update | ||||
|       sudo apt-get install golang-1.11-go | ||||
|       alias go="/usr/lib/go-1.11/bin/go" | ||||
|       go version | ||||
|  | ||||
| install_deps: &install_deps | ||||
|   run: | ||||
|     name: Install deps | ||||
|     command: | | ||||
|       /usr/lib/go-1.11/bin/go mod vendor | ||||
|       /usr/lib/go-1.11/bin/go get -u github.com/gobuffalo/packr/packr | ||||
|  | ||||
| install_httpie: &install_httpie | ||||
|   run: | ||||
|     name: install httpie | ||||
|     command: | | ||||
|       sudo apt-get -y update && sudo apt-get -y install httpie | ||||
|  | ||||
| install_jq: &install_jq | ||||
|   run: | ||||
|     name: install jq | ||||
|     command: | | ||||
|       sudo apt-get update && sudo apt-get -y install jq | ||||
|  | ||||
| build_binary: &build_binary | ||||
|   run: | ||||
|     name: build binary | ||||
|     command: | | ||||
|       /usr/lib/go-1.11/bin/go build -o ${OUTPUT_DIR}/fx fx.go | ||||
|  | ||||
| unit_test: &unit_test | ||||
|   run: | ||||
|     name: unit test | ||||
|     command: | | ||||
|       make unit-test | ||||
|       bash <(curl -s https://codecov.io/bash) -t ${CODECOV_TOKEN} | ||||
| cli_test: &cli_test | ||||
|   run: | ||||
|     name: cli test | ||||
|     command: make cli-test | ||||
|  | ||||
| version: 2 | ||||
| jobs: | ||||
|   test: | ||||
|     <<: *defaults | ||||
|     steps: | ||||
|       - checkout | ||||
|       - *install_golang | ||||
|       - *install_deps | ||||
|       - *unit_test | ||||
|       - *build_binary | ||||
|       - run: | ||||
|           name: Pull images | ||||
|           command: make pull | ||||
|       - *cli_test | ||||
|  | ||||
| workflows: | ||||
|   version: 2 | ||||
|   workflow: | ||||
|     jobs: | ||||
|       - test | ||||
							
								
								
									
										8
									
								
								.github/dependabot.yml
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										8
									
								
								.github/dependabot.yml
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,8 @@ | ||||
| version: 2 | ||||
| updates: | ||||
| - package-ecosystem: gomod | ||||
|   directory: "/" | ||||
|   schedule: | ||||
|     interval: daily | ||||
|     time: "21:00" | ||||
|   open-pull-requests-limit: 10 | ||||
							
								
								
									
										55
									
								
								.github/workflows/ci.yml
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										55
									
								
								.github/workflows/ci.yml
									
									
									
									
										vendored
									
									
								
							| @@ -13,27 +13,23 @@ jobs: | ||||
|       - name: check out | ||||
|         uses: actions/checkout@master | ||||
|  | ||||
|       - name: setup docker | ||||
|       - name: kind create a k8s cluster | ||||
|         run: | | ||||
|           ./scripts/provision.sh | ||||
|           kind create cluster | ||||
|  | ||||
|       - name: setup k8s and kind | ||||
|         run: | | ||||
|           export GOBIN=$(go env GOPATH)/bin | ||||
|           export PATH=$PATH:$GOBIN | ||||
|           mkdir -p $GOBIN | ||||
|           curl -LO https://storage.googleapis.com/kubernetes-release/release/`curl -s https://storage.googleapis.com/kubernetes-release/release/stable.txt`/bin/linux/amd64/kubectl | ||||
|           chmod +x kubectl && mv kubectl $GOBIN | ||||
|           wget https://github.com/kubernetes-sigs/kind/releases/download/v0.5.0/kind-linux-amd64 && chmod +x kind-linux-amd64 && mv kind-linux-amd64 $GOBIN/kind | ||||
|           ./scripts/setup_kind.sh | ||||
|       # - name: lint | ||||
|       #   run: | | ||||
|       #     make lint | ||||
|  | ||||
|       - name: unit test | ||||
|         env: | ||||
|           DOCKER_PASSWORD: ${{ secrets.DOCKER_PASSWORD }} | ||||
|           DOCKER_USERNAME: ${{ secrets.DOCKER_USERNAME }} | ||||
|           CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }} | ||||
|         run: | | ||||
|           export KUBECONFIG=/home/runner/.kube/kind-config-fx-test | ||||
|           DEBUG=true go test -v ./container_runtimes/... ./deploy/... | ||||
|           # export KUBECONFIG="$(kind get kubeconfig-path)" | ||||
|           make unit-test | ||||
|           bash <(curl -s https://codecov.io/bash) -t ${CODECOV_TOKEN} | ||||
|  | ||||
|       - name: build fx | ||||
|         run: | | ||||
| @@ -47,33 +43,30 @@ jobs: | ||||
|           make test | ||||
|           # make docker-publish #TODO in release workflow | ||||
|  | ||||
|       - name: lint | ||||
|         run: | | ||||
|           export GOBIN=$(go env GOPATH)/bin | ||||
|           export PATH=$PATH:$GOBIN | ||||
|           go get -u github.com/golangci/golangci-lint/cmd/golangci-lint | ||||
|           golangci-lint run | ||||
|  | ||||
|  | ||||
|       - name: test fx cli | ||||
|         env: | ||||
|           REMOTE_HOST_ADDR: ${{secrets.DOCKER_REMOTE_HOST_ADDR}} | ||||
|           REMOTE_HOST_USER: ${{secrets.DOCKER_REMOTE_HOST_USER}} | ||||
|           REMOTE_HOST_PASSWORD: ${{secrets.DOCKER_REMOTE_HOST_PASSWORD}} | ||||
|         run: | | ||||
|           echo $KUBECONFIG | ||||
|           unset KUBECONFIG | ||||
|           make cli-test | ||||
|           make cli-test-ci | ||||
|  | ||||
|       - name: test AKS | ||||
|         env: | ||||
|           AKS_KUBECONFIG: ${{ secrets.AKS_KUBECONFIG }} | ||||
|         run: | | ||||
|           export KUBECONFIG=${HOME}/.kube/aks | ||||
|           echo ${AKS_KUBECONFIG} | base64 -d > $KUBECONFIG | ||||
|           if [[ -z "$AKS_KUBECONFIG" ]];then | ||||
|             echo "skip deploy test since no valid KUBECONFIG" | ||||
|           else | ||||
|             DEBUG=true ./build/fx up -n hello -p 12345 examples/functions/JavaScript/func.js | ||||
|             ./build/fx down hello | ||||
|             rm ${KUBECONFIG} | ||||
|           fi | ||||
|           echo "skip since aks environment not ready yet" | ||||
|           # export KUBECONFIG=${HOME}/.kube/aks | ||||
|           # echo ${AKS_KUBECONFIG} | base64 -d > $KUBECONFIG | ||||
|           # if [[ -z "$AKS_KUBECONFIG" ]];then | ||||
|           #   echo "skip deploy test since no valid KUBECONFIG" | ||||
|           # else | ||||
|           #   DEBUG=true ./build/fx up -n hello -p 12345 examples/functions/JavaScript/func.js | ||||
|           #   ./build/fx down hello | ||||
|           #   rm ${KUBECONFIG} | ||||
|           # fi | ||||
|  | ||||
|   Installation: | ||||
|     runs-on: ${{ matrix.os }} | ||||
|   | ||||
							
								
								
									
										30
									
								
								.github/workflows/docker.yml
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										30
									
								
								.github/workflows/docker.yml
									
									
									
									
										vendored
									
									
								
							| @@ -35,10 +35,10 @@ jobs: | ||||
|           docker build -t metrue/fx-d-base:latest -f ./assets/dockerfiles/base/d/Dockerfile ./assets/dockerfiles/base/d | ||||
|           docker push metrue/fx-d-base:latest | ||||
|  | ||||
|       # - name: build and publish fx java image | ||||
|       #   run: | | ||||
|       #     docker build -t metrue/fx-go-base:latest -f ./assets/dockerfiles/base/java/Dockerfile ./assets/dockerfiles/base/java | ||||
|       #     docker push metrue/fx-java-base:latest | ||||
|       - name: build and publish fx go image | ||||
|         run: | | ||||
|           docker build -t metrue/fx-go-base:latest -f ./assets/dockerfiles/base/go/Dockerfile ./assets/dockerfiles/base/go | ||||
|           docker push metrue/fx-go-base:latest | ||||
|  | ||||
|       - name: build and publish fx node image | ||||
|         if: always() | ||||
| @@ -57,14 +57,26 @@ jobs: | ||||
|         run: | | ||||
|           docker push metrue/fx-python-base:latest | ||||
|  | ||||
|       # - name: build and publish fx rust image | ||||
|       #   if: always() | ||||
|       #   run: | | ||||
|       #     docker build -t metrue/fx-rust-base:latest -f ./assets/dockerfiles/base/rust/Dockerfile ./assets/dockerfiles/base/python | ||||
|       #     docker push metrue/fx-rust-base:latest | ||||
|       - name: build and publish fx perl image | ||||
|         if: always() | ||||
|         run: | | ||||
|           docker build -t metrue/fx-perl-base:latest -f ./assets/dockerfiles/base/perl/Dockerfile ./assets/dockerfiles/base/perl | ||||
|           docker push metrue/fx-perl-base:latest | ||||
|  | ||||
|       - name: build and publish fx julia image | ||||
|         if: always() | ||||
|         run: | | ||||
|           docker build -t metrue/fx-julia-base:latest -f ./assets/dockerfiles/base/julia/Dockerfile ./assets/dockerfiles/base/julia | ||||
|           docker push metrue/fx-julia-base:latest | ||||
|  | ||||
|       - name: build and publish fx crystal image | ||||
|         if: always() | ||||
|         run: | | ||||
|           docker build -t metrue/fx-crystal-base:latest -f ./assets/dockerfiles/base/crystal/Dockerfile ./assets/dockerfiles/base/crystal | ||||
|           docker push metrue/fx-crystal-base:latest | ||||
|  | ||||
|       - name: build and publish fx php image | ||||
|         if: always() | ||||
|         run: | | ||||
|           docker build -t metrue/fx-php-base:latest -f ./assets/dockerfiles/base/php/Dockerfile ./assets/dockerfiles/base/php | ||||
|           docker push metrue/fx-php-base:latest | ||||
|   | ||||
							
								
								
									
										40
									
								
								.github/workflows/release.yml
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										40
									
								
								.github/workflows/release.yml
									
									
									
									
										vendored
									
									
								
							| @@ -18,40 +18,27 @@ jobs: | ||||
|       - name: check out | ||||
|         uses: actions/checkout@master | ||||
|  | ||||
|       - name: setup docker | ||||
|       - name: kind create a k8s cluster | ||||
|         run: | | ||||
|           ./scripts/provision.sh | ||||
|           kind create cluster | ||||
|  | ||||
|       - name: setup k8s and kind | ||||
|         run: | | ||||
|           export GOBIN=$(go env GOPATH)/bin | ||||
|           export PATH=$PATH:$GOBIN | ||||
|           mkdir -p $GOBIN | ||||
|           curl -LO https://storage.googleapis.com/kubernetes-release/release/`curl -s https://storage.googleapis.com/kubernetes-release/release/stable.txt`/bin/linux/amd64/kubectl | ||||
|           chmod +x kubectl && mv kubectl $GOBIN | ||||
|           wget https://github.com/kubernetes-sigs/kind/releases/download/v0.5.0/kind-linux-amd64 && chmod +x kind-linux-amd64 && mv kind-linux-amd64 $GOBIN/kind | ||||
|           ./scripts/setup_kind.sh | ||||
|       # - name: lint | ||||
|       #   run: | | ||||
|       #     docker run --rm -v $(pwd):/app -w /app golangci/golangci-lint \ | ||||
|       #     golangci-lint run -v | ||||
|  | ||||
|       - name: unit test | ||||
|         env: | ||||
|           DOCKER_PASSWORD: ${{ secrets.DOCKER_PASSWORD }} | ||||
|           DOCKER_USERNAME: ${{ secrets.DOCKER_USERNAME }} | ||||
|         run: | | ||||
|           export KUBECONFIG=/home/runner/.kube/kind-config-fx-test | ||||
|           DEBUG=true go test -v ./container_runtimes/... ./deploy/... | ||||
|           # export KUBECONFIG="$(kind get kubeconfig-path)" | ||||
|           make unit-test | ||||
|  | ||||
|       - name: build fx | ||||
|         run: | | ||||
|           make build | ||||
|  | ||||
|       - name: lint | ||||
|         run: | | ||||
|           export GOBIN=$(go env GOPATH)/bin | ||||
|           export PATH=$PATH:$GOBIN | ||||
|           go get -u github.com/golangci/golangci-lint/cmd/golangci-lint | ||||
|           golangci-lint run | ||||
|  | ||||
|  | ||||
|       - name: test fx cli | ||||
|         run: | | ||||
|           echo $KUBECONFIG | ||||
| @@ -64,11 +51,12 @@ jobs: | ||||
|           DOCKER_USERNAME: ${{ secrets.DOCKER_USERNAME }} | ||||
|           DOCKER_PASSWORD: ${{ secrets.DOCKER_PASSWORD }} | ||||
|         run: | | ||||
|           export KUBECONFIG=${HOME}/.kube/aks | ||||
|           echo ${AKS_KUBECONFIG} | base64 -d > $KUBECONFIG | ||||
|           DEBUG=true ./build/fx up -n hello -p 12345 examples/functions/JavaScript/func.js | ||||
|           ./build/fx down hello | ||||
|           rm ${KUBECONFIG} | ||||
|           echo "skip since aks environment not ready yet" | ||||
|           # export KUBECONFIG=${HOME}/.kube/aks | ||||
|           # echo ${AKS_KUBECONFIG} | base64 -d > $KUBECONFIG | ||||
|           # DEBUG=true ./build/fx up -n hello -p 12345 examples/functions/JavaScript/func.js | ||||
|           # ./build/fx down hello | ||||
|           # rm ${KUBECONFIG} | ||||
|   Release: | ||||
|     runs-on: ${{ matrix.os }} | ||||
|     needs: [Test] | ||||
|   | ||||
| @@ -1,12 +1,14 @@ | ||||
| run: | ||||
|   deadline: 10m | ||||
|   timeout: 10m | ||||
|   deadline: 20m | ||||
|   timeout: 20m | ||||
|   issues-exit-code: 1 | ||||
|   tests: true | ||||
|   skip-dirs: | ||||
|     - examples | ||||
|     - api/images | ||||
|     - test/functions | ||||
|     - assets/ | ||||
|     - bundler/go/assets | ||||
| linters: | ||||
|   enable: | ||||
|     - goimports | ||||
|   | ||||
| @@ -21,14 +21,14 @@ archives: | ||||
|     files: | ||||
|       - README.md | ||||
| brews: | ||||
|   - | ||||
|     github: | ||||
|       owner: metrue | ||||
|       name: homebrew-fx | ||||
|   - homepage: "https://github.com/metrue/fx" | ||||
|     description: "fx, a simple but powerful Function as a Service build tools" | ||||
|     folder: Formula | ||||
|     commit_author: | ||||
|       name: metrue | ||||
|       email: h.minghe@gmail.com | ||||
|     folder: Formula | ||||
|     caveats: "" | ||||
|     homepage: "https://github.com/metrue/fx" | ||||
|     description: "fx, a simple but powerful Function as a Service build tools" | ||||
|     tap: | ||||
|       owner: metrue | ||||
|       name: homebrew-fx | ||||
|     dependencies: | ||||
|       - docker | ||||
|   | ||||
							
								
								
									
										47
									
								
								Makefile
									
									
									
									
									
								
							
							
						
						
									
										47
									
								
								Makefile
									
									
									
									
									
								
							| @@ -1,14 +1,22 @@ | ||||
| OUTPUT_DIR=./build | ||||
| DIST_DIR=./dist | ||||
| OUTPUT_DIR ?=./build | ||||
| DIST_DIR ?=./dist | ||||
| DOCKER_REMOTE_HOST_ADDR ?= "127.0.0.1" | ||||
| DOCKER_REMOTE_HOST_USER ?= $(whoami) | ||||
|  | ||||
| lint: | ||||
| 	golangci-lint run | ||||
| 	docker pull golangci/golangci-lint | ||||
| 	docker run --rm -v $(CURDIR):/app -w /app golangci/golangci-lint golangci-lint run -v | ||||
|  | ||||
| generate: | ||||
| 	packr | ||||
| 	go get -u github.com/gobuffalo/packr/v2/... | ||||
| 	go get -u github.com/gobuffalo/packr/v2/packr2 | ||||
| 	packr2 | ||||
|  | ||||
| b: | ||||
| 	go build -ldflags="-s -w" -o ${OUTPUT_DIR}/fx fx.go | ||||
|  | ||||
| build: | ||||
| 	go build -o ${OUTPUT_DIR}/fx fx.go | ||||
| 	go build -ldflags="-s -w" -o ${OUTPUT_DIR}/fx fx.go | ||||
|  | ||||
| pull: | ||||
| 	./scripts/pull.sh | ||||
| @@ -23,8 +31,11 @@ clean: | ||||
| unit-test: | ||||
| 	./scripts/coverage.sh | ||||
|  | ||||
| cli-test-ci: | ||||
| 	./scripts/test_cli.sh 'js' | ||||
|  | ||||
| cli-test: | ||||
| 	./scripts/test_cli.sh | ||||
| 	./scripts/test_cli.sh 'js rb py go java d pl php' | ||||
|  | ||||
| http-test: | ||||
| 	./scripts/http_test.sh | ||||
| @@ -32,3 +43,27 @@ http-test: | ||||
| zip: | ||||
| 	zip -r images.zip images/ | ||||
| .PHONY: test build start list clean generate | ||||
|  | ||||
| start_docker_infra: | ||||
| 	docker build -t fx-docker-infra -f test/Dockerfile ./test | ||||
| 	docker run --rm --name fx-docker-infra -p 2222:22 -v /var/run/docker.sock:/var/run/docker.sock -d fx-docker-infra | ||||
|  | ||||
| test_docker_infra: | ||||
| 	CICD=true SSH_PORT=2222 SSH_KEY_FILE=./test/id_rsa ./build/fx infra create --name docker-local -t docker --host root@127.0.0.1 | ||||
|  | ||||
| stop_docker_infra: | ||||
| 	docker stop fx-docker-infra | ||||
|  | ||||
| start_k3s_infra: | ||||
| 	multipass launch --name k3s-master --cpus 1 --mem 512M --disk 3G  --cloud-init ./test/k3s/ssh-cloud-init.yaml | ||||
| 	multipass launch --name k3s-worker1 --cpus 1 --mem 512M --disk 3G  --cloud-init ./test/k3s/ssh-cloud-init.yaml | ||||
| 	multipass launch --name k3s-worker2 --cpus 1 --mem 512M --disk 3G  --cloud-init ./test/k3s/ssh-cloud-init.yaml | ||||
|  | ||||
| test_k3s_infra: | ||||
| 	./scripts/test_k3s_infra.sh | ||||
|  | ||||
| stop_k3s_infra: | ||||
| 	multipass delete k3s-master | ||||
| 	multipass delete k3s-worker1 | ||||
| 	multipass delete k3s-worker2 | ||||
| 	multipass purge | ||||
|   | ||||
							
								
								
									
										220
									
								
								README.md
									
									
									
									
									
								
							
							
						
						
									
										220
									
								
								README.md
									
									
									
									
									
								
							| @@ -1,25 +1,25 @@ | ||||
| fx | ||||
| ------ | ||||
|  | ||||
| Poor man's function as a service. | ||||
| <br/> | ||||
|  | ||||
|  | ||||
| [](https://codecov.io/gh/metrue/fx) | ||||
|  | ||||
|  | ||||
| [](https://codecov.io/gh/metrue/fx) | ||||
| [](https://goreportcard.com/report/github.com/metrue/fx) | ||||
| [](http://godoc.org/github.com/metrue/fx) | ||||
|  | ||||
|  | ||||
|  | ||||
| [](https://github.com/metrue/fx/releases/latest) | ||||
|  | ||||
| ## Table of Contents | ||||
| - [Introduction](#introduction) | ||||
| - [Installation](#installation) | ||||
| - [Usage](#usage) | ||||
| - [Contribute](#contribute) | ||||
|  | ||||
|  | ||||
| ## Introduction | ||||
|  | ||||
| fx is a tool to help you do Function as a Service on your own server. fx can make your stateless function a service in seconds. The most exciting thing is that you can write your functions with most programming languages. | ||||
| fx is a tool to help you do Function as a Service on your own server, fx can make your stateless function a service in seconds, both Docker host and Kubernetes cluster supported. The most exciting thing is that you can write your functions with most programming languages. | ||||
|  | ||||
| Feel free hacking fx to support the languages not listed. Welcome to tweet me [@_metrue](https://twitter.com/_metrue) on Twitter, [@metrue](https://www.weibo.com/u/2165714507) on Weibo. | ||||
|  | ||||
| @@ -35,10 +35,14 @@ Feel free hacking fx to support the languages not listed. Welcome to tweet me [@ | ||||
| | PHP           | Supported     | [@chlins](https://github.com/chlins)| [/examples/PHP](https://github.com/metrue/fx/tree/master/examples/functions/PHP) | | ||||
| | Julia         | Supported     | [@matbesancon](https://github.com/matbesancon)| [/examples/Julia](https://github.com/metrue/fx/tree/master/examples/functions/Julia) | | ||||
| | D             | Supported     | [@andre2007](https://github.com/andre2007)| [/examples/D](https://github.com/metrue/fx/tree/master/examples/functions/D) | | ||||
| | Perl          | Supported     | fx            | [/examples/Perl](https://github.com/metrue/fx/tree/master/examples/functions/Perl) | | ||||
| | Crystal       | Supported     | [@mvrilo](https://github.com/mvrilo)       | [/examples/Crystal](https://github.com/metrue/fx/tree/master/examples/functions/Crystal) | | ||||
| | R             | Working on [need your help](https://github.com/metrue/fx/issues/31)   | || | ||||
|  | ||||
| # Installation | ||||
|  | ||||
| Binaries are available for Windows, MacOS and Linux/Unix on x86. For other architectures and platforms, follow instructions to [build fx from source](#buildtest). | ||||
|  | ||||
| * MacOS | ||||
|  | ||||
| ``` | ||||
| @@ -58,16 +62,14 @@ curl -o- https://raw.githubusercontent.com/metrue/fx/master/scripts/install.sh | | ||||
| curl -o- https://raw.githubusercontent.com/metrue/fx/master/scripts/install.sh | sudo bash | ||||
| ``` | ||||
|  | ||||
| fx will be installed into /usr/local/bin, sometimes you may need `source ~/.zshrc` or `source ~/.bashrc` to make fx available in `$PAHT`. | ||||
| fx will be installed into /usr/local/bin, sometimes you may need `source ~/.zshrc` or `source ~/.bashrc` to make fx available in `$PATH`. | ||||
|  | ||||
| * Window | ||||
| * Windows | ||||
|  | ||||
| You can go the release page to [download](https://github.com/metrue/fx/releases) fx manually; | ||||
|  | ||||
| ## Usage | ||||
|  | ||||
| Make sure [Docker](https://docs.docker.com/engine/installation/) installed and running on your server first. then type `fx -h` on your terminal to check out basic help. | ||||
|  | ||||
| ``` | ||||
| NAME: | ||||
|    fx - makes function as a service | ||||
| @@ -75,17 +77,11 @@ NAME: | ||||
| USAGE: | ||||
|    fx [global options] command [command options] [arguments...] | ||||
|  | ||||
| VERSION: | ||||
|    0.6.0 | ||||
|  | ||||
| COMMANDS: | ||||
|    infra     manage infrastructure of fx | ||||
|    image     manage image of service | ||||
|    doctor    health check for fx | ||||
|    up        deploy a function or a group of functions | ||||
|    up        deploy a function | ||||
|    down      destroy a service | ||||
|    list, ls  list deployed services | ||||
|    call      run a function instantly | ||||
|    image     manage image of service | ||||
|    help, h   Shows a list of commands or help for one command | ||||
|  | ||||
| GLOBAL OPTIONS: | ||||
| @@ -93,99 +89,54 @@ GLOBAL OPTIONS: | ||||
|    --version, -v  print the version | ||||
| ``` | ||||
|  | ||||
| 1. List your current machines and activate you machine | ||||
| ### Deploy function | ||||
|  | ||||
| #### Local Docker environment | ||||
|  | ||||
| By default, function will be deployed on localhost, make sure [Docker](https://docs.docker.com/engine/installation/) installed and running on your server first. then type `fx -h` on your terminal to check out basic help. | ||||
|  | ||||
| ``` | ||||
| $ fx up --name hello ./examples/functions/JavaScript/func.js | ||||
|  | ||||
| +------------------------------------------------------------------+-----------+---------------+ | ||||
| |                                ID                                |   NAME    |   ENDPOINT    | | ||||
| +------------------------------------------------------------------+-----------+---------------+ | ||||
| | 5b24d36608ee392c937a61a530805f74551ddec304aea3aca2ffa0fabcf98cf3 | /hello    | 0.0.0.0:58328 | | ||||
| +------------------------------------------------------------------+-----------+---------------+ | ||||
| ``` | ||||
|  | ||||
| #### Remote host | ||||
|  | ||||
| Use `--host` to specify the target host for your function, or you can just set it to `FX_HOST` environment variable. | ||||
|  | ||||
| ```shell | ||||
| $ fx infra ls     # list machines | ||||
| $ fx up --host roo@<your host> --name hello ./examples/functions/JavaScript/func.js | ||||
|  | ||||
| { | ||||
| 	"localhost": { | ||||
| 		"Host": "localhost", | ||||
| 		"User": "", | ||||
| 		"Password": "", | ||||
| 		"Enabled": true, | ||||
| 		"Provisioned": false | ||||
| 	} | ||||
| } | ||||
|  | ||||
| $ fx infra activate localhost    # activate 'localhost' | ||||
|  | ||||
| 2019/08/10 13:21:20  info Provision:pull python Docker base iamge: ✓ | ||||
| 2019/08/10 13:21:21  info Provision:pull d Docker base image: ✓ | ||||
| 2019/08/10 13:21:23  info Provision:pull java Docker base image: ✓ | ||||
| 2019/08/10 13:21:28  info Provision:pull julia Docker base image: ✓ | ||||
| 2019/08/10 13:21:31  info Provision:pull node Docker base image: ✓ | ||||
| 2019/08/10 13:22:09  info Provision:pull go Docker base image: ✓ | ||||
| 2019/08/10 13:22:09  info provision machine localhost: ✓ | ||||
| 2019/08/10 13:22:09  info enble machine localhost: ✓ | ||||
| ``` | ||||
| It may take seconds since `fx` needs to download some basic resources | ||||
|  | ||||
| *Note* you can add a remote host as fx machine also, | ||||
| ``` | ||||
| $ fx infra add --name my_aws_vm --host 13.121.202.227 --user root --password yourpassword | ||||
|  | ||||
| $ fx infra list | ||||
| { | ||||
| 	"my_aws_vm": { | ||||
| 		"Host": "13.121.202.227", | ||||
| 		"User": "root", | ||||
| 		"Password": "yourpassword", | ||||
| 		"Enabled": false, | ||||
| 		"Provisioned": false | ||||
| 	}, | ||||
| 	"localhost": { | ||||
| 		"Host": "localhost", | ||||
| 		"User": "", | ||||
| 		"Password": "", | ||||
| 		"Enabled": true, | ||||
| 		"Provisioned": true | ||||
| 	} | ||||
| } | ||||
|  | ||||
| $ fx infra activate my_aws_vm | ||||
|  | ||||
| ``` | ||||
| then your function will be deployed onto remote host also. | ||||
|  | ||||
| 2. Write a function | ||||
|  | ||||
| You can check out [examples](https://github.com/metrue/fx/tree/master/examples/functions) for reference. Let's write a function as an example,  it calculates the sum of two numbers then returns: | ||||
|  | ||||
| ```js | ||||
| module.exports = (ctx) => { | ||||
|     ctx.body = 'hello world' | ||||
| } | ||||
| ``` | ||||
| Then save it to a file `func.js`. | ||||
|  | ||||
| 3. Deploy your function as a service | ||||
|  | ||||
| Give your service a port with `--port`, and name with `--name`, heath checking with `--healthcheck` if you want. | ||||
|  | ||||
| ```shell | ||||
| $ fx up -name fx_service_name -p 10001 --healthcheck func.js | ||||
|  | ||||
| 2019/08/10 13:26:37  info Pack Service: ✓ | ||||
| 2019/08/10 13:26:39  info Build Service: ✓ | ||||
| 2019/08/10 13:26:39  info Run Service: ✓ | ||||
| 2019/08/10 13:26:39  info Service (fx_service_name) is running on: 0.0.0.0:10001 | ||||
| 2019/08/10 13:26:39  info up function fx_service_name(func.js) to machine localhost: ✓ | ||||
| +------------------------------------------------------------------+-----------+---------------+ | ||||
| |                                ID                                |   NAME    |   ENDPOINT    | | ||||
| +------------------------------------------------------------------+-----------+---------------+ | ||||
| | 5b24d36608ee392c937a61a530805f74551ddec304aea3aca2ffa0fabcf98cf3 | /hello    | 0.0.0.0:58345 | | ||||
| +------------------------------------------------------------------+-----------+---------------+ | ||||
| ``` | ||||
|  | ||||
| if you want see what the source code of your service looks like, you can export it into a dirctory, | ||||
| #### Kubernetes | ||||
|  | ||||
| ```shell | ||||
| $ fx image export -o <path of dir> func.js | ||||
| 2019/09/25 19:31:19  info exported to <path of dir>: ✓ | ||||
| ``` | ||||
| $ FX_KUBECONF=~/.kube/config fx up examples/functions/JavaScript/func.js --name hello | ||||
|  | ||||
| +-------------------------------+------+----------------+ | ||||
| | ID                     | NAME        |    ENDPOINT    | | ||||
| +----+--------------------------+-----------------------+ | ||||
| |  5b24d36608ee392c937a  | hello-fx    | 10.0.242.75:80 | | ||||
| +------------------------+-------------+----------------+ | ||||
| ``` | ||||
|  | ||||
| 4. Test your service | ||||
| ### Test service | ||||
|  | ||||
| then you can test your service: | ||||
|  | ||||
| ```shell | ||||
| $ curl -v 0.0.0.0:10001 | ||||
| $ curl -v 0.0.0.0:58328 | ||||
|  | ||||
|  | ||||
| GET / HTTP/1.1 | ||||
| @@ -207,34 +158,7 @@ hello world | ||||
|  | ||||
| ``` | ||||
|  | ||||
| ## Docker | ||||
|  | ||||
|   TODO | ||||
|  | ||||
| ## Kubernetes | ||||
|  | ||||
| **fx** supports deploy function to be a service onto Kubernetes cluster infrasture, and we encourage you to do that other than on bare Docker environment, there are lots of advantage to run your function on Kubernetes like self-healing, load balancing, easy horizontal scaling, etc. It's pretty simple to deploy your function onto Kubernetes with **fx**, you just set KUBECONFIG in your enviroment. | ||||
|  | ||||
| ```shell | ||||
| KUBECONFIG=<Your KUBECONFIG> fx deploy -n fx-service-abc_js -p 12349 examples/functions/JavaScript/func.js   # function will be deploy to your Kubernetes cluster and expose a IP address of your loadbalencer | ||||
| ``` | ||||
|  | ||||
| or | ||||
|  | ||||
| ```shell | ||||
| $ export KUBECONFIG=<Your KUBECONFIG> | ||||
| $ fx deploy -n fx-service-abc_js -p 12349 examples/functions/JavaScript/func.js   # function will be deploy to your Kubernetes cluster and expose a IP address of your loadbalencer | ||||
| ``` | ||||
|  | ||||
| * Local Kubernetes Cluster | ||||
|  | ||||
| Docker for Mac and Docker for Windows already support Kubernetes with single node cluster, we can use it directly, and the default `KUBECONFIG` is `~/.kube/config`. | ||||
|  | ||||
| ```shell | ||||
| $ export KUBECONFIG=~/.kube/config  # then fx will take the config to deloy function | ||||
| ``` | ||||
|  | ||||
| if you have multiple Kubernetes clusters configured, you have to set context correctly. FYI [configure-access-multiple-clusters](https://kubernetes.io/docs/tasks/access-application-cluster/configure-access-multiple-clusters/) | ||||
| ## Use Public Cloud Kubernetes Service as infrastructure to run your functions | ||||
|  | ||||
| * Azure Kubernetes Service (AKS) | ||||
|  | ||||
| @@ -258,7 +182,7 @@ aks-nodepool1-31718369-0   Ready    agent   6m44s   v1.12.8 | ||||
| Since AKS's config will be merged into `~/.kube/config` and set to be current context after you run `az aks get-credentials` command, so you can just set KUBECONFIG to default config also, | ||||
|  | ||||
| ```shell | ||||
| $ export KUBECONFIG=~/.kube/config  # then fx will take the config to deloy function | ||||
| $ export FX_KUBECONF=~/.kube/config  # then fx will take the config to deloy function | ||||
| ``` | ||||
|  | ||||
| But we would suggest you run `kubectl config current-context` to check if the current context is what you want. | ||||
| @@ -266,31 +190,31 @@ But we would suggest you run `kubectl config current-context` to check if the cu | ||||
| * Amazon Elastic Kubernetes Service (EKS) | ||||
|   TODO | ||||
|  | ||||
| * Google Kubernetes Engine (GKET) | ||||
|   TODO | ||||
| * Google Kubernetes Engine (GKE) | ||||
|  | ||||
| ## Contribute | ||||
| First you should create a Kubernetes cluster in your GKE, then make sure your KUBECONFIG is ready in `~/.kube/config`, if not, you can run following commands, | ||||
|  | ||||
| fx uses [Project](https://github.com/metrue/fx/projects/4) to manage the development. | ||||
|  | ||||
| #### Prerequisites | ||||
|  | ||||
| Docker: make sure [Docker](https://docs.docker.com/engine/installation/) installed and running on your server. | ||||
|  | ||||
|  | ||||
| #### Build & Test | ||||
|  | ||||
| ``` | ||||
| $ git clone https://github.com/metrue/fx | ||||
| $ cd fx | ||||
| $ make build | ||||
| ``` shell | ||||
| $ gcloud auth login | ||||
| $ gcloud container clusters get-credentials <your cluster> --zone <zone> --project <project> | ||||
| ``` | ||||
|  | ||||
| Then you can build and test: | ||||
| Then make sure you current context is GKE cluster, you can check it with command, | ||||
|  | ||||
| ``` shell | ||||
| $ kubectl config current-context | ||||
| ``` | ||||
| $ make build | ||||
| $ ./build/fx -h | ||||
|  | ||||
| Then you can deploy your function onto GKE cluster with, | ||||
|  | ||||
| ```shell | ||||
| $ FX_KUBECONF=~/.kube/config fx up examples/functions/JavaScript/func.js --name hellojs | ||||
| ``` | ||||
|  | ||||
| * Setup your own Kubernetes cluster | ||||
|  | ||||
| ```shell | ||||
| fx infra create --type k3s --name fx-cluster-1 --master root@123.11.2.3 --agents 'root@1.1.1.1,root@2.2.2.2' | ||||
| ``` | ||||
|  | ||||
|  | ||||
|   | ||||
							
								
								
									
										7
									
								
								assets/dockerfiles/base/crystal/Dockerfile
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										7
									
								
								assets/dockerfiles/base/crystal/Dockerfile
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,7 @@ | ||||
| FROM crystallang/crystal:latest | ||||
|  | ||||
| WORKDIR /fx | ||||
|  | ||||
| COPY . /fx | ||||
|  | ||||
| RUN shards install | ||||
							
								
								
									
										18
									
								
								assets/dockerfiles/base/crystal/shard.lock
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										18
									
								
								assets/dockerfiles/base/crystal/shard.lock
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,18 @@ | ||||
| version: 2.0 | ||||
| shards: | ||||
|   exception_page: | ||||
|     git: https://github.com/crystal-loot/exception_page.git | ||||
|     version: 0.1.4 | ||||
|  | ||||
|   kemal: | ||||
|     git: https://github.com/kemalcr/kemal.git | ||||
|     version: 0.26.1 | ||||
|  | ||||
|   kilt: | ||||
|     git: https://github.com/jeromegn/kilt.git | ||||
|     version: 0.4.0 | ||||
|  | ||||
|   radix: | ||||
|     git: https://github.com/luislavena/radix.git | ||||
|     version: 0.3.9 | ||||
|  | ||||
							
								
								
									
										6
									
								
								assets/dockerfiles/base/crystal/shard.yml
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										6
									
								
								assets/dockerfiles/base/crystal/shard.yml
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,6 @@ | ||||
| name: fx-crystal-base | ||||
| version: 0.1.0 | ||||
| dependencies: | ||||
|   kemal: | ||||
|     github: kemalcr/kemal | ||||
|     commit: a819d4792bbc63d993d6dd2b15f9af5efb0c2d8c | ||||
							
								
								
									
										4
									
								
								assets/dockerfiles/base/go/Dockerfile
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										4
									
								
								assets/dockerfiles/base/go/Dockerfile
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,4 @@ | ||||
| FROM golang:1.15 | ||||
|  | ||||
| # dependency management | ||||
| RUN go get github.com/gin-gonic/gin | ||||
							
								
								
									
										2
									
								
								assets/dockerfiles/base/node/Dockerfile
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										2
									
								
								assets/dockerfiles/base/node/Dockerfile
									
									
									
									
										vendored
									
									
								
							| @@ -1,4 +1,4 @@ | ||||
| FROM node:latest | ||||
| FROM node:alpine | ||||
|  | ||||
| COPY . . | ||||
| RUN npm install | ||||
|   | ||||
							
								
								
									
										836
									
								
								assets/dockerfiles/base/node/package-lock.json
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										836
									
								
								assets/dockerfiles/base/node/package-lock.json
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,836 @@ | ||||
| { | ||||
|   "name": "fx-node-base", | ||||
|   "version": "1.0.0", | ||||
|   "lockfileVersion": 1, | ||||
|   "requires": true, | ||||
|   "dependencies": { | ||||
|     "@koa/cors": { | ||||
|       "version": "2.2.3", | ||||
|       "resolved": "https://registry.npmjs.org/@koa/cors/-/cors-2.2.3.tgz", | ||||
|       "integrity": "sha512-tCVVXa39ETsit5kGBtEWWimjLn1sDaeu8+0phgb8kT3GmBDZOykkI3ZO8nMjV2p3MGkJI4K5P+bxR8Ztq0bwsA==", | ||||
|       "requires": { | ||||
|         "vary": "^1.1.2" | ||||
|       } | ||||
|     }, | ||||
|     "accepts": { | ||||
|       "version": "1.3.7", | ||||
|       "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.7.tgz", | ||||
|       "integrity": "sha512-Il80Qs2WjYlJIBNzNkK6KYqlVMTbZLXgHx2oT0pU/fjRHyEp+PEfEPY0R3WCwAGVOtauxh1hOxNgIf5bv7dQpA==", | ||||
|       "requires": { | ||||
|         "mime-types": "~2.1.24", | ||||
|         "negotiator": "0.6.2" | ||||
|       } | ||||
|     }, | ||||
|     "ajv": { | ||||
|       "version": "6.12.2", | ||||
|       "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.2.tgz", | ||||
|       "integrity": "sha512-k+V+hzjm5q/Mr8ef/1Y9goCmlsK4I6Sm74teeyGvFk1XrOsbsKLjEdrvny42CZ+a8sXbk8KWpY/bDwS+FLL2UQ==", | ||||
|       "requires": { | ||||
|         "fast-deep-equal": "^3.1.1", | ||||
|         "fast-json-stable-stringify": "^2.0.0", | ||||
|         "json-schema-traverse": "^0.4.1", | ||||
|         "uri-js": "^4.2.2" | ||||
|       } | ||||
|     }, | ||||
|     "any-promise": { | ||||
|       "version": "1.3.0", | ||||
|       "resolved": "https://registry.npmjs.org/any-promise/-/any-promise-1.3.0.tgz", | ||||
|       "integrity": "sha1-q8av7tzqUugJzcA3au0845Y10X8=" | ||||
|     }, | ||||
|     "asn1": { | ||||
|       "version": "0.2.4", | ||||
|       "resolved": "https://registry.npmjs.org/asn1/-/asn1-0.2.4.tgz", | ||||
|       "integrity": "sha512-jxwzQpLQjSmWXgwaCZE9Nz+glAG01yF1QnWgbhGwHI5A6FRIEY6IVqtHhIepHqI7/kyEyQEagBC5mBEFlIYvdg==", | ||||
|       "requires": { | ||||
|         "safer-buffer": "~2.1.0" | ||||
|       } | ||||
|     }, | ||||
|     "assert-plus": { | ||||
|       "version": "1.0.0", | ||||
|       "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", | ||||
|       "integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=" | ||||
|     }, | ||||
|     "asynckit": { | ||||
|       "version": "0.4.0", | ||||
|       "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", | ||||
|       "integrity": "sha1-x57Zf380y48robyXkLzDZkdLS3k=" | ||||
|     }, | ||||
|     "aws-sign2": { | ||||
|       "version": "0.7.0", | ||||
|       "resolved": "https://registry.npmjs.org/aws-sign2/-/aws-sign2-0.7.0.tgz", | ||||
|       "integrity": "sha1-tG6JCTSpWR8tL2+G1+ap8bP+dqg=" | ||||
|     }, | ||||
|     "aws4": { | ||||
|       "version": "1.9.1", | ||||
|       "resolved": "https://registry.npmjs.org/aws4/-/aws4-1.9.1.tgz", | ||||
|       "integrity": "sha512-wMHVg2EOHaMRxbzgFJ9gtjOOCrI80OHLG14rxi28XwOW8ux6IiEbRCGGGqCtdAIg4FQCbW20k9RsT4y3gJlFug==" | ||||
|     }, | ||||
|     "basic-auth": { | ||||
|       "version": "2.0.1", | ||||
|       "resolved": "https://registry.npmjs.org/basic-auth/-/basic-auth-2.0.1.tgz", | ||||
|       "integrity": "sha512-NF+epuEdnUYVlGuhaxbbq+dvJttwLnGY+YixlXlME5KpQ5W3CnXA5cVTneY3SPbPDRkcjMbifrwmFYcClgOZeg==", | ||||
|       "requires": { | ||||
|         "safe-buffer": "5.1.2" | ||||
|       } | ||||
|     }, | ||||
|     "bcrypt-pbkdf": { | ||||
|       "version": "1.0.2", | ||||
|       "resolved": "https://registry.npmjs.org/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.2.tgz", | ||||
|       "integrity": "sha1-pDAdOJtqQ/m2f/PKEaP2Y342Dp4=", | ||||
|       "requires": { | ||||
|         "tweetnacl": "^0.14.3" | ||||
|       } | ||||
|     }, | ||||
|     "bintrees": { | ||||
|       "version": "1.0.1", | ||||
|       "resolved": "https://registry.npmjs.org/bintrees/-/bintrees-1.0.1.tgz", | ||||
|       "integrity": "sha1-DmVcm5wkNeqraL9AJyJtK1WjRSQ=" | ||||
|     }, | ||||
|     "bytes": { | ||||
|       "version": "3.1.0", | ||||
|       "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.0.tgz", | ||||
|       "integrity": "sha512-zauLjrfCG+xvoyaqLoV8bLVXXNGC4JqlxFCutSDWA6fJrTo2ZuvLYTqZ7aHBLZSMOopbzwv8f+wZcVzfVTI2Dg==" | ||||
|     }, | ||||
|     "cache-content-type": { | ||||
|       "version": "1.0.1", | ||||
|       "resolved": "https://registry.npmjs.org/cache-content-type/-/cache-content-type-1.0.1.tgz", | ||||
|       "integrity": "sha512-IKufZ1o4Ut42YUrZSo8+qnMTrFuKkvyoLXUywKz9GJ5BrhOFGhLdkx9sG4KAnVvbY6kEcSFjLQul+DVmBm2bgA==", | ||||
|       "requires": { | ||||
|         "mime-types": "^2.1.18", | ||||
|         "ylru": "^1.2.0" | ||||
|       } | ||||
|     }, | ||||
|     "caseless": { | ||||
|       "version": "0.12.0", | ||||
|       "resolved": "https://registry.npmjs.org/caseless/-/caseless-0.12.0.tgz", | ||||
|       "integrity": "sha1-G2gcIf+EAzyCZUMJBolCDRhxUdw=" | ||||
|     }, | ||||
|     "co": { | ||||
|       "version": "4.6.0", | ||||
|       "resolved": "https://registry.npmjs.org/co/-/co-4.6.0.tgz", | ||||
|       "integrity": "sha1-bqa989hTrlTMuOR7+gvz+QMfsYQ=" | ||||
|     }, | ||||
|     "co-body": { | ||||
|       "version": "6.0.0", | ||||
|       "resolved": "https://registry.npmjs.org/co-body/-/co-body-6.0.0.tgz", | ||||
|       "integrity": "sha512-9ZIcixguuuKIptnY8yemEOuhb71L/lLf+Rl5JfJEUiDNJk0e02MBt7BPxR2GEh5mw8dPthQYR4jPI/BnS1MQgw==", | ||||
|       "requires": { | ||||
|         "inflation": "^2.0.0", | ||||
|         "qs": "^6.5.2", | ||||
|         "raw-body": "^2.3.3", | ||||
|         "type-is": "^1.6.16" | ||||
|       } | ||||
|     }, | ||||
|     "combined-stream": { | ||||
|       "version": "1.0.8", | ||||
|       "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", | ||||
|       "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", | ||||
|       "requires": { | ||||
|         "delayed-stream": "~1.0.0" | ||||
|       } | ||||
|     }, | ||||
|     "content-disposition": { | ||||
|       "version": "0.5.3", | ||||
|       "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.3.tgz", | ||||
|       "integrity": "sha512-ExO0774ikEObIAEV9kDo50o+79VCUdEB6n6lzKgGwupcVeRlhrj3qGAfwq8G6uBJjkqLrhT0qEYFcWng8z1z0g==", | ||||
|       "requires": { | ||||
|         "safe-buffer": "5.1.2" | ||||
|       } | ||||
|     }, | ||||
|     "content-type": { | ||||
|       "version": "1.0.4", | ||||
|       "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.4.tgz", | ||||
|       "integrity": "sha512-hIP3EEPs8tB9AT1L+NUqtwOAps4mk2Zob89MWXMHjHWg9milF/j4osnnQLXBCBFBk/tvIG/tUc9mOUJiPBhPXA==" | ||||
|     }, | ||||
|     "cookies": { | ||||
|       "version": "0.8.0", | ||||
|       "resolved": "https://registry.npmjs.org/cookies/-/cookies-0.8.0.tgz", | ||||
|       "integrity": "sha512-8aPsApQfebXnuI+537McwYsDtjVxGm8gTIzQI3FDW6t5t/DAhERxtnbEPN/8RX+uZthoz4eCOgloXaE5cYyNow==", | ||||
|       "requires": { | ||||
|         "depd": "~2.0.0", | ||||
|         "keygrip": "~1.1.0" | ||||
|       } | ||||
|     }, | ||||
|     "copy-to": { | ||||
|       "version": "2.0.1", | ||||
|       "resolved": "https://registry.npmjs.org/copy-to/-/copy-to-2.0.1.tgz", | ||||
|       "integrity": "sha1-JoD7uAaKSNCGVrYJgJK9r8kG9KU=" | ||||
|     }, | ||||
|     "core-util-is": { | ||||
|       "version": "1.0.2", | ||||
|       "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", | ||||
|       "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=" | ||||
|     }, | ||||
|     "dashdash": { | ||||
|       "version": "1.14.1", | ||||
|       "resolved": "https://registry.npmjs.org/dashdash/-/dashdash-1.14.1.tgz", | ||||
|       "integrity": "sha1-hTz6D3y+L+1d4gMmuN1YEDX24vA=", | ||||
|       "requires": { | ||||
|         "assert-plus": "^1.0.0" | ||||
|       } | ||||
|     }, | ||||
|     "debug": { | ||||
|       "version": "4.1.1", | ||||
|       "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz", | ||||
|       "integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==", | ||||
|       "requires": { | ||||
|         "ms": "^2.1.1" | ||||
|       } | ||||
|     }, | ||||
|     "deep-equal": { | ||||
|       "version": "1.0.1", | ||||
|       "resolved": "https://registry.npmjs.org/deep-equal/-/deep-equal-1.0.1.tgz", | ||||
|       "integrity": "sha1-9dJgKStmDghO/0zbyfCK0yR0SLU=" | ||||
|     }, | ||||
|     "delayed-stream": { | ||||
|       "version": "1.0.0", | ||||
|       "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", | ||||
|       "integrity": "sha1-3zrhmayt+31ECqrgsp4icrJOxhk=" | ||||
|     }, | ||||
|     "delegates": { | ||||
|       "version": "1.0.0", | ||||
|       "resolved": "https://registry.npmjs.org/delegates/-/delegates-1.0.0.tgz", | ||||
|       "integrity": "sha1-hMbhWbgZBP3KWaDvRM2HDTElD5o=" | ||||
|     }, | ||||
|     "depd": { | ||||
|       "version": "2.0.0", | ||||
|       "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz", | ||||
|       "integrity": "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==" | ||||
|     }, | ||||
|     "destroy": { | ||||
|       "version": "1.0.4", | ||||
|       "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.0.4.tgz", | ||||
|       "integrity": "sha1-l4hXRCxEdJ5CBmE+N5RiBYJqvYA=" | ||||
|     }, | ||||
|     "ecc-jsbn": { | ||||
|       "version": "0.1.2", | ||||
|       "resolved": "https://registry.npmjs.org/ecc-jsbn/-/ecc-jsbn-0.1.2.tgz", | ||||
|       "integrity": "sha1-OoOpBOVDUyh4dMVkt1SThoSamMk=", | ||||
|       "requires": { | ||||
|         "jsbn": "~0.1.0", | ||||
|         "safer-buffer": "^2.1.0" | ||||
|       } | ||||
|     }, | ||||
|     "ee-first": { | ||||
|       "version": "1.1.1", | ||||
|       "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", | ||||
|       "integrity": "sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0=" | ||||
|     }, | ||||
|     "encodeurl": { | ||||
|       "version": "1.0.2", | ||||
|       "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz", | ||||
|       "integrity": "sha1-rT/0yG7C0CkyL1oCw6mmBslbP1k=" | ||||
|     }, | ||||
|     "escape-html": { | ||||
|       "version": "1.0.3", | ||||
|       "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", | ||||
|       "integrity": "sha1-Aljq5NPQwJdN4cFpGI7wBR0dGYg=" | ||||
|     }, | ||||
|     "etag": { | ||||
|       "version": "1.8.1", | ||||
|       "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz", | ||||
|       "integrity": "sha1-Qa4u62XvpiJorr/qg6x9eSmbCIc=" | ||||
|     }, | ||||
|     "express-to-koa": { | ||||
|       "version": "2.0.0", | ||||
|       "resolved": "https://registry.npmjs.org/express-to-koa/-/express-to-koa-2.0.0.tgz", | ||||
|       "integrity": "sha512-71zECby9NZHFGQ+kD+cJ5VaNUdCUw3oXkSC6PCmKxxfyVA11mVQCfwQqb7VjBmQbIJ2WNeiAeTOj7M5EqrMlOQ==" | ||||
|     }, | ||||
|     "extend": { | ||||
|       "version": "3.0.2", | ||||
|       "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz", | ||||
|       "integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==" | ||||
|     }, | ||||
|     "extsprintf": { | ||||
|       "version": "1.3.0", | ||||
|       "resolved": "https://registry.npmjs.org/extsprintf/-/extsprintf-1.3.0.tgz", | ||||
|       "integrity": "sha1-lpGEQOMEGnpBT4xS48V06zw+HgU=" | ||||
|     }, | ||||
|     "fast-deep-equal": { | ||||
|       "version": "3.1.1", | ||||
|       "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.1.tgz", | ||||
|       "integrity": "sha512-8UEa58QDLauDNfpbrX55Q9jrGHThw2ZMdOky5Gl1CDtVeJDPVrG4Jxx1N8jw2gkWaff5UUuX1KJd+9zGe2B+ZA==" | ||||
|     }, | ||||
|     "fast-json-stable-stringify": { | ||||
|       "version": "2.1.0", | ||||
|       "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", | ||||
|       "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==" | ||||
|     }, | ||||
|     "forever-agent": { | ||||
|       "version": "0.6.1", | ||||
|       "resolved": "https://registry.npmjs.org/forever-agent/-/forever-agent-0.6.1.tgz", | ||||
|       "integrity": "sha1-+8cfDEGt6zf5bFd60e1C2P2sypE=" | ||||
|     }, | ||||
|     "form-data": { | ||||
|       "version": "2.3.3", | ||||
|       "resolved": "https://registry.npmjs.org/form-data/-/form-data-2.3.3.tgz", | ||||
|       "integrity": "sha512-1lLKB2Mu3aGP1Q/2eCOx0fNbRMe7XdwktwOruhfqqd0rIJWwN4Dh+E3hrPSlDCXnSR7UtZ1N38rVXm+6+MEhJQ==", | ||||
|       "requires": { | ||||
|         "asynckit": "^0.4.0", | ||||
|         "combined-stream": "^1.0.6", | ||||
|         "mime-types": "^2.1.12" | ||||
|       } | ||||
|     }, | ||||
|     "fresh": { | ||||
|       "version": "0.5.2", | ||||
|       "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz", | ||||
|       "integrity": "sha1-PYyt2Q2XZWn6g1qx+OSyOhBWBac=" | ||||
|     }, | ||||
|     "get-port": { | ||||
|       "version": "3.2.0", | ||||
|       "resolved": "https://registry.npmjs.org/get-port/-/get-port-3.2.0.tgz", | ||||
|       "integrity": "sha1-3Xzn3hh8Bsi/NTeWrHHgmfCYDrw=" | ||||
|     }, | ||||
|     "getpass": { | ||||
|       "version": "0.1.7", | ||||
|       "resolved": "https://registry.npmjs.org/getpass/-/getpass-0.1.7.tgz", | ||||
|       "integrity": "sha1-Xv+OPmhNVprkyysSgmBOi6YhSfo=", | ||||
|       "requires": { | ||||
|         "assert-plus": "^1.0.0" | ||||
|       } | ||||
|     }, | ||||
|     "har-schema": { | ||||
|       "version": "2.0.0", | ||||
|       "resolved": "https://registry.npmjs.org/har-schema/-/har-schema-2.0.0.tgz", | ||||
|       "integrity": "sha1-qUwiJOvKwEeCoNkDVSHyRzW37JI=" | ||||
|     }, | ||||
|     "har-validator": { | ||||
|       "version": "5.1.3", | ||||
|       "resolved": "https://registry.npmjs.org/har-validator/-/har-validator-5.1.3.tgz", | ||||
|       "integrity": "sha512-sNvOCzEQNr/qrvJgc3UG/kD4QtlHycrzwS+6mfTrrSq97BvaYcPZZI1ZSqGSPR73Cxn4LKTD4PttRwfU7jWq5g==", | ||||
|       "requires": { | ||||
|         "ajv": "^6.5.5", | ||||
|         "har-schema": "^2.0.0" | ||||
|       } | ||||
|     }, | ||||
|     "http-assert": { | ||||
|       "version": "1.4.1", | ||||
|       "resolved": "https://registry.npmjs.org/http-assert/-/http-assert-1.4.1.tgz", | ||||
|       "integrity": "sha512-rdw7q6GTlibqVVbXr0CKelfV5iY8G2HqEUkhSk297BMbSpSL8crXC+9rjKoMcZZEsksX30le6f/4ul4E28gegw==", | ||||
|       "requires": { | ||||
|         "deep-equal": "~1.0.1", | ||||
|         "http-errors": "~1.7.2" | ||||
|       } | ||||
|     }, | ||||
|     "http-errors": { | ||||
|       "version": "1.7.3", | ||||
|       "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.7.3.tgz", | ||||
|       "integrity": "sha512-ZTTX0MWrsQ2ZAhA1cejAwDLycFsd7I7nVtnkT3Ol0aqodaKW+0CTZDQ1uBv5whptCnc8e8HeRRJxRs0kmm/Qfw==", | ||||
|       "requires": { | ||||
|         "depd": "~1.1.2", | ||||
|         "inherits": "2.0.4", | ||||
|         "setprototypeof": "1.1.1", | ||||
|         "statuses": ">= 1.5.0 < 2", | ||||
|         "toidentifier": "1.0.0" | ||||
|       }, | ||||
|       "dependencies": { | ||||
|         "depd": { | ||||
|           "version": "1.1.2", | ||||
|           "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz", | ||||
|           "integrity": "sha1-m81S4UwJd2PnSbJ0xDRu0uVgtak=" | ||||
|         } | ||||
|       } | ||||
|     }, | ||||
|     "http-signature": { | ||||
|       "version": "1.2.0", | ||||
|       "resolved": "https://registry.npmjs.org/http-signature/-/http-signature-1.2.0.tgz", | ||||
|       "integrity": "sha1-muzZJRFHcvPZW2WmCruPfBj7rOE=", | ||||
|       "requires": { | ||||
|         "assert-plus": "^1.0.0", | ||||
|         "jsprim": "^1.2.2", | ||||
|         "sshpk": "^1.7.0" | ||||
|       } | ||||
|     }, | ||||
|     "iconv-lite": { | ||||
|       "version": "0.4.24", | ||||
|       "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", | ||||
|       "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", | ||||
|       "requires": { | ||||
|         "safer-buffer": ">= 2.1.2 < 3" | ||||
|       } | ||||
|     }, | ||||
|     "inflation": { | ||||
|       "version": "2.0.0", | ||||
|       "resolved": "https://registry.npmjs.org/inflation/-/inflation-2.0.0.tgz", | ||||
|       "integrity": "sha1-i0F+R8KPklpFEz2RTKH9OJEH8w8=" | ||||
|     }, | ||||
|     "inherits": { | ||||
|       "version": "2.0.4", | ||||
|       "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", | ||||
|       "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" | ||||
|     }, | ||||
|     "is-generator-function": { | ||||
|       "version": "1.0.7", | ||||
|       "resolved": "https://registry.npmjs.org/is-generator-function/-/is-generator-function-1.0.7.tgz", | ||||
|       "integrity": "sha512-YZc5EwyO4f2kWCax7oegfuSr9mFz1ZvieNYBEjmukLxgXfBUbxAWGVF7GZf0zidYtoBl3WvC07YK0wT76a+Rtw==" | ||||
|     }, | ||||
|     "is-typedarray": { | ||||
|       "version": "1.0.0", | ||||
|       "resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz", | ||||
|       "integrity": "sha1-5HnICFjfDBsR3dppQPlgEfzaSpo=" | ||||
|     }, | ||||
|     "isstream": { | ||||
|       "version": "0.1.2", | ||||
|       "resolved": "https://registry.npmjs.org/isstream/-/isstream-0.1.2.tgz", | ||||
|       "integrity": "sha1-R+Y/evVa+m+S4VAOaQ64uFKcCZo=" | ||||
|     }, | ||||
|     "jsbn": { | ||||
|       "version": "0.1.1", | ||||
|       "resolved": "https://registry.npmjs.org/jsbn/-/jsbn-0.1.1.tgz", | ||||
|       "integrity": "sha1-peZUwuWi3rXyAdls77yoDA7y9RM=" | ||||
|     }, | ||||
|     "json-schema": { | ||||
|       "version": "0.2.3", | ||||
|       "resolved": "https://registry.npmjs.org/json-schema/-/json-schema-0.2.3.tgz", | ||||
|       "integrity": "sha1-tIDIkuWaLwWVTOcnvT8qTogvnhM=" | ||||
|     }, | ||||
|     "json-schema-traverse": { | ||||
|       "version": "0.4.1", | ||||
|       "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", | ||||
|       "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==" | ||||
|     }, | ||||
|     "json-stringify-safe": { | ||||
|       "version": "5.0.1", | ||||
|       "resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz", | ||||
|       "integrity": "sha1-Epai1Y/UXxmg9s4B1lcB4sc1tus=" | ||||
|     }, | ||||
|     "jsprim": { | ||||
|       "version": "1.4.1", | ||||
|       "resolved": "https://registry.npmjs.org/jsprim/-/jsprim-1.4.1.tgz", | ||||
|       "integrity": "sha1-MT5mvB5cwG5Di8G3SZwuXFastqI=", | ||||
|       "requires": { | ||||
|         "assert-plus": "1.0.0", | ||||
|         "extsprintf": "1.3.0", | ||||
|         "json-schema": "0.2.3", | ||||
|         "verror": "1.10.0" | ||||
|       } | ||||
|     }, | ||||
|     "keygrip": { | ||||
|       "version": "1.1.0", | ||||
|       "resolved": "https://registry.npmjs.org/keygrip/-/keygrip-1.1.0.tgz", | ||||
|       "integrity": "sha512-iYSchDJ+liQ8iwbSI2QqsQOvqv58eJCEanyJPJi+Khyu8smkcKSFUCbPwzFcL7YVtZ6eONjqRX/38caJ7QjRAQ==", | ||||
|       "requires": { | ||||
|         "tsscmp": "1.0.6" | ||||
|       } | ||||
|     }, | ||||
|     "koa": { | ||||
|       "version": "2.13.0", | ||||
|       "resolved": "https://registry.npmjs.org/koa/-/koa-2.13.0.tgz", | ||||
|       "integrity": "sha512-i/XJVOfPw7npbMv67+bOeXr3gPqOAw6uh5wFyNs3QvJ47tUx3M3V9rIE0//WytY42MKz4l/MXKyGkQ2LQTfLUQ==", | ||||
|       "requires": { | ||||
|         "accepts": "^1.3.5", | ||||
|         "cache-content-type": "^1.0.0", | ||||
|         "content-disposition": "~0.5.2", | ||||
|         "content-type": "^1.0.4", | ||||
|         "cookies": "~0.8.0", | ||||
|         "debug": "~3.1.0", | ||||
|         "delegates": "^1.0.0", | ||||
|         "depd": "^1.1.2", | ||||
|         "destroy": "^1.0.4", | ||||
|         "encodeurl": "^1.0.2", | ||||
|         "escape-html": "^1.0.3", | ||||
|         "fresh": "~0.5.2", | ||||
|         "http-assert": "^1.3.0", | ||||
|         "http-errors": "^1.6.3", | ||||
|         "is-generator-function": "^1.0.7", | ||||
|         "koa-compose": "^4.1.0", | ||||
|         "koa-convert": "^1.2.0", | ||||
|         "on-finished": "^2.3.0", | ||||
|         "only": "~0.0.2", | ||||
|         "parseurl": "^1.3.2", | ||||
|         "statuses": "^1.5.0", | ||||
|         "type-is": "^1.6.16", | ||||
|         "vary": "^1.1.2" | ||||
|       }, | ||||
|       "dependencies": { | ||||
|         "debug": { | ||||
|           "version": "3.1.0", | ||||
|           "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", | ||||
|           "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==", | ||||
|           "requires": { | ||||
|             "ms": "2.0.0" | ||||
|           } | ||||
|         }, | ||||
|         "depd": { | ||||
|           "version": "1.1.2", | ||||
|           "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz", | ||||
|           "integrity": "sha1-m81S4UwJd2PnSbJ0xDRu0uVgtak=" | ||||
|         }, | ||||
|         "ms": { | ||||
|           "version": "2.0.0", | ||||
|           "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", | ||||
|           "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=" | ||||
|         } | ||||
|       } | ||||
|     }, | ||||
|     "koa-bodyparser": { | ||||
|       "version": "4.3.0", | ||||
|       "resolved": "https://registry.npmjs.org/koa-bodyparser/-/koa-bodyparser-4.3.0.tgz", | ||||
|       "integrity": "sha512-uyV8G29KAGwZc4q/0WUAjH+Tsmuv9ImfBUF2oZVyZtaeo0husInagyn/JH85xMSxM0hEk/mbCII5ubLDuqW/Rw==", | ||||
|       "requires": { | ||||
|         "co-body": "^6.0.0", | ||||
|         "copy-to": "^2.0.1" | ||||
|       } | ||||
|     }, | ||||
|     "koa-compose": { | ||||
|       "version": "4.1.0", | ||||
|       "resolved": "https://registry.npmjs.org/koa-compose/-/koa-compose-4.1.0.tgz", | ||||
|       "integrity": "sha512-8ODW8TrDuMYvXRwra/Kh7/rJo9BtOfPc6qO8eAfC80CnCvSjSl0bkRM24X6/XBBEyj0v1nRUQ1LyOy3dbqOWXw==" | ||||
|     }, | ||||
|     "koa-convert": { | ||||
|       "version": "1.2.0", | ||||
|       "resolved": "https://registry.npmjs.org/koa-convert/-/koa-convert-1.2.0.tgz", | ||||
|       "integrity": "sha1-2kCHXfSd4FOQmNFwC1CCDOvNIdA=", | ||||
|       "requires": { | ||||
|         "co": "^4.6.0", | ||||
|         "koa-compose": "^3.0.0" | ||||
|       }, | ||||
|       "dependencies": { | ||||
|         "koa-compose": { | ||||
|           "version": "3.2.1", | ||||
|           "resolved": "https://registry.npmjs.org/koa-compose/-/koa-compose-3.2.1.tgz", | ||||
|           "integrity": "sha1-qFzLQLfZhtjlo0Wzoazo6rz1Tec=", | ||||
|           "requires": { | ||||
|             "any-promise": "^1.1.0" | ||||
|           } | ||||
|         } | ||||
|       } | ||||
|     }, | ||||
|     "media-typer": { | ||||
|       "version": "0.3.0", | ||||
|       "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", | ||||
|       "integrity": "sha1-hxDXrwqmJvj/+hzgAWhUUmMlV0g=" | ||||
|     }, | ||||
|     "mime": { | ||||
|       "version": "1.6.0", | ||||
|       "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz", | ||||
|       "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==" | ||||
|     }, | ||||
|     "mime-db": { | ||||
|       "version": "1.44.0", | ||||
|       "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.44.0.tgz", | ||||
|       "integrity": "sha512-/NOTfLrsPBVeH7YtFPgsVWveuL+4SjjYxaQ1xtM1KMFj7HdxlBlxeyNLzhyJVx7r4rZGJAZ/6lkKCitSc/Nmpg==" | ||||
|     }, | ||||
|     "mime-types": { | ||||
|       "version": "2.1.27", | ||||
|       "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.27.tgz", | ||||
|       "integrity": "sha512-JIhqnCasI9yD+SsmkquHBxTSEuZdQX5BuQnS2Vc7puQQQ+8yiP5AY5uWhpdv4YL4VM5c6iliiYWPgJ/nJQLp7w==", | ||||
|       "requires": { | ||||
|         "mime-db": "1.44.0" | ||||
|       } | ||||
|     }, | ||||
|     "moment": { | ||||
|       "version": "2.26.0", | ||||
|       "resolved": "https://registry.npmjs.org/moment/-/moment-2.26.0.tgz", | ||||
|       "integrity": "sha512-oIixUO+OamkUkwjhAVE18rAMfRJNsNe/Stid/gwHSOfHrOtw9EhAY2AHvdKZ/k/MggcYELFCJz/Sn2pL8b8JMw==" | ||||
|     }, | ||||
|     "ms": { | ||||
|       "version": "2.1.2", | ||||
|       "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", | ||||
|       "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" | ||||
|     }, | ||||
|     "negotiator": { | ||||
|       "version": "0.6.2", | ||||
|       "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.2.tgz", | ||||
|       "integrity": "sha512-hZXc7K2e+PgeI1eDBe/10Ard4ekbfrrqG8Ep+8Jmf4JID2bNg7NvCPOZN+kfF574pFQI7mum2AUqDidoKqcTOw==" | ||||
|     }, | ||||
|     "node-fetch": { | ||||
|       "version": "2.6.1", | ||||
|       "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.1.tgz", | ||||
|       "integrity": "sha512-V4aYg89jEoVRxRb2fJdAg8FHvI7cEyYdVAh94HH0UIK8oJxUfkjlDQN9RbMx+bEjP7+ggMiFRprSti032Oipxw==" | ||||
|     }, | ||||
|     "oauth-sign": { | ||||
|       "version": "0.9.0", | ||||
|       "resolved": "https://registry.npmjs.org/oauth-sign/-/oauth-sign-0.9.0.tgz", | ||||
|       "integrity": "sha512-fexhUFFPTGV8ybAtSIGbV6gOkSv8UtRbDBnAyLQw4QPKkgNlsH2ByPGtMUqdWkos6YCRmAqViwgZrJc/mRDzZQ==" | ||||
|     }, | ||||
|     "on-finished": { | ||||
|       "version": "2.3.0", | ||||
|       "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.3.0.tgz", | ||||
|       "integrity": "sha1-IPEzZIGwg811M3mSoWlxqi2QaUc=", | ||||
|       "requires": { | ||||
|         "ee-first": "1.1.1" | ||||
|       } | ||||
|     }, | ||||
|     "only": { | ||||
|       "version": "0.0.2", | ||||
|       "resolved": "https://registry.npmjs.org/only/-/only-0.0.2.tgz", | ||||
|       "integrity": "sha1-Kv3oTQPlC5qO3EROMGEKcCle37Q=" | ||||
|     }, | ||||
|     "parseurl": { | ||||
|       "version": "1.3.3", | ||||
|       "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz", | ||||
|       "integrity": "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==" | ||||
|     }, | ||||
|     "path-to-regexp": { | ||||
|       "version": "6.1.0", | ||||
|       "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-6.1.0.tgz", | ||||
|       "integrity": "sha512-h9DqehX3zZZDCEm+xbfU0ZmwCGFCAAraPJWMXJ4+v32NjZJilVg3k1TcKsRgIb8IQ/izZSaydDc1OhJCZvs2Dw==" | ||||
|     }, | ||||
|     "performance-now": { | ||||
|       "version": "2.1.0", | ||||
|       "resolved": "https://registry.npmjs.org/performance-now/-/performance-now-2.1.0.tgz", | ||||
|       "integrity": "sha1-Ywn04OX6kT7BxpMHrjZLSzd8nns=" | ||||
|     }, | ||||
|     "prom-client": { | ||||
|       "version": "11.5.3", | ||||
|       "resolved": "https://registry.npmjs.org/prom-client/-/prom-client-11.5.3.tgz", | ||||
|       "integrity": "sha512-iz22FmTbtkyL2vt0MdDFY+kWof+S9UB/NACxSn2aJcewtw+EERsen0urSkZ2WrHseNdydsvcxCTAnPcSMZZv4Q==", | ||||
|       "requires": { | ||||
|         "tdigest": "^0.1.1" | ||||
|       } | ||||
|     }, | ||||
|     "psl": { | ||||
|       "version": "1.8.0", | ||||
|       "resolved": "https://registry.npmjs.org/psl/-/psl-1.8.0.tgz", | ||||
|       "integrity": "sha512-RIdOzyoavK+hA18OGGWDqUTsCLhtA7IcZ/6NCs4fFJaHBDab+pDDmDIByWFRQJq2Cd7r1OoQxBGKOaztq+hjIQ==" | ||||
|     }, | ||||
|     "punycode": { | ||||
|       "version": "2.1.1", | ||||
|       "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz", | ||||
|       "integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==" | ||||
|     }, | ||||
|     "qs": { | ||||
|       "version": "6.9.4", | ||||
|       "resolved": "https://registry.npmjs.org/qs/-/qs-6.9.4.tgz", | ||||
|       "integrity": "sha512-A1kFqHekCTM7cz0udomYUoYNWjBebHm/5wzU/XqrBRBNWectVH0QIiN+NEcZ0Dte5hvzHwbr8+XQmguPhJ6WdQ==" | ||||
|     }, | ||||
|     "range-parser": { | ||||
|       "version": "1.2.1", | ||||
|       "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz", | ||||
|       "integrity": "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==" | ||||
|     }, | ||||
|     "raw-body": { | ||||
|       "version": "2.4.1", | ||||
|       "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.4.1.tgz", | ||||
|       "integrity": "sha512-9WmIKF6mkvA0SLmA2Knm9+qj89e+j1zqgyn8aXGd7+nAduPoqgI9lO57SAZNn/Byzo5P7JhXTyg9PzaJbH73bA==", | ||||
|       "requires": { | ||||
|         "bytes": "3.1.0", | ||||
|         "http-errors": "1.7.3", | ||||
|         "iconv-lite": "0.4.24", | ||||
|         "unpipe": "1.0.0" | ||||
|       } | ||||
|     }, | ||||
|     "request": { | ||||
|       "version": "2.88.2", | ||||
|       "resolved": "https://registry.npmjs.org/request/-/request-2.88.2.tgz", | ||||
|       "integrity": "sha512-MsvtOrfG9ZcrOwAW+Qi+F6HbD0CWXEh9ou77uOb7FM2WPhwT7smM833PzanhJLsgXjN89Ir6V2PczXNnMpwKhw==", | ||||
|       "requires": { | ||||
|         "aws-sign2": "~0.7.0", | ||||
|         "aws4": "^1.8.0", | ||||
|         "caseless": "~0.12.0", | ||||
|         "combined-stream": "~1.0.6", | ||||
|         "extend": "~3.0.2", | ||||
|         "forever-agent": "~0.6.1", | ||||
|         "form-data": "~2.3.2", | ||||
|         "har-validator": "~5.1.3", | ||||
|         "http-signature": "~1.2.0", | ||||
|         "is-typedarray": "~1.0.0", | ||||
|         "isstream": "~0.1.2", | ||||
|         "json-stringify-safe": "~5.0.1", | ||||
|         "mime-types": "~2.1.19", | ||||
|         "oauth-sign": "~0.9.0", | ||||
|         "performance-now": "^2.1.0", | ||||
|         "qs": "~6.5.2", | ||||
|         "safe-buffer": "^5.1.2", | ||||
|         "tough-cookie": "~2.5.0", | ||||
|         "tunnel-agent": "^0.6.0", | ||||
|         "uuid": "^3.3.2" | ||||
|       }, | ||||
|       "dependencies": { | ||||
|         "qs": { | ||||
|           "version": "6.5.2", | ||||
|           "resolved": "https://registry.npmjs.org/qs/-/qs-6.5.2.tgz", | ||||
|           "integrity": "sha512-N5ZAX4/LxJmF+7wN74pUD6qAh9/wnvdQcjq9TZjevvXzSUo7bfmw91saqMjzGS2xq91/odN2dW/WOl7qQHNDGA==" | ||||
|         } | ||||
|       } | ||||
|     }, | ||||
|     "safe-buffer": { | ||||
|       "version": "5.1.2", | ||||
|       "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", | ||||
|       "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" | ||||
|     }, | ||||
|     "safer-buffer": { | ||||
|       "version": "2.1.2", | ||||
|       "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", | ||||
|       "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==" | ||||
|     }, | ||||
|     "send": { | ||||
|       "version": "0.17.1", | ||||
|       "resolved": "https://registry.npmjs.org/send/-/send-0.17.1.tgz", | ||||
|       "integrity": "sha512-BsVKsiGcQMFwT8UxypobUKyv7irCNRHk1T0G680vk88yf6LBByGcZJOTJCrTP2xVN6yI+XjPJcNuE3V4fT9sAg==", | ||||
|       "requires": { | ||||
|         "debug": "2.6.9", | ||||
|         "depd": "~1.1.2", | ||||
|         "destroy": "~1.0.4", | ||||
|         "encodeurl": "~1.0.2", | ||||
|         "escape-html": "~1.0.3", | ||||
|         "etag": "~1.8.1", | ||||
|         "fresh": "0.5.2", | ||||
|         "http-errors": "~1.7.2", | ||||
|         "mime": "1.6.0", | ||||
|         "ms": "2.1.1", | ||||
|         "on-finished": "~2.3.0", | ||||
|         "range-parser": "~1.2.1", | ||||
|         "statuses": "~1.5.0" | ||||
|       }, | ||||
|       "dependencies": { | ||||
|         "debug": { | ||||
|           "version": "2.6.9", | ||||
|           "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", | ||||
|           "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", | ||||
|           "requires": { | ||||
|             "ms": "2.0.0" | ||||
|           }, | ||||
|           "dependencies": { | ||||
|             "ms": { | ||||
|               "version": "2.0.0", | ||||
|               "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", | ||||
|               "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=" | ||||
|             } | ||||
|           } | ||||
|         }, | ||||
|         "depd": { | ||||
|           "version": "1.1.2", | ||||
|           "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz", | ||||
|           "integrity": "sha1-m81S4UwJd2PnSbJ0xDRu0uVgtak=" | ||||
|         }, | ||||
|         "ms": { | ||||
|           "version": "2.1.1", | ||||
|           "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.1.tgz", | ||||
|           "integrity": "sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg==" | ||||
|         } | ||||
|       } | ||||
|     }, | ||||
|     "setprototypeof": { | ||||
|       "version": "1.1.1", | ||||
|       "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.1.1.tgz", | ||||
|       "integrity": "sha512-JvdAWfbXeIGaZ9cILp38HntZSFSo3mWg6xGcJJsd+d4aRMOqauag1C63dJfDw7OaMYwEbHMOxEZ1lqVRYP2OAw==" | ||||
|     }, | ||||
|     "sshpk": { | ||||
|       "version": "1.16.1", | ||||
|       "resolved": "https://registry.npmjs.org/sshpk/-/sshpk-1.16.1.tgz", | ||||
|       "integrity": "sha512-HXXqVUq7+pcKeLqqZj6mHFUMvXtOJt1uoUx09pFW6011inTMxqI8BA8PM95myrIyyKwdnzjdFjLiE6KBPVtJIg==", | ||||
|       "requires": { | ||||
|         "asn1": "~0.2.3", | ||||
|         "assert-plus": "^1.0.0", | ||||
|         "bcrypt-pbkdf": "^1.0.0", | ||||
|         "dashdash": "^1.12.0", | ||||
|         "ecc-jsbn": "~0.1.1", | ||||
|         "getpass": "^0.1.1", | ||||
|         "jsbn": "~0.1.0", | ||||
|         "safer-buffer": "^2.0.2", | ||||
|         "tweetnacl": "~0.14.0" | ||||
|       } | ||||
|     }, | ||||
|     "statuses": { | ||||
|       "version": "1.5.0", | ||||
|       "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.5.0.tgz", | ||||
|       "integrity": "sha1-Fhx9rBd2Wf2YEfQ3cfqZOBR4Yow=" | ||||
|     }, | ||||
|     "swagger-stats": { | ||||
|       "version": "0.95.17", | ||||
|       "resolved": "https://registry.npmjs.org/swagger-stats/-/swagger-stats-0.95.17.tgz", | ||||
|       "integrity": "sha512-3p+sWzWpxWES5SAM6GeKa6jWrMvh5gmczKdscdmOl4e6n9e4gfz0HioBZQqRgdLKgRR2ZeSR4f7+e3mMjqcEhQ==", | ||||
|       "requires": { | ||||
|         "basic-auth": "^2.0.1", | ||||
|         "cookies": "^0.8.0", | ||||
|         "debug": "^4.1.1", | ||||
|         "moment": "^2.24.0", | ||||
|         "path-to-regexp": "^6.1.0", | ||||
|         "prom-client": "^11.5.3", | ||||
|         "qs": "^6.9.1", | ||||
|         "request": "^2.88.0", | ||||
|         "send": "^0.17.1", | ||||
|         "uuid": "^3.4.0" | ||||
|       } | ||||
|     }, | ||||
|     "tdigest": { | ||||
|       "version": "0.1.1", | ||||
|       "resolved": "https://registry.npmjs.org/tdigest/-/tdigest-0.1.1.tgz", | ||||
|       "integrity": "sha1-Ljyyw56kSeVdHmzZEReszKRYgCE=", | ||||
|       "requires": { | ||||
|         "bintrees": "1.0.1" | ||||
|       } | ||||
|     }, | ||||
|     "toidentifier": { | ||||
|       "version": "1.0.0", | ||||
|       "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.0.tgz", | ||||
|       "integrity": "sha512-yaOH/Pk/VEhBWWTlhI+qXxDFXlejDGcQipMlyxda9nthulaxLZUNcUqFxokp0vcYnvteJln5FNQDRrxj3YcbVw==" | ||||
|     }, | ||||
|     "tough-cookie": { | ||||
|       "version": "2.5.0", | ||||
|       "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.5.0.tgz", | ||||
|       "integrity": "sha512-nlLsUzgm1kfLXSXfRZMc1KLAugd4hqJHDTvc2hDIwS3mZAfMEuMbc03SujMF+GEcpaX/qboeycw6iO8JwVv2+g==", | ||||
|       "requires": { | ||||
|         "psl": "^1.1.28", | ||||
|         "punycode": "^2.1.1" | ||||
|       } | ||||
|     }, | ||||
|     "tsscmp": { | ||||
|       "version": "1.0.6", | ||||
|       "resolved": "https://registry.npmjs.org/tsscmp/-/tsscmp-1.0.6.tgz", | ||||
|       "integrity": "sha512-LxhtAkPDTkVCMQjt2h6eBVY28KCjikZqZfMcC15YBeNjkgUpdCfBu5HoiOTDu86v6smE8yOjyEktJ8hlbANHQA==" | ||||
|     }, | ||||
|     "tunnel-agent": { | ||||
|       "version": "0.6.0", | ||||
|       "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz", | ||||
|       "integrity": "sha1-J6XeoGs2sEoKmWZ3SykIaPD8QP0=", | ||||
|       "requires": { | ||||
|         "safe-buffer": "^5.0.1" | ||||
|       } | ||||
|     }, | ||||
|     "tweetnacl": { | ||||
|       "version": "0.14.5", | ||||
|       "resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-0.14.5.tgz", | ||||
|       "integrity": "sha1-WuaBd/GS1EViadEIr6k/+HQ/T2Q=" | ||||
|     }, | ||||
|     "type-is": { | ||||
|       "version": "1.6.18", | ||||
|       "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.18.tgz", | ||||
|       "integrity": "sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==", | ||||
|       "requires": { | ||||
|         "media-typer": "0.3.0", | ||||
|         "mime-types": "~2.1.24" | ||||
|       } | ||||
|     }, | ||||
|     "unpipe": { | ||||
|       "version": "1.0.0", | ||||
|       "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", | ||||
|       "integrity": "sha1-sr9O6FFKrmFltIF4KdIbLvSZBOw=" | ||||
|     }, | ||||
|     "uri-js": { | ||||
|       "version": "4.2.2", | ||||
|       "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.2.2.tgz", | ||||
|       "integrity": "sha512-KY9Frmirql91X2Qgjry0Wd4Y+YTdrdZheS8TFwvkbLWf/G5KNJDCh6pKL5OZctEW4+0Baa5idK2ZQuELRwPznQ==", | ||||
|       "requires": { | ||||
|         "punycode": "^2.1.0" | ||||
|       } | ||||
|     }, | ||||
|     "uuid": { | ||||
|       "version": "3.4.0", | ||||
|       "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.4.0.tgz", | ||||
|       "integrity": "sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A==" | ||||
|     }, | ||||
|     "vary": { | ||||
|       "version": "1.1.2", | ||||
|       "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", | ||||
|       "integrity": "sha1-IpnwLG3tMNSllhsLn3RSShj2NPw=" | ||||
|     }, | ||||
|     "verror": { | ||||
|       "version": "1.10.0", | ||||
|       "resolved": "https://registry.npmjs.org/verror/-/verror-1.10.0.tgz", | ||||
|       "integrity": "sha1-OhBcoXBTr1XW4nDB+CiGguGNpAA=", | ||||
|       "requires": { | ||||
|         "assert-plus": "^1.0.0", | ||||
|         "core-util-is": "1.0.2", | ||||
|         "extsprintf": "^1.2.0" | ||||
|       } | ||||
|     }, | ||||
|     "ylru": { | ||||
|       "version": "1.2.1", | ||||
|       "resolved": "https://registry.npmjs.org/ylru/-/ylru-1.2.1.tgz", | ||||
|       "integrity": "sha512-faQrqNMzcPCHGVC2aaOINk13K+aaBDUPjGWl0teOXywElLjyVAB6Oe2jj62jHYtwsU49jXhScYbvPENK+6zAvQ==" | ||||
|     } | ||||
|   } | ||||
| } | ||||
							
								
								
									
										11
									
								
								assets/dockerfiles/base/node/package.json
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										11
									
								
								assets/dockerfiles/base/node/package.json
									
									
									
									
										vendored
									
									
								
							| @@ -1,5 +1,5 @@ | ||||
| { | ||||
|   "name": "aok", | ||||
|   "name": "fx-node-base", | ||||
|   "version": "1.0.0", | ||||
|   "description": "", | ||||
|   "main": "index.js", | ||||
| @@ -10,12 +10,13 @@ | ||||
|   "author": "", | ||||
|   "license": "ISC", | ||||
|   "dependencies": { | ||||
|     "@koa/cors": "^2.2.3", | ||||
|     "express-to-koa": "^2.0.0", | ||||
|     "get-port": "^3.2.0", | ||||
|     "is-generator-function": "^1.0.6", | ||||
|     "koa": "^2.3.0", | ||||
|     "koa-bodyparser": "^4.2.0" | ||||
|   }, | ||||
|   "devDependencies": { | ||||
|     "get-port-cli": "^1.1.0" | ||||
|     "koa-bodyparser": "^4.2.0", | ||||
|     "node-fetch": "^2.6.1", | ||||
|     "swagger-stats": "^0.95.17" | ||||
|   } | ||||
| } | ||||
|   | ||||
							
								
								
									
										10
									
								
								assets/dockerfiles/base/perl/Dockerfile
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										10
									
								
								assets/dockerfiles/base/perl/Dockerfile
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,10 @@ | ||||
| FROM alpine:3.4 | ||||
| MAINTAINER Mojolicious | ||||
|  | ||||
| ADD . . | ||||
| COPY cpanfile / | ||||
| ENV EV_EXTRA_DEFS -DEV_NO_ATFORK | ||||
|  | ||||
| RUN apk update && \ | ||||
|   apk add perl perl-io-socket-ssl perl-dbd-pg perl-dev g++ make wget curl && \ | ||||
|   curl -L https://cpanmin.us | perl - App::cpanminus && cpanm --installdeps . -M https://cpan.metacpan.org | ||||
							
								
								
									
										3
									
								
								assets/dockerfiles/base/perl/cpanfile
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										3
									
								
								assets/dockerfiles/base/perl/cpanfile
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,3 @@ | ||||
| requires "EV"; | ||||
| requires "JSON"; | ||||
| requires "Mojolicious::Lite"; | ||||
							
								
								
									
										1
									
								
								assets/dockerfiles/base/php/Dockerfile
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										1
									
								
								assets/dockerfiles/base/php/Dockerfile
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1 @@ | ||||
| FROM php:latest | ||||
							
								
								
									
										3
									
								
								assets/dockerfiles/base/ruby/Dockerfile
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										3
									
								
								assets/dockerfiles/base/ruby/Dockerfile
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,3 @@ | ||||
| FROM ruby:latest | ||||
|  | ||||
| RUN gem install sinatra | ||||
							
								
								
									
										986
									
								
								assets/dockerfiles/base/rust/Cargo.lock
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										986
									
								
								assets/dockerfiles/base/rust/Cargo.lock
									
									
									
										generated
									
									
										vendored
									
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
							
								
								
									
										4
									
								
								assets/dockerfiles/base/rust/Cargo.toml
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										4
									
								
								assets/dockerfiles/base/rust/Cargo.toml
									
									
									
									
										vendored
									
									
								
							| @@ -5,8 +5,8 @@ authors = ["FrontMage <xbgxwh@outlook.com>"] | ||||
| edition = "2018" | ||||
|  | ||||
| [dependencies] | ||||
| rocket = "0.4.0-rc.2" | ||||
| rocket_contrib = "0.4.0-rc.2" | ||||
| rocket = "0.4.5" | ||||
| rocket_contrib = "0.4.5" | ||||
| serde_json = "1.0" | ||||
| serde_derive = "1.0.70" | ||||
| serde = "1.0.70" | ||||
|   | ||||
							
								
								
									
										15
									
								
								assets/dockerfiles/base/rust/Dockerfile
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										15
									
								
								assets/dockerfiles/base/rust/Dockerfile
									
									
									
									
										vendored
									
									
								
							| @@ -1,7 +1,12 @@ | ||||
| FROM liuchong/rustup | ||||
|  | ||||
| WORKDIR /usr/src/myapp | ||||
| FROM clux/muslrust:nightly AS builder | ||||
| WORKDIR /build | ||||
| COPY . . | ||||
| RUN cp ./config ~/.cargo/ && rustup default nightly && cargo build | ||||
| RUN ln -s /usr/bin/g++ /usr/bin/musl-g++ && cargo build --release | ||||
|  | ||||
| FROM scratch | ||||
| WORKDIR /usr/src/myapp | ||||
| COPY --from=builder /build/target/x86_64-unknown-linux-musl/release/rust /usr/src/myapp/ | ||||
| COPY ./Rocket.toml /usr/src/myapp/ | ||||
| EXPOSE 3000 | ||||
| CMD ["cargo", "run"] | ||||
| ENV ROCKET_ENV=prod | ||||
| CMD ["/usr/src/myapp/rust"] | ||||
|   | ||||
							
								
								
									
										18
									
								
								assets/dockerfiles/base/rust/Rocket.toml
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										18
									
								
								assets/dockerfiles/base/rust/Rocket.toml
									
									
									
									
										vendored
									
									
								
							| @@ -1,5 +1,23 @@ | ||||
| [development] | ||||
| address = "localhost" | ||||
| port = 3000 | ||||
| workers = 8 | ||||
| keep_alive = 5 | ||||
| log = "normal" | ||||
| limits = { forms = 32768 } | ||||
|  | ||||
| [staging] | ||||
| address = "0.0.0.0" | ||||
| port = 3000 | ||||
| workers = 8 | ||||
| keep_alive = 5 | ||||
| log = "normal" | ||||
| limits = { forms = 32768 } | ||||
|  | ||||
| [production] | ||||
| address = "0.0.0.0" | ||||
| port = 3000 | ||||
| workers = 8 | ||||
| keep_alive = 5 | ||||
| log = "critical" | ||||
| limits = { forms = 32768 } | ||||
|   | ||||
							
								
								
									
										2
									
								
								assets/dockerfiles/base/rust/src/fns/mod.rs
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										2
									
								
								assets/dockerfiles/base/rust/src/fns/mod.rs
									
									
									
									
										vendored
									
									
								
							| @@ -4,7 +4,7 @@ pub mod fns { | ||||
|         pub result: i32, | ||||
|     } | ||||
|  | ||||
|     #[derive(Deserialize)] | ||||
|     #[derive(Deserialize, FromForm)] | ||||
|     pub struct Request { | ||||
|         pub a: i32, | ||||
|         pub b: i32, | ||||
|   | ||||
							
								
								
									
										10
									
								
								assets/dockerfiles/base/rust/src/main.rs
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										10
									
								
								assets/dockerfiles/base/rust/src/main.rs
									
									
									
									
										vendored
									
									
								
							| @@ -10,13 +10,19 @@ extern crate serde_json; | ||||
|  | ||||
| mod fns; | ||||
|  | ||||
| use rocket::request::Form; | ||||
| use rocket_contrib::json::Json; | ||||
|  | ||||
| #[get("/?<req..>")] | ||||
| fn get(req: Form<fns::fns::Request>) -> Json<fns::fns::Response> { | ||||
|     Json(fns::fns::func(req.0)) | ||||
| } | ||||
|  | ||||
| #[post("/", format = "application/json", data = "<req>")] | ||||
| fn index(req: Json<fns::fns::Request>) -> Json<fns::fns::Response> { | ||||
| fn post(req: Json<fns::fns::Request>) -> Json<fns::fns::Response> { | ||||
|     Json(fns::fns::func(req.0)) | ||||
| } | ||||
|  | ||||
| fn main() { | ||||
|     rocket::ignite().mount("/", routes![index]).launch(); | ||||
|     rocket::ignite().mount("/", routes![get, post]).launch(); | ||||
| } | ||||
|   | ||||
							
								
								
									
										50
									
								
								bundle/bundle.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										50
									
								
								bundle/bundle.go
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,50 @@ | ||||
| package bundle | ||||
|  | ||||
| import ( | ||||
| 	"fmt" | ||||
|  | ||||
| 	"github.com/metrue/fx/bundler" | ||||
| 	"github.com/metrue/fx/bundler/crystal" | ||||
| 	"github.com/metrue/fx/bundler/d" | ||||
| 	golang "github.com/metrue/fx/bundler/go" | ||||
| 	"github.com/metrue/fx/bundler/java" | ||||
| 	"github.com/metrue/fx/bundler/julia" | ||||
| 	"github.com/metrue/fx/bundler/node" | ||||
| 	"github.com/metrue/fx/bundler/perl" | ||||
| 	"github.com/metrue/fx/bundler/php" | ||||
| 	"github.com/metrue/fx/bundler/python" | ||||
| 	"github.com/metrue/fx/bundler/ruby" | ||||
| 	"github.com/metrue/fx/bundler/rust" | ||||
| ) | ||||
|  | ||||
| // Bundle function to project | ||||
| func Bundle(workdir string, language string, fn string, deps ...string) error { | ||||
| 	var bundler bundler.Bundler | ||||
| 	switch language { | ||||
| 	case "d": | ||||
| 		bundler = d.New() | ||||
| 	case "node": | ||||
| 		bundler = node.New() | ||||
| 	case "go": | ||||
| 		bundler = golang.New() | ||||
| 	case "java": | ||||
| 		bundler = java.New() | ||||
| 	case "julia": | ||||
| 		bundler = julia.New() | ||||
| 	case "perl": | ||||
| 		bundler = perl.New() | ||||
| 	case "python": | ||||
| 		bundler = python.New() | ||||
| 	case "ruby": | ||||
| 		bundler = ruby.New() | ||||
| 	case "rust": | ||||
| 		bundler = rust.New() | ||||
| 	case "crystal": | ||||
| 		bundler = crystal.New() | ||||
| 	case "php": | ||||
| 		bundler = php.New() | ||||
| 	default: | ||||
| 		return fmt.Errorf("%s not suppported yet", language) | ||||
| 	} | ||||
| 	return bundler.Bundle(workdir, fn, deps...) | ||||
| } | ||||
							
								
								
									
										117
									
								
								bundle/bundler_test.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										117
									
								
								bundle/bundler_test.go
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,117 @@ | ||||
| package bundle | ||||
|  | ||||
| import ( | ||||
| 	"io/ioutil" | ||||
| 	"os" | ||||
| 	"testing" | ||||
| ) | ||||
|  | ||||
| func createFn(content string, t *testing.T) string { | ||||
| 	fd, err := ioutil.TempFile("", "fx_func_*.js") | ||||
| 	if err != nil { | ||||
| 		t.Fatal(err) | ||||
| 	} | ||||
| 	err = ioutil.WriteFile(fd.Name(), []byte(content), 0666) | ||||
| 	if err != nil { | ||||
| 		t.Fatal(err) | ||||
| 	} | ||||
|  | ||||
| 	return fd.Name() | ||||
| } | ||||
|  | ||||
| func TestBundle(t *testing.T) { | ||||
| 	workdir, err := ioutil.TempDir("", "fx-test") | ||||
| 	if err != nil { | ||||
| 		t.Fatal(err) | ||||
| 	} | ||||
| 	defer os.RemoveAll(workdir) | ||||
|  | ||||
| 	cases := []struct { | ||||
| 		workdir  string | ||||
| 		language string | ||||
| 		fn       string | ||||
| 		deps     []string | ||||
| 	}{ | ||||
| 		{ | ||||
| 			workdir:  workdir, | ||||
| 			language: "d", | ||||
| 			fn: ` | ||||
| module.exports = (ctx) => { | ||||
|   ctx.body = 'hello fx' | ||||
| } | ||||
| 			`, | ||||
| 		}, | ||||
| 		{ | ||||
| 			workdir:  workdir, | ||||
| 			language: "go", | ||||
| 			fn: ` | ||||
| module.exports = (ctx) => { | ||||
|   ctx.body = 'hello fx' | ||||
| } | ||||
| 			`, | ||||
| 		}, | ||||
| 		{ | ||||
| 			workdir:  workdir, | ||||
| 			language: "java", | ||||
| 			fn: ` | ||||
| module.exports = (ctx) => { | ||||
|   ctx.body = 'hello fx' | ||||
| } | ||||
| 			`, | ||||
| 		}, | ||||
| 		{ | ||||
| 			workdir:  workdir, | ||||
| 			language: "julia", | ||||
| 			fn: ` | ||||
| module.exports = (ctx) => { | ||||
|   ctx.body = 'hello fx' | ||||
| } | ||||
| 			`, | ||||
| 		}, | ||||
| 		{ | ||||
| 			workdir:  workdir, | ||||
| 			language: "perl", | ||||
| 			fn: ` | ||||
| module.exports = (ctx) => { | ||||
|   ctx.body = 'hello fx' | ||||
| } | ||||
| 			`, | ||||
| 		}, | ||||
| 		{ | ||||
| 			workdir:  workdir, | ||||
| 			language: "python", | ||||
| 			fn: ` | ||||
| module.exports = (ctx) => { | ||||
|   ctx.body = 'hello fx' | ||||
| } | ||||
| 			`, | ||||
| 		}, | ||||
| 		{ | ||||
| 			workdir:  workdir, | ||||
| 			language: "ruby", | ||||
| 			fn: ` | ||||
| module.exports = (ctx) => { | ||||
|   ctx.body = 'hello fx' | ||||
| } | ||||
| 			`, | ||||
| 		}, | ||||
| 		{ | ||||
| 			workdir:  workdir, | ||||
| 			language: "rust", | ||||
| 			fn: ` | ||||
| module.exports = (ctx) => { | ||||
|   ctx.body = 'hello fx' | ||||
| } | ||||
| 			`, | ||||
| 		}, | ||||
| 	} | ||||
|  | ||||
| 	for _, c := range cases { | ||||
| 		fn := createFn(c.fn, t) | ||||
| 		defer os.Remove(fn) | ||||
|  | ||||
| 		if err := Bundle(c.workdir, c.language, fn, c.deps...); err != nil { | ||||
| 			t.Fatal(err) | ||||
| 		} | ||||
| 	} | ||||
| } | ||||
							
								
								
									
										63
									
								
								bundler/README.md
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										63
									
								
								bundler/README.md
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,63 @@ | ||||
| The only thing `fx` does is to make a single function to be an HTTP service, `fx` takes two steps to finish the process, | ||||
| * Wraps the function into a web server project and make it be the handler function of the HTTP request. | ||||
| * Builds the bundled web server to be Docker image, then run it as a Docker container and expose the service port. | ||||
|  | ||||
| `bundler` is the component responsible for step 1: wrap a single function (and its dependencies) into a web server.  Take a Node web service as an example, the project looks like this, | ||||
| ``` | ||||
| helloworld | ||||
| ├── Dockerfile | ||||
| ├── app.js | ||||
| └── fx.js | ||||
| ``` | ||||
|  | ||||
| And the codes is pretty simple, | ||||
|  | ||||
| **app.js** | ||||
| ```javascript | ||||
| const Koa = require('koa'); | ||||
| const bodyParser = require('koa-bodyparser'); | ||||
| const cors = require('@koa/cors'); | ||||
| const fx = require('./fx'); | ||||
|  | ||||
| const app = new Koa(); | ||||
| app.use(cors({ | ||||
|   origin: '*', | ||||
| })); | ||||
| app.use(bodyParser()); | ||||
| app.use(fx); | ||||
|  | ||||
| app.listen(3000); | ||||
| ``` | ||||
|  | ||||
| **fx.js** | ||||
| ```javascript | ||||
| module.exports = (ctx) => { | ||||
|   ctx.body = 'hello world' | ||||
| } | ||||
| ``` | ||||
|  | ||||
| **Dockerfile** | ||||
| ```dockerfile | ||||
| FROM metrue/fx-node-base | ||||
|  | ||||
| COPY . . | ||||
| EXPOSE 3000 | ||||
| CMD ["node", "app.js"] | ||||
| ``` | ||||
|  | ||||
| You can see that it's a web service built with `Koa`,  the request handler function defined in `fx.js` to response plain text `hello world`,  so to make a general JavaScript/Node function to be a web service, we only have to put it into `fx.js` above, then build and run it with Docker and that's it. | ||||
|  | ||||
| To support different programming languages, `fx` needs to implement different `bundlers`, the reasons are, | ||||
| * The way to set up a web service is different in different languages | ||||
| * The way to manage dependency is different in different languages. | ||||
|  | ||||
| So there will be (are) different `bundlers` in `fx`. | ||||
| ``` | ||||
| go-bundler: based on Gin | ||||
| ruby-bundler: based on Sinatra | ||||
| node-bundler: based on Koa | ||||
| python-bundler: based on flask | ||||
| ... | ||||
| ``` | ||||
|  | ||||
|  | ||||
							
								
								
									
										88
									
								
								bundler/bundler.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										88
									
								
								bundler/bundler.go
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,88 @@ | ||||
| package bundler | ||||
|  | ||||
| import ( | ||||
| 	"io/ioutil" | ||||
| 	"os" | ||||
| 	"path/filepath" | ||||
| 	"strings" | ||||
|  | ||||
| 	"github.com/gobuffalo/packd" | ||||
| 	"github.com/gobuffalo/packr/v2" | ||||
| 	"github.com/metrue/fx/constants" | ||||
| 	"github.com/metrue/fx/utils" | ||||
| ) | ||||
|  | ||||
| // Bundler defines interface | ||||
| type Bundler interface { | ||||
| 	Scaffold(output string) error | ||||
| 	Bundle(output string, fn string, deps ...string) error | ||||
| } | ||||
|  | ||||
| // IsHandler check if it's handle file | ||||
| func IsHandler(name string, lang string) bool { | ||||
| 	basename := filepath.Base(name) | ||||
| 	nameWithoutExt := strings.TrimSuffix(basename, filepath.Ext(basename)) | ||||
| 	if constants.ExtLangMapping[filepath.Ext(basename)] != lang { | ||||
| 		return false | ||||
| 	} | ||||
|  | ||||
| 	return (nameWithoutExt == "fx" || | ||||
| 		// Fx is for Java | ||||
| 		nameWithoutExt == "Fx" || | ||||
| 		// mod.rs is for Rust) | ||||
| 		nameWithoutExt == "mod") | ||||
| } | ||||
|  | ||||
| // Restore directory from packr box | ||||
| func Restore(box *packr.Box, output string) error { | ||||
| 	if err := box.Walk(func(name string, fd packd.File) error { | ||||
| 		content, err := box.Find(name) | ||||
| 		if err != nil { | ||||
| 			return err | ||||
| 		} | ||||
|  | ||||
| 		dest := filepath.Join(output, name) | ||||
| 		if err := utils.EnsureFile(dest); err != nil { | ||||
| 			return err | ||||
| 		} | ||||
|  | ||||
| 		if err := ioutil.WriteFile(dest, content, 0600); err != nil { | ||||
| 			return err | ||||
| 		} | ||||
|  | ||||
| 		return nil | ||||
| 	}); err != nil { | ||||
| 		return err | ||||
| 	} | ||||
| 	return nil | ||||
| } | ||||
|  | ||||
| // Bundle bundle a function | ||||
| func Bundle(box *packr.Box, output string, language string, fn string, deps ...string) error { | ||||
| 	if err := Restore(box, output); err != nil { | ||||
| 		return err | ||||
| 	} | ||||
|  | ||||
| 	if err := utils.Merge(output, deps...); err != nil { | ||||
| 		return err | ||||
| 	} | ||||
|  | ||||
| 	// Replace the default handler source file with given function source file | ||||
| 	if err := filepath.Walk(output, func(path string, info os.FileInfo, err error) error { | ||||
| 		if err != nil { | ||||
| 			return err | ||||
| 		} | ||||
|  | ||||
| 		if IsHandler(path, language) { | ||||
| 			if err := utils.CopyFile(fn, path); err != nil { | ||||
| 				return err | ||||
| 			} | ||||
| 		} | ||||
|  | ||||
| 		return nil | ||||
| 	}); err != nil { | ||||
| 		return err | ||||
| 	} | ||||
|  | ||||
| 	return nil | ||||
| } | ||||
							
								
								
									
										51
									
								
								bundler/bundler_test.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										51
									
								
								bundler/bundler_test.go
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,51 @@ | ||||
| package bundler | ||||
|  | ||||
| import ( | ||||
| 	"io/ioutil" | ||||
| 	"log" | ||||
| 	"os" | ||||
| 	"testing" | ||||
|  | ||||
| 	"github.com/gobuffalo/packr/v2" | ||||
| ) | ||||
|  | ||||
| func TestBundler(t *testing.T) { | ||||
| 	t.Run("Restore", func(t *testing.T) { | ||||
| 		box := packr.New("", "./node/assets") | ||||
| 		outputDir, err := ioutil.TempDir("", "fx_koa") | ||||
| 		if err != nil { | ||||
| 			t.Fatal(err) | ||||
| 		} | ||||
| 		defer os.RemoveAll(outputDir) | ||||
| 		if err := Restore(box, outputDir); err != nil { | ||||
| 			t.Fatal(err) | ||||
| 		} | ||||
| 	}) | ||||
|  | ||||
| 	t.Run("Bundle", func(t *testing.T) { | ||||
| 		fd, err := ioutil.TempFile("", "fx_func_*.js") | ||||
| 		if err != nil { | ||||
| 			t.Fatal(err) | ||||
| 		} | ||||
| 		defer os.Remove(fd.Name()) | ||||
|  | ||||
| 		content := ` | ||||
| module.exports = (ctx) => { | ||||
|   ctx.body = 'hello fx' | ||||
| }` | ||||
| 		if err = ioutil.WriteFile(fd.Name(), []byte(content), 0666); err != nil { | ||||
| 			t.Fatal(err) | ||||
| 		} | ||||
|  | ||||
| 		outputDir, err := ioutil.TempDir("", "fx_koa") | ||||
| 		if err != nil { | ||||
| 			log.Fatal(err) | ||||
| 		} | ||||
| 		defer os.RemoveAll(outputDir) | ||||
|  | ||||
| 		box := packr.New("", "./node/assets") | ||||
| 		if err := Bundle(box, outputDir, "node", fd.Name()); err != nil { | ||||
| 			t.Fatal(err) | ||||
| 		} | ||||
| 	}) | ||||
| } | ||||
							
								
								
									
										13
									
								
								bundler/crystal/a_crystal-packr.go.tmpl
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										13
									
								
								bundler/crystal/a_crystal-packr.go.tmpl
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,13 @@ | ||||
| // Code generated by github.com/gobuffalo/packr. DO NOT EDIT. | ||||
|  | ||||
| package crystal | ||||
|  | ||||
| import "github.com/gobuffalo/packr" | ||||
|  | ||||
| // You can use the "packr clean" command to clean up this, | ||||
| // and any other packr generated files. | ||||
| func init() { | ||||
| 	_ = packr.PackJSONBytes("crystal", "Dockerfile", "\"RlJPTSBtZXRydWUvZngtY3J5c3RhbC1iYXNlCgpFWFBPU0UgMzAwMAoKQ09QWSAuIC4KClJVTiBjcnlzdGFsIGJ1aWxkIC0tdmVyYm9zZSAgLW8gLi9meGNyIC4vKi5jcgoKQ01EIFsiLi9meGNyIl0K\"") | ||||
| 	_ = packr.PackJSONBytes("crystal", "app.cr", "\"cmVxdWlyZSAia2VtYWwiCnJlcXVpcmUgImd6aXAiCnJlcXVpcmUgImpzb24iCnJlcXVpcmUgIi4vZngiCgpwb3N0ICIvIiBkbyB8Y3R4fAogICAgZnggY3R4CmVuZAoKZ2V0ICIvIiBkbyB8Y3R4fAogICAgZnggY3R4CmVuZAoKS2VtYWwucnVuCg==\"") | ||||
| 	_ = packr.PackJSONBytes("crystal", "fx.cr", "\"ZGVmIGZ4KGN0eCkKICAiaGVsbG8gd29ybGQiCmVuZAo=\"") | ||||
| } | ||||
							
								
								
									
										9
									
								
								bundler/crystal/assets/Dockerfile
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										9
									
								
								bundler/crystal/assets/Dockerfile
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,9 @@ | ||||
| FROM metrue/fx-crystal-base | ||||
|  | ||||
| EXPOSE 3000 | ||||
|  | ||||
| COPY . . | ||||
|  | ||||
| RUN crystal build --verbose  -o ./fxcr ./*.cr | ||||
|  | ||||
| CMD ["./fxcr"] | ||||
							
								
								
									
										14
									
								
								bundler/crystal/assets/app.cr
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										14
									
								
								bundler/crystal/assets/app.cr
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,14 @@ | ||||
| require "kemal" | ||||
| require "gzip" | ||||
| require "json" | ||||
| require "./fx" | ||||
|  | ||||
| post "/" do |ctx| | ||||
|     fx ctx | ||||
| end | ||||
|  | ||||
| get "/" do |ctx| | ||||
|     fx ctx | ||||
| end | ||||
|  | ||||
| Kemal.run | ||||
							
								
								
									
										3
									
								
								bundler/crystal/assets/fx.cr
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										3
									
								
								bundler/crystal/assets/fx.cr
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,3 @@ | ||||
| def fx(ctx) | ||||
|   "hello world" | ||||
| end | ||||
							
								
								
									
										8
									
								
								bundler/crystal/crystal-packr.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										8
									
								
								bundler/crystal/crystal-packr.go
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,8 @@ | ||||
| // +build !skippackr | ||||
| // Code generated by github.com/gobuffalo/packr/v2. DO NOT EDIT. | ||||
|  | ||||
| // You can use the "packr clean" command to clean up this, | ||||
| // and any other packr generated files. | ||||
| package crystal | ||||
|  | ||||
| import _ "github.com/metrue/fx/packrd" | ||||
							
								
								
									
										32
									
								
								bundler/crystal/crystal.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										32
									
								
								bundler/crystal/crystal.go
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,32 @@ | ||||
| package crystal | ||||
|  | ||||
| import ( | ||||
| 	"github.com/gobuffalo/packr/v2" | ||||
| 	"github.com/metrue/fx/bundler" | ||||
| ) | ||||
|  | ||||
| // Crystal defines crystal bundler | ||||
| type Crystal struct { | ||||
| 	assets *packr.Box | ||||
| } | ||||
|  | ||||
| // New a crystal bundler | ||||
| func New() *Crystal { | ||||
| 	return &Crystal{ | ||||
| 		assets: packr.New("crystal", "./assets"), | ||||
| 	} | ||||
| } | ||||
|  | ||||
| // Scaffold a crystal/kemal app | ||||
| func (k *Crystal) Scaffold(output string) error { | ||||
| 	return bundler.Restore(k.assets, output) | ||||
| } | ||||
|  | ||||
| // Bundle a function into a kemal project | ||||
| func (k *Crystal) Bundle(output string, fn string, deps ...string) error { | ||||
| 	return bundler.Bundle(k.assets, output, "crystal", fn, deps...) | ||||
| } | ||||
|  | ||||
| var ( | ||||
| 	_ bundler.Bundler = &Crystal{} | ||||
| ) | ||||
							
								
								
									
										143
									
								
								bundler/crystal/crystal_test.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										143
									
								
								bundler/crystal/crystal_test.go
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,143 @@ | ||||
| package crystal | ||||
|  | ||||
| import ( | ||||
| 	"io/ioutil" | ||||
| 	"log" | ||||
| 	"os" | ||||
| 	"reflect" | ||||
| 	"testing" | ||||
|  | ||||
| 	"github.com/metrue/fx/utils" | ||||
| ) | ||||
|  | ||||
| func TestCrystalBundler(t *testing.T) { | ||||
| 	t.Run("Scaffold", func(t *testing.T) { | ||||
| 		outputDir, err := ioutil.TempDir("", "fx_crystal") | ||||
| 		if err != nil { | ||||
| 			log.Fatal(err) | ||||
| 		} | ||||
| 		defer os.RemoveAll(outputDir) | ||||
|  | ||||
| 		crystal := New() | ||||
| 		if err := crystal.Scaffold(outputDir); err != nil { | ||||
| 			t.Fatal(err) | ||||
| 		} | ||||
|  | ||||
| 		diff, _, _, err := utils.Diff(outputDir, "./assets") | ||||
| 		if err != nil { | ||||
| 			t.Fatal(err) | ||||
| 		} | ||||
|  | ||||
| 		if diff { | ||||
| 			t.Fatalf("%s is not equal with %s", outputDir, "./assets") | ||||
| 		} | ||||
| 	}) | ||||
|  | ||||
| 	t.Run("BundleSingleFunc", func(t *testing.T) { | ||||
| 		fd, err := ioutil.TempFile("", "fx_func_*.crystal") | ||||
| 		if err != nil { | ||||
| 			t.Fatal(err) | ||||
| 		} | ||||
| 		defer os.Remove(fd.Name()) | ||||
|  | ||||
| 		content := `def fx(ctx) | ||||
| 	"hello world" | ||||
| end` | ||||
| 		err = ioutil.WriteFile(fd.Name(), []byte(content), 0666) | ||||
| 		if err != nil { | ||||
| 			t.Fatal(err) | ||||
| 		} | ||||
|  | ||||
| 		outputDir, err := ioutil.TempDir("", "fx_crystal") | ||||
| 		if err != nil { | ||||
| 			log.Fatal(err) | ||||
| 		} | ||||
| 		defer os.RemoveAll(outputDir) | ||||
|  | ||||
| 		crystal := New() | ||||
| 		if err := crystal.Bundle(outputDir, fd.Name()); err != nil { | ||||
| 			t.Fatal(err) | ||||
| 		} | ||||
|  | ||||
| 		diff, pre, cur, err := utils.Diff("./assets", outputDir) | ||||
| 		if err != nil { | ||||
| 			t.Fatal(err) | ||||
| 		} | ||||
|  | ||||
| 		if !diff { | ||||
| 			t.Fatalf("handle function should be changed") | ||||
| 		} | ||||
|  | ||||
| 		if !reflect.DeepEqual(cur, []byte(content)) { | ||||
| 			t.Fatalf("it should be %s but got %s", content, cur) | ||||
| 		} | ||||
|  | ||||
| 		preHandleFunc, err := ioutil.ReadFile("./assets/fx.cr") | ||||
| 		if err != nil { | ||||
| 			t.Fatal(err) | ||||
| 		} | ||||
| 		if !reflect.DeepEqual(pre, preHandleFunc) { | ||||
| 			{ | ||||
| 			} | ||||
| 			t.Fatalf("it should get %s but got %s", preHandleFunc, pre) | ||||
| 		} | ||||
| 	}) | ||||
|  | ||||
| 	t.Run("BundleFuncAndDeps", func(t *testing.T) { | ||||
| 		fd, err := ioutil.TempFile("", "fx_func_*.cr") | ||||
| 		if err != nil { | ||||
| 			t.Fatal(err) | ||||
| 		} | ||||
| 		defer os.Remove(fd.Name()) | ||||
|  | ||||
| 		content, err := ioutil.ReadFile("./assets/fx.cr") | ||||
| 		if err != nil { | ||||
| 			t.Fatal(err) | ||||
| 		} | ||||
| 		err = ioutil.WriteFile(fd.Name(), content, 0666) | ||||
| 		if err != nil { | ||||
| 			t.Fatal(err) | ||||
| 		} | ||||
|  | ||||
| 		addFunc := `def fx(a, b) | ||||
| 	a + b | ||||
| end | ||||
| ` | ||||
| 		addFd, err := ioutil.TempFile("", "fx_add_func_*.cr") | ||||
| 		if err != nil { | ||||
| 			t.Fatal(err) | ||||
| 		} | ||||
|  | ||||
| 		err = ioutil.WriteFile(addFd.Name(), []byte(addFunc), 0644) | ||||
| 		if err != nil { | ||||
| 			t.Fatal(err) | ||||
| 		} | ||||
|  | ||||
| 		outputDir, err := ioutil.TempDir("", "fx_crystal") | ||||
| 		if err != nil { | ||||
| 			log.Fatal(err) | ||||
| 		} | ||||
| 		defer os.RemoveAll(outputDir) | ||||
|  | ||||
| 		crystal := New() | ||||
| 		if err := crystal.Bundle(outputDir, fd.Name(), addFd.Name()); err != nil { | ||||
| 			t.Fatal(err) | ||||
| 		} | ||||
|  | ||||
| 		diff, pre, cur, err := utils.Diff("./assets", outputDir) | ||||
| 		if err != nil { | ||||
| 			t.Fatal(err) | ||||
| 		} | ||||
|  | ||||
| 		if !diff { | ||||
| 			t.Fatalf("handle function should be changed") | ||||
| 		} | ||||
|  | ||||
| 		if !reflect.DeepEqual(cur, []byte(addFunc)) { | ||||
| 			t.Fatalf("it should be %s but got %s", content, cur) | ||||
| 		} | ||||
| 		if pre != nil { | ||||
| 			t.Fatal(pre) | ||||
| 		} | ||||
| 	}) | ||||
| } | ||||
							
								
								
									
										14
									
								
								bundler/d/a_d-packr.go.tmpl
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										14
									
								
								bundler/d/a_d-packr.go.tmpl
									
									
									
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because one or more lines are too long
											
										
									
								
							
							
								
								
									
										8
									
								
								bundler/d/d-packr.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										8
									
								
								bundler/d/d-packr.go
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,8 @@ | ||||
| // +build !skippackr | ||||
| // Code generated by github.com/gobuffalo/packr/v2. DO NOT EDIT. | ||||
|  | ||||
| // You can use the "packr clean" command to clean up this, | ||||
| // and any other packr generated files. | ||||
| package d | ||||
|  | ||||
| import _ "github.com/metrue/fx/packrd" | ||||
							
								
								
									
										32
									
								
								bundler/d/d.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										32
									
								
								bundler/d/d.go
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,32 @@ | ||||
| package d | ||||
|  | ||||
| import ( | ||||
| 	"github.com/gobuffalo/packr/v2" | ||||
| 	"github.com/metrue/fx/bundler" | ||||
| ) | ||||
|  | ||||
| // D defines d bundler | ||||
| type D struct { | ||||
| 	assets *packr.Box | ||||
| } | ||||
|  | ||||
| // New a koa bundler | ||||
| func New() *D { | ||||
| 	return &D{ | ||||
| 		assets: packr.New("d", "./assets"), | ||||
| 	} | ||||
| } | ||||
|  | ||||
| // Scaffold a koa app | ||||
| func (d *D) Scaffold(output string) error { | ||||
| 	return bundler.Restore(d.assets, output) | ||||
| } | ||||
|  | ||||
| // Bundle a function into a koa project | ||||
| func (d *D) Bundle(output string, fn string, deps ...string) error { | ||||
| 	return bundler.Bundle(d.assets, output, "d", fn, deps...) | ||||
| } | ||||
|  | ||||
| var ( | ||||
| 	_ bundler.Bundler = &D{} | ||||
| ) | ||||
							
								
								
									
										13
									
								
								bundler/go/a_golang-packr.go.tmpl
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										13
									
								
								bundler/go/a_golang-packr.go.tmpl
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,13 @@ | ||||
| // Code generated by github.com/gobuffalo/packr. DO NOT EDIT. | ||||
|  | ||||
| package golang | ||||
|  | ||||
| import "github.com/gobuffalo/packr" | ||||
|  | ||||
| // You can use the "packr clean" command to clean up this, | ||||
| // and any other packr generated files. | ||||
| func init() { | ||||
| 	_ = packr.PackJSONBytes("go", "Dockerfile", "\"RlJPTSBtZXRydWUvZngtZ28tYmFzZQoKQ09QWSAuIC9nby9zcmMvZ2l0aHViLmNvbS9tZXRydWUvZngKV09SS0RJUiAvZ28vc3JjL2dpdGh1Yi5jb20vbWV0cnVlL2Z4CgpSVU4gZ28gYnVpbGQgLWxkZmxhZ3MgIi13IC1zIiAtbyBmeCBmeC5nbyBhcHAuZ28KCkVYUE9TRSAzMDAwCgpDTUQgWyIuL2Z4Il0K\"") | ||||
| 	_ = packr.PackJSONBytes("go", "app.go", "\"cGFja2FnZSBtYWluCgppbXBvcnQgKAoJImdpdGh1Yi5jb20vZ2luLWdvbmljL2dpbiIKKQoKZnVuYyBtYWluKCkgewoJciA6PSBnaW4uRGVmYXVsdCgpCglyLkdFVCgiLyIsIGZ4KQoJci5QT1NUKCIvIiwgZngpCglpZiBlcnIgOj0gci5SdW4oIjozMDAwIik7IGVyciAhPSBuaWwgewoJCXBhbmljKGVycikKCX0KfQo=\"") | ||||
| 	_ = packr.PackJSONBytes("go", "fx.go", "\"cGFja2FnZSBtYWluCgppbXBvcnQgImdpdGh1Yi5jb20vZ2luLWdvbmljL2dpbiIKCmZ1bmMgZngoY3R4ICpnaW4uQ29udGV4dCkgewoJY3R4LkpTT04oMjAwLCBnaW4uSHsKCQkibWVzc2FnZSI6ICJoZWxsbyB3b3JsZCIsCgl9KQp9Cg==\"") | ||||
| } | ||||
| @@ -1,4 +1,4 @@ | ||||
| FROM metrue/fx-go-base:latest | ||||
| FROM metrue/fx-go-base | ||||
| 
 | ||||
| COPY . /go/src/github.com/metrue/fx | ||||
| WORKDIR /go/src/github.com/metrue/fx | ||||
							
								
								
									
										32
									
								
								bundler/go/go.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										32
									
								
								bundler/go/go.go
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,32 @@ | ||||
| package golang | ||||
|  | ||||
| import ( | ||||
| 	"github.com/gobuffalo/packr/v2" | ||||
| 	"github.com/metrue/fx/bundler" | ||||
| ) | ||||
|  | ||||
| // Gin defines javascript bundler | ||||
| type Gin struct { | ||||
| 	assets *packr.Box | ||||
| } | ||||
|  | ||||
| // New a koa bundler | ||||
| func New() *Gin { | ||||
| 	return &Gin{ | ||||
| 		assets: packr.New("go", "./assets"), | ||||
| 	} | ||||
| } | ||||
|  | ||||
| // Scaffold a koa app | ||||
| func (g *Gin) Scaffold(output string) error { | ||||
| 	return bundler.Restore(g.assets, output) | ||||
| } | ||||
|  | ||||
| // Bundle a function into a koa project | ||||
| func (g *Gin) Bundle(output string, fn string, deps ...string) error { | ||||
| 	return bundler.Bundle(g.assets, output, "go", fn, deps...) | ||||
| } | ||||
|  | ||||
| var ( | ||||
| 	_ bundler.Bundler = &Gin{} | ||||
| ) | ||||
							
								
								
									
										143
									
								
								bundler/go/go_test.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										143
									
								
								bundler/go/go_test.go
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,143 @@ | ||||
| package golang | ||||
|  | ||||
| import ( | ||||
| 	"io/ioutil" | ||||
| 	"log" | ||||
| 	"os" | ||||
| 	"reflect" | ||||
| 	"testing" | ||||
|  | ||||
| 	"github.com/metrue/fx/utils" | ||||
| ) | ||||
|  | ||||
| func TestKoaBundler(t *testing.T) { | ||||
| 	t.Run("Scaffold", func(t *testing.T) { | ||||
| 		outputDir, err := ioutil.TempDir("", "fx_koa") | ||||
| 		if err != nil { | ||||
| 			log.Fatal(err) | ||||
| 		} | ||||
| 		defer os.RemoveAll(outputDir) | ||||
|  | ||||
| 		koa := New() | ||||
| 		if err := koa.Scaffold(outputDir); err != nil { | ||||
| 			t.Fatal(err) | ||||
| 		} | ||||
|  | ||||
| 		diff, _, _, err := utils.Diff(outputDir, "./assets") | ||||
| 		if err != nil { | ||||
| 			t.Fatal(err) | ||||
| 		} | ||||
|  | ||||
| 		if diff { | ||||
| 			t.Fatalf("%s is not equal with %s", outputDir, "./assets") | ||||
| 		} | ||||
| 	}) | ||||
|  | ||||
| 	t.Run("BundleSingleFunc", func(t *testing.T) { | ||||
| 		fd, err := ioutil.TempFile("", "fx_func_*.js") | ||||
| 		if err != nil { | ||||
| 			t.Fatal(err) | ||||
| 		} | ||||
| 		defer os.Remove(fd.Name()) | ||||
|  | ||||
| 		content := ` | ||||
| module.exports = (ctx) => { | ||||
|   ctx.body = 'hello fx' | ||||
| }` | ||||
| 		err = ioutil.WriteFile(fd.Name(), []byte(content), 0666) | ||||
| 		if err != nil { | ||||
| 			t.Fatal(err) | ||||
| 		} | ||||
|  | ||||
| 		outputDir, err := ioutil.TempDir("", "fx_koa") | ||||
| 		if err != nil { | ||||
| 			log.Fatal(err) | ||||
| 		} | ||||
| 		defer os.RemoveAll(outputDir) | ||||
|  | ||||
| 		koa := New() | ||||
| 		if err := koa.Bundle(outputDir, fd.Name()); err != nil { | ||||
| 			t.Fatal(err) | ||||
| 		} | ||||
|  | ||||
| 		diff, pre, cur, err := utils.Diff("./assets", outputDir) | ||||
| 		if err != nil { | ||||
| 			t.Fatal(err) | ||||
| 		} | ||||
|  | ||||
| 		if !diff { | ||||
| 			t.Fatalf("handle functino should be changed") | ||||
| 		} | ||||
|  | ||||
| 		if !reflect.DeepEqual(cur, []byte(content)) { | ||||
| 			t.Fatalf("it should be %s but got %s", content, cur) | ||||
| 		} | ||||
|  | ||||
| 		preHandleFunc, err := ioutil.ReadFile("./assets/fx.go") | ||||
| 		if err != nil { | ||||
| 			t.Fatal(err) | ||||
| 		} | ||||
| 		if !reflect.DeepEqual(pre, preHandleFunc) { | ||||
| 			{ | ||||
| 			} | ||||
| 			t.Fatalf("it should get %s but got %s", preHandleFunc, pre) | ||||
| 		} | ||||
| 	}) | ||||
|  | ||||
| 	t.Run("BundleFuncAndDeps", func(t *testing.T) { | ||||
| 		fd, err := ioutil.TempFile("", "fx_func_*.js") | ||||
| 		if err != nil { | ||||
| 			t.Fatal(err) | ||||
| 		} | ||||
| 		defer os.Remove(fd.Name()) | ||||
|  | ||||
| 		content, err := ioutil.ReadFile("./assets/fx.go") | ||||
| 		if err != nil { | ||||
| 			t.Fatal(err) | ||||
| 		} | ||||
| 		err = ioutil.WriteFile(fd.Name(), content, 0666) | ||||
| 		if err != nil { | ||||
| 			t.Fatal(err) | ||||
| 		} | ||||
|  | ||||
| 		addFunc := ` | ||||
| module.exports = (a, b) => a+b | ||||
|   ` | ||||
| 		addFd, err := ioutil.TempFile("", "fx_add_func_*.js") | ||||
| 		if err != nil { | ||||
| 			t.Fatal(err) | ||||
| 		} | ||||
|  | ||||
| 		err = ioutil.WriteFile(addFd.Name(), []byte(addFunc), 0644) | ||||
| 		if err != nil { | ||||
| 			t.Fatal(err) | ||||
| 		} | ||||
|  | ||||
| 		outputDir, err := ioutil.TempDir("", "fx_koa") | ||||
| 		if err != nil { | ||||
| 			log.Fatal(err) | ||||
| 		} | ||||
| 		defer os.RemoveAll(outputDir) | ||||
|  | ||||
| 		koa := New() | ||||
| 		if err := koa.Bundle(outputDir, fd.Name(), addFd.Name()); err != nil { | ||||
| 			t.Fatal(err) | ||||
| 		} | ||||
|  | ||||
| 		diff, pre, cur, err := utils.Diff("./assets", outputDir) | ||||
| 		if err != nil { | ||||
| 			t.Fatal(err) | ||||
| 		} | ||||
|  | ||||
| 		if !diff { | ||||
| 			t.Fatalf("handle functino should be changed") | ||||
| 		} | ||||
|  | ||||
| 		if !reflect.DeepEqual(cur, []byte(addFunc)) { | ||||
| 			t.Fatalf("it should be %s but got %s", content, cur) | ||||
| 		} | ||||
| 		if pre != nil { | ||||
| 			t.Fatal(pre) | ||||
| 		} | ||||
| 	}) | ||||
| } | ||||
							
								
								
									
										8
									
								
								bundler/go/golang-packr.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										8
									
								
								bundler/go/golang-packr.go
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,8 @@ | ||||
| // +build !skippackr | ||||
| // Code generated by github.com/gobuffalo/packr/v2. DO NOT EDIT. | ||||
|  | ||||
| // You can use the "packr clean" command to clean up this, | ||||
| // and any other packr generated files. | ||||
| package golang | ||||
|  | ||||
| import _ "github.com/metrue/fx/packrd" | ||||
							
								
								
									
										14
									
								
								bundler/java/a_java-packr.go.tmpl
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										14
									
								
								bundler/java/a_java-packr.go.tmpl
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,14 @@ | ||||
| // Code generated by github.com/gobuffalo/packr. DO NOT EDIT. | ||||
|  | ||||
| package java | ||||
|  | ||||
| import "github.com/gobuffalo/packr" | ||||
|  | ||||
| // You can use the "packr clean" command to clean up this, | ||||
| // and any other packr generated files. | ||||
| func init() { | ||||
| 	_ = packr.PackJSONBytes("java", "Dockerfile", "\"RlJPTSBtZXRydWUvZngtamF2YS1iYXNlCgojIEFkZGluZyBzb3VyY2UsIGNvbXBpbGUgYW5kIHBhY2thZ2UgaW50byBhIGZhdCBqYXIKQUREIHNyYyAvY29kZS9zcmMKUlVOIFsibXZuIiwgInBhY2thZ2UiXQoKRVhQT1NFIDMwMDAKQ01EIFsiL3Vzci9saWIvanZtL2phdmEtOC1vcGVuamRrLWFtZDY0L2Jpbi9qYXZhIiwgIi1qYXIiLCAidGFyZ2V0L2Z4LWFwcC1qYXZhLTAuMS4wLmphciJdCg==\"") | ||||
| 	_ = packr.PackJSONBytes("java", "pom.xml", "\"PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iVVRGLTgiPz4KPHByb2plY3QgeG1sbnM9Imh0dHA6Ly9tYXZlbi5hcGFjaGUub3JnL1BPTS80LjAuMCIgeG1sbnM6eHNpPSJodHRwOi8vd3d3LnczLm9yZy8yMDAxL1hNTFNjaGVtYS1pbnN0YW5jZSIKICAgIHhzaTpzY2hlbWFMb2NhdGlvbj0iaHR0cDovL21hdmVuLmFwYWNoZS5vcmcvUE9NLzQuMC4wIGh0dHA6Ly9tYXZlbi5hcGFjaGUub3JnL21hdmVuLXY0XzBfMC54c2QiPgogICAgPG1vZGVsVmVyc2lvbj40LjAuMDwvbW9kZWxWZXJzaW9uPgogICAgPGdyb3VwSWQ+b3JnLnNwcmluZ2ZyYW1ld29yazwvZ3JvdXBJZD4KICAgIDxhcnRpZmFjdElkPmZ4LWFwcC1qYXZhPC9hcnRpZmFjdElkPgogICAgPHBhY2thZ2luZz5qYXI8L3BhY2thZ2luZz4KICAgIDx2ZXJzaW9uPjAuMS4wPC92ZXJzaW9uPgoKICAgIDxidWlsZD4KICAgICAgICA8cGx1Z2lucz4KICAgICAgICAgICAgPHBsdWdpbj4KICAgICAgICAgICAgICAgIDxncm91cElkPm9yZy5hcGFjaGUubWF2ZW4ucGx1Z2luczwvZ3JvdXBJZD4KICAgICAgICAgICAgICAgIDxhcnRpZmFjdElkPm1hdmVuLXNoYWRlLXBsdWdpbjwvYXJ0aWZhY3RJZD4KICAgICAgICAgICAgICAgIDx2ZXJzaW9uPjIuMTwvdmVyc2lvbj4KICAgICAgICAgICAgICAgIDxleGVjdXRpb25zPgogICAgICAgICAgICAgICAgICAgIDxleGVjdXRpb24+CiAgICAgICAgICAgICAgICAgICAgICAgIDxwaGFzZT5wYWNrYWdlPC9waGFzZT4KICAgICAgICAgICAgICAgICAgICAgICAgPGdvYWxzPgogICAgICAgICAgICAgICAgICAgICAgICAgICAgPGdvYWw+c2hhZGU8L2dvYWw+CiAgICAgICAgICAgICAgICAgICAgICAgIDwvZ29hbHM+CiAgICAgICAgICAgICAgICAgICAgICAgIDxjb25maWd1cmF0aW9uPgogICAgICAgICAgICAgICAgICAgICAgICAgICAgPHRyYW5zZm9ybWVycz4KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICA8dHJhbnNmb3JtZXIKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaW1wbGVtZW50YXRpb249Im9yZy5hcGFjaGUubWF2ZW4ucGx1Z2lucy5zaGFkZS5yZXNvdXJjZS5NYW5pZmVzdFJlc291cmNlVHJhbnNmb3JtZXIiPgogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICA8bWFpbkNsYXNzPmZ4LmFwcDwvbWFpbkNsYXNzPgogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIDwvdHJhbnNmb3JtZXI+CiAgICAgICAgICAgICAgICAgICAgICAgICAgICA8L3RyYW5zZm9ybWVycz4KICAgICAgICAgICAgICAgICAgICAgICAgPC9jb25maWd1cmF0aW9uPgogICAgICAgICAgICAgICAgICAgIDwvZXhlY3V0aW9uPgogICAgICAgICAgICAgICAgPC9leGVjdXRpb25zPgogICAgICAgICAgICA8L3BsdWdpbj4KICAgICAgICA8L3BsdWdpbnM+CiAgICA8L2J1aWxkPgogICAgPHByb3BlcnRpZXM+CiAgICAgICAgPG1hdmVuLmNvbXBpbGVyLnNvdXJjZT44PC9tYXZlbi5jb21waWxlci5zb3VyY2U+CiAgICAgICAgPG1hdmVuLmNvbXBpbGVyLnRhcmdldD44PC9tYXZlbi5jb21waWxlci50YXJnZXQ+CiAgPC9wcm9wZXJ0aWVzPgogIDxkZXBlbmRlbmNpZXM+CiAgPGRlcGVuZGVuY3k+CiAgICA8Z3JvdXBJZD5pby5qYXZhbGluPC9ncm91cElkPgogICAgPGFydGlmYWN0SWQ+amF2YWxpbjwvYXJ0aWZhY3RJZD4KICAgIDx2ZXJzaW9uPjEuMS4xPC92ZXJzaW9uPgogIDwvZGVwZW5kZW5jeT4KICA8ZGVwZW5kZW5jeT4KICAgIDxncm91cElkPm9yZy5qc29uPC9ncm91cElkPgogICAgPGFydGlmYWN0SWQ+anNvbjwvYXJ0aWZhY3RJZD4KICAgIDx2ZXJzaW9uPjIwMTcxMDE4PC92ZXJzaW9uPgogIDwvZGVwZW5kZW5jeT4KICA8L2RlcGVuZGVuY2llcz4KPC9wcm9qZWN0Pgo=\"") | ||||
| 	_ = packr.PackJSONBytes("java", "src/main/java/fx/Fx.java", "\"cGFja2FnZSBmeDsKCmltcG9ydCBvcmcuanNvbi5KU09OT2JqZWN0OwoKcHVibGljIGNsYXNzIEZ4IHsKICAgIHB1YmxpYyBpbnQgaGFuZGxlKEpTT05PYmplY3QgaW5wdXQpIHsKICAgICAgICBTdHJpbmcgYSA9IGlucHV0LmdldCgiYSIpLnRvU3RyaW5nKCk7CiAgICAgICAgU3RyaW5nIGIgPSBpbnB1dC5nZXQoImIiKS50b1N0cmluZygpOwogICAgICAgIHJldHVybiBJbnRlZ2VyLnBhcnNlSW50KGEpICsgSW50ZWdlci5wYXJzZUludChiKTsKICAgIH0KfQo=\"") | ||||
| 	_ = packr.PackJSONBytes("java", "src/main/java/fx/app.java", "\"cGFja2FnZSBmeDsKCmltcG9ydCBpby5qYXZhbGluLkphdmFsaW47CmltcG9ydCBvcmcuanNvbi5KU09OT2JqZWN0OwoKcHVibGljIGNsYXNzIGFwcCB7CiAgICBwdWJsaWMgc3RhdGljIHZvaWQgbWFpbihTdHJpbmdbXSBhcmdzKSB7CiAgICAgICAgSmF2YWxpbiBhcHAgPSBKYXZhbGluLnN0YXJ0KDMwMDApOwogICAgICAgIEZ4IGhhbmRsZXIgPSBuZXcgRngoKTsKICAgICAgICBhcHAucG9zdCgiLyIsIGN0eCAtPiB7CiAgICAgICAgICAgIEpTT05PYmplY3Qgb2JqID0gbmV3IEpTT05PYmplY3QoY3R4LmJvZHkoKSk7CiAgICAgICAgICAgIGN0eC5yZXN1bHQoIiIraGFuZGxlci5oYW5kbGUob2JqKSk7CiAgICAgICAgfSk7CiAgICB9Cn0K\"") | ||||
| } | ||||
							
								
								
									
										8
									
								
								bundler/java/java-packr.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										8
									
								
								bundler/java/java-packr.go
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,8 @@ | ||||
| // +build !skippackr | ||||
| // Code generated by github.com/gobuffalo/packr/v2. DO NOT EDIT. | ||||
|  | ||||
| // You can use the "packr clean" command to clean up this, | ||||
| // and any other packr generated files. | ||||
| package java | ||||
|  | ||||
| import _ "github.com/metrue/fx/packrd" | ||||
							
								
								
									
										32
									
								
								bundler/java/java.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										32
									
								
								bundler/java/java.go
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,32 @@ | ||||
| package java | ||||
|  | ||||
| import ( | ||||
| 	"github.com/gobuffalo/packr/v2" | ||||
| 	"github.com/metrue/fx/bundler" | ||||
| ) | ||||
|  | ||||
| // Java defines javascript bundler | ||||
| type Java struct { | ||||
| 	assets *packr.Box | ||||
| } | ||||
|  | ||||
| // New a koa bundler | ||||
| func New() *Java { | ||||
| 	return &Java{ | ||||
| 		assets: packr.New("java", "./assets"), | ||||
| 	} | ||||
| } | ||||
|  | ||||
| // Scaffold a koa app | ||||
| func (k *Java) Scaffold(output string) error { | ||||
| 	return bundler.Restore(k.assets, output) | ||||
| } | ||||
|  | ||||
| // Bundle a function into a koa project | ||||
| func (k *Java) Bundle(output string, fn string, deps ...string) error { | ||||
| 	return bundler.Bundle(k.assets, output, "java", fn, deps...) | ||||
| } | ||||
|  | ||||
| var ( | ||||
| 	_ bundler.Bundler = &Java{} | ||||
| ) | ||||
							
								
								
									
										155
									
								
								bundler/java/java_test.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										155
									
								
								bundler/java/java_test.go
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,155 @@ | ||||
| package java | ||||
|  | ||||
| import ( | ||||
| 	"io/ioutil" | ||||
| 	"log" | ||||
| 	"os" | ||||
| 	"reflect" | ||||
| 	"testing" | ||||
|  | ||||
| 	"github.com/metrue/fx/utils" | ||||
| ) | ||||
|  | ||||
| func TestJavaBundler(t *testing.T) { | ||||
| 	t.Run("Scaffold", func(t *testing.T) { | ||||
| 		outputDir, err := ioutil.TempDir("", "fx_java") | ||||
| 		if err != nil { | ||||
| 			log.Fatal(err) | ||||
| 		} | ||||
| 		defer os.RemoveAll(outputDir) | ||||
|  | ||||
| 		java := New() | ||||
| 		if err := java.Scaffold(outputDir); err != nil { | ||||
| 			t.Fatal(err) | ||||
| 		} | ||||
|  | ||||
| 		diff, _, _, err := utils.Diff(outputDir, "./assets") | ||||
| 		if err != nil { | ||||
| 			t.Fatal(err) | ||||
| 		} | ||||
|  | ||||
| 		if diff { | ||||
| 			t.Fatalf("%s is not equal with %s", outputDir, "./assets") | ||||
| 		} | ||||
| 	}) | ||||
|  | ||||
| 	t.Run("BundleSingleFunc", func(t *testing.T) { | ||||
| 		fd, err := ioutil.TempFile("", "fx_func_*.java") | ||||
| 		if err != nil { | ||||
| 			t.Fatal(err) | ||||
| 		} | ||||
| 		defer os.Remove(fd.Name()) | ||||
|  | ||||
| 		content := `package fx; | ||||
|  | ||||
| import io.javalin.Javalin; | ||||
| import org.json.JSONObject; | ||||
|  | ||||
| public class app { | ||||
|     public static void main(String[] args) { | ||||
|         Javalin app = Javalin.start(3000); | ||||
|         Fx handler = new Fx(); | ||||
|         app.post("/", ctx -> { | ||||
|             JSONObject obj = new JSONObject(ctx.body()); | ||||
|             ctx.result(""+handler.handle(obj)); | ||||
|         }); | ||||
|     } | ||||
| } | ||||
| 		` | ||||
| 		err = ioutil.WriteFile(fd.Name(), []byte(content), 0666) | ||||
| 		if err != nil { | ||||
| 			t.Fatal(err) | ||||
| 		} | ||||
|  | ||||
| 		outputDir, err := ioutil.TempDir("", "fx_java") | ||||
| 		if err != nil { | ||||
| 			log.Fatal(err) | ||||
| 		} | ||||
| 		defer os.RemoveAll(outputDir) | ||||
|  | ||||
| 		java := New() | ||||
| 		if err := java.Bundle(outputDir, fd.Name()); err != nil { | ||||
| 			t.Fatal(err) | ||||
| 		} | ||||
|  | ||||
| 		diff, pre, cur, err := utils.Diff("./assets", outputDir) | ||||
| 		if err != nil { | ||||
| 			t.Fatal(err) | ||||
| 		} | ||||
|  | ||||
| 		if !diff { | ||||
| 			t.Fatalf("handle functino should be changed") | ||||
| 		} | ||||
|  | ||||
| 		if !reflect.DeepEqual(cur, []byte(content)) { | ||||
| 			t.Fatalf("it should be %s but got %s", content, cur) | ||||
| 		} | ||||
|  | ||||
| 		preHandleFunc, err := ioutil.ReadFile("./assets/src/main/java/fx/Fx.java") | ||||
| 		if err != nil { | ||||
| 			t.Fatal(err) | ||||
| 		} | ||||
| 		if !reflect.DeepEqual(pre, preHandleFunc) { | ||||
| 			{ | ||||
| 			} | ||||
| 			t.Fatalf("it should get %s but got %s", preHandleFunc, pre) | ||||
| 		} | ||||
| 	}) | ||||
|  | ||||
| 	t.Run("BundleFuncAndDeps", func(t *testing.T) { | ||||
| 		fd, err := ioutil.TempFile("", "fx_func_*.js") | ||||
| 		if err != nil { | ||||
| 			t.Fatal(err) | ||||
| 		} | ||||
| 		defer os.Remove(fd.Name()) | ||||
|  | ||||
| 		content, err := ioutil.ReadFile("./assets/src/main/java/fx/Fx.java") | ||||
| 		if err != nil { | ||||
| 			t.Fatal(err) | ||||
| 		} | ||||
| 		err = ioutil.WriteFile(fd.Name(), content, 0666) | ||||
| 		if err != nil { | ||||
| 			t.Fatal(err) | ||||
| 		} | ||||
|  | ||||
| 		addFunc := ` | ||||
| module.exports = (a, b) => a+b | ||||
|   ` | ||||
| 		addFd, err := ioutil.TempFile("", "fx_add_func_*.js") | ||||
| 		if err != nil { | ||||
| 			t.Fatal(err) | ||||
| 		} | ||||
|  | ||||
| 		err = ioutil.WriteFile(addFd.Name(), []byte(addFunc), 0644) | ||||
| 		if err != nil { | ||||
| 			t.Fatal(err) | ||||
| 		} | ||||
|  | ||||
| 		outputDir, err := ioutil.TempDir("", "fx_java") | ||||
| 		if err != nil { | ||||
| 			log.Fatal(err) | ||||
| 		} | ||||
| 		defer os.RemoveAll(outputDir) | ||||
|  | ||||
| 		java := New() | ||||
| 		if err := java.Bundle(outputDir, fd.Name(), addFd.Name()); err != nil { | ||||
| 			t.Fatal(err) | ||||
| 		} | ||||
|  | ||||
| 		diff, pre, cur, err := utils.Diff("./assets", outputDir) | ||||
| 		if err != nil { | ||||
| 			t.Fatal(err) | ||||
| 		} | ||||
|  | ||||
| 		if !diff { | ||||
| 			t.Fatalf("handle functino should be changed") | ||||
| 		} | ||||
|  | ||||
| 		if !reflect.DeepEqual(cur, []byte(addFunc)) { | ||||
| 			t.Fatalf("it should be %s but got %s", content, cur) | ||||
| 		} | ||||
| 		if pre != nil { | ||||
| 			t.Fatal(pre) | ||||
| 		} | ||||
| 	}) | ||||
| } | ||||
							
								
								
									
										15
									
								
								bundler/julia/a_julia-packr.go.tmpl
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										15
									
								
								bundler/julia/a_julia-packr.go.tmpl
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,15 @@ | ||||
| // Code generated by github.com/gobuffalo/packr. DO NOT EDIT. | ||||
|  | ||||
| package julia | ||||
|  | ||||
| import "github.com/gobuffalo/packr" | ||||
|  | ||||
| // You can use the "packr clean" command to clean up this, | ||||
| // and any other packr generated files. | ||||
| func init() { | ||||
| 	_ = packr.PackJSONBytes("julia", "Dockerfile", "\"RlJPTSBqdWxpYTowLjcKCkNPUFkgLiAvYXBwCgpSVU4gYXB0LWdldCB1cGRhdGUgJiYgYXB0LWdldCBpbnN0YWxsIC15IGdjYyBhcHQtdXRpbHMgdW56aXAgbWFrZSBsaWJodHRwLXBhcnNlci1kZXYKUlVOIGp1bGlhIC9hcHAvZGVwcy5qbAoKQ01EIGp1bGlhIC9hcHAvYXBwLmpsCkVYUE9TRSAzMDAwCg==\"") | ||||
| 	_ = packr.PackJSONBytes("julia", "REQUIRE", "\"SHR0cFBhcnNlcgpIdHRwU2VydmVyCkpTT04KVW5tYXJzaGFs\"") | ||||
| 	_ = packr.PackJSONBytes("julia", "app.jl", "\"dXNpbmcgSHR0cFNlcnZlcgppbXBvcnQgSlNPTgppbXBvcnQgVW5tYXJzaGFsCgppbmNsdWRlKCJmeC5qbCIpCgpzcnYgPSBTZXJ2ZXIoKSBkbyByZXE6OlJlcXVlc3QsIHJlczo6UmVzcG9uc2UKICAgIGlmIGxlbmd0aChyZXEuZGF0YSkgPT0gMAogICAgICAgIHJlcy5zdGF0dXMgPSA0MDAKICAgIGVsc2UKICAgICAgICBwYXJzZWRfZGF0YSA9IEpTT04uUGFyc2VyLnBhcnNlKGpvaW4oW0NoYXIodikgZm9yIHYgaW4gcmVxLmRhdGFdKSkKICAgICAgICBkYXRhID0gVW5tYXJzaGFsLnVubWFyc2hhbChJbnB1dCwgcGFyc2VkX2RhdGEpCiAgICAgICAgc3RyaW5nKGZ4KGRhdGEpKQogICAgZW5kCmVuZAoKcnVuKHNydiwgMzAwMCkK\"") | ||||
| 	_ = packr.PackJSONBytes("julia", "deps.jl", "\"b3BlbigiL2FwcC9SRVFVSVJFIikgZG8gZgoJZGVwcyA9IHJlYWRsaW5lcyhmKQoJZm9yIGQgaW4gZGVwcwoJCVBrZy5hZGQoZCkKCWVuZAplbmQKUGtnLmJ1aWxkKCJIdHRwUGFyc2VyIikK\"") | ||||
| 	_ = packr.PackJSONBytes("julia", "fx.jl", "\"c3RydWN0IElucHV0CiAgICBhOjpOdW1iZXIKICAgIGI6Ok51bWJlcgplbmQKCmZ4ID0gZnVuY3Rpb24oaW5wdXQ6OklucHV0KQogICAgcmV0dXJuIGlucHV0LmEgKyBpbnB1dC5iCmVuZAo=\"") | ||||
| } | ||||
| @@ -1,4 +1,3 @@ | ||||
| 
 | ||||
| struct Input | ||||
|     a::Number | ||||
|     b::Number | ||||
							
								
								
									
										8
									
								
								bundler/julia/julia-packr.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										8
									
								
								bundler/julia/julia-packr.go
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,8 @@ | ||||
| // +build !skippackr | ||||
| // Code generated by github.com/gobuffalo/packr/v2. DO NOT EDIT. | ||||
|  | ||||
| // You can use the "packr clean" command to clean up this, | ||||
| // and any other packr generated files. | ||||
| package julia | ||||
|  | ||||
| import _ "github.com/metrue/fx/packrd" | ||||
							
								
								
									
										32
									
								
								bundler/julia/julia.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										32
									
								
								bundler/julia/julia.go
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,32 @@ | ||||
| package julia | ||||
|  | ||||
| import ( | ||||
| 	"github.com/gobuffalo/packr/v2" | ||||
| 	"github.com/metrue/fx/bundler" | ||||
| ) | ||||
|  | ||||
| // Julia defines javascript bundler | ||||
| type Julia struct { | ||||
| 	assets *packr.Box | ||||
| } | ||||
|  | ||||
| // New a koa bundler | ||||
| func New() *Julia { | ||||
| 	return &Julia{ | ||||
| 		assets: packr.New("julia", "./assets"), | ||||
| 	} | ||||
| } | ||||
|  | ||||
| // Scaffold a koa app | ||||
| func (k *Julia) Scaffold(output string) error { | ||||
| 	return bundler.Restore(k.assets, output) | ||||
| } | ||||
|  | ||||
| // Bundle a function into a koa project | ||||
| func (k *Julia) Bundle(output string, fn string, deps ...string) error { | ||||
| 	return bundler.Bundle(k.assets, output, "julia", fn, deps...) | ||||
| } | ||||
|  | ||||
| var ( | ||||
| 	_ bundler.Bundler = &Julia{} | ||||
| ) | ||||
							
								
								
									
										148
									
								
								bundler/julia/julia_test.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										148
									
								
								bundler/julia/julia_test.go
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,148 @@ | ||||
| package julia | ||||
|  | ||||
| import ( | ||||
| 	"io/ioutil" | ||||
| 	"log" | ||||
| 	"os" | ||||
| 	"reflect" | ||||
| 	"testing" | ||||
|  | ||||
| 	"github.com/metrue/fx/utils" | ||||
| ) | ||||
|  | ||||
| func TestJuliaBundler(t *testing.T) { | ||||
| 	t.Run("Scaffold", func(t *testing.T) { | ||||
| 		outputDir, err := ioutil.TempDir("", "fx_julia") | ||||
| 		if err != nil { | ||||
| 			log.Fatal(err) | ||||
| 		} | ||||
| 		defer os.RemoveAll(outputDir) | ||||
|  | ||||
| 		julia := New() | ||||
| 		if err := julia.Scaffold(outputDir); err != nil { | ||||
| 			t.Fatal(err) | ||||
| 		} | ||||
|  | ||||
| 		diff, _, _, err := utils.Diff(outputDir, "./assets") | ||||
| 		if err != nil { | ||||
| 			t.Fatal(err) | ||||
| 		} | ||||
|  | ||||
| 		if diff { | ||||
| 			t.Fatalf("%s is not equal with %s", outputDir, "./assets") | ||||
| 		} | ||||
| 	}) | ||||
|  | ||||
| 	t.Run("BundleSingleFunc", func(t *testing.T) { | ||||
| 		fd, err := ioutil.TempFile("", "fx_func_*.julia") | ||||
| 		if err != nil { | ||||
| 			t.Fatal(err) | ||||
| 		} | ||||
| 		defer os.Remove(fd.Name()) | ||||
|  | ||||
| 		content := `struct Input | ||||
|     a::Number | ||||
|     b::Number | ||||
| end | ||||
|  | ||||
| fx = function(input::Input) | ||||
|     return input.a + input.b | ||||
| end | ||||
| 		` | ||||
| 		err = ioutil.WriteFile(fd.Name(), []byte(content), 0666) | ||||
| 		if err != nil { | ||||
| 			t.Fatal(err) | ||||
| 		} | ||||
|  | ||||
| 		outputDir, err := ioutil.TempDir("", "fx_julia") | ||||
| 		if err != nil { | ||||
| 			log.Fatal(err) | ||||
| 		} | ||||
| 		defer os.RemoveAll(outputDir) | ||||
|  | ||||
| 		julia := New() | ||||
| 		if err := julia.Bundle(outputDir, fd.Name()); err != nil { | ||||
| 			t.Fatal(err) | ||||
| 		} | ||||
|  | ||||
| 		diff, pre, cur, err := utils.Diff("./assets", outputDir) | ||||
| 		if err != nil { | ||||
| 			t.Fatal(err) | ||||
| 		} | ||||
|  | ||||
| 		if !diff { | ||||
| 			t.Fatalf("handle function should be changed") | ||||
| 		} | ||||
|  | ||||
| 		if !reflect.DeepEqual(cur, []byte(content)) { | ||||
| 			t.Fatalf("it should be %s but got %s", content, cur) | ||||
| 		} | ||||
|  | ||||
| 		preHandleFunc, err := ioutil.ReadFile("./assets/fx.jl") | ||||
| 		if err != nil { | ||||
| 			t.Fatal(err) | ||||
| 		} | ||||
| 		if !reflect.DeepEqual(pre, preHandleFunc) { | ||||
| 			{ | ||||
| 			} | ||||
| 			t.Fatalf("it should get %s but got %s", preHandleFunc, pre) | ||||
| 		} | ||||
| 	}) | ||||
|  | ||||
| 	t.Run("BundleFuncAndDeps", func(t *testing.T) { | ||||
| 		fd, err := ioutil.TempFile("", "fx_func_*.js") | ||||
| 		if err != nil { | ||||
| 			t.Fatal(err) | ||||
| 		} | ||||
| 		defer os.Remove(fd.Name()) | ||||
|  | ||||
| 		content, err := ioutil.ReadFile("./assets/fx.jl") | ||||
| 		if err != nil { | ||||
| 			t.Fatal(err) | ||||
| 		} | ||||
| 		err = ioutil.WriteFile(fd.Name(), content, 0666) | ||||
| 		if err != nil { | ||||
| 			t.Fatal(err) | ||||
| 		} | ||||
|  | ||||
| 		addFunc := ` | ||||
| module.exports = (a, b) => a+b | ||||
|   ` | ||||
| 		addFd, err := ioutil.TempFile("", "fx_add_func_*.js") | ||||
| 		if err != nil { | ||||
| 			t.Fatal(err) | ||||
| 		} | ||||
|  | ||||
| 		err = ioutil.WriteFile(addFd.Name(), []byte(addFunc), 0644) | ||||
| 		if err != nil { | ||||
| 			t.Fatal(err) | ||||
| 		} | ||||
|  | ||||
| 		outputDir, err := ioutil.TempDir("", "fx_julia") | ||||
| 		if err != nil { | ||||
| 			log.Fatal(err) | ||||
| 		} | ||||
| 		defer os.RemoveAll(outputDir) | ||||
|  | ||||
| 		julia := New() | ||||
| 		if err := julia.Bundle(outputDir, fd.Name(), addFd.Name()); err != nil { | ||||
| 			t.Fatal(err) | ||||
| 		} | ||||
|  | ||||
| 		diff, pre, cur, err := utils.Diff("./assets", outputDir) | ||||
| 		if err != nil { | ||||
| 			t.Fatal(err) | ||||
| 		} | ||||
|  | ||||
| 		if !diff { | ||||
| 			t.Fatalf("handle functino should be changed") | ||||
| 		} | ||||
|  | ||||
| 		if !reflect.DeepEqual(cur, []byte(addFunc)) { | ||||
| 			t.Fatalf("it should be %s but got %s", content, cur) | ||||
| 		} | ||||
| 		if pre != nil { | ||||
| 			t.Fatal(pre) | ||||
| 		} | ||||
| 	}) | ||||
| } | ||||
							
								
								
									
										13
									
								
								bundler/node/a_node-packr.go.tmpl
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										13
									
								
								bundler/node/a_node-packr.go.tmpl
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,13 @@ | ||||
| // Code generated by github.com/gobuffalo/packr. DO NOT EDIT. | ||||
|  | ||||
| package node | ||||
|  | ||||
| import "github.com/gobuffalo/packr" | ||||
|  | ||||
| // You can use the "packr clean" command to clean up this, | ||||
| // and any other packr generated files. | ||||
| func init() { | ||||
| 	_ = packr.PackJSONBytes("node", "Dockerfile", "\"RlJPTSBtZXRydWUvZngtbm9kZS1iYXNlCgpDT1BZIC4gLgpFWFBPU0UgMzAwMApDTUQgWyJub2RlIiwgImFwcC5qcyJdCg==\"") | ||||
| 	_ = packr.PackJSONBytes("node", "app.js", "\"Y29uc3QgS29hID0gcmVxdWlyZSgna29hJyk7CmNvbnN0IGJvZHlQYXJzZXIgPSByZXF1aXJlKCdrb2EtYm9keXBhcnNlcicpOwpjb25zdCBjb3JzID0gcmVxdWlyZSgnQGtvYS9jb3JzJyk7CmNvbnN0IHN3U3RhdHMgPSByZXF1aXJlKCdzd2FnZ2VyLXN0YXRzJyk7CmNvbnN0IGUyayA9IHJlcXVpcmUoJ2V4cHJlc3MtdG8ta29hJyk7CmNvbnN0IGZ4ID0gcmVxdWlyZSgnLi9meCcpOwoKY29uc3QgYXBwID0gbmV3IEtvYSgpOwoKYXBwLnVzZShlMmsoc3dTdGF0cy5nZXRNaWRkbGV3YXJlKHt9KSkpOwphcHAudXNlKGNvcnMoewogIG9yaWdpbjogJyonLAp9KSk7CmFwcC51c2UoYm9keVBhcnNlcigpKTsKYXBwLnVzZShmeCk7CgphcHAubGlzdGVuKDMwMDApOwo=\"") | ||||
| 	_ = packr.PackJSONBytes("node", "fx.js", "\"bW9kdWxlLmV4cG9ydHMgPSAoY3R4KSA9PiB7CiAgY3R4LmJvZHkgPSAnaGVsbG8gd29ybGQnCn0K\"") | ||||
| } | ||||
							
								
								
									
										17
									
								
								bundler/node/assets/app.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										17
									
								
								bundler/node/assets/app.js
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,17 @@ | ||||
| const Koa = require('koa'); | ||||
| const bodyParser = require('koa-bodyparser'); | ||||
| const cors = require('@koa/cors'); | ||||
| const swStats = require('swagger-stats'); | ||||
| const e2k = require('express-to-koa'); | ||||
| const fx = require('./fx'); | ||||
|  | ||||
| const app = new Koa(); | ||||
|  | ||||
| app.use(e2k(swStats.getMiddleware({}))); | ||||
| app.use(cors({ | ||||
|   origin: '*', | ||||
| })); | ||||
| app.use(bodyParser()); | ||||
| app.use(fx); | ||||
|  | ||||
| app.listen(3000); | ||||
							
								
								
									
										8
									
								
								bundler/node/node-packr.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										8
									
								
								bundler/node/node-packr.go
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,8 @@ | ||||
| // +build !skippackr | ||||
| // Code generated by github.com/gobuffalo/packr/v2. DO NOT EDIT. | ||||
|  | ||||
| // You can use the "packr clean" command to clean up this, | ||||
| // and any other packr generated files. | ||||
| package node | ||||
|  | ||||
| import _ "github.com/metrue/fx/packrd" | ||||
							
								
								
									
										34
									
								
								bundler/node/node.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										34
									
								
								bundler/node/node.go
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,34 @@ | ||||
| package node | ||||
|  | ||||
| import ( | ||||
| 	"github.com/gobuffalo/packr/v2" | ||||
| 	"github.com/metrue/fx/bundler" | ||||
| ) | ||||
|  | ||||
| const language = "node" | ||||
|  | ||||
| // Node defines node bundler | ||||
| type Node struct { | ||||
| 	assets *packr.Box | ||||
| } | ||||
|  | ||||
| // New a koa bundler | ||||
| func New() *Node { | ||||
| 	return &Node{ | ||||
| 		assets: packr.New("node", "./assets"), | ||||
| 	} | ||||
| } | ||||
|  | ||||
| // Scaffold a koa app | ||||
| func (k *Node) Scaffold(output string) error { | ||||
| 	return bundler.Restore(k.assets, output) | ||||
| } | ||||
|  | ||||
| // Bundle a function into a koa project | ||||
| func (k *Node) Bundle(output string, fn string, deps ...string) error { | ||||
| 	return bundler.Bundle(k.assets, output, language, fn, deps...) | ||||
| } | ||||
|  | ||||
| var ( | ||||
| 	_ bundler.Bundler = &Node{} | ||||
| ) | ||||
							
								
								
									
										143
									
								
								bundler/node/node_test.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										143
									
								
								bundler/node/node_test.go
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,143 @@ | ||||
| package node | ||||
|  | ||||
| import ( | ||||
| 	"io/ioutil" | ||||
| 	"log" | ||||
| 	"os" | ||||
| 	"reflect" | ||||
| 	"testing" | ||||
|  | ||||
| 	"github.com/metrue/fx/utils" | ||||
| ) | ||||
|  | ||||
| func TestNodeBundler(t *testing.T) { | ||||
| 	t.Run("Scaffold", func(t *testing.T) { | ||||
| 		outputDir, err := ioutil.TempDir("", "fx_koa") | ||||
| 		if err != nil { | ||||
| 			log.Fatal(err) | ||||
| 		} | ||||
| 		defer os.RemoveAll(outputDir) | ||||
|  | ||||
| 		koa := New() | ||||
| 		if err := koa.Scaffold(outputDir); err != nil { | ||||
| 			t.Fatal(err) | ||||
| 		} | ||||
|  | ||||
| 		diff, _, _, err := utils.Diff(outputDir, "./assets") | ||||
| 		if err != nil { | ||||
| 			t.Fatal(err) | ||||
| 		} | ||||
|  | ||||
| 		if diff { | ||||
| 			t.Fatalf("%s is not equal with %s", outputDir, "./assets") | ||||
| 		} | ||||
| 	}) | ||||
|  | ||||
| 	t.Run("BundleSingleFunc", func(t *testing.T) { | ||||
| 		fd, err := ioutil.TempFile("", "fx_func_*.js") | ||||
| 		if err != nil { | ||||
| 			t.Fatal(err) | ||||
| 		} | ||||
| 		defer os.Remove(fd.Name()) | ||||
|  | ||||
| 		content := ` | ||||
| module.exports = (ctx) => { | ||||
|   ctx.body = 'hello fx' | ||||
| }` | ||||
| 		err = ioutil.WriteFile(fd.Name(), []byte(content), 0666) | ||||
| 		if err != nil { | ||||
| 			t.Fatal(err) | ||||
| 		} | ||||
|  | ||||
| 		outputDir, err := ioutil.TempDir("", "fx_koa") | ||||
| 		if err != nil { | ||||
| 			log.Fatal(err) | ||||
| 		} | ||||
| 		defer os.RemoveAll(outputDir) | ||||
|  | ||||
| 		koa := New() | ||||
| 		if err := koa.Bundle(outputDir, fd.Name()); err != nil { | ||||
| 			t.Fatal(err) | ||||
| 		} | ||||
|  | ||||
| 		diff, pre, cur, err := utils.Diff("./assets", outputDir) | ||||
| 		if err != nil { | ||||
| 			t.Fatal(err) | ||||
| 		} | ||||
|  | ||||
| 		if !diff { | ||||
| 			t.Fatalf("handle functino should be changed") | ||||
| 		} | ||||
|  | ||||
| 		if !reflect.DeepEqual(cur, []byte(content)) { | ||||
| 			t.Fatalf("it should be %s but got %s", content, cur) | ||||
| 		} | ||||
|  | ||||
| 		preHandleFunc, err := ioutil.ReadFile("./assets/fx.js") | ||||
| 		if err != nil { | ||||
| 			t.Fatal(err) | ||||
| 		} | ||||
| 		if !reflect.DeepEqual(pre, preHandleFunc) { | ||||
| 			{ | ||||
| 			} | ||||
| 			t.Fatalf("it should get %s but got %s", preHandleFunc, pre) | ||||
| 		} | ||||
| 	}) | ||||
|  | ||||
| 	t.Run("BundleFuncAndDeps", func(t *testing.T) { | ||||
| 		fd, err := ioutil.TempFile("", "fx_func_*.js") | ||||
| 		if err != nil { | ||||
| 			t.Fatal(err) | ||||
| 		} | ||||
| 		defer os.Remove(fd.Name()) | ||||
|  | ||||
| 		content, err := ioutil.ReadFile("./assets/fx.js") | ||||
| 		if err != nil { | ||||
| 			t.Fatal(err) | ||||
| 		} | ||||
| 		err = ioutil.WriteFile(fd.Name(), content, 0666) | ||||
| 		if err != nil { | ||||
| 			t.Fatal(err) | ||||
| 		} | ||||
|  | ||||
| 		addFunc := ` | ||||
| module.exports = (a, b) => a+b | ||||
|   ` | ||||
| 		addFd, err := ioutil.TempFile("", "fx_add_func_*.js") | ||||
| 		if err != nil { | ||||
| 			t.Fatal(err) | ||||
| 		} | ||||
|  | ||||
| 		err = ioutil.WriteFile(addFd.Name(), []byte(addFunc), 0644) | ||||
| 		if err != nil { | ||||
| 			t.Fatal(err) | ||||
| 		} | ||||
|  | ||||
| 		outputDir, err := ioutil.TempDir("", "fx_koa") | ||||
| 		if err != nil { | ||||
| 			log.Fatal(err) | ||||
| 		} | ||||
| 		defer os.RemoveAll(outputDir) | ||||
|  | ||||
| 		koa := New() | ||||
| 		if err := koa.Bundle(outputDir, fd.Name(), addFd.Name()); err != nil { | ||||
| 			t.Fatal(err) | ||||
| 		} | ||||
|  | ||||
| 		diff, pre, cur, err := utils.Diff("./assets", outputDir) | ||||
| 		if err != nil { | ||||
| 			t.Fatal(err) | ||||
| 		} | ||||
|  | ||||
| 		if !diff { | ||||
| 			t.Fatalf("handle functino should be changed") | ||||
| 		} | ||||
|  | ||||
| 		if !reflect.DeepEqual(cur, []byte(addFunc)) { | ||||
| 			t.Fatalf("it should be %s but got %s", content, cur) | ||||
| 		} | ||||
| 		if pre != nil { | ||||
| 			t.Fatal(pre) | ||||
| 		} | ||||
| 	}) | ||||
| } | ||||
							
								
								
									
										13
									
								
								bundler/perl/a_perl-packr.go.tmpl
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										13
									
								
								bundler/perl/a_perl-packr.go.tmpl
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,13 @@ | ||||
| // Code generated by github.com/gobuffalo/packr. DO NOT EDIT. | ||||
|  | ||||
| package perl | ||||
|  | ||||
| import "github.com/gobuffalo/packr" | ||||
|  | ||||
| // You can use the "packr clean" command to clean up this, | ||||
| // and any other packr generated files. | ||||
| func init() { | ||||
| 	_ = packr.PackJSONBytes("perl", "Dockerfile", "\"RlJPTSBtZXRydWUvZngtcGVybC1iYXNlCgpBREQgLiAuCgpFWFBPU0UgMzAwMApDTUQgWyJwZXJsIiwgImFwcC5wbCIsICJkYWVtb24iXQo=\"") | ||||
| 	_ = packr.PackJSONBytes("perl", "app.pl", "\"dXNlIE1vam9saWNpb3VzOjpMaXRlOwoKcmVxdWlyZSAiLi9meC5wbCI7CgpnZXQgJy8nID0+IHN1YiB7CiAgbXkgJGN0eCA9IHNoaWZ0OwogIG15ICRyZXMgPSBmeCgkY3R4KTsKICAkY3R4LT5yZW5kZXIoanNvbiA9PiAkcmVzKTsKfTsKCnBvc3QgJy8nID0+IHN1YiB7CiAgbXkgJGN0eCA9IHNoaWZ0OwogIG15ICRyZXMgPSBmeCgkY3R4KTsKICAkY3R4LT5yZW5kZXIoanNvbiA9PiAkcmVzKTsKfTsKCmFwcC0+c3RhcnQ7Cg==\"") | ||||
| 	_ = packr.PackJSONBytes("perl", "fx.pl", "\"c3ViIGZ4IHsKICBteSAkY3R4ID0gc2hpZnQ7CiAgcmV0dXJuICdoZWxsbyBmeCcKfQoKMTsK\"") | ||||
| } | ||||
							
								
								
									
										6
									
								
								bundler/perl/assets/Dockerfile
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										6
									
								
								bundler/perl/assets/Dockerfile
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,6 @@ | ||||
| FROM metrue/fx-perl-base | ||||
|  | ||||
| ADD . . | ||||
|  | ||||
| EXPOSE 3000 | ||||
| CMD ["perl", "app.pl", "daemon"] | ||||
							
								
								
									
										17
									
								
								bundler/perl/assets/app.pl
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										17
									
								
								bundler/perl/assets/app.pl
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,17 @@ | ||||
| use Mojolicious::Lite; | ||||
|  | ||||
| require "./fx.pl"; | ||||
|  | ||||
| get '/' => sub { | ||||
|   my $ctx = shift; | ||||
|   my $res = fx($ctx); | ||||
|   $ctx->render(json => $res); | ||||
| }; | ||||
|  | ||||
| post '/' => sub { | ||||
|   my $ctx = shift; | ||||
|   my $res = fx($ctx); | ||||
|   $ctx->render(json => $res); | ||||
| }; | ||||
|  | ||||
| app->start; | ||||
							
								
								
									
										6
									
								
								bundler/perl/assets/fx.pl
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										6
									
								
								bundler/perl/assets/fx.pl
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,6 @@ | ||||
| sub fx { | ||||
|   my $ctx = shift; | ||||
|   return 'hello fx' | ||||
| } | ||||
|  | ||||
| 1; | ||||
							
								
								
									
										8
									
								
								bundler/perl/perl-packr.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										8
									
								
								bundler/perl/perl-packr.go
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,8 @@ | ||||
| // +build !skippackr | ||||
| // Code generated by github.com/gobuffalo/packr/v2. DO NOT EDIT. | ||||
|  | ||||
| // You can use the "packr clean" command to clean up this, | ||||
| // and any other packr generated files. | ||||
| package perl | ||||
|  | ||||
| import _ "github.com/metrue/fx/packrd" | ||||
							
								
								
									
										32
									
								
								bundler/perl/perl.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										32
									
								
								bundler/perl/perl.go
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,32 @@ | ||||
| package perl | ||||
|  | ||||
| import ( | ||||
| 	"github.com/gobuffalo/packr/v2" | ||||
| 	"github.com/metrue/fx/bundler" | ||||
| ) | ||||
|  | ||||
| // Julia defines javascript bundler | ||||
| type Julia struct { | ||||
| 	assets *packr.Box | ||||
| } | ||||
|  | ||||
| // New a koa bundler | ||||
| func New() *Julia { | ||||
| 	return &Julia{ | ||||
| 		assets: packr.New("perl", "./assets"), | ||||
| 	} | ||||
| } | ||||
|  | ||||
| // Scaffold a koa app | ||||
| func (k *Julia) Scaffold(output string) error { | ||||
| 	return bundler.Restore(k.assets, output) | ||||
| } | ||||
|  | ||||
| // Bundle a function into a koa project | ||||
| func (k *Julia) Bundle(output string, fn string, deps ...string) error { | ||||
| 	return bundler.Bundle(k.assets, output, "perl", fn, deps...) | ||||
| } | ||||
|  | ||||
| var ( | ||||
| 	_ bundler.Bundler = &Julia{} | ||||
| ) | ||||
							
								
								
									
										148
									
								
								bundler/perl/perl_test.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										148
									
								
								bundler/perl/perl_test.go
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,148 @@ | ||||
| package perl | ||||
|  | ||||
| import ( | ||||
| 	"io/ioutil" | ||||
| 	"log" | ||||
| 	"os" | ||||
| 	"reflect" | ||||
| 	"testing" | ||||
|  | ||||
| 	"github.com/metrue/fx/utils" | ||||
| ) | ||||
|  | ||||
| func TestJuliaBundler(t *testing.T) { | ||||
| 	t.Run("Scaffold", func(t *testing.T) { | ||||
| 		outputDir, err := ioutil.TempDir("", "fx_julia") | ||||
| 		if err != nil { | ||||
| 			log.Fatal(err) | ||||
| 		} | ||||
| 		defer os.RemoveAll(outputDir) | ||||
|  | ||||
| 		julia := New() | ||||
| 		if err := julia.Scaffold(outputDir); err != nil { | ||||
| 			t.Fatal(err) | ||||
| 		} | ||||
|  | ||||
| 		diff, _, _, err := utils.Diff(outputDir, "./assets") | ||||
| 		if err != nil { | ||||
| 			t.Fatal(err) | ||||
| 		} | ||||
|  | ||||
| 		if diff { | ||||
| 			t.Fatalf("%s is not equal with %s", outputDir, "./assets") | ||||
| 		} | ||||
| 	}) | ||||
|  | ||||
| 	t.Run("BundleSingleFunc", func(t *testing.T) { | ||||
| 		fd, err := ioutil.TempFile("", "fx_func_*.julia") | ||||
| 		if err != nil { | ||||
| 			t.Fatal(err) | ||||
| 		} | ||||
| 		defer os.Remove(fd.Name()) | ||||
|  | ||||
| 		content := `struct Input | ||||
|     a::Number | ||||
|     b::Number | ||||
| end | ||||
|  | ||||
| fx = function(input::Input) | ||||
|     return input.a + input.b | ||||
| end | ||||
| 		` | ||||
| 		err = ioutil.WriteFile(fd.Name(), []byte(content), 0666) | ||||
| 		if err != nil { | ||||
| 			t.Fatal(err) | ||||
| 		} | ||||
|  | ||||
| 		outputDir, err := ioutil.TempDir("", "fx_julia") | ||||
| 		if err != nil { | ||||
| 			log.Fatal(err) | ||||
| 		} | ||||
| 		defer os.RemoveAll(outputDir) | ||||
|  | ||||
| 		julia := New() | ||||
| 		if err := julia.Bundle(outputDir, fd.Name()); err != nil { | ||||
| 			t.Fatal(err) | ||||
| 		} | ||||
|  | ||||
| 		diff, pre, cur, err := utils.Diff("./assets", outputDir) | ||||
| 		if err != nil { | ||||
| 			t.Fatal(err) | ||||
| 		} | ||||
|  | ||||
| 		if !diff { | ||||
| 			t.Fatalf("handle function should be changed") | ||||
| 		} | ||||
|  | ||||
| 		if !reflect.DeepEqual(cur, []byte(content)) { | ||||
| 			t.Fatalf("it should be %s but got %s", content, cur) | ||||
| 		} | ||||
|  | ||||
| 		preHandleFunc, err := ioutil.ReadFile("./assets/fx.pl") | ||||
| 		if err != nil { | ||||
| 			t.Fatal(err) | ||||
| 		} | ||||
| 		if !reflect.DeepEqual(pre, preHandleFunc) { | ||||
| 			{ | ||||
| 			} | ||||
| 			t.Fatalf("it should get %s but got %s", preHandleFunc, pre) | ||||
| 		} | ||||
| 	}) | ||||
|  | ||||
| 	t.Run("BundleFuncAndDeps", func(t *testing.T) { | ||||
| 		fd, err := ioutil.TempFile("", "fx_func_*.js") | ||||
| 		if err != nil { | ||||
| 			t.Fatal(err) | ||||
| 		} | ||||
| 		defer os.Remove(fd.Name()) | ||||
|  | ||||
| 		content, err := ioutil.ReadFile("./assets/fx.pl") | ||||
| 		if err != nil { | ||||
| 			t.Fatal(err) | ||||
| 		} | ||||
| 		err = ioutil.WriteFile(fd.Name(), content, 0666) | ||||
| 		if err != nil { | ||||
| 			t.Fatal(err) | ||||
| 		} | ||||
|  | ||||
| 		addFunc := ` | ||||
| module.exports = (a, b) => a+b | ||||
|   ` | ||||
| 		addFd, err := ioutil.TempFile("", "fx_add_func_*.js") | ||||
| 		if err != nil { | ||||
| 			t.Fatal(err) | ||||
| 		} | ||||
|  | ||||
| 		err = ioutil.WriteFile(addFd.Name(), []byte(addFunc), 0644) | ||||
| 		if err != nil { | ||||
| 			t.Fatal(err) | ||||
| 		} | ||||
|  | ||||
| 		outputDir, err := ioutil.TempDir("", "fx_julia") | ||||
| 		if err != nil { | ||||
| 			log.Fatal(err) | ||||
| 		} | ||||
| 		defer os.RemoveAll(outputDir) | ||||
|  | ||||
| 		julia := New() | ||||
| 		if err := julia.Bundle(outputDir, fd.Name(), addFd.Name()); err != nil { | ||||
| 			t.Fatal(err) | ||||
| 		} | ||||
|  | ||||
| 		diff, pre, cur, err := utils.Diff("./assets", outputDir) | ||||
| 		if err != nil { | ||||
| 			t.Fatal(err) | ||||
| 		} | ||||
|  | ||||
| 		if !diff { | ||||
| 			t.Fatalf("handle functino should be changed") | ||||
| 		} | ||||
|  | ||||
| 		if !reflect.DeepEqual(cur, []byte(addFunc)) { | ||||
| 			t.Fatalf("it should be %s but got %s", content, cur) | ||||
| 		} | ||||
| 		if pre != nil { | ||||
| 			t.Fatal(pre) | ||||
| 		} | ||||
| 	}) | ||||
| } | ||||
							
								
								
									
										13
									
								
								bundler/php/a_php-packr.go.tmpl
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										13
									
								
								bundler/php/a_php-packr.go.tmpl
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,13 @@ | ||||
| // Code generated by github.com/gobuffalo/packr. DO NOT EDIT. | ||||
|  | ||||
| package php | ||||
|  | ||||
| import "github.com/gobuffalo/packr" | ||||
|  | ||||
| // You can use the "packr clean" command to clean up this, | ||||
| // and any other packr generated files. | ||||
| func init() { | ||||
| 	_ = packr.PackJSONBytes("php", "Dockerfile", "\"RlJPTSBtZXRydWUvZngtcGhwLWJhc2UKCkNPUFkgLiAuCgpFWFBPU0UgMzAwMAoKQ01EIHBocCAtUyAwLjAuMC4wOjMwMDAK\"") | ||||
| 	_ = packr.PackJSONBytes("php", "app.php", "\"PD9waHAKICAgIGluY2x1ZGUoImZ4LnBocCIpOwogICAgJGRhdGEgPSBmaWxlX2dldF9jb250ZW50cygicGhwOi8vaW5wdXQiKTsKICAgICRyZXMgPSBqc29uX2RlY29kZSgkZGF0YSx0cnVlKTsKICAgICR2ID0gRngoJHJlc1siYSJdLCRyZXNbImIiXSk7CiAgICBlY2hvICR2Owo=\"") | ||||
| 	_ = packr.PackJSONBytes("php", "fx.php", "\"PD9waHAKICAgIGZ1bmN0aW9uIEZ4KCRhLCRiKSB7CiAgICAgICAgcmV0dXJuICRhKyRiOwogICAgfQo=\"") | ||||
| } | ||||
| @@ -1,5 +1,7 @@ | ||||
| FROM php:latest | ||||
| FROM metrue/fx-php-base | ||||
| 
 | ||||
| COPY . . | ||||
| 
 | ||||
| EXPOSE 3000 | ||||
| 
 | ||||
| CMD php -S 0.0.0.0:3000 | ||||
							
								
								
									
										4
									
								
								bundler/php/assets/fx.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										4
									
								
								bundler/php/assets/fx.php
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,4 @@ | ||||
| <?php | ||||
|     function Fx($a,$b) { | ||||
|         return $a+$b; | ||||
|     } | ||||
| @@ -2,5 +2,5 @@ | ||||
|     include("fx.php"); | ||||
|     $data = file_get_contents("php://input"); | ||||
|     $res = json_decode($data,true); | ||||
|     $v = Fx($res); | ||||
|     $v = Fx($res["a"],$res["b"]); | ||||
|     echo $v; | ||||
							
								
								
									
										8
									
								
								bundler/php/php-packr.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										8
									
								
								bundler/php/php-packr.go
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,8 @@ | ||||
| // +build !skippackr | ||||
| // Code generated by github.com/gobuffalo/packr/v2. DO NOT EDIT. | ||||
|  | ||||
| // You can use the "packr clean" command to clean up this, | ||||
| // and any other packr generated files. | ||||
| package php | ||||
|  | ||||
| import _ "github.com/metrue/fx/packrd" | ||||
							
								
								
									
										32
									
								
								bundler/php/php.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										32
									
								
								bundler/php/php.go
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,32 @@ | ||||
| package php | ||||
|  | ||||
| import ( | ||||
| 	"github.com/gobuffalo/packr/v2" | ||||
| 	"github.com/metrue/fx/bundler" | ||||
| ) | ||||
|  | ||||
| // Php defines php bundler | ||||
| type Php struct { | ||||
| 	assets *packr.Box | ||||
| } | ||||
|  | ||||
| // New a koa bundler | ||||
| func New() *Php { | ||||
| 	return &Php{ | ||||
| 		assets: packr.New("php", "./assets"), | ||||
| 	} | ||||
| } | ||||
|  | ||||
| // Scaffold a koa app | ||||
| func (k *Php) Scaffold(output string) error { | ||||
| 	return bundler.Restore(k.assets, output) | ||||
| } | ||||
|  | ||||
| // Bundle a function into a koa project | ||||
| func (k *Php) Bundle(output string, fn string, deps ...string) error { | ||||
| 	return bundler.Bundle(k.assets, output, "php", fn, deps...) | ||||
| } | ||||
|  | ||||
| var ( | ||||
| 	_ bundler.Bundler = &Php{} | ||||
| ) | ||||
							
								
								
									
										144
									
								
								bundler/php/php_test.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										144
									
								
								bundler/php/php_test.go
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,144 @@ | ||||
| package php | ||||
|  | ||||
| import ( | ||||
| 	"io/ioutil" | ||||
| 	"log" | ||||
| 	"os" | ||||
| 	"reflect" | ||||
| 	"testing" | ||||
|  | ||||
| 	"github.com/metrue/fx/utils" | ||||
| ) | ||||
|  | ||||
| func TestPhpBundler(t *testing.T) { | ||||
| 	t.Run("Scaffold", func(t *testing.T) { | ||||
| 		outputDir, err := ioutil.TempDir("", "fx_php") | ||||
| 		if err != nil { | ||||
| 			log.Fatal(err) | ||||
| 		} | ||||
| 		defer os.RemoveAll(outputDir) | ||||
|  | ||||
| 		php := New() | ||||
| 		if err := php.Scaffold(outputDir); err != nil { | ||||
| 			t.Fatal(err) | ||||
| 		} | ||||
|  | ||||
| 		diff, _, _, err := utils.Diff(outputDir, "./assets") | ||||
| 		if err != nil { | ||||
| 			t.Fatal(err) | ||||
| 		} | ||||
|  | ||||
| 		if diff { | ||||
| 			t.Fatalf("%s is not equal with %s", outputDir, "./assets") | ||||
| 		} | ||||
| 	}) | ||||
|  | ||||
| 	t.Run("BundleSingleFunc", func(t *testing.T) { | ||||
| 		fd, err := ioutil.TempFile("", "fx_func_*.php") | ||||
| 		if err != nil { | ||||
| 			t.Fatal(err) | ||||
| 		} | ||||
| 		defer os.Remove(fd.Name()) | ||||
|  | ||||
| 		content := `<?php | ||||
|     function Fx($a,$b) { | ||||
|         return $a + $b; | ||||
|     } | ||||
| 		` | ||||
| 		err = ioutil.WriteFile(fd.Name(), []byte(content), 0666) | ||||
| 		if err != nil { | ||||
| 			t.Fatal(err) | ||||
| 		} | ||||
|  | ||||
| 		outputDir, err := ioutil.TempDir("", "fx_php") | ||||
| 		if err != nil { | ||||
| 			log.Fatal(err) | ||||
| 		} | ||||
| 		defer os.RemoveAll(outputDir) | ||||
|  | ||||
| 		php := New() | ||||
| 		if err := php.Bundle(outputDir, fd.Name()); err != nil { | ||||
| 			t.Fatal(err) | ||||
| 		} | ||||
|  | ||||
| 		diff, pre, cur, err := utils.Diff("./assets", outputDir) | ||||
| 		if err != nil { | ||||
| 			t.Fatal(err) | ||||
| 		} | ||||
|  | ||||
| 		if !diff { | ||||
| 			t.Fatalf("handle function should be changed: %s == %s", pre, cur) | ||||
| 		} | ||||
|  | ||||
| 		if !reflect.DeepEqual(cur, []byte(content)) { | ||||
| 			t.Fatalf("it should be %s but got %s", content, cur) | ||||
| 		} | ||||
|  | ||||
| 		preHandleFunc, err := ioutil.ReadFile("./assets/fx.php") | ||||
| 		if err != nil { | ||||
| 			t.Fatal(err) | ||||
| 		} | ||||
| 		if !reflect.DeepEqual(pre, preHandleFunc) { | ||||
| 			{ | ||||
| 			} | ||||
| 			t.Fatalf("it should get %s but got %s", preHandleFunc, pre) | ||||
| 		} | ||||
| 	}) | ||||
|  | ||||
| 	t.Run("BundleFuncAndDeps", func(t *testing.T) { | ||||
| 		fd, err := ioutil.TempFile("", "fx_func_*.js") | ||||
| 		if err != nil { | ||||
| 			t.Fatal(err) | ||||
| 		} | ||||
| 		defer os.Remove(fd.Name()) | ||||
|  | ||||
| 		content, err := ioutil.ReadFile("./assets/fx.php") | ||||
| 		if err != nil { | ||||
| 			t.Fatal(err) | ||||
| 		} | ||||
| 		err = ioutil.WriteFile(fd.Name(), content, 0666) | ||||
| 		if err != nil { | ||||
| 			t.Fatal(err) | ||||
| 		} | ||||
|  | ||||
| 		addFunc := ` | ||||
| module.exports = (a, b) => a+b | ||||
|   ` | ||||
| 		addFd, err := ioutil.TempFile("", "fx_add_func_*.js") | ||||
| 		if err != nil { | ||||
| 			t.Fatal(err) | ||||
| 		} | ||||
|  | ||||
| 		err = ioutil.WriteFile(addFd.Name(), []byte(addFunc), 0644) | ||||
| 		if err != nil { | ||||
| 			t.Fatal(err) | ||||
| 		} | ||||
|  | ||||
| 		outputDir, err := ioutil.TempDir("", "fx_php") | ||||
| 		if err != nil { | ||||
| 			log.Fatal(err) | ||||
| 		} | ||||
| 		defer os.RemoveAll(outputDir) | ||||
|  | ||||
| 		php := New() | ||||
| 		if err := php.Bundle(outputDir, fd.Name(), addFd.Name()); err != nil { | ||||
| 			t.Fatal(err) | ||||
| 		} | ||||
|  | ||||
| 		diff, pre, cur, err := utils.Diff("./assets", outputDir) | ||||
| 		if err != nil { | ||||
| 			t.Fatal(err) | ||||
| 		} | ||||
|  | ||||
| 		if !diff { | ||||
| 			t.Fatalf("handle functino should be changed") | ||||
| 		} | ||||
|  | ||||
| 		if !reflect.DeepEqual(cur, []byte(addFunc)) { | ||||
| 			t.Fatalf("it should be %s but got %s", content, cur) | ||||
| 		} | ||||
| 		if pre != nil { | ||||
| 			t.Fatal(pre) | ||||
| 		} | ||||
| 	}) | ||||
| } | ||||
							
								
								
									
										13
									
								
								bundler/python/a_python-packr.go.tmpl
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										13
									
								
								bundler/python/a_python-packr.go.tmpl
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,13 @@ | ||||
| // Code generated by github.com/gobuffalo/packr. DO NOT EDIT. | ||||
|  | ||||
| package python | ||||
|  | ||||
| import "github.com/gobuffalo/packr" | ||||
|  | ||||
| // You can use the "packr clean" command to clean up this, | ||||
| // and any other packr generated files. | ||||
| func init() { | ||||
| 	_ = packr.PackJSONBytes("python", "Dockerfile", "\"RlJPTSBtZXRydWUvZngtcHl0aG9uLWJhc2UKCkNPUFkgLiAuCkVYUE9TRSAzMDAwCkNNRCBmbGFzayBydW4gLWggMC4wLjAuMCAtcCAzMDAwCg==\"") | ||||
| 	_ = packr.PackJSONBytes("python", "app.py", "\"ZnJvbSBmeCBpbXBvcnQgZngKZnJvbSBmbGFzayBpbXBvcnQgRmxhc2ssIHJlcXVlc3QsIGpzb25pZnkKYXBwID0gRmxhc2soX19uYW1lX18pCgpAYXBwLnJvdXRlKCcvJywgbWV0aG9kcz1bJ1BPU1QnLCAnR0VUJ10pCmRlZiBoYW5kbGUoKToKICAgIHJldHVybiBmeChyZXF1ZXN0KQo=\"") | ||||
| 	_ = packr.PackJSONBytes("python", "fx.py", "\"ZGVmIGZ4KHJlcXVlc3QpOgogICAgcmV0dXJuICJoZWxsbyB3b3JsZCIK\"") | ||||
| } | ||||
							
								
								
									
										8
									
								
								bundler/python/python-packr.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										8
									
								
								bundler/python/python-packr.go
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,8 @@ | ||||
| // +build !skippackr | ||||
| // Code generated by github.com/gobuffalo/packr/v2. DO NOT EDIT. | ||||
|  | ||||
| // You can use the "packr clean" command to clean up this, | ||||
| // and any other packr generated files. | ||||
| package python | ||||
|  | ||||
| import _ "github.com/metrue/fx/packrd" | ||||
							
								
								
									
										32
									
								
								bundler/python/python.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										32
									
								
								bundler/python/python.go
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,32 @@ | ||||
| package python | ||||
|  | ||||
| import ( | ||||
| 	"github.com/gobuffalo/packr/v2" | ||||
| 	"github.com/metrue/fx/bundler" | ||||
| ) | ||||
|  | ||||
| // Julia defines javascript bundler | ||||
| type Julia struct { | ||||
| 	assets *packr.Box | ||||
| } | ||||
|  | ||||
| // New a koa bundler | ||||
| func New() *Julia { | ||||
| 	return &Julia{ | ||||
| 		assets: packr.New("python", "./assets"), | ||||
| 	} | ||||
| } | ||||
|  | ||||
| // Scaffold a koa app | ||||
| func (k *Julia) Scaffold(output string) error { | ||||
| 	return bundler.Restore(k.assets, output) | ||||
| } | ||||
|  | ||||
| // Bundle a function into a koa project | ||||
| func (k *Julia) Bundle(output string, fn string, deps ...string) error { | ||||
| 	return bundler.Bundle(k.assets, output, "python", fn, deps...) | ||||
| } | ||||
|  | ||||
| var ( | ||||
| 	_ bundler.Bundler = &Julia{} | ||||
| ) | ||||
							
								
								
									
										148
									
								
								bundler/python/python_test.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										148
									
								
								bundler/python/python_test.go
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,148 @@ | ||||
| package python | ||||
|  | ||||
| import ( | ||||
| 	"io/ioutil" | ||||
| 	"log" | ||||
| 	"os" | ||||
| 	"reflect" | ||||
| 	"testing" | ||||
|  | ||||
| 	"github.com/metrue/fx/utils" | ||||
| ) | ||||
|  | ||||
| func TestJuliaBundler(t *testing.T) { | ||||
| 	t.Run("Scaffold", func(t *testing.T) { | ||||
| 		outputDir, err := ioutil.TempDir("", "fx_julia") | ||||
| 		if err != nil { | ||||
| 			log.Fatal(err) | ||||
| 		} | ||||
| 		defer os.RemoveAll(outputDir) | ||||
|  | ||||
| 		julia := New() | ||||
| 		if err := julia.Scaffold(outputDir); err != nil { | ||||
| 			t.Fatal(err) | ||||
| 		} | ||||
|  | ||||
| 		diff, _, _, err := utils.Diff(outputDir, "./assets") | ||||
| 		if err != nil { | ||||
| 			t.Fatal(err) | ||||
| 		} | ||||
|  | ||||
| 		if diff { | ||||
| 			t.Fatalf("%s is not equal with %s", outputDir, "./assets") | ||||
| 		} | ||||
| 	}) | ||||
|  | ||||
| 	t.Run("BundleSingleFunc", func(t *testing.T) { | ||||
| 		fd, err := ioutil.TempFile("", "fx_func_*.julia") | ||||
| 		if err != nil { | ||||
| 			t.Fatal(err) | ||||
| 		} | ||||
| 		defer os.Remove(fd.Name()) | ||||
|  | ||||
| 		content := `struct Input | ||||
|     a::Number | ||||
|     b::Number | ||||
| end | ||||
|  | ||||
| fx = function(input::Input) | ||||
|     return input.a + input.b | ||||
| end | ||||
| 		` | ||||
| 		err = ioutil.WriteFile(fd.Name(), []byte(content), 0666) | ||||
| 		if err != nil { | ||||
| 			t.Fatal(err) | ||||
| 		} | ||||
|  | ||||
| 		outputDir, err := ioutil.TempDir("", "fx_julia") | ||||
| 		if err != nil { | ||||
| 			log.Fatal(err) | ||||
| 		} | ||||
| 		defer os.RemoveAll(outputDir) | ||||
|  | ||||
| 		julia := New() | ||||
| 		if err := julia.Bundle(outputDir, fd.Name()); err != nil { | ||||
| 			t.Fatal(err) | ||||
| 		} | ||||
|  | ||||
| 		diff, pre, cur, err := utils.Diff("./assets", outputDir) | ||||
| 		if err != nil { | ||||
| 			t.Fatal(err) | ||||
| 		} | ||||
|  | ||||
| 		if !diff { | ||||
| 			t.Fatalf("handle function should be changed") | ||||
| 		} | ||||
|  | ||||
| 		if !reflect.DeepEqual(cur, []byte(content)) { | ||||
| 			t.Fatalf("it should be %s but got %s", content, cur) | ||||
| 		} | ||||
|  | ||||
| 		preHandleFunc, err := ioutil.ReadFile("./assets/fx.py") | ||||
| 		if err != nil { | ||||
| 			t.Fatal(err) | ||||
| 		} | ||||
| 		if !reflect.DeepEqual(pre, preHandleFunc) { | ||||
| 			{ | ||||
| 			} | ||||
| 			t.Fatalf("it should get %s but got %s", preHandleFunc, pre) | ||||
| 		} | ||||
| 	}) | ||||
|  | ||||
| 	t.Run("BundleFuncAndDeps", func(t *testing.T) { | ||||
| 		fd, err := ioutil.TempFile("", "fx_func_*.js") | ||||
| 		if err != nil { | ||||
| 			t.Fatal(err) | ||||
| 		} | ||||
| 		defer os.Remove(fd.Name()) | ||||
|  | ||||
| 		content, err := ioutil.ReadFile("./assets/fx.py") | ||||
| 		if err != nil { | ||||
| 			t.Fatal(err) | ||||
| 		} | ||||
| 		err = ioutil.WriteFile(fd.Name(), content, 0666) | ||||
| 		if err != nil { | ||||
| 			t.Fatal(err) | ||||
| 		} | ||||
|  | ||||
| 		addFunc := ` | ||||
| module.exports = (a, b) => a+b | ||||
|   ` | ||||
| 		addFd, err := ioutil.TempFile("", "fx_add_func_*.js") | ||||
| 		if err != nil { | ||||
| 			t.Fatal(err) | ||||
| 		} | ||||
|  | ||||
| 		err = ioutil.WriteFile(addFd.Name(), []byte(addFunc), 0644) | ||||
| 		if err != nil { | ||||
| 			t.Fatal(err) | ||||
| 		} | ||||
|  | ||||
| 		outputDir, err := ioutil.TempDir("", "fx_julia") | ||||
| 		if err != nil { | ||||
| 			log.Fatal(err) | ||||
| 		} | ||||
| 		defer os.RemoveAll(outputDir) | ||||
|  | ||||
| 		julia := New() | ||||
| 		if err := julia.Bundle(outputDir, fd.Name(), addFd.Name()); err != nil { | ||||
| 			t.Fatal(err) | ||||
| 		} | ||||
|  | ||||
| 		diff, pre, cur, err := utils.Diff("./assets", outputDir) | ||||
| 		if err != nil { | ||||
| 			t.Fatal(err) | ||||
| 		} | ||||
|  | ||||
| 		if !diff { | ||||
| 			t.Fatalf("handle functino should be changed") | ||||
| 		} | ||||
|  | ||||
| 		if !reflect.DeepEqual(cur, []byte(addFunc)) { | ||||
| 			t.Fatalf("it should be %s but got %s", content, cur) | ||||
| 		} | ||||
| 		if pre != nil { | ||||
| 			t.Fatal(pre) | ||||
| 		} | ||||
| 	}) | ||||
| } | ||||
							
								
								
									
										13
									
								
								bundler/ruby/a_ruby-packr.go.tmpl
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										13
									
								
								bundler/ruby/a_ruby-packr.go.tmpl
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,13 @@ | ||||
| // Code generated by github.com/gobuffalo/packr. DO NOT EDIT. | ||||
|  | ||||
| package ruby | ||||
|  | ||||
| import "github.com/gobuffalo/packr" | ||||
|  | ||||
| // You can use the "packr clean" command to clean up this, | ||||
| // and any other packr generated files. | ||||
| func init() { | ||||
| 	_ = packr.PackJSONBytes("ruby", "Dockerfile", "\"RlJPTSBtZXRydWUvZngtcnVieS1iYXNlCgpDT1BZIC4gLgpFWFBPU0UgMzAwMApDTUQgcnVieSBhcHAucmIgLXAgMzAwMCAtbyAwLjAuMC4wCg==\"") | ||||
| 	_ = packr.PackJSONBytes("ruby", "app.rb", "\"cmVxdWlyZSAnc2luYXRyYScKcmVxdWlyZSAnanNvbicKCnJlcXVpcmVfcmVsYXRpdmUgJ2Z4LnJiJwoKc2V0IDpwb3J0LCAzMDAwCgpwb3N0ICcvJyBkbwogICAgY3R4ID0gewogICAgICA6cmVxdWVzdCA9PiByZXF1ZXN0LAogICAgICA6cmVzcG9uc2UgPT4gcmVzcG9uc2UsCiAgICAgIDpzdGF0dXMgPT4gc3RhdHVzLAogICAgICA6aGVhZGVycyA9PiBoZWFkZXJzLAogICAgfQogICAgZnggY3R4CmVuZAoKZ2V0ICcvJyBkbwogICAgY3R4ID0gewogICAgICA6cmVxdWVzdCA9PiByZXF1ZXN0LAogICAgICA6cmVzcG9uc2UgPT4gcmVzcG9uc2UsCiAgICAgIDpzdGF0dXMgPT4gc3RhdHVzLAogICAgICA6aGVhZGVycyA9PiBoZWFkZXJzLAogICAgfQogICAgZnggY3R4CmVuZAo=\"") | ||||
| 	_ = packr.PackJSONBytes("ruby", "fx.rb", "\"IwojIGN0eCA9IHsKIyAgIDpyZXF1ZXN0ID0+IHJlcXVlc3QsCiMgICA6cmVzcG9uc2UgPT4gcmVzcG9uc2UsCiMgICA6c3RhdHVzID0+IHN0YXR1cywKIyAgIDpoZWFkZXJzID0+IGhlYWRlcnMsCiMgfQpkZWYgZngoY3R4KQogIGN0eFs6cmVzcG9uc2VdLmJvZHkgPSAiaGVsbG8gd29ybGQiCmVuZAo=\"") | ||||
| } | ||||
| @@ -1,6 +1,4 @@ | ||||
| FROM ruby:latest | ||||
| 
 | ||||
| RUN gem install sinatra | ||||
| FROM metrue/fx-ruby-base | ||||
| 
 | ||||
| COPY . . | ||||
| EXPOSE 3000 | ||||
Some files were not shown because too many files have changed in this diff Show More
		Reference in New Issue
	
	Block a user