├── .dockerignore ├── .eslintrc.yml ├── .gitattributes ├── .github ├── CODEOWNERS ├── pull_request_template.md └── workflows │ ├── build.yml │ ├── pull-request-lint.yml │ ├── release.yml │ ├── update-tesseract.yml │ └── upgrade-main.yml ├── .gitignore ├── .mergify.yml ├── .npmignore ├── .projen ├── deps.json ├── files.json └── tasks.json ├── .projenrc.ts ├── Dockerfile.al1 ├── Dockerfile.al2 ├── LICENSE ├── README.md ├── cdk.json ├── continous-integration ├── README.md ├── lambda-handlers │ ├── node │ │ ├── .gitattributes │ │ ├── .gitignore │ │ ├── .npmignore │ │ ├── .projen │ │ │ ├── deps.json │ │ │ ├── files.json │ │ │ └── tasks.json │ │ ├── README.md │ │ ├── faust.png │ │ ├── index.js │ │ ├── package.json │ │ └── yarn.lock │ └── python │ │ ├── Pipfile │ │ ├── Pipfile.lock │ │ ├── faust.png │ │ ├── handler.py │ │ └── requirements.txt └── main.ts ├── create_release_assets.sh ├── example ├── README.md ├── cdk │ ├── .eslintrc.json │ ├── .gitattributes │ ├── .gitignore │ ├── .npmignore │ ├── .projen │ │ ├── deps.json │ │ ├── files.json │ │ └── tasks.json │ ├── README.md │ ├── cdk.json │ ├── deployment.png │ ├── package.json │ ├── src │ │ ├── lambda-handlers │ │ │ ├── handler.py │ │ │ └── requirements.txt │ │ └── main.ts │ ├── tsconfig.dev.json │ ├── tsconfig.json │ └── yarn.lock └── serverless │ ├── Dockerfile │ ├── README.md │ ├── deployment.png │ ├── handler.py │ ├── package-lock.json │ ├── package.json │ ├── requirements.txt │ └── serverless.yml ├── package.json ├── ready-to-use ├── README.md └── amazonlinux-2 │ ├── TESSERACT-README.md │ ├── bin │ └── tesseract │ ├── lib │ ├── libgomp.so.1 │ ├── libjbig.so.2.0 │ ├── libjpeg.so.62 │ ├── libleptonica.so.6 │ ├── libpng15.so.15 │ ├── libtesseract.so.5 │ ├── libtiff.so.5 │ └── libwebp.so.4 │ └── tesseract │ └── share │ └── tessdata │ ├── deu.traineddata │ ├── eng.traineddata │ └── osd.traineddata ├── tsconfig.dev.json ├── tsconfig.json └── yarn.lock /.dockerignore: -------------------------------------------------------------------------------- 1 | * -------------------------------------------------------------------------------- /.eslintrc.yml: -------------------------------------------------------------------------------- 1 | # ~~ Generated by projen. To modify, edit .projenrc.ts and run "npx projen". 2 | 3 | env: 4 | jest: true 5 | node: true 6 | root: true 7 | plugins: 8 | - "@typescript-eslint" 9 | - import 10 | parser: "@typescript-eslint/parser" 11 | parserOptions: 12 | ecmaVersion: 2018 13 | sourceType: module 14 | project: ./tsconfig.dev.json 15 | extends: 16 | - plugin:import/typescript 17 | - plugin:prettier/recommended 18 | settings: 19 | import/parsers: 20 | "@typescript-eslint/parser": 21 | - .ts 22 | - .tsx 23 | import/resolver: 24 | node: {} 25 | typescript: 26 | project: ./tsconfig.dev.json 27 | alwaysTryTypes: true 28 | ignorePatterns: 29 | - "**/node_modules/" 30 | - "*.d.ts" 31 | - build 32 | - cdk.out 33 | - "**/__snapshots__" 34 | - example 35 | - "!.projenrc.ts" 36 | - "!projenrc/**/*.ts" 37 | rules: 38 | curly: 39 | - error 40 | - multi-line 41 | - consistent 42 | "@typescript-eslint/no-require-imports": error 43 | import/no-extraneous-dependencies: 44 | - error 45 | - devDependencies: 46 | - "**/test/**" 47 | - "**/build-tools/**" 48 | - .projenrc.ts 49 | - projenrc/**/*.ts 50 | optionalDependencies: false 51 | peerDependencies: true 52 | import/no-unresolved: 53 | - error 54 | import/order: 55 | - warn 56 | - groups: 57 | - builtin 58 | - external 59 | alphabetize: 60 | order: asc 61 | caseInsensitive: true 62 | import/no-duplicates: 63 | - error 64 | no-shadow: 65 | - off 66 | "@typescript-eslint/no-shadow": error 67 | "@typescript-eslint/no-floating-promises": error 68 | no-return-await: 69 | - off 70 | "@typescript-eslint/return-await": error 71 | dot-notation: 72 | - error 73 | no-bitwise: 74 | - error 75 | "@typescript-eslint/member-ordering": 76 | - error 77 | - default: 78 | - public-static-field 79 | - public-static-method 80 | - protected-static-field 81 | - protected-static-method 82 | - private-static-field 83 | - private-static-method 84 | - field 85 | - constructor 86 | - method 87 | prettier/prettier: 88 | - error 89 | - singleQuote: true 90 | printWidth: 140 91 | trailingComma: all 92 | overrides: 93 | - files: 94 | - .projenrc.ts 95 | rules: 96 | "@typescript-eslint/no-require-imports": off 97 | import/no-extraneous-dependencies: off 98 | -------------------------------------------------------------------------------- /.gitattributes: -------------------------------------------------------------------------------- 1 | # ~~ Generated by projen. To modify, edit .projenrc.ts and run "npx projen". 2 | 3 | * text=auto eol=lf 4 | *.snap linguist-generated 5 | /.eslintrc.yml linguist-generated 6 | /.gitattributes linguist-generated 7 | /.github/pull_request_template.md linguist-generated 8 | /.github/workflows/build.yml linguist-generated 9 | /.github/workflows/pull-request-lint.yml linguist-generated 10 | /.github/workflows/release.yml linguist-generated 11 | /.github/workflows/upgrade-main.yml linguist-generated 12 | /.gitignore linguist-generated 13 | /.mergify.yml linguist-generated 14 | /.npmignore linguist-generated 15 | /.projen/** linguist-generated 16 | /.projen/deps.json linguist-generated 17 | /.projen/files.json linguist-generated 18 | /.projen/tasks.json linguist-generated 19 | /cdk.json linguist-generated 20 | /LICENSE linguist-generated 21 | /package.json linguist-generated 22 | /tsconfig.dev.json linguist-generated 23 | /tsconfig.json linguist-generated 24 | /yarn.lock linguist-generated -------------------------------------------------------------------------------- /.github/CODEOWNERS: -------------------------------------------------------------------------------- 1 | * @bweigel -------------------------------------------------------------------------------- /.github/pull_request_template.md: -------------------------------------------------------------------------------- 1 | Fixes # -------------------------------------------------------------------------------- /.github/workflows/build.yml: -------------------------------------------------------------------------------- 1 | # ~~ Generated by projen. To modify, edit .projenrc.ts and run "npx projen". 2 | 3 | name: build 4 | on: 5 | pull_request: {} 6 | workflow_dispatch: {} 7 | jobs: 8 | build: 9 | runs-on: ubuntu-latest 10 | permissions: 11 | contents: write 12 | outputs: 13 | self_mutation_happened: ${{ steps.self_mutation.outputs.self_mutation_happened }} 14 | env: 15 | CI: "true" 16 | steps: 17 | - name: Checkout 18 | uses: actions/checkout@v4 19 | with: 20 | ref: ${{ github.event.pull_request.head.ref }} 21 | repository: ${{ github.event.pull_request.head.repo.full_name }} 22 | - uses: actions/setup-python@v5 23 | with: 24 | python-version: "3.8" 25 | - name: Install pipenv 26 | run: curl https://raw.githubusercontent.com/pypa/pipenv/master/get-pipenv.py | python 27 | - uses: aws-actions/setup-sam@v2 28 | - name: Install dependencies 29 | run: yarn install --check-files 30 | - name: build 31 | run: npx projen build 32 | - name: Find mutations 33 | id: self_mutation 34 | run: |- 35 | git add . 36 | git diff --binary --staged --patch --exit-code > repo.patch || echo "self_mutation_happened=true" >> $GITHUB_OUTPUT 37 | working-directory: ./ 38 | - name: Upload patch 39 | if: steps.self_mutation.outputs.self_mutation_happened 40 | uses: actions/upload-artifact@v4.4.0 41 | with: 42 | name: repo.patch 43 | path: repo.patch 44 | overwrite: true 45 | - name: Fail build on mutation 46 | if: steps.self_mutation.outputs.self_mutation_happened 47 | run: |- 48 | echo "::error::Files were changed during build (see build log). If this was triggered from a fork, you will need to update your branch." 49 | cat repo.patch 50 | exit 1 51 | self-mutation: 52 | needs: build 53 | runs-on: ubuntu-latest 54 | permissions: 55 | contents: write 56 | if: always() && needs.build.outputs.self_mutation_happened && !(github.event.pull_request.head.repo.full_name != github.repository) 57 | steps: 58 | - name: Generate token 59 | id: generate_token 60 | uses: actions/create-github-app-token@3ff1caaa28b64c9cc276ce0a02e2ff584f3900c5 61 | with: 62 | app-id: ${{ secrets.PROJEN_APP_ID }} 63 | private-key: ${{ secrets.PROJEN_APP_PRIVATE_KEY }} 64 | - name: Checkout 65 | uses: actions/checkout@v4 66 | with: 67 | token: ${{ steps.generate_token.outputs.token }} 68 | ref: ${{ github.event.pull_request.head.ref }} 69 | repository: ${{ github.event.pull_request.head.repo.full_name }} 70 | - name: Download patch 71 | uses: actions/download-artifact@v4 72 | with: 73 | name: repo.patch 74 | path: ${{ runner.temp }} 75 | - name: Apply patch 76 | run: '[ -s ${{ runner.temp }}/repo.patch ] && git apply ${{ runner.temp }}/repo.patch || echo "Empty patch. Skipping."' 77 | - name: Set git identity 78 | run: |- 79 | git config user.name "github-actions" 80 | git config user.email "github-actions@github.com" 81 | - name: Push changes 82 | env: 83 | PULL_REQUEST_REF: ${{ github.event.pull_request.head.ref }} 84 | run: |- 85 | git add . 86 | git commit -s -m "chore: self mutation" 87 | git push origin HEAD:$PULL_REQUEST_REF 88 | -------------------------------------------------------------------------------- /.github/workflows/pull-request-lint.yml: -------------------------------------------------------------------------------- 1 | # ~~ Generated by projen. To modify, edit .projenrc.ts and run "npx projen". 2 | 3 | name: pull-request-lint 4 | on: 5 | pull_request_target: 6 | types: 7 | - labeled 8 | - opened 9 | - synchronize 10 | - reopened 11 | - ready_for_review 12 | - edited 13 | merge_group: {} 14 | jobs: 15 | validate: 16 | name: Validate PR title 17 | runs-on: ubuntu-latest 18 | permissions: 19 | pull-requests: write 20 | if: (github.event_name == 'pull_request' || github.event_name == 'pull_request_target') 21 | steps: 22 | - uses: amannn/action-semantic-pull-request@v5.4.0 23 | env: 24 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} 25 | with: 26 | types: |- 27 | feat 28 | fix 29 | chore 30 | build 31 | docs 32 | requireScope: false 33 | -------------------------------------------------------------------------------- /.github/workflows/release.yml: -------------------------------------------------------------------------------- 1 | # ~~ Generated by projen. To modify, edit .projenrc.ts and run "npx projen". 2 | 3 | name: release 4 | on: 5 | schedule: 6 | - cron: 0 0 1 1 * 7 | workflow_dispatch: {} 8 | concurrency: 9 | group: ${{ github.workflow }} 10 | cancel-in-progress: false 11 | jobs: 12 | release: 13 | runs-on: ubuntu-latest 14 | permissions: 15 | contents: write 16 | outputs: 17 | latest_commit: ${{ steps.git_remote.outputs.latest_commit }} 18 | tag_exists: ${{ steps.check_tag_exists.outputs.exists }} 19 | env: 20 | CI: "true" 21 | steps: 22 | - name: Checkout 23 | uses: actions/checkout@v4 24 | with: 25 | fetch-depth: 0 26 | - name: Set git identity 27 | run: |- 28 | git config user.name "github-actions" 29 | git config user.email "github-actions@github.com" 30 | - uses: actions/setup-python@v5 31 | with: 32 | python-version: "3.8" 33 | - name: Install pipenv 34 | run: curl https://raw.githubusercontent.com/pypa/pipenv/master/get-pipenv.py | python 35 | - uses: aws-actions/setup-sam@v2 36 | - name: Install dependencies 37 | run: yarn install --check-files --frozen-lockfile 38 | - name: release 39 | run: npx projen release 40 | - name: Check if version has already been tagged 41 | id: check_tag_exists 42 | run: |- 43 | TAG=$(cat dist/releasetag.txt) 44 | ([ ! -z "$TAG" ] && git ls-remote -q --exit-code --tags origin $TAG && (echo "exists=true" >> $GITHUB_OUTPUT)) || (echo "exists=false" >> $GITHUB_OUTPUT) 45 | cat $GITHUB_OUTPUT 46 | - name: Check for new commits 47 | id: git_remote 48 | run: |- 49 | echo "latest_commit=$(git ls-remote origin -h ${{ github.ref }} | cut -f1)" >> $GITHUB_OUTPUT 50 | cat $GITHUB_OUTPUT 51 | - name: Backup artifact permissions 52 | if: ${{ steps.git_remote.outputs.latest_commit == github.sha }} 53 | run: cd dist && getfacl -R . > permissions-backup.acl 54 | continue-on-error: true 55 | - name: Upload artifact 56 | if: ${{ steps.git_remote.outputs.latest_commit == github.sha }} 57 | uses: actions/upload-artifact@v4.4.0 58 | with: 59 | name: build-artifact 60 | path: dist 61 | overwrite: true 62 | release_github: 63 | name: Publish to GitHub Releases 64 | needs: release 65 | runs-on: ubuntu-latest 66 | permissions: 67 | contents: write 68 | if: needs.release.outputs.tag_exists != 'true' && needs.release.outputs.latest_commit == github.sha 69 | steps: 70 | - uses: actions/setup-node@v4 71 | with: 72 | node-version: lts/* 73 | - name: Download build artifacts 74 | uses: actions/download-artifact@v4 75 | with: 76 | name: build-artifact 77 | path: dist 78 | - name: Restore build artifact permissions 79 | run: cd dist && setfacl --restore=permissions-backup.acl 80 | continue-on-error: true 81 | - name: Release 82 | env: 83 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} 84 | run: errout=$(mktemp); gh release create $(cat dist/releasetag.txt) -R $GITHUB_REPOSITORY -F dist/changelog.md -t $(cat dist/releasetag.txt) --target $GITHUB_SHA 2> $errout && true; exitcode=$?; if [ $exitcode -ne 0 ] && ! grep -q "Release.tag_name already exists" $errout; then cat $errout; exit $exitcode; fi 85 | upload_release_artifact: 86 | needs: 87 | - release 88 | - release_github 89 | runs-on: ubuntu-latest 90 | permissions: 91 | contents: write 92 | if: needs.release.outputs.latest_commit == github.sha 93 | steps: 94 | - uses: actions/setup-node@v4 95 | with: 96 | node-version: "18" 97 | - name: Download build artifacts 98 | uses: actions/download-artifact@v4 99 | with: 100 | name: build-artifact 101 | path: dist 102 | - name: Restore build artifact permissions 103 | run: cd dist && setfacl --restore=permissions-backup.acl 104 | continue-on-error: true 105 | - name: Upload Release Artifacts 106 | env: 107 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} 108 | GITHUB_REPOSITORY: ${{ github.repository }} 109 | GITHUB_REF: ${{ github.ref }} 110 | run: errout=$(mktemp); gh release upload $(cat dist/releasetag.txt) --clobber -R $GITHUB_REPOSITORY dist/tesseract-al2-x86.zip 2> $errout && true; exitcode=$?; if [ $exitcode -ne 0 ] && ! grep -q "Release.tag_name already exists" $errout; then cat $errout; exit $exitcode; fi 111 | -------------------------------------------------------------------------------- /.github/workflows/update-tesseract.yml: -------------------------------------------------------------------------------- 1 | name: "Bump tesseract version" 2 | on: 3 | schedule: 4 | - cron: "0 0 * * MON" 5 | workflow_dispatch: 6 | 7 | jobs: 8 | diff: 9 | runs-on: ubuntu-latest 10 | steps: 11 | - uses: actions/github-script@v6 12 | id: tesseract 13 | with: 14 | result-encoding: string 15 | script: | 16 | const latest = (await github.rest.repos.getLatestRelease({ 17 | owner: 'tesseract-ocr', 18 | repo: 'tesseract', 19 | })).data.tag_name; 20 | return latest; 21 | 22 | - uses: actions/github-script@v6 23 | id: leptonica 24 | with: 25 | result-encoding: string 26 | script: | 27 | const latest = (await github.rest.repos.getLatestRelease({ 28 | owner: 'DanBloomberg', 29 | repo: 'leptonica', 30 | })).data.tag_name; 31 | return latest; 32 | - uses: actions/checkout@v3 33 | with: 34 | fetch-depth: 1 35 | - name: update-dockerfile 36 | run: | 37 | sed -i 's/\(TESSERACT_VERSION=\)[0-9\.]*$/\1${{ steps.tesseract.outputs.result }}/g' Dockerfile.al1 38 | sed -i 's/\(TESSERACT_VERSION=\)[0-9\.]*$/\1${{ steps.tesseract.outputs.result }}/g' Dockerfile.al2 39 | sed -i 's/\(LEPTONICA_VERSION=\)[0-9\.]*$/\1${{ steps.leptonica.outputs.result }}/g' Dockerfile.al1 40 | sed -i 's/\(LEPTONICA_VERSION=\)[0-9\.]*$/\1${{ steps.leptonica.outputs.result }}/g' Dockerfile.al2 41 | - name: update-README 42 | run: | 43 | sed -i 's/\(https:\/\/img\.shields\.io\/badge\/Tesseract-\)\(v\?\([0-9]\+\.\?\)\{3\}\)\(-green\)/\1${{ steps.tesseract.outputs.result }}\4/g' README.md 44 | sed -i 's/\(https:\/\/img\.shields\.io\/badge\/Leptonica-\)\(v\?\([0-9]\+\.\?\)\{3\}\)\(-green\)/\1${{ steps.leptonica.outputs.result }}\4/g' README.md 45 | - name: Create Pull Request 46 | uses: peter-evans/create-pull-request@v4 47 | with: 48 | commit-message: "chore: bump tesseract to ${{ steps.tesseract.outputs.result }} & leptonica to ${{ steps.leptonica.outputs.result }}" 49 | title: "chore: bump tesseract to ${{ steps.tesseract.outputs.result }} & leptonica to ${{ steps.leptonica.outputs.result }}" -------------------------------------------------------------------------------- /.github/workflows/upgrade-main.yml: -------------------------------------------------------------------------------- 1 | # ~~ Generated by projen. To modify, edit .projenrc.ts and run "npx projen". 2 | 3 | name: upgrade-main 4 | on: 5 | workflow_dispatch: {} 6 | schedule: 7 | - cron: 0 0 * * 1 8 | jobs: 9 | upgrade: 10 | name: Upgrade 11 | runs-on: ubuntu-latest 12 | permissions: 13 | contents: read 14 | outputs: 15 | patch_created: ${{ steps.create_patch.outputs.patch_created }} 16 | steps: 17 | - name: Checkout 18 | uses: actions/checkout@v4 19 | with: 20 | ref: main 21 | - uses: actions/setup-python@v5 22 | with: 23 | python-version: "3.8" 24 | - name: Install pipenv 25 | run: curl https://raw.githubusercontent.com/pypa/pipenv/master/get-pipenv.py | python 26 | - uses: aws-actions/setup-sam@v2 27 | - name: Install dependencies 28 | run: yarn install --check-files --frozen-lockfile 29 | - name: Upgrade dependencies 30 | run: npx projen upgrade 31 | - name: Find mutations 32 | id: create_patch 33 | run: |- 34 | git add . 35 | git diff --staged --patch --exit-code > repo.patch || echo "patch_created=true" >> $GITHUB_OUTPUT 36 | working-directory: ./ 37 | - name: Upload patch 38 | if: steps.create_patch.outputs.patch_created 39 | uses: actions/upload-artifact@v4.4.0 40 | with: 41 | name: repo.patch 42 | path: repo.patch 43 | overwrite: true 44 | pr: 45 | name: Create Pull Request 46 | needs: upgrade 47 | runs-on: ubuntu-latest 48 | permissions: 49 | contents: read 50 | if: ${{ needs.upgrade.outputs.patch_created }} 51 | steps: 52 | - name: Generate token 53 | id: generate_token 54 | uses: actions/create-github-app-token@3ff1caaa28b64c9cc276ce0a02e2ff584f3900c5 55 | with: 56 | app-id: ${{ secrets.PROJEN_APP_ID }} 57 | private-key: ${{ secrets.PROJEN_APP_PRIVATE_KEY }} 58 | - name: Checkout 59 | uses: actions/checkout@v4 60 | with: 61 | ref: main 62 | - name: Download patch 63 | uses: actions/download-artifact@v4 64 | with: 65 | name: repo.patch 66 | path: ${{ runner.temp }} 67 | - name: Apply patch 68 | run: '[ -s ${{ runner.temp }}/repo.patch ] && git apply ${{ runner.temp }}/repo.patch || echo "Empty patch. Skipping."' 69 | - name: Set git identity 70 | run: |- 71 | git config user.name "github-actions" 72 | git config user.email "github-actions@github.com" 73 | - name: Create Pull Request 74 | id: create-pr 75 | uses: peter-evans/create-pull-request@v6 76 | with: 77 | token: ${{ steps.generate_token.outputs.token }} 78 | commit-message: |- 79 | chore(deps): Dependency update 80 | 81 | Upgrades project dependencies. See details in [workflow run]. 82 | 83 | [Workflow Run]: ${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }} 84 | 85 | ------ 86 | 87 | *Automatically created by projen via the "upgrade-main" workflow* 88 | branch: github-actions/upgrade-main 89 | title: "chore(deps): Dependency update" 90 | labels: dependencies 91 | body: |- 92 | Upgrades project dependencies. See details in [workflow run]. 93 | 94 | [Workflow Run]: ${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }} 95 | 96 | ------ 97 | 98 | *Automatically created by projen via the "upgrade-main" workflow* 99 | author: github-actions 100 | committer: github-actions 101 | signoff: true 102 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # ~~ Generated by projen. To modify, edit .projenrc.ts and run "npx projen". 2 | !/.gitattributes 3 | !/.projen/tasks.json 4 | !/.projen/deps.json 5 | !/.projen/files.json 6 | !/.github/workflows/pull-request-lint.yml 7 | !/package.json 8 | !/LICENSE 9 | !/.npmignore 10 | logs 11 | *.log 12 | npm-debug.log* 13 | yarn-debug.log* 14 | yarn-error.log* 15 | lerna-debug.log* 16 | report.[0-9]*.[0-9]*.[0-9]*.[0-9]*.json 17 | pids 18 | *.pid 19 | *.seed 20 | *.pid.lock 21 | lib-cov 22 | coverage 23 | *.lcov 24 | .nyc_output 25 | build/Release 26 | node_modules/ 27 | jspm_packages/ 28 | *.tsbuildinfo 29 | .eslintcache 30 | *.tgz 31 | .yarn-integrity 32 | .cache 33 | layer 34 | .serverless 35 | .mypy_cache 36 | *.zip 37 | **/*test-output.txt 38 | cdk.out/ 39 | /test-reports/ 40 | junit.xml 41 | /coverage/ 42 | !/.github/workflows/build.yml 43 | /dist/changelog.md 44 | /dist/version.txt 45 | !/.github/workflows/release.yml 46 | !/.mergify.yml 47 | !/.github/workflows/upgrade-main.yml 48 | !/.github/pull_request_template.md 49 | !/test/ 50 | !/tsconfig.json 51 | !/tsconfig.dev.json 52 | !/continous-integration/ 53 | /lib 54 | /dist/ 55 | !/.eslintrc.yml 56 | /assets/ 57 | !/cdk.json 58 | /cdk.out/ 59 | .cdk.staging/ 60 | .parcel-cache/ 61 | !/.projenrc.ts 62 | -------------------------------------------------------------------------------- /.mergify.yml: -------------------------------------------------------------------------------- 1 | # ~~ Generated by projen. To modify, edit .projenrc.ts and run "npx projen". 2 | 3 | queue_rules: 4 | - name: default 5 | update_method: merge 6 | conditions: 7 | - "#approved-reviews-by>=1" 8 | - -label~=(do-not-merge) 9 | - status-success=build 10 | merge_method: squash 11 | commit_message_template: |- 12 | {{ title }} (#{{ number }}) 13 | 14 | {{ body }} 15 | pull_request_rules: 16 | - name: Automatic merge on approval and successful build 17 | actions: 18 | delete_head_branch: {} 19 | queue: 20 | name: default 21 | conditions: 22 | - "#approved-reviews-by>=1" 23 | - -label~=(do-not-merge) 24 | - status-success=build 25 | -------------------------------------------------------------------------------- /.npmignore: -------------------------------------------------------------------------------- 1 | # ~~ Generated by projen. To modify, edit .projenrc.ts and run "npx projen". 2 | /.projen/ 3 | /test-reports/ 4 | junit.xml 5 | /coverage/ 6 | permissions-backup.acl 7 | /dist/changelog.md 8 | /dist/version.txt 9 | /.mergify.yml 10 | /test/ 11 | /tsconfig.dev.json 12 | /continous-integration/ 13 | !/lib/ 14 | !/lib/**/*.js 15 | !/lib/**/*.d.ts 16 | dist 17 | /tsconfig.json 18 | /.github/ 19 | /.vscode/ 20 | /.idea/ 21 | /.projenrc.js 22 | tsconfig.tsbuildinfo 23 | /.eslintrc.json 24 | !/assets/ 25 | cdk.out/ 26 | .cdk.staging/ 27 | /.gitattributes 28 | /.projenrc.ts 29 | /projenrc 30 | -------------------------------------------------------------------------------- /.projen/deps.json: -------------------------------------------------------------------------------- 1 | { 2 | "dependencies": [ 3 | { 4 | "name": "@types/jest", 5 | "type": "build" 6 | }, 7 | { 8 | "name": "@types/node", 9 | "type": "build" 10 | }, 11 | { 12 | "name": "@typescript-eslint/eslint-plugin", 13 | "version": "^8", 14 | "type": "build" 15 | }, 16 | { 17 | "name": "@typescript-eslint/parser", 18 | "version": "^8", 19 | "type": "build" 20 | }, 21 | { 22 | "name": "aws-cdk", 23 | "version": "^2", 24 | "type": "build" 25 | }, 26 | { 27 | "name": "commit-and-tag-version", 28 | "version": "^12", 29 | "type": "build" 30 | }, 31 | { 32 | "name": "esbuild", 33 | "type": "build" 34 | }, 35 | { 36 | "name": "eslint-config-prettier", 37 | "type": "build" 38 | }, 39 | { 40 | "name": "eslint-import-resolver-typescript", 41 | "type": "build" 42 | }, 43 | { 44 | "name": "eslint-plugin-import", 45 | "type": "build" 46 | }, 47 | { 48 | "name": "eslint-plugin-prettier", 49 | "type": "build" 50 | }, 51 | { 52 | "name": "eslint", 53 | "version": "^9", 54 | "type": "build" 55 | }, 56 | { 57 | "name": "jest", 58 | "type": "build" 59 | }, 60 | { 61 | "name": "jest-junit", 62 | "version": "^16", 63 | "type": "build" 64 | }, 65 | { 66 | "name": "prettier", 67 | "type": "build" 68 | }, 69 | { 70 | "name": "projen", 71 | "type": "build" 72 | }, 73 | { 74 | "name": "ts-jest", 75 | "type": "build" 76 | }, 77 | { 78 | "name": "ts-node", 79 | "type": "build" 80 | }, 81 | { 82 | "name": "typescript", 83 | "type": "build" 84 | }, 85 | { 86 | "name": "aws-cdk-lib", 87 | "version": "^2.95.0", 88 | "type": "runtime" 89 | }, 90 | { 91 | "name": "constructs", 92 | "version": "^10.0.5", 93 | "type": "runtime" 94 | } 95 | ], 96 | "//": "~~ Generated by projen. To modify, edit .projenrc.ts and run \"npx projen\"." 97 | } 98 | -------------------------------------------------------------------------------- /.projen/files.json: -------------------------------------------------------------------------------- 1 | { 2 | "files": [ 3 | ".eslintrc.yml", 4 | ".gitattributes", 5 | ".github/pull_request_template.md", 6 | ".github/workflows/build.yml", 7 | ".github/workflows/pull-request-lint.yml", 8 | ".github/workflows/release.yml", 9 | ".github/workflows/upgrade-main.yml", 10 | ".gitignore", 11 | ".mergify.yml", 12 | ".npmignore", 13 | ".projen/deps.json", 14 | ".projen/files.json", 15 | ".projen/tasks.json", 16 | "cdk.json", 17 | "LICENSE", 18 | "tsconfig.dev.json", 19 | "tsconfig.json" 20 | ], 21 | "//": "~~ Generated by projen. To modify, edit .projenrc.ts and run \"npx projen\"." 22 | } 23 | -------------------------------------------------------------------------------- /.projen/tasks.json: -------------------------------------------------------------------------------- 1 | { 2 | "tasks": { 3 | "build": { 4 | "name": "build", 5 | "description": "Full release build", 6 | "steps": [ 7 | { 8 | "spawn": "default" 9 | }, 10 | { 11 | "spawn": "pre-compile" 12 | }, 13 | { 14 | "spawn": "compile" 15 | }, 16 | { 17 | "spawn": "post-compile" 18 | }, 19 | { 20 | "spawn": "test" 21 | }, 22 | { 23 | "spawn": "package" 24 | } 25 | ] 26 | }, 27 | "bump": { 28 | "name": "bump", 29 | "description": "Bumps version based on latest git tag and generates a changelog entry", 30 | "env": { 31 | "OUTFILE": "package.json", 32 | "CHANGELOG": "dist/changelog.md", 33 | "BUMPFILE": "dist/version.txt", 34 | "RELEASETAG": "dist/releasetag.txt", 35 | "RELEASE_TAG_PREFIX": "", 36 | "VERSIONRCOPTIONS": "{\"types\":[{\"type\":\"feat\",\"hidden\":true},{\"type\":\"fix\",\"hidden\":true},{\"type\":\"chore\",\"hidden\":true},{\"type\":\"docs\",\"hidden\":true},{\"type\":\"style\",\"hidden\":true},{\"type\":\"refactor\",\"hidden\":true},{\"type\":\"perf\",\"hidden\":true},{\"type\":\"test\",\"hidden\":true}]}", 37 | "BUMP_PACKAGE": "commit-and-tag-version@^12" 38 | }, 39 | "steps": [ 40 | { 41 | "builtin": "release/bump-version" 42 | } 43 | ], 44 | "condition": "git log --oneline -1 | grep -qv \"chore(release):\"" 45 | }, 46 | "bundle": { 47 | "name": "bundle", 48 | "description": "Prepare assets" 49 | }, 50 | "bundle:binary": { 51 | "name": "bundle:binary", 52 | "steps": [ 53 | { 54 | "spawn": "synth:silent" 55 | }, 56 | { 57 | "exec": "rm -rf ./ready-to-use/amazonlinux-2/*" 58 | }, 59 | { 60 | "exec": "cp -r cdk.out/$(cat cdk.out/tesseract-lambda-ci.template.json | jq -r '.Resources.al2layer.Metadata.\"aws:asset:path\"')/. ./ready-to-use/amazonlinux-2" 61 | } 62 | ] 63 | }, 64 | "clobber": { 65 | "name": "clobber", 66 | "description": "hard resets to HEAD of origin and cleans the local repo", 67 | "env": { 68 | "BRANCH": "$(git branch --show-current)" 69 | }, 70 | "steps": [ 71 | { 72 | "exec": "git checkout -b scratch", 73 | "name": "save current HEAD in \"scratch\" branch" 74 | }, 75 | { 76 | "exec": "git checkout $BRANCH" 77 | }, 78 | { 79 | "exec": "git fetch origin", 80 | "name": "fetch latest changes from origin" 81 | }, 82 | { 83 | "exec": "git reset --hard origin/$BRANCH", 84 | "name": "hard reset to origin commit" 85 | }, 86 | { 87 | "exec": "git clean -fdx", 88 | "name": "clean all untracked files" 89 | }, 90 | { 91 | "say": "ready to rock! (unpushed commits are under the \"scratch\" branch)" 92 | } 93 | ], 94 | "condition": "git diff --exit-code > /dev/null" 95 | }, 96 | "compile": { 97 | "name": "compile", 98 | "description": "Only compile" 99 | }, 100 | "default": { 101 | "name": "default", 102 | "description": "Synthesize project files", 103 | "steps": [ 104 | { 105 | "exec": "ts-node --project tsconfig.dev.json .projenrc.ts" 106 | } 107 | ] 108 | }, 109 | "deploy": { 110 | "name": "deploy", 111 | "description": "Deploys your CDK app to the AWS cloud", 112 | "steps": [ 113 | { 114 | "exec": "cdk deploy", 115 | "receiveArgs": true 116 | } 117 | ] 118 | }, 119 | "destroy": { 120 | "name": "destroy", 121 | "description": "Destroys your cdk app in the AWS cloud", 122 | "steps": [ 123 | { 124 | "exec": "cdk destroy", 125 | "receiveArgs": true 126 | } 127 | ] 128 | }, 129 | "diff": { 130 | "name": "diff", 131 | "description": "Diffs the currently deployed app against your code", 132 | "steps": [ 133 | { 134 | "exec": "cdk diff" 135 | } 136 | ] 137 | }, 138 | "eject": { 139 | "name": "eject", 140 | "description": "Remove projen from the project", 141 | "env": { 142 | "PROJEN_EJECTING": "true" 143 | }, 144 | "steps": [ 145 | { 146 | "spawn": "default" 147 | } 148 | ] 149 | }, 150 | "eslint": { 151 | "name": "eslint", 152 | "description": "Runs eslint against the codebase", 153 | "env": { 154 | "ESLINT_USE_FLAT_CONFIG": "false" 155 | }, 156 | "steps": [ 157 | { 158 | "exec": "eslint --ext .ts,.tsx --fix --no-error-on-unmatched-pattern $@ continous-integration example layer test build-tools projenrc .projenrc.ts", 159 | "receiveArgs": true 160 | } 161 | ] 162 | }, 163 | "install": { 164 | "name": "install", 165 | "description": "Install project dependencies and update lockfile (non-frozen)", 166 | "steps": [ 167 | { 168 | "exec": "yarn install --check-files" 169 | } 170 | ] 171 | }, 172 | "install:ci": { 173 | "name": "install:ci", 174 | "description": "Install project dependencies using frozen lockfile", 175 | "steps": [ 176 | { 177 | "exec": "yarn install --check-files --frozen-lockfile" 178 | } 179 | ] 180 | }, 181 | "package": { 182 | "name": "package", 183 | "description": "Creates the distribution package", 184 | "steps": [ 185 | { 186 | "exec": "mkdir -p ./dist" 187 | }, 188 | { 189 | "spawn": "bundle:binary" 190 | }, 191 | { 192 | "spawn": "test:integration" 193 | }, 194 | { 195 | "exec": "mkdir -p dist/js" 196 | }, 197 | { 198 | "exec": "npm pack --pack-destination dist/js" 199 | }, 200 | { 201 | "exec": "zip -r ../../dist/tesseract-al2-x86.zip .", 202 | "cwd": "./ready-to-use/amazonlinux-2" 203 | } 204 | ] 205 | }, 206 | "post-compile": { 207 | "name": "post-compile", 208 | "description": "Runs after successful compilation", 209 | "steps": [ 210 | { 211 | "spawn": "synth:silent" 212 | } 213 | ] 214 | }, 215 | "post-upgrade": { 216 | "name": "post-upgrade", 217 | "steps": [ 218 | { 219 | "exec": "npx projen upgrade:subprojects" 220 | } 221 | ] 222 | }, 223 | "pre-compile": { 224 | "name": "pre-compile", 225 | "description": "Prepare the project for compilation" 226 | }, 227 | "release": { 228 | "name": "release", 229 | "description": "Prepare a release from \"main\" branch", 230 | "env": { 231 | "RELEASE": "true" 232 | }, 233 | "steps": [ 234 | { 235 | "exec": "rm -fr dist" 236 | }, 237 | { 238 | "spawn": "bump" 239 | }, 240 | { 241 | "spawn": "build" 242 | }, 243 | { 244 | "spawn": "unbump" 245 | }, 246 | { 247 | "exec": "git diff --ignore-space-at-eol --exit-code" 248 | } 249 | ] 250 | }, 251 | "synth": { 252 | "name": "synth", 253 | "description": "Synthesizes your cdk app into cdk.out", 254 | "steps": [ 255 | { 256 | "exec": "cdk synth" 257 | } 258 | ] 259 | }, 260 | "synth:silent": { 261 | "name": "synth:silent", 262 | "description": "Synthesizes your cdk app into cdk.out and suppresses the template in stdout (part of \"yarn build\")", 263 | "steps": [ 264 | { 265 | "exec": "cdk synth -q" 266 | } 267 | ] 268 | }, 269 | "test": { 270 | "name": "test", 271 | "description": "Run tests", 272 | "steps": [ 273 | { 274 | "exec": "jest --passWithNoTests --updateSnapshot", 275 | "receiveArgs": true 276 | }, 277 | { 278 | "spawn": "eslint" 279 | } 280 | ] 281 | }, 282 | "test:integration": { 283 | "name": "test:integration", 284 | "steps": [ 285 | { 286 | "spawn": "test:integration:python" 287 | }, 288 | { 289 | "spawn": "test:integration:node" 290 | } 291 | ] 292 | }, 293 | "test:integration:node": { 294 | "name": "test:integration:node", 295 | "steps": [ 296 | { 297 | "spawn": "synth:silent" 298 | }, 299 | { 300 | "exec": "sam local invoke -t cdk.out/tesseract-lambda-ci.template.json node --no-event > node-test-output.txt && cat node-test-output.txt | grep -Eiv \"(fail|error|exception)\"" 301 | } 302 | ] 303 | }, 304 | "test:integration:python": { 305 | "name": "test:integration:python", 306 | "steps": [ 307 | { 308 | "spawn": "synth:silent" 309 | }, 310 | { 311 | "exec": "sam local invoke -t cdk.out/tesseract-lambda-ci.template.json python --no-event > py-test-output.txt && cat py-test-output.txt | grep -Eiv \"(fail|error|exception)\"" 312 | } 313 | ] 314 | }, 315 | "test:watch": { 316 | "name": "test:watch", 317 | "description": "Run jest in watch mode", 318 | "steps": [ 319 | { 320 | "exec": "jest --watch" 321 | } 322 | ] 323 | }, 324 | "unbump": { 325 | "name": "unbump", 326 | "description": "Restores version to 0.0.0", 327 | "env": { 328 | "OUTFILE": "package.json", 329 | "CHANGELOG": "dist/changelog.md", 330 | "BUMPFILE": "dist/version.txt", 331 | "RELEASETAG": "dist/releasetag.txt", 332 | "RELEASE_TAG_PREFIX": "", 333 | "VERSIONRCOPTIONS": "{\"types\":[{\"type\":\"feat\",\"hidden\":true},{\"type\":\"fix\",\"hidden\":true},{\"type\":\"chore\",\"hidden\":true},{\"type\":\"docs\",\"hidden\":true},{\"type\":\"style\",\"hidden\":true},{\"type\":\"refactor\",\"hidden\":true},{\"type\":\"perf\",\"hidden\":true},{\"type\":\"test\",\"hidden\":true}]}", 334 | "BUMP_PACKAGE": "commit-and-tag-version@^12" 335 | }, 336 | "steps": [ 337 | { 338 | "builtin": "release/reset-version" 339 | } 340 | ] 341 | }, 342 | "upgrade": { 343 | "name": "upgrade", 344 | "description": "Dependency update", 345 | "env": { 346 | "CI": "0" 347 | }, 348 | "steps": [ 349 | { 350 | "exec": "npx npm-check-updates@16 --upgrade --target=minor --peer --no-deprecated --dep=dev,peer,prod,optional --filter=@types/jest,@types/node,esbuild,eslint-config-prettier,eslint-import-resolver-typescript,eslint-plugin-import,eslint-plugin-prettier,jest,prettier,projen,ts-jest,ts-node,typescript" 351 | }, 352 | { 353 | "exec": "yarn install --check-files" 354 | }, 355 | { 356 | "exec": "yarn upgrade @types/jest @types/node @typescript-eslint/eslint-plugin @typescript-eslint/parser aws-cdk commit-and-tag-version esbuild eslint-config-prettier eslint-import-resolver-typescript eslint-plugin-import eslint-plugin-prettier eslint jest jest-junit prettier projen ts-jest ts-node typescript aws-cdk-lib constructs" 357 | }, 358 | { 359 | "exec": "npx projen" 360 | }, 361 | { 362 | "spawn": "post-upgrade" 363 | } 364 | ] 365 | }, 366 | "upgrade:ci:py": { 367 | "name": "upgrade:ci:py", 368 | "steps": [ 369 | { 370 | "exec": "pipenv lock && pipenv requirements > requirements.txt", 371 | "cwd": "continous-integration/lambda-handlers/python" 372 | }, 373 | { 374 | "exec": "cp continous-integration/lambda-handlers/python/requirements.txt example/cdk/src/lambda-handlers/requirements.txt" 375 | }, 376 | { 377 | "exec": "cp continous-integration/lambda-handlers/python/requirements.txt example/serverless/requirements.txt" 378 | } 379 | ] 380 | }, 381 | "upgrade:subprojects": { 382 | "name": "upgrade:subprojects", 383 | "steps": [ 384 | { 385 | "spawn": "upgrade:ci:py" 386 | } 387 | ] 388 | }, 389 | "watch": { 390 | "name": "watch", 391 | "description": "Watches changes in your source code and rebuilds and deploys to the current account", 392 | "steps": [ 393 | { 394 | "exec": "cdk deploy --hotswap" 395 | }, 396 | { 397 | "exec": "cdk watch" 398 | } 399 | ] 400 | } 401 | }, 402 | "env": { 403 | "PATH": "$(npx -c \"node --print process.env.PATH\")" 404 | }, 405 | "//": "~~ Generated by projen. To modify, edit .projenrc.ts and run \"npx projen\"." 406 | } 407 | -------------------------------------------------------------------------------- /.projenrc.ts: -------------------------------------------------------------------------------- 1 | import { exec } from 'child_process'; 2 | import { awscdk, Component, github } from 'projen'; 3 | import { JobPermission } from 'projen/lib/github/workflows-model'; 4 | import { NodeProject, TrailingComma, UpgradeDependenciesSchedule } from 'projen/lib/javascript'; 5 | import { ReleaseTrigger } from 'projen/lib/release'; 6 | 7 | const defaultReleaseBranch = 'main'; 8 | const setupPythonAction = 'actions/setup-python@v5'; 9 | const setupNodeAction = 'actions/setup-node@v4'; 10 | const setupSamAction = 'aws-actions/setup-sam@v2'; 11 | const downloadArtifactAction = 'actions/download-artifact@v4'; 12 | const nodeActionVersion = '18'; 13 | 14 | const project = new awscdk.AwsCdkTypeScriptApp({ 15 | cdkVersion: '2.95.0', 16 | defaultReleaseBranch, 17 | name: 'aws-lambda-tesseract-layer', 18 | description: 'A layer for AWS Lambda containing the tesseract C libraries and tesseract executable. ', 19 | projenrcTs: true, 20 | srcdir: 'continous-integration', 21 | // Use built-in dep upgrades 22 | dependabot: false, 23 | gitignore: ['layer', '.serverless', '.mypy_cache', '*.zip', '**/*test-output.txt', 'cdk.out/'], 24 | autoApproveUpgrades: false, 25 | depsUpgrade: true, 26 | depsUpgradeOptions: { 27 | pullRequestTitle: 'Dependency update', 28 | workflowOptions: { 29 | // Don't forget to set GitHub App credentials in Repo. 30 | projenCredentials: github.GithubCredentials.fromApp(), 31 | schedule: UpgradeDependenciesSchedule.WEEKLY, 32 | labels: ['dependencies'], 33 | }, 34 | }, 35 | scripts: { 36 | //postinstall: 'npm ci --prefix example/cdk && npm ci --prefix example/serverless', 37 | 'post-upgrade': 'npx projen upgrade:subprojects', 38 | }, 39 | release: true, 40 | releaseTrigger: ReleaseTrigger.scheduled({ schedule: '0 0 1 1 *' }), 41 | githubOptions: { 42 | mergify: true, 43 | projenCredentials: github.GithubCredentials.fromApp(), 44 | pullRequestLintOptions: { 45 | semanticTitleOptions: { types: ['feat', 'fix', 'chore', 'build', 'docs'] }, 46 | }, 47 | }, 48 | workflowBootstrapSteps: [ 49 | { 50 | uses: setupPythonAction, 51 | with: { 52 | 'python-version': '3.8', 53 | }, 54 | }, 55 | { 56 | name: 'Install pipenv', 57 | run: 'curl https://raw.githubusercontent.com/pypa/pipenv/master/get-pipenv.py | python', 58 | }, 59 | { 60 | uses: setupSamAction, 61 | }, 62 | ], 63 | versionrcOptions: { 64 | types: [ 65 | { type: 'feat', hidden: true }, 66 | { type: 'fix', hidden: true }, 67 | { type: 'chore', hidden: true }, 68 | { type: 'docs', hidden: true }, 69 | { type: 'style', hidden: true }, 70 | { type: 'refactor', hidden: true }, 71 | { type: 'perf', hidden: true }, 72 | { type: 'test', hidden: true }, 73 | ], 74 | }, 75 | 76 | buildWorkflow: true, 77 | package: false, 78 | eslint: true, 79 | prettier: false, 80 | eslintOptions: { 81 | dirs: ['continous-integration', 'example', 'layer'], 82 | prettier: true, 83 | yaml: true, 84 | ignorePatterns: ['**/node_modules/', '*.d.ts', 'build', 'cdk.out', '**/__snapshots__', 'example'], 85 | }, 86 | docgen: false, 87 | licensed: true, 88 | // see https://github.com/aws/aws-cdk/issues/20622#issuecomment-1300400594 89 | jestOptions: { 90 | jestConfig: { 91 | moduleNameMapper: { 92 | ['^aws-cdk-lib/.warnings.jsii.js$']: '/node_modules/aws-cdk-lib/.warnings.jsii.js', 93 | }, 94 | }, 95 | }, 96 | }); 97 | 98 | class BinaryPatchComponent extends Component { 99 | /** 100 | * Hacky way to get binary patch 101 | */ 102 | postSynthesize(): void { 103 | exec("sed -i 's/\\(git diff\\)/\\1 --binary/g' .github/workflows/build.yml", (err, _, stderr) => { 104 | if (err) { 105 | console.log(`error: ${err.message}`); 106 | return; 107 | } 108 | if (stderr) { 109 | console.log(`stderr: ${stderr}`); 110 | return; 111 | } 112 | }); 113 | } 114 | } 115 | 116 | new BinaryPatchComponent(project); 117 | 118 | project.addTask(`test:integration:python`, { 119 | steps: [ 120 | { 121 | spawn: `synth:silent`, 122 | }, 123 | { 124 | exec: `sam local invoke -t cdk.out/tesseract-lambda-ci.template.json python --no-event > py-test-output.txt && cat py-test-output.txt | grep -Eiv \"(fail|error|exception)\"`, 125 | }, 126 | ], 127 | }); 128 | project.addTask(`test:integration:node`, { 129 | steps: [ 130 | { 131 | spawn: `synth:silent`, 132 | }, 133 | { 134 | exec: `sam local invoke -t cdk.out/tesseract-lambda-ci.template.json node --no-event > node-test-output.txt && cat node-test-output.txt | grep -Eiv \"(fail|error|exception)\"`, 135 | }, 136 | ], 137 | }); 138 | const testIntegration = project.addTask(`test:integration`, { 139 | steps: [ 140 | { 141 | spawn: `test:integration:python`, 142 | }, 143 | { 144 | spawn: `test:integration:node`, 145 | }, 146 | ], 147 | }); 148 | const bundle = project.addTask(`bundle:binary`, { 149 | steps: [ 150 | { 151 | spawn: `synth:silent`, 152 | }, 153 | { 154 | exec: `rm -rf ./ready-to-use/amazonlinux-2/*`, 155 | }, 156 | { 157 | exec: `cp -r cdk.out/$(cat cdk.out/tesseract-lambda-ci.template.json | jq -r '.Resources.al2layer.Metadata.\"aws:asset:path\"')/. ./ready-to-use/amazonlinux-2`, 158 | }, 159 | ], 160 | }); 161 | project.packageTask.prependSpawn(testIntegration); 162 | project.packageTask.prependSpawn(bundle); 163 | project.packageTask.prependExec(`mkdir -p ./dist`); 164 | project.packageTask.exec(`zip -r ../../dist/tesseract-al2-x86.zip .`, { cwd: './ready-to-use/amazonlinux-2' }); 165 | project.addTask('upgrade:ci:py', { 166 | steps: [ 167 | { 168 | exec: 'pipenv lock && pipenv requirements > requirements.txt', 169 | cwd: 'continous-integration/lambda-handlers/python', 170 | }, 171 | { 172 | exec: 'cp continous-integration/lambda-handlers/python/requirements.txt example/cdk/src/lambda-handlers/requirements.txt', 173 | }, 174 | { 175 | exec: 'cp continous-integration/lambda-handlers/python/requirements.txt example/serverless/requirements.txt', 176 | }, 177 | ], 178 | }); 179 | project.release?.addJobs({ 180 | upload_release_artifact: { 181 | runsOn: ['ubuntu-latest'], 182 | permissions: { contents: JobPermission.WRITE }, 183 | needs: ['release', 'release_github'], 184 | if: 'needs.release.outputs.latest_commit == github.sha', 185 | steps: [ 186 | { 187 | uses: setupNodeAction, 188 | with: { 189 | 'node-version': nodeActionVersion, 190 | }, 191 | }, 192 | { 193 | name: 'Download build artifacts', 194 | uses: downloadArtifactAction, 195 | with: { 196 | name: 'build-artifact', 197 | path: 'dist', 198 | }, 199 | }, 200 | { 201 | name: 'Restore build artifact permissions', 202 | run: 'cd dist && setfacl --restore=permissions-backup.acl', 203 | continueOnError: true, 204 | }, 205 | { 206 | name: 'Upload Release Artifacts', 207 | env: { 208 | GITHUB_TOKEN: '${{ secrets.GITHUB_TOKEN }}', 209 | GITHUB_REPOSITORY: '${{ github.repository }}', 210 | GITHUB_REF: '${{ github.ref }}', 211 | }, 212 | run: 'errout=$(mktemp); gh release upload $(cat dist/releasetag.txt) --clobber -R $GITHUB_REPOSITORY dist/tesseract-al2-x86.zip 2> $errout && true; exitcode=$?; if [ $exitcode -ne 0 ] && ! grep -q "Release.tag_name already exists" $errout; then cat $errout; exit $exitcode; fi', 213 | }, 214 | ], 215 | }, 216 | }); 217 | project.eslint?.addRules({ 218 | 'prettier/prettier': ['error', { singleQuote: true, printWidth: 140, trailingComma: TrailingComma.ALL }], 219 | }); 220 | 221 | /** Example */ 222 | 223 | new awscdk.AwsCdkTypeScriptApp({ 224 | cdkVersion: '2.55.0', 225 | name: 'aws-lambda-tesseract-layer-example', 226 | defaultReleaseBranch, 227 | parent: project, 228 | outdir: 'example/cdk', 229 | depsUpgrade: true, 230 | licensed: false, 231 | }); 232 | new NodeProject({ 233 | name: 'node-lambda', 234 | defaultReleaseBranch, 235 | parent: project, 236 | outdir: 'continous-integration/lambda-handlers/node', 237 | deps: ['tesseractocr'], 238 | devDeps: ['esbuild'], 239 | depsUpgrade: true, 240 | licensed: false, 241 | }); 242 | 243 | project.addTask('upgrade:subprojects', { 244 | steps: [{ spawn: 'upgrade:ci:py' }], 245 | }); 246 | project.synth(); 247 | -------------------------------------------------------------------------------- /Dockerfile.al1: -------------------------------------------------------------------------------- 1 | ## Builds binaries for Amazonlinux 1 2 | FROM lambci/lambda-base:build 3 | 4 | ARG LEPTONICA_VERSION=1.84.1 5 | ARG TESSERACT_VERSION=5.4.1 6 | ARG AUTOCONF_ARCHIVE_VERSION=2017.09.28 7 | ARG TMP_BUILD=/tmp 8 | ARG TESSERACT=/opt/tesseract 9 | ARG LEPTONICA=/opt/leptonica 10 | ARG DIST=/opt/build-dist 11 | # change OCR_LANG to enable the layer for different languages 12 | ARG OCR_LANG=deu 13 | # change TESSERACT_DATA_SUFFIX to use different datafiles (options: "_best", "_fast" and "") 14 | ARG TESSERACT_DATA_SUFFIX=_fast 15 | ARG TESSERACT_DATA_VERSION=4.1.0 16 | 17 | RUN yum makecache fast; yum clean all && yum -y update && yum -y upgrade; yum clean all && \ 18 | yum install -y yum-plugin-ovl; yum clean all && yum -y groupinstall "Development Tools"; yum clean all 19 | 20 | RUN yum -y install gcc gcc-c++ make autoconf aclocal automake libtool \ 21 | libjpeg-devel libpng-devel libtiff-devel zlib-devel \ 22 | libzip-devel freetype-devel lcms2-devel libwebp-devel \ 23 | libicu-devel tcl-devel tk-devel pango-devel cairo-devel; yum clean all 24 | 25 | WORKDIR ${TMP_BUILD}/leptonica-build 26 | RUN curl -L https://github.com/DanBloomberg/leptonica/releases/download/${LEPTONICA_VERSION}/leptonica-${LEPTONICA_VERSION}.tar.gz | tar xz && cd ${TMP_BUILD}/leptonica-build/leptonica-${LEPTONICA_VERSION} && \ 27 | ./configure --prefix=${LEPTONICA} && make && make install && cp -r ./src/.libs /opt/liblept 28 | 29 | RUN echo "/opt/leptonica/lib" > /etc/ld.so.conf.d/leptonica.conf && ldconfig 30 | 31 | WORKDIR ${TMP_BUILD}/autoconf-build 32 | RUN curl https://ftp.gnu.org/gnu/autoconf-archive/autoconf-archive-${AUTOCONF_ARCHIVE_VERSION}.tar.xz | tar xJ && \ 33 | cd autoconf-archive-${AUTOCONF_ARCHIVE_VERSION} && ./configure && make && make install && cp ./m4/* /usr/share/aclocal/ 34 | 35 | WORKDIR ${TMP_BUILD}/tesseract-build 36 | RUN curl -L https://github.com/tesseract-ocr/tesseract/archive/${TESSERACT_VERSION}.tar.gz | tar xz && \ 37 | cd tesseract-${TESSERACT_VERSION} && ./autogen.sh && PKG_CONFIG_PATH=/opt/leptonica/lib/pkgconfig LIBLEPT_HEADERSDIR=/opt/leptonica/include \ 38 | ./configure --prefix=${TESSERACT} --with-extra-includes=/opt/leptonica/include --with-extra-libraries=/opt/leptonica/lib 'CXXFLAGS=-mavx2' && make && make install 39 | 40 | WORKDIR /opt 41 | RUN mkdir -p ${DIST}/lib && mkdir -p ${DIST}/bin && \ 42 | cp ${TESSERACT}/bin/tesseract ${DIST}/bin/ && \ 43 | cp ${TESSERACT}/lib/libtesseract.so.4 ${DIST}/lib/ && \ 44 | cp ${LEPTONICA}/lib/libleptonica.so.6.0.0 ${DIST}/lib/libleptonica.so.6 && \ 45 | cp /usr/lib64/libwebp.so.4 ${DIST}/lib/ && \ 46 | echo -e "LEPTONICA_VERSION=${LEPTONICA_VERSION}\nTESSERACT_VERSION=${TESSERACT_VERSION}\nTESSERACT_DATA_FILES=tessdata${TESSERACT_DATA_SUFFIX}/${TESSERACT_DATA_VERSION}\nTESSERACT_DATA_LANGUAGES=osd,eng,${OCR_LANG}" > ${DIST}/TESSERACT-README.md && \ 47 | find ${DIST}/lib -name '*.so*' | xargs strip -s 48 | 49 | WORKDIR ${DIST}/tesseract/share/tessdata 50 | RUN curl -L https://github.com/tesseract-ocr/tessdata${TESSERACT_DATA_SUFFIX}/raw/${TESSERACT_DATA_VERSION}/osd.traineddata > osd.traineddata && \ 51 | curl -L https://github.com/tesseract-ocr/tessdata${TESSERACT_DATA_SUFFIX}/raw/${TESSERACT_DATA_VERSION}/eng.traineddata > eng.traineddata && \ 52 | curl -L https://github.com/tesseract-ocr/tessdata${TESSERACT_DATA_SUFFIX}/raw/${TESSERACT_DATA_VERSION}/${OCR_LANG}.traineddata > ${OCR_LANG}.traineddata 53 | 54 | WORKDIR /var/task 55 | -------------------------------------------------------------------------------- /Dockerfile.al2: -------------------------------------------------------------------------------- 1 | ## Builds binaries for Amazonlinux 2 2 | FROM public.ecr.aws/sam/build-provided.al2:1.97 3 | 4 | ARG LEPTONICA_VERSION=1.84.1 5 | ARG TESSERACT_VERSION=5.4.1 6 | ARG AUTOCONF_ARCHIVE_VERSION=2017.09.28 7 | ARG TMP_BUILD=/tmp 8 | ARG TESSERACT=/opt/tesseract 9 | ARG LEPTONICA=/opt/leptonica 10 | ARG DIST=/opt/build-dist 11 | # change OCR_LANG to enable the layer for different languages 12 | ARG OCR_LANG=deu 13 | # change TESSERACT_DATA_SUFFIX to use different datafiles (options: "_best", "_fast" and "") 14 | ARG TESSERACT_DATA_SUFFIX=_fast 15 | ARG TESSERACT_DATA_VERSION=4.1.0 16 | ARG COMPILER_OPTIONS='CXXFLAGS=-mavx2' 17 | 18 | RUN yum makecache fast; yum clean all && yum -y update && yum -y upgrade; yum clean all && \ 19 | yum install -y yum-plugin-ovl; yum clean all && yum -y groupinstall "Development Tools"; yum clean all 20 | 21 | RUN yum -y install clang gcc-c++ make autoconf aclocal automake libtool \ 22 | libjpeg-devel libpng-devel libtiff-devel zlib-devel \ 23 | libzip-devel freetype-devel lcms2-devel libwebp-devel \ 24 | libicu-devel tcl-devel tk-devel pango-devel cairo-devel; yum clean all 25 | 26 | WORKDIR ${TMP_BUILD}/leptonica-build 27 | RUN curl -L https://github.com/DanBloomberg/leptonica/releases/download/${LEPTONICA_VERSION}/leptonica-${LEPTONICA_VERSION}.tar.gz | tar xz && cd ${TMP_BUILD}/leptonica-build/leptonica-${LEPTONICA_VERSION} && \ 28 | ./configure --prefix=${LEPTONICA} && make && make install && cp -r ./src/.libs /opt/liblept 29 | 30 | RUN echo "/opt/leptonica/lib" > /etc/ld.so.conf.d/leptonica.conf && /usr/sbin/ldconfig 31 | 32 | WORKDIR ${TMP_BUILD}/autoconf-build 33 | RUN curl https://ftp.gnu.org/gnu/autoconf-archive/autoconf-archive-${AUTOCONF_ARCHIVE_VERSION}.tar.xz | tar xJ && \ 34 | cd autoconf-archive-${AUTOCONF_ARCHIVE_VERSION} && ./configure && make && make install && cp ./m4/* /usr/share/aclocal/ 35 | 36 | WORKDIR ${TMP_BUILD}/tesseract-build 37 | RUN curl -L https://github.com/tesseract-ocr/tesseract/archive/${TESSERACT_VERSION}.tar.gz | tar xz && \ 38 | cd tesseract-${TESSERACT_VERSION} && ./autogen.sh && PKG_CONFIG_PATH=/opt/leptonica/lib/pkgconfig LIBLEPT_HEADERSDIR=/opt/leptonica/include \ 39 | ./configure --prefix=${TESSERACT} --with-extra-includes=/opt/leptonica/include --with-extra-libraries=/opt/leptonica/lib ${COMPILER_OPTIONS} && make && make install 40 | 41 | WORKDIR /opt 42 | RUN mkdir -p ${DIST}/lib && mkdir -p ${DIST}/bin && \ 43 | cp ${TESSERACT}/bin/tesseract ${DIST}/bin/ && \ 44 | cp ${TESSERACT}/lib/libtesseract.so.5 ${DIST}/lib/ && \ 45 | cp ${LEPTONICA}/lib/libleptonica.so.6.0.0 ${DIST}/lib/libleptonica.so.6 && \ 46 | cp /usr/lib64/libgomp.so.1 ${DIST}/lib/ && \ 47 | cp /usr/lib64/libwebp.so.4 ${DIST}/lib/ && \ 48 | cp /usr/lib64/libpng15.so.15 ${DIST}/lib/ && \ 49 | cp /usr/lib64/libjpeg.so.62 ${DIST}/lib/ && \ 50 | cp /usr/lib64/libtiff.so.5 ${DIST}/lib/ && \ 51 | cp /usr/lib64/libjbig.so.2.0 ${DIST}/lib/ && \ 52 | echo -e "LEPTONICA_VERSION=${LEPTONICA_VERSION}\nTESSERACT_VERSION=${TESSERACT_VERSION}\nTESSERACT_DATA_FILES=tessdata${TESSERACT_DATA_SUFFIX}/${TESSERACT_DATA_VERSION}\nTESSERACT_DATA_LANGUAGES=osd,eng,${OCR_LANG}" > ${DIST}/TESSERACT-README.md && \ 53 | find ${DIST}/lib -name '*.so*' | xargs strip -s 54 | 55 | WORKDIR ${DIST}/tesseract/share/tessdata 56 | RUN curl -L https://github.com/tesseract-ocr/tessdata${TESSERACT_DATA_SUFFIX}/raw/${TESSERACT_DATA_VERSION}/osd.traineddata > osd.traineddata && \ 57 | curl -L https://github.com/tesseract-ocr/tessdata${TESSERACT_DATA_SUFFIX}/raw/${TESSERACT_DATA_VERSION}/eng.traineddata > eng.traineddata && \ 58 | curl -L https://github.com/tesseract-ocr/tessdata${TESSERACT_DATA_SUFFIX}/raw/${TESSERACT_DATA_VERSION}/${OCR_LANG}.traineddata > ${OCR_LANG}.traineddata 59 | 60 | WORKDIR /var/task 61 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | 2 | Apache License 3 | Version 2.0, January 2004 4 | http://www.apache.org/licenses/ 5 | 6 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 7 | 8 | 1. Definitions. 9 | 10 | "License" shall mean the terms and conditions for use, reproduction, 11 | and distribution as defined by Sections 1 through 9 of this document. 12 | 13 | "Licensor" shall mean the copyright owner or entity authorized by 14 | the copyright owner that is granting the License. 15 | 16 | "Legal Entity" shall mean the union of the acting entity and all 17 | other entities that control, are controlled by, or are under common 18 | control with that entity. For the purposes of this definition, 19 | "control" means (i) the power, direct or indirect, to cause the 20 | direction or management of such entity, whether by contract or 21 | otherwise, or (ii) ownership of fifty percent (50%) or more of the 22 | outstanding shares, or (iii) beneficial ownership of such entity. 23 | 24 | "You" (or "Your") shall mean an individual or Legal Entity 25 | exercising permissions granted by this License. 26 | 27 | "Source" form shall mean the preferred form for making modifications, 28 | including but not limited to software source code, documentation 29 | source, and configuration files. 30 | 31 | "Object" form shall mean any form resulting from mechanical 32 | transformation or translation of a Source form, including but 33 | not limited to compiled object code, generated documentation, 34 | and conversions to other media types. 35 | 36 | "Work" shall mean the work of authorship, whether in Source or 37 | Object form, made available under the License, as indicated by a 38 | copyright notice that is included in or attached to the work 39 | (an example is provided in the Appendix below). 40 | 41 | "Derivative Works" shall mean any work, whether in Source or Object 42 | form, that is based on (or derived from) the Work and for which the 43 | editorial revisions, annotations, elaborations, or other modifications 44 | represent, as a whole, an original work of authorship. For the purposes 45 | of this License, Derivative Works shall not include works that remain 46 | separable from, or merely link (or bind by name) to the interfaces of, 47 | the Work and Derivative Works thereof. 48 | 49 | "Contribution" shall mean any work of authorship, including 50 | the original version of the Work and any modifications or additions 51 | to that Work or Derivative Works thereof, that is intentionally 52 | submitted to Licensor for inclusion in the Work by the copyright owner 53 | or by an individual or Legal Entity authorized to submit on behalf of 54 | the copyright owner. For the purposes of this definition, "submitted" 55 | means any form of electronic, verbal, or written communication sent 56 | to the Licensor or its representatives, including but not limited to 57 | communication on electronic mailing lists, source code control systems, 58 | and issue tracking systems that are managed by, or on behalf of, the 59 | Licensor for the purpose of discussing and improving the Work, but 60 | excluding communication that is conspicuously marked or otherwise 61 | designated in writing by the copyright owner as "Not a Contribution." 62 | 63 | "Contributor" shall mean Licensor and any individual or Legal Entity 64 | on behalf of whom a Contribution has been received by Licensor and 65 | subsequently incorporated within the Work. 66 | 67 | 2. Grant of Copyright License. Subject to the terms and conditions of 68 | this License, each Contributor hereby grants to You a perpetual, 69 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 70 | copyright license to reproduce, prepare Derivative Works of, 71 | publicly display, publicly perform, sublicense, and distribute the 72 | Work and such Derivative Works in Source or Object form. 73 | 74 | 3. Grant of Patent License. Subject to the terms and conditions of 75 | this License, each Contributor hereby grants to You a perpetual, 76 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 77 | (except as stated in this section) patent license to make, have made, 78 | use, offer to sell, sell, import, and otherwise transfer the Work, 79 | where such license applies only to those patent claims licensable 80 | by such Contributor that are necessarily infringed by their 81 | Contribution(s) alone or by combination of their Contribution(s) 82 | with the Work to which such Contribution(s) was submitted. If You 83 | institute patent litigation against any entity (including a 84 | cross-claim or counterclaim in a lawsuit) alleging that the Work 85 | or a Contribution incorporated within the Work constitutes direct 86 | or contributory patent infringement, then any patent licenses 87 | granted to You under this License for that Work shall terminate 88 | as of the date such litigation is filed. 89 | 90 | 4. Redistribution. You may reproduce and distribute copies of the 91 | Work or Derivative Works thereof in any medium, with or without 92 | modifications, and in Source or Object form, provided that You 93 | meet the following conditions: 94 | 95 | (a) You must give any other recipients of the Work or 96 | Derivative Works a copy of this License; and 97 | 98 | (b) You must cause any modified files to carry prominent notices 99 | stating that You changed the files; and 100 | 101 | (c) You must retain, in the Source form of any Derivative Works 102 | that You distribute, all copyright, patent, trademark, and 103 | attribution notices from the Source form of the Work, 104 | excluding those notices that do not pertain to any part of 105 | the Derivative Works; and 106 | 107 | (d) If the Work includes a "NOTICE" text file as part of its 108 | distribution, then any Derivative Works that You distribute must 109 | include a readable copy of the attribution notices contained 110 | within such NOTICE file, excluding those notices that do not 111 | pertain to any part of the Derivative Works, in at least one 112 | of the following places: within a NOTICE text file distributed 113 | as part of the Derivative Works; within the Source form or 114 | documentation, if provided along with the Derivative Works; or, 115 | within a display generated by the Derivative Works, if and 116 | wherever such third-party notices normally appear. The contents 117 | of the NOTICE file are for informational purposes only and 118 | do not modify the License. You may add Your own attribution 119 | notices within Derivative Works that You distribute, alongside 120 | or as an addendum to the NOTICE text from the Work, provided 121 | that such additional attribution notices cannot be construed 122 | as modifying the License. 123 | 124 | You may add Your own copyright statement to Your modifications and 125 | may provide additional or different license terms and conditions 126 | for use, reproduction, or distribution of Your modifications, or 127 | for any such Derivative Works as a whole, provided Your use, 128 | reproduction, and distribution of the Work otherwise complies with 129 | the conditions stated in this License. 130 | 131 | 5. Submission of Contributions. Unless You explicitly state otherwise, 132 | any Contribution intentionally submitted for inclusion in the Work 133 | by You to the Licensor shall be under the terms and conditions of 134 | this License, without any additional terms or conditions. 135 | Notwithstanding the above, nothing herein shall supersede or modify 136 | the terms of any separate license agreement you may have executed 137 | with Licensor regarding such Contributions. 138 | 139 | 6. Trademarks. This License does not grant permission to use the trade 140 | names, trademarks, service marks, or product names of the Licensor, 141 | except as required for reasonable and customary use in describing the 142 | origin of the Work and reproducing the content of the NOTICE file. 143 | 144 | 7. Disclaimer of Warranty. Unless required by applicable law or 145 | agreed to in writing, Licensor provides the Work (and each 146 | Contributor provides its Contributions) on an "AS IS" BASIS, 147 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 148 | implied, including, without limitation, any warranties or conditions 149 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 150 | PARTICULAR PURPOSE. You are solely responsible for determining the 151 | appropriateness of using or redistributing the Work and assume any 152 | risks associated with Your exercise of permissions under this License. 153 | 154 | 8. Limitation of Liability. In no event and under no legal theory, 155 | whether in tort (including negligence), contract, or otherwise, 156 | unless required by applicable law (such as deliberate and grossly 157 | negligent acts) or agreed to in writing, shall any Contributor be 158 | liable to You for damages, including any direct, indirect, special, 159 | incidental, or consequential damages of any character arising as a 160 | result of this License or out of the use or inability to use the 161 | Work (including but not limited to damages for loss of goodwill, 162 | work stoppage, computer failure or malfunction, or any and all 163 | other commercial damages or losses), even if such Contributor 164 | has been advised of the possibility of such damages. 165 | 166 | 9. Accepting Warranty or Additional Liability. While redistributing 167 | the Work or Derivative Works thereof, You may choose to offer, 168 | and charge a fee for, acceptance of support, warranty, indemnity, 169 | or other liability obligations and/or rights consistent with this 170 | License. However, in accepting such obligations, You may act only 171 | on Your own behalf and on Your sole responsibility, not on behalf 172 | of any other Contributor, and only if You agree to indemnify, 173 | defend, and hold each Contributor harmless for any liability 174 | incurred by, or claims asserted against, such Contributor by reason 175 | of your accepting any such warranty or additional liability. 176 | 177 | END OF TERMS AND CONDITIONS 178 | 179 | APPENDIX: How to apply the Apache License to your work. 180 | 181 | To apply the Apache License to your work, attach the following 182 | boilerplate notice, with the fields enclosed by brackets "[]" 183 | replaced with your own identifying information. (Don't include 184 | the brackets!) The text should be enclosed in the appropriate 185 | comment syntax for the file format. We also recommend that a 186 | file or class name and description of purpose be included on the 187 | same "printed page" as the copyright notice for easier 188 | identification within third-party archives. 189 | 190 | Copyright [yyyy] [name of copyright owner] 191 | 192 | Licensed under the Apache License, Version 2.0 (the "License"); 193 | you may not use this file except in compliance with the License. 194 | You may obtain a copy of the License at 195 | 196 | http://www.apache.org/licenses/LICENSE-2.0 197 | 198 | Unless required by applicable law or agreed to in writing, software 199 | distributed under the License is distributed on an "AS IS" BASIS, 200 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 201 | See the License for the specific language governing permissions and 202 | limitations under the License. 203 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | Tesseract OCR Lambda Layer 2 | === 3 | 4 | ![Tesseract](https://img.shields.io/badge/Tesseract-5.4.1-green?style=flat-square) 5 | ![Leptonica](https://img.shields.io/badge/Leptonica-1.84.1-green?style=flat-square) 6 | 7 | ![Examples available for Runtimes](https://img.shields.io/badge/Examples_(Lambda_runtimes)-Python_3.6(AL1),Python_3.8(AL2)-informational?style=flat-square) 8 | ![Examples available for IaC Tools](https://img.shields.io/badge/Examples_(IaC)-Serverless_Framework,_AWS_CDK-informational?style=flat-square) 9 | 10 | 11 | ![Continuos Integration](https://github.com/bweigel/aws-lambda-tesseract-layer/workflows/Continuos%20Integration/badge.svg) 12 | 13 | > AWS Lambda layer containing the [tesseract OCR](https://github.com/tesseract-ocr/tesseract) libraries and command-line binary for Lambda Runtimes running on Amazon Linux 1 and 2. 14 | 15 | > :warning: [The Amazon Linux AMI (Version 1) is being deprecated](https://aws.amazon.com/blogs/aws/update-on-amazon-linux-ami-end-of-life/). Users are advised to not use Lambda runtimes (i.e. Python 3.6) based on this version. Refer also to the [AWS Lambda runtime deprecation policy](https://docs.aws.amazon.com/lambda/latest/dg/lambda-runtimes.html#runtime-support-policy). 16 | 17 | 18 | 19 | - [Quickstart](#quickstart) 20 | - [Ready-to-use binaries](#ready-to-use-binaries) 21 | - [Use with Serverless Framework](#use-with-serverless-framework) 22 | - [Use with AWS CDK](#use-with-aws-cdk) 23 | - [Build tesseract layer from source using Docker](#build-tesseract-layer-from-source-using-docker) 24 | - [available `Dockerfile`s](#available-dockerfiles) 25 | - [Building a different tesseract version and/or language](#building-a-different-tesseract-version-andor-language) 26 | - [Deployment size optimization](#deployment-size-optimization) 27 | - [Building the layer binaries directly using CDK](#building-the-layer-binaries-directly-using-cdk) 28 | - [Layer contents](#layer-contents) 29 | - [Known Issues](#known-issues) 30 | - [Avoiding Pillow library issues](#avoiding-pillow-library-issues) 31 | - [Unable to import module 'handler': cannot import name '_imaging'](#unable-to-import-module-handler-cannot-import-name-_imaging) 32 | - [Contributors :heart:](#contributors-heart) 33 | 34 | 35 | 36 | # Quickstart 37 | 38 | This repo comes with ready-to-use binaries compiled against the AWS Lambda Runtimes (based on Amazon Linux 1 and 2). 39 | Example Projects in Python 3.6 (& 3.8) using Serverless Framework and CDK are provided: 40 | 41 | ```bash 42 | ## Demo using Serverless Framework and prebuilt layer 43 | cd example/serverless 44 | npm ci 45 | npx sls deploy 46 | 47 | ## or .. 48 | 49 | ## Demo using CDK and prebuilt layer 50 | cd example/cdk 51 | npm ci 52 | npx cdk deploy 53 | ``` 54 | # Ready-to-use binaries 55 | 56 | For compiled, ready to use binaries that you can put in your layer see [`ready-to-use`](./ready-to-use), or check out the [latest release](https://github.com/bweigel/aws-lambda-tesseract-layer/releases/latest). 57 | 58 | See [examples](./example) for some ready-to-use examples. 59 | 60 | ## Use with Serverless Framework 61 | 62 | > [Serverless Framework](https://www.serverless.com/framework/docs/getting-started/) 63 | 64 | Reference the path to the ready-to-use layer contents in your `serverless.yml`: 65 | 66 | ```yaml 67 | service: tesseract-ocr-layer 68 | 69 | provider: 70 | name: aws 71 | 72 | # define layer 73 | layers: 74 | tesseractAl2: 75 | # and path to contents 76 | path: ready-to-use/amazonlinux-2 77 | compatibleRuntimes: 78 | - python3.8 79 | 80 | functions: 81 | tesseract-ocr: 82 | handler: ... 83 | runtime: python3.8 84 | # reference layer in function 85 | layers: 86 | - { Ref: TesseractAl2LambdaLayer } 87 | events: 88 | - http: 89 | path: ocr 90 | method: post 91 | ``` 92 | 93 | Deploy 94 | 95 | ``` 96 | npx sls deploy 97 | ``` 98 | 99 | ## Use with AWS CDK 100 | 101 | > [AWS CDK](https://github.com/aws/aws-cdk#getting-started) 102 | 103 | Reference the path to the layer contents in your constructs: 104 | 105 | ```typescript 106 | const app = new App(); 107 | const stack = new Stack(app, 'tesseract-lambda-ci'); 108 | 109 | const al2Layer = new lambda.LayerVersion(stack, 'al2-layer', { 110 | // reference the directory containing the ready-to-use layer 111 | code: Code.fromAsset(path.resolve(__dirname, './ready-to-use/amazonlinux-2')), 112 | description: 'AL2 Tesseract Layer', 113 | }); 114 | new lambda.Function(stack, 'python38', { 115 | // reference the source code to your function 116 | code: lambda.Code.fromAsset(path.resolve(__dirname, 'lambda-handlers')), 117 | runtime: Runtime.PYTHON_3_8, 118 | // add tesseract layer to function 119 | layers: [al2Layer], 120 | memorySize: 512, 121 | timeout: Duration.seconds(30), 122 | handler: 'handler.main', 123 | }); 124 | ``` 125 | 126 | # Build tesseract layer from source using Docker 127 | 128 | You can build layer contents manually with the [provided `Dockerfile`s](#available-dockerfiles). 129 | 130 | Build layer using your preferred `Dockerfile`: 131 | 132 | ```bash 133 | ## build 134 | docker build -t tesseract-lambda-layer -f [Dockerfile.al1|Dockerfile.al2] . 135 | ## run container 136 | export CONTAINER=$(docker run -d tesseract-lambda-layer false) 137 | ## copy tesseract files from container to local folder layer 138 | docker cp $CONTAINER:/opt/build-dist layer 139 | ## remove Docker container 140 | docker rm $CONTAINER 141 | unset CONTAINER 142 | ``` 143 | 144 | ## available `Dockerfile`s 145 | 146 | | Dockerfile | Base-Image | compatible Runtimes | 147 | | :-------------------------------------- | :------------- | :-------------------------------------------------------------------- | 148 | | `Dockerfile.al1` (:warning: deprecated) | Amazon Linux 1 | Python 2.7/3.6/3.7, Ruby 2.5, Java 8 (OpenJDK), Go 1.x, .NET Core 2.1 | 149 | | `Dockerfile.al2` | Amazon Linux 2 | Python 3.8, Ruby 2.7, Java 8/11 (Coretto), .NET Core 3.1 | 150 | 151 | 152 | ## Building a different tesseract version and/or language 153 | 154 | Per default the build generates the [tesseract 4.1.3](https://github.com/tesseract-ocr/tesseract/releases/tag/4.1.3) (amazonlinux-1) or [5.2.0](https://github.com/tesseract-ocr/tesseract/releases/tag/5.2.0) (amazonlinux-2) OCR libraries with the _fast_ german, english and osd (orientation and script detection) [data files](https://github.com/tesseract-ocr/tesseract/wiki/Data-Files) included. 155 | 156 | The build process can be modified using different build time arguments (defined as `ARG` in `Dockerfile.al[1|2]`), using the `--build-arg` option of `docker build`. 157 | 158 | | Build-Argument | description | available versions | 159 | | :----------------------- | :---------------------------------------------------------------------------------------------------------------- | :---------------------------------------------------------------------------------------------------------------------------------------- | 160 | | `TESSERACT_VERSION` | the tesseract OCR engine | https://github.com/tesseract-ocr/tesseract/releases | 161 | | `LEPTONICA_VERSION` | fundamental image processing and analysis library | https://github.com/danbloomberg/leptonica/releases | 162 | | `OCR_LANG` | Language to install (in addition to `eng` and `osd`) | https://github.com/tesseract-ocr/tessdata (`.traineddata`) | 163 | | `TESSERACT_DATA_SUFFIX` | Trained LSTM models for tesseract. Can be empty (default), `_best` (best inference) and `_fast` (fast inference). | https://github.com/tesseract-ocr/tessdata, https://github.com/tesseract-ocr/tessdata_best, https://github.com/tesseract-ocr/tessdata_fast | 164 | | `TESSERACT_DATA_VERSION` | Version of the trained LSTM models for tesseract. (currently - in July 2022 - only `4.1.0` is available) | https://github.com/tesseract-ocr/tessdata/releases/tag/4.1.0 | 165 | 166 | 167 | **Example of custom build** 168 | 169 | ```bash 170 | ## Build a Dockerimage based on Amazon Linux 2, with French language support 171 | docker build --build-arg OCR_LANG=fra -t tesseract-lambda-layer-french -f Dockerfile.al2 . 172 | ## Build a Dockerimage based on Amazon Linux 2, with Tesseract 4.0.0 and french language support 173 | docker build --build-arg TESSERACT_VERSION=4.0.0 --build-arg OCR_LANG=fra -t tesseract-lambda-layer -f Dockerfile.al2 . 174 | ``` 175 | 176 | ## Deployment size optimization 177 | 178 | The library files that are content of the layer are stripped, before deployment to make them more suitable for the lambda environment. See `Dockerfile`s: 179 | 180 | ```Dockerfile 181 | RUN ... \ 182 | find ${DIST}/lib -name '*.so*' | xargs strip -s 183 | ``` 184 | 185 | The stripping can cause issues, when the build runtime and the lambda runtime are different (e.g. if building on Amazon Linux 1 and running on Amazon Linux 2). 186 | 187 | ## Building the layer binaries directly using CDK 188 | 189 | You can build the layer directly and get the artifacts (like in [ready-to-use](./ready-to-use/)). This is done using AWS CDK with the [`bundling` option](https://aws.amazon.com/blogs/devops/building-apps-with-aws-cdk/). 190 | 191 | Refer to [continous-integration](./continous-integration/README.md) and the [corresponding Github Workflow](https://github.com/bweigel/aws-lambda-tesseract-layer/actions?query=workflow%3A%22Continuos+Integration%22) for an example. 192 | 193 | ## Layer contents 194 | 195 | The layer contents get deployed to `/opt`, when used by a function. See [here](https://docs.aws.amazon.com/lambda/latest/dg/configuration-layers.html) for details. 196 | See [ready-to-use](./ready-to-use/) for layer contents for Amazon Linux 1 and Amazon Linux 2 (TODO). 197 | 198 | # Known Issues 199 | ## Avoiding Pillow library issues 200 | Use [cloud9 IDE](https://aws.amazon.com/cloud9/) with AMI linux to deploy [example](./example). Or alternately follow instructions for getting correct binaries for lambda using [EC2](https://forums.aws.amazon.com/thread.jspa?messageID=915630). AWS lambda uses AMI linux distro which needs correct python binaries. This step is not needed for deploying layer function. Layer function and example function are separately deployed. 201 | 202 | ## Unable to import module 'handler': cannot import name '_imaging' 203 | 204 | You might run into an issue like this: 205 | 206 | ``` 207 | /var/task/PIL/_imaging.cpython-36m-x86_64-linux-gnu.so: ELF load command address/offset not properly aligned 208 | Unable to import module 'handler': cannot import name '_imaging' 209 | ``` 210 | 211 | The root cause is a faulty stripping of libraries using [`strip`](https://man7.org/linux/man-pages/man1/strip.1.html) [here](https://github.com/bweigel/aws-lambda-tesseract-layer/blob/42b725f653520b2b4d7081998ef8dca6b9b9d7df/Dockerfile#L46). 212 | 213 | **Quickfix** 214 | > You can just disable stripping (comment out the line in the `Dockerfile`) and the libraries (`*.so`) won't be stripped. This also means the library files will be larger and your artifact might exceed lambda limits. 215 | 216 | **A lenghtier fix** 217 | 218 | AWS Lambda Runtimes work on top of Amazon Linux. Depending on the Runtime AWS Lambda uses Amazon Linux Version 1 or Version 2 under the hood. 219 | For example the Python 3.8 Runtime uses Amazon Linux 2, whereas Python <= 3.7 uses version 1. 220 | 221 | The current Dockerfile runs on top of Amazon Linux Version 1. So artifacts for runtimes running version 2 will throw the above error. 222 | You can try and use a base Dockerimage for Amazon Linux 2 in these cases: 223 | 224 | ```Dockerfile 225 | FROM: lambci/lambda-base-2:build 226 | ... 227 | ``` 228 | 229 | or, as @secretshardul suggested 230 | 231 | >simple solution: Use AWS cloud9 to deploy example folder. Layer can be deployed from anywhere. 232 | >complex solution: Deploy EC2 instance with AMI linux and get correct binaries. 233 | 234 | # Contributors :heart: 235 | 236 | - @secretshardul 237 | - @TheLucasMoore for providing a Dockerfile that builds working binaries for Python 3.8 / Amazon Linux 2 238 | -------------------------------------------------------------------------------- /cdk.json: -------------------------------------------------------------------------------- 1 | { 2 | "app": "npx ts-node -P tsconfig.json --prefer-ts-exts continous-integration/main.ts", 3 | "output": "cdk.out", 4 | "build": "npx projen bundle", 5 | "watch": { 6 | "include": [ 7 | "continous-integration/**/*.ts", 8 | "test/**/*.ts" 9 | ], 10 | "exclude": [ 11 | "README.md", 12 | "cdk*.json", 13 | "**/*.d.ts", 14 | "**/*.js", 15 | "tsconfig.json", 16 | "package*.json", 17 | "yarn.lock", 18 | "node_modules" 19 | ] 20 | }, 21 | "//": "~~ Generated by projen. To modify, edit .projenrc.ts and run \"npx projen\"." 22 | } 23 | -------------------------------------------------------------------------------- /continous-integration/README.md: -------------------------------------------------------------------------------- 1 | > This is used for integration testing and bundling purposes. 2 | 3 | ## Integration Testing 4 | 5 | A simple CDK template uses the `Dockerfile` to bundle a layer containing tesseract. 6 | 7 | Using `npx cdk synth` the CDK app is synthesized. The artifacts are bundled as this happens. 8 | The output artifacts of the synth command (i.e. cloudformation template, layer, testing lambda) is put into `cdk.out` by the CDK. 9 | 10 | AWS SAM CLI is used to invoke a testing function locally using the respective runtime and layer. 11 | The result is checked for errors. 12 | 13 | Commands to reproduce: 14 | 15 | ```bash 16 | npm ci 17 | npx cdk --app 'npx ts-node index.ts' synth 18 | ## run integration test using Python 3.10 19 | npx npm run test:integration:python 20 | ## run integration test using NodeJs 18 21 | npx npm run test:integration:node 22 | ``` 23 | 24 | ## Bundling 25 | 26 | After `npx cdk synth` was executed bundles of the binary can be created with `npm run bundle:binary`. 27 | The bundles will be put into the `ready-to-use` folder. -------------------------------------------------------------------------------- /continous-integration/lambda-handlers/node/.gitattributes: -------------------------------------------------------------------------------- 1 | # ~~ Generated by projen. To modify, edit .projenrc.js and run "npx projen". 2 | 3 | * text=auto eol=lf 4 | /.gitattributes linguist-generated 5 | /.gitignore linguist-generated 6 | /.npmignore linguist-generated 7 | /.projen/** linguist-generated 8 | /.projen/deps.json linguist-generated 9 | /.projen/files.json linguist-generated 10 | /.projen/tasks.json linguist-generated 11 | /package.json linguist-generated 12 | /yarn.lock linguist-generated -------------------------------------------------------------------------------- /continous-integration/lambda-handlers/node/.gitignore: -------------------------------------------------------------------------------- 1 | # ~~ Generated by projen. To modify, edit .projenrc.js and run "npx projen". 2 | !/.gitattributes 3 | !/.projen/tasks.json 4 | !/.projen/deps.json 5 | !/.projen/files.json 6 | !/package.json 7 | !/.npmignore 8 | logs 9 | *.log 10 | npm-debug.log* 11 | yarn-debug.log* 12 | yarn-error.log* 13 | lerna-debug.log* 14 | report.[0-9]*.[0-9]*.[0-9]*.[0-9]*.json 15 | pids 16 | *.pid 17 | *.seed 18 | *.pid.lock 19 | lib-cov 20 | coverage 21 | *.lcov 22 | .nyc_output 23 | build/Release 24 | node_modules/ 25 | jspm_packages/ 26 | *.tsbuildinfo 27 | .eslintcache 28 | *.tgz 29 | .yarn-integrity 30 | .cache 31 | /test-reports/ 32 | junit.xml 33 | /coverage/ 34 | -------------------------------------------------------------------------------- /continous-integration/lambda-handlers/node/.npmignore: -------------------------------------------------------------------------------- 1 | # ~~ Generated by projen. To modify, edit .projenrc.js and run "npx projen". 2 | /.projen/ 3 | /test-reports/ 4 | junit.xml 5 | /coverage/ 6 | /.gitattributes 7 | -------------------------------------------------------------------------------- /continous-integration/lambda-handlers/node/.projen/deps.json: -------------------------------------------------------------------------------- 1 | { 2 | "dependencies": [ 3 | { 4 | "name": "esbuild", 5 | "type": "build" 6 | }, 7 | { 8 | "name": "jest", 9 | "type": "build" 10 | }, 11 | { 12 | "name": "jest-junit", 13 | "version": "^16", 14 | "type": "build" 15 | }, 16 | { 17 | "name": "tesseractocr", 18 | "type": "runtime" 19 | } 20 | ], 21 | "//": "~~ Generated by projen. To modify, edit .projenrc.js and run \"npx projen\"." 22 | } 23 | -------------------------------------------------------------------------------- /continous-integration/lambda-handlers/node/.projen/files.json: -------------------------------------------------------------------------------- 1 | { 2 | "files": [ 3 | ".gitattributes", 4 | ".gitignore", 5 | ".npmignore", 6 | ".projen/deps.json", 7 | ".projen/files.json", 8 | ".projen/tasks.json" 9 | ], 10 | "//": "~~ Generated by projen. To modify, edit .projenrc.js and run \"npx projen\"." 11 | } 12 | -------------------------------------------------------------------------------- /continous-integration/lambda-handlers/node/.projen/tasks.json: -------------------------------------------------------------------------------- 1 | { 2 | "tasks": { 3 | "build": { 4 | "name": "build", 5 | "description": "Full release build", 6 | "steps": [ 7 | { 8 | "spawn": "pre-compile" 9 | }, 10 | { 11 | "spawn": "compile" 12 | }, 13 | { 14 | "spawn": "post-compile" 15 | }, 16 | { 17 | "spawn": "test" 18 | }, 19 | { 20 | "spawn": "package" 21 | } 22 | ] 23 | }, 24 | "compile": { 25 | "name": "compile", 26 | "description": "Only compile" 27 | }, 28 | "default": { 29 | "name": "default", 30 | "description": "Synthesize project files", 31 | "steps": [ 32 | { 33 | "exec": "npx projen default", 34 | "cwd": "../../.." 35 | } 36 | ] 37 | }, 38 | "install": { 39 | "name": "install", 40 | "description": "Install project dependencies and update lockfile (non-frozen)", 41 | "steps": [ 42 | { 43 | "exec": "yarn install --check-files" 44 | } 45 | ] 46 | }, 47 | "install:ci": { 48 | "name": "install:ci", 49 | "description": "Install project dependencies using frozen lockfile", 50 | "steps": [ 51 | { 52 | "exec": "yarn install --check-files --frozen-lockfile" 53 | } 54 | ] 55 | }, 56 | "package": { 57 | "name": "package", 58 | "description": "Creates the distribution package", 59 | "steps": [ 60 | { 61 | "exec": "mkdir -p dist/js" 62 | }, 63 | { 64 | "exec": "npm pack --pack-destination dist/js" 65 | } 66 | ] 67 | }, 68 | "post-compile": { 69 | "name": "post-compile", 70 | "description": "Runs after successful compilation" 71 | }, 72 | "post-upgrade": { 73 | "name": "post-upgrade", 74 | "description": "Runs after upgrading dependencies" 75 | }, 76 | "pre-compile": { 77 | "name": "pre-compile", 78 | "description": "Prepare the project for compilation" 79 | }, 80 | "test": { 81 | "name": "test", 82 | "description": "Run tests", 83 | "steps": [ 84 | { 85 | "exec": "jest --passWithNoTests --updateSnapshot", 86 | "receiveArgs": true 87 | } 88 | ] 89 | }, 90 | "test:watch": { 91 | "name": "test:watch", 92 | "description": "Run jest in watch mode", 93 | "steps": [ 94 | { 95 | "exec": "jest --watch" 96 | } 97 | ] 98 | }, 99 | "upgrade": { 100 | "name": "upgrade", 101 | "description": "upgrade dependencies", 102 | "env": { 103 | "CI": "0" 104 | }, 105 | "steps": [ 106 | { 107 | "exec": "npx npm-check-updates@16 --upgrade --target=minor --peer --no-deprecated --dep=dev,peer,prod,optional --filter=esbuild,jest,tesseractocr" 108 | }, 109 | { 110 | "exec": "yarn install --check-files" 111 | }, 112 | { 113 | "exec": "yarn upgrade esbuild jest jest-junit tesseractocr" 114 | }, 115 | { 116 | "exec": "npx projen" 117 | }, 118 | { 119 | "spawn": "post-upgrade" 120 | } 121 | ] 122 | } 123 | }, 124 | "env": { 125 | "PATH": "$(npx -c \"node --print process.env.PATH\")" 126 | }, 127 | "//": "~~ Generated by projen. To modify, edit .projenrc.js and run \"npx projen\"." 128 | } 129 | -------------------------------------------------------------------------------- /continous-integration/lambda-handlers/node/README.md: -------------------------------------------------------------------------------- 1 | # replace this -------------------------------------------------------------------------------- /continous-integration/lambda-handlers/node/faust.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bweigel/aws-lambda-tesseract-layer/8f88da851a8f5cb45f168450977403e7743f5f6c/continous-integration/lambda-handlers/node/faust.png -------------------------------------------------------------------------------- /continous-integration/lambda-handlers/node/index.js: -------------------------------------------------------------------------------- 1 | import recognize from 'tesseractocr' 2 | 3 | exports.handler = async function(event) { 4 | const text = await recognize('faust.png') 5 | return { 6 | statusCode: 200, 7 | body: text 8 | }; 9 | }; 10 | -------------------------------------------------------------------------------- /continous-integration/lambda-handlers/node/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "node-lambda", 3 | "scripts": { 4 | "build": "npx projen build", 5 | "compile": "npx projen compile", 6 | "default": "npx projen default", 7 | "package": "npx projen package", 8 | "post-compile": "npx projen post-compile", 9 | "post-upgrade": "npx projen post-upgrade", 10 | "pre-compile": "npx projen pre-compile", 11 | "test": "npx projen test", 12 | "test:watch": "npx projen test:watch", 13 | "upgrade": "npx projen upgrade", 14 | "projen": "npx projen" 15 | }, 16 | "devDependencies": { 17 | "esbuild": "^0.17.5", 18 | "jest": "^29.4.1", 19 | "jest-junit": "^16" 20 | }, 21 | "dependencies": { 22 | "tesseractocr": "^2.0.3" 23 | }, 24 | "main": "lib/index.js", 25 | "license": "UNLICENSED", 26 | "publishConfig": { 27 | "access": "public" 28 | }, 29 | "version": "0.0.0", 30 | "jest": { 31 | "coverageProvider": "v8", 32 | "clearMocks": true, 33 | "collectCoverage": true, 34 | "coverageReporters": [ 35 | "json", 36 | "lcov", 37 | "clover", 38 | "cobertura", 39 | "text" 40 | ], 41 | "coverageDirectory": "coverage", 42 | "coveragePathIgnorePatterns": [ 43 | "/node_modules/" 44 | ], 45 | "testPathIgnorePatterns": [ 46 | "/node_modules/" 47 | ], 48 | "watchPathIgnorePatterns": [ 49 | "/node_modules/" 50 | ], 51 | "testMatch": [ 52 | "**/__tests__/**/*.[jt]s?(x)", 53 | "**/*(*.)@(spec|test).[jt]s?(x)" 54 | ], 55 | "reporters": [ 56 | "default", 57 | [ 58 | "jest-junit", 59 | { 60 | "outputDirectory": "test-reports" 61 | } 62 | ] 63 | ] 64 | }, 65 | "//": "~~ Generated by projen. To modify, edit .projenrc.js and run \"npx projen\"." 66 | } 67 | -------------------------------------------------------------------------------- /continous-integration/lambda-handlers/python/Pipfile: -------------------------------------------------------------------------------- 1 | [[source]] 2 | url = "https://pypi.org/simple" 3 | verify_ssl = true 4 | name = "pypi" 5 | 6 | [packages] 7 | pillow = "*" 8 | pytesseract = "*" 9 | requests = "*" 10 | 11 | [dev-packages] 12 | 13 | [requires] 14 | python_version = "3.8" 15 | -------------------------------------------------------------------------------- /continous-integration/lambda-handlers/python/Pipfile.lock: -------------------------------------------------------------------------------- 1 | { 2 | "_meta": { 3 | "hash": { 4 | "sha256": "48e19e58946c3ebd885d7bc4500eeb15e0a94f975d7b51ac7b09548f0bf9ee5b" 5 | }, 6 | "pipfile-spec": 6, 7 | "requires": { 8 | "python_version": "3.8" 9 | }, 10 | "sources": [ 11 | { 12 | "name": "pypi", 13 | "url": "https://pypi.org/simple", 14 | "verify_ssl": true 15 | } 16 | ] 17 | }, 18 | "default": { 19 | "certifi": { 20 | "hashes": [ 21 | "sha256:0a816057ea3cdefcef70270d2c515e4506bbc954f417fa5ade2021213bb8f0c6", 22 | "sha256:30350364dfe371162649852c63336a15c70c6510c2ad5015b21c2345311805f3" 23 | ], 24 | "markers": "python_version >= '3.6'", 25 | "version": "==2025.4.26" 26 | }, 27 | "charset-normalizer": { 28 | "hashes": [ 29 | "sha256:005fa3432484527f9732ebd315da8da8001593e2cf46a3d817669f062c3d9ed4", 30 | "sha256:046595208aae0120559a67693ecc65dd75d46f7bf687f159127046628178dc45", 31 | "sha256:0c29de6a1a95f24b9a1aa7aefd27d2487263f00dfd55a77719b530788f75cff7", 32 | "sha256:0c8c57f84ccfc871a48a47321cfa49ae1df56cd1d965a09abe84066f6853b9c0", 33 | "sha256:0f5d9ed7f254402c9e7d35d2f5972c9bbea9040e99cd2861bd77dc68263277c7", 34 | "sha256:18dd2e350387c87dabe711b86f83c9c78af772c748904d372ade190b5c7c9d4d", 35 | "sha256:1b1bde144d98e446b056ef98e59c256e9294f6b74d7af6846bf5ffdafd687a7d", 36 | "sha256:1c95a1e2902a8b722868587c0e1184ad5c55631de5afc0eb96bc4b0d738092c0", 37 | "sha256:1cad5f45b3146325bb38d6855642f6fd609c3f7cad4dbaf75549bf3b904d3184", 38 | "sha256:21b2899062867b0e1fde9b724f8aecb1af14f2778d69aacd1a5a1853a597a5db", 39 | "sha256:24498ba8ed6c2e0b56d4acbf83f2d989720a93b41d712ebd4f4979660db4417b", 40 | "sha256:25a23ea5c7edc53e0f29bae2c44fcb5a1aa10591aae107f2a2b2583a9c5cbc64", 41 | "sha256:289200a18fa698949d2b39c671c2cc7a24d44096784e76614899a7ccf2574b7b", 42 | "sha256:28a1005facc94196e1fb3e82a3d442a9d9110b8434fc1ded7a24a2983c9888d8", 43 | "sha256:32fc0341d72e0f73f80acb0a2c94216bd704f4f0bce10aedea38f30502b271ff", 44 | "sha256:36b31da18b8890a76ec181c3cf44326bf2c48e36d393ca1b72b3f484113ea344", 45 | "sha256:3c21d4fca343c805a52c0c78edc01e3477f6dd1ad7c47653241cf2a206d4fc58", 46 | "sha256:3fddb7e2c84ac87ac3a947cb4e66d143ca5863ef48e4a5ecb83bd48619e4634e", 47 | "sha256:43e0933a0eff183ee85833f341ec567c0980dae57c464d8a508e1b2ceb336471", 48 | "sha256:4a476b06fbcf359ad25d34a057b7219281286ae2477cc5ff5e3f70a246971148", 49 | "sha256:4e594135de17ab3866138f496755f302b72157d115086d100c3f19370839dd3a", 50 | "sha256:50bf98d5e563b83cc29471fa114366e6806bc06bc7a25fd59641e41445327836", 51 | "sha256:5a9979887252a82fefd3d3ed2a8e3b937a7a809f65dcb1e068b090e165bbe99e", 52 | "sha256:5baececa9ecba31eff645232d59845c07aa030f0c81ee70184a90d35099a0e63", 53 | "sha256:5bf4545e3b962767e5c06fe1738f951f77d27967cb2caa64c28be7c4563e162c", 54 | "sha256:6333b3aa5a12c26b2a4d4e7335a28f1475e0e5e17d69d55141ee3cab736f66d1", 55 | "sha256:65c981bdbd3f57670af8b59777cbfae75364b483fa8a9f420f08094531d54a01", 56 | "sha256:68a328e5f55ec37c57f19ebb1fdc56a248db2e3e9ad769919a58672958e8f366", 57 | "sha256:6a0289e4589e8bdfef02a80478f1dfcb14f0ab696b5a00e1f4b8a14a307a3c58", 58 | "sha256:6b66f92b17849b85cad91259efc341dce9c1af48e2173bf38a85c6329f1033e5", 59 | "sha256:6c9379d65defcab82d07b2a9dfbfc2e95bc8fe0ebb1b176a3190230a3ef0e07c", 60 | "sha256:6fc1f5b51fa4cecaa18f2bd7a003f3dd039dd615cd69a2afd6d3b19aed6775f2", 61 | "sha256:70f7172939fdf8790425ba31915bfbe8335030f05b9913d7ae00a87d4395620a", 62 | "sha256:721c76e84fe669be19c5791da68232ca2e05ba5185575086e384352e2c309597", 63 | "sha256:7222ffd5e4de8e57e03ce2cef95a4c43c98fcb72ad86909abdfc2c17d227fc1b", 64 | "sha256:75d10d37a47afee94919c4fab4c22b9bc2a8bf7d4f46f87363bcf0573f3ff4f5", 65 | "sha256:76af085e67e56c8816c3ccf256ebd136def2ed9654525348cfa744b6802b69eb", 66 | "sha256:770cab594ecf99ae64c236bc9ee3439c3f46be49796e265ce0cc8bc17b10294f", 67 | "sha256:7a6ab32f7210554a96cd9e33abe3ddd86732beeafc7a28e9955cdf22ffadbab0", 68 | "sha256:7c48ed483eb946e6c04ccbe02c6b4d1d48e51944b6db70f697e089c193404941", 69 | "sha256:7f56930ab0abd1c45cd15be65cc741c28b1c9a34876ce8c17a2fa107810c0af0", 70 | "sha256:8075c35cd58273fee266c58c0c9b670947c19df5fb98e7b66710e04ad4e9ff86", 71 | "sha256:8272b73e1c5603666618805fe821edba66892e2870058c94c53147602eab29c7", 72 | "sha256:82d8fd25b7f4675d0c47cf95b594d4e7b158aca33b76aa63d07186e13c0e0ab7", 73 | "sha256:844da2b5728b5ce0e32d863af26f32b5ce61bc4273a9c720a9f3aa9df73b1455", 74 | "sha256:8755483f3c00d6c9a77f490c17e6ab0c8729e39e6390328e42521ef175380ae6", 75 | "sha256:915f3849a011c1f593ab99092f3cecfcb4d65d8feb4a64cf1bf2d22074dc0ec4", 76 | "sha256:926ca93accd5d36ccdabd803392ddc3e03e6d4cd1cf17deff3b989ab8e9dbcf0", 77 | "sha256:982bb1e8b4ffda883b3d0a521e23abcd6fd17418f6d2c4118d257a10199c0ce3", 78 | "sha256:98f862da73774290f251b9df8d11161b6cf25b599a66baf087c1ffe340e9bfd1", 79 | "sha256:9cbfacf36cb0ec2897ce0ebc5d08ca44213af24265bd56eca54bee7923c48fd6", 80 | "sha256:a370b3e078e418187da8c3674eddb9d983ec09445c99a3a263c2011993522981", 81 | "sha256:a955b438e62efdf7e0b7b52a64dc5c3396e2634baa62471768a64bc2adb73d5c", 82 | "sha256:aa6af9e7d59f9c12b33ae4e9450619cf2488e2bbe9b44030905877f0b2324980", 83 | "sha256:aa88ca0b1932e93f2d961bf3addbb2db902198dca337d88c89e1559e066e7645", 84 | "sha256:aaeeb6a479c7667fbe1099af9617c83aaca22182d6cf8c53966491a0f1b7ffb7", 85 | "sha256:aaf27faa992bfee0264dc1f03f4c75e9fcdda66a519db6b957a3f826e285cf12", 86 | "sha256:b2680962a4848b3c4f155dc2ee64505a9c57186d0d56b43123b17ca3de18f0fa", 87 | "sha256:b2d318c11350e10662026ad0eb71bb51c7812fc8590825304ae0bdd4ac283acd", 88 | "sha256:b33de11b92e9f75a2b545d6e9b6f37e398d86c3e9e9653c4864eb7e89c5773ef", 89 | "sha256:b3daeac64d5b371dea99714f08ffc2c208522ec6b06fbc7866a450dd446f5c0f", 90 | "sha256:be1e352acbe3c78727a16a455126d9ff83ea2dfdcbc83148d2982305a04714c2", 91 | "sha256:bee093bf902e1d8fc0ac143c88902c3dfc8941f7ea1d6a8dd2bcb786d33db03d", 92 | "sha256:c72fbbe68c6f32f251bdc08b8611c7b3060612236e960ef848e0a517ddbe76c5", 93 | "sha256:c9e36a97bee9b86ef9a1cf7bb96747eb7a15c2f22bdb5b516434b00f2a599f02", 94 | "sha256:cddf7bd982eaa998934a91f69d182aec997c6c468898efe6679af88283b498d3", 95 | "sha256:cf713fe9a71ef6fd5adf7a79670135081cd4431c2943864757f0fa3a65b1fafd", 96 | "sha256:d11b54acf878eef558599658b0ffca78138c8c3655cf4f3a4a673c437e67732e", 97 | "sha256:d41c4d287cfc69060fa91cae9683eacffad989f1a10811995fa309df656ec214", 98 | "sha256:d524ba3f1581b35c03cb42beebab4a13e6cdad7b36246bd22541fa585a56cccd", 99 | "sha256:daac4765328a919a805fa5e2720f3e94767abd632ae410a9062dff5412bae65a", 100 | "sha256:db4c7bf0e07fc3b7d89ac2a5880a6a8062056801b83ff56d8464b70f65482b6c", 101 | "sha256:dc7039885fa1baf9be153a0626e337aa7ec8bf96b0128605fb0d77788ddc1681", 102 | "sha256:dccab8d5fa1ef9bfba0590ecf4d46df048d18ffe3eec01eeb73a42e0d9e7a8ba", 103 | "sha256:dedb8adb91d11846ee08bec4c8236c8549ac721c245678282dcb06b221aab59f", 104 | "sha256:e45ba65510e2647721e35323d6ef54c7974959f6081b58d4ef5d87c60c84919a", 105 | "sha256:e53efc7c7cee4c1e70661e2e112ca46a575f90ed9ae3fef200f2a25e954f4b28", 106 | "sha256:e635b87f01ebc977342e2697d05b56632f5f879a4f15955dfe8cef2448b51691", 107 | "sha256:e70e990b2137b29dc5564715de1e12701815dacc1d056308e2b17e9095372a82", 108 | "sha256:e8082b26888e2f8b36a042a58307d5b917ef2b1cacab921ad3323ef91901c71a", 109 | "sha256:e8323a9b031aa0393768b87f04b4164a40037fb2a3c11ac06a03ffecd3618027", 110 | "sha256:e92fca20c46e9f5e1bb485887d074918b13543b1c2a1185e69bb8d17ab6236a7", 111 | "sha256:eb30abc20df9ab0814b5a2524f23d75dcf83cde762c161917a2b4b7b55b1e518", 112 | "sha256:eba9904b0f38a143592d9fc0e19e2df0fa2e41c3c3745554761c5f6447eedabf", 113 | "sha256:ef8de666d6179b009dce7bcb2ad4c4a779f113f12caf8dc77f0162c29d20490b", 114 | "sha256:efd387a49825780ff861998cd959767800d54f8308936b21025326de4b5a42b9", 115 | "sha256:f0aa37f3c979cf2546b73e8222bbfa3dc07a641585340179d768068e3455e544", 116 | "sha256:f4074c5a429281bf056ddd4c5d3b740ebca4d43ffffe2ef4bf4d2d05114299da", 117 | "sha256:f69a27e45c43520f5487f27627059b64aaf160415589230992cec34c5e18a509", 118 | "sha256:fb707f3e15060adf5b7ada797624a6c6e0138e2a26baa089df64c68ee98e040f", 119 | "sha256:fcbe676a55d7445b22c10967bceaaf0ee69407fbe0ece4d032b6eb8d4565982a", 120 | "sha256:fdb20a30fe1175ecabed17cbf7812f7b804b8a315a25f24678bcdf120a90077f" 121 | ], 122 | "markers": "python_version >= '3.7'", 123 | "version": "==3.4.2" 124 | }, 125 | "idna": { 126 | "hashes": [ 127 | "sha256:12f65c9b470abda6dc35cf8e63cc574b1c52b11df2c86030af0ac09b01b13ea9", 128 | "sha256:946d195a0d259cbba61165e88e65941f16e9b36ea6ddb97f00452bae8b1287d3" 129 | ], 130 | "markers": "python_version >= '3.6'", 131 | "version": "==3.10" 132 | }, 133 | "packaging": { 134 | "hashes": [ 135 | "sha256:29572ef2b1f17581046b3a2227d5c611fb25ec70ca1ba8554b24b0e69331a484", 136 | "sha256:d443872c98d677bf60f6a1f2f8c1cb748e8fe762d2bf9d3148b5599295b0fc4f" 137 | ], 138 | "markers": "python_version >= '3.8'", 139 | "version": "==25.0" 140 | }, 141 | "pillow": { 142 | "hashes": [ 143 | "sha256:02a2be69f9c9b8c1e97cf2713e789d4e398c751ecfd9967c18d0ce304efbf885", 144 | "sha256:030abdbe43ee02e0de642aee345efa443740aa4d828bfe8e2eb11922ea6a21ea", 145 | "sha256:06b2f7898047ae93fad74467ec3d28fe84f7831370e3c258afa533f81ef7f3df", 146 | "sha256:0755ffd4a0c6f267cccbae2e9903d95477ca2f77c4fcf3a3a09570001856c8a5", 147 | "sha256:0a9ec697746f268507404647e531e92889890a087e03681a3606d9b920fbee3c", 148 | "sha256:0ae24a547e8b711ccaaf99c9ae3cd975470e1a30caa80a6aaee9a2f19c05701d", 149 | "sha256:134ace6dc392116566980ee7436477d844520a26a4b1bd4053f6f47d096997fd", 150 | "sha256:166c1cd4d24309b30d61f79f4a9114b7b2313d7450912277855ff5dfd7cd4a06", 151 | "sha256:1b5dea9831a90e9d0721ec417a80d4cbd7022093ac38a568db2dd78363b00908", 152 | "sha256:1d846aea995ad352d4bdcc847535bd56e0fd88d36829d2c90be880ef1ee4668a", 153 | "sha256:1ef61f5dd14c300786318482456481463b9d6b91ebe5ef12f405afbba77ed0be", 154 | "sha256:297e388da6e248c98bc4a02e018966af0c5f92dfacf5a5ca22fa01cb3179bca0", 155 | "sha256:298478fe4f77a4408895605f3482b6cc6222c018b2ce565c2b6b9c354ac3229b", 156 | "sha256:29dbdc4207642ea6aad70fbde1a9338753d33fb23ed6956e706936706f52dd80", 157 | "sha256:2db98790afc70118bd0255c2eeb465e9767ecf1f3c25f9a1abb8ffc8cfd1fe0a", 158 | "sha256:32cda9e3d601a52baccb2856b8ea1fc213c90b340c542dcef77140dfa3278a9e", 159 | "sha256:37fb69d905be665f68f28a8bba3c6d3223c8efe1edf14cc4cfa06c241f8c81d9", 160 | "sha256:416d3a5d0e8cfe4f27f574362435bc9bae57f679a7158e0096ad2beb427b8696", 161 | "sha256:43efea75eb06b95d1631cb784aa40156177bf9dd5b4b03ff38979e048258bc6b", 162 | "sha256:4b35b21b819ac1dbd1233317adeecd63495f6babf21b7b2512d244ff6c6ce309", 163 | "sha256:4d9667937cfa347525b319ae34375c37b9ee6b525440f3ef48542fcf66f2731e", 164 | "sha256:5161eef006d335e46895297f642341111945e2c1c899eb406882a6c61a4357ab", 165 | "sha256:543f3dc61c18dafb755773efc89aae60d06b6596a63914107f75459cf984164d", 166 | "sha256:551d3fd6e9dc15e4c1eb6fc4ba2b39c0c7933fa113b220057a34f4bb3268a060", 167 | "sha256:59291fb29317122398786c2d44427bbd1a6d7ff54017075b22be9d21aa59bd8d", 168 | "sha256:5b001114dd152cfd6b23befeb28d7aee43553e2402c9f159807bf55f33af8a8d", 169 | "sha256:5b4815f2e65b30f5fbae9dfffa8636d992d49705723fe86a3661806e069352d4", 170 | "sha256:5dc6761a6efc781e6a1544206f22c80c3af4c8cf461206d46a1e6006e4429ff3", 171 | "sha256:5e84b6cc6a4a3d76c153a6b19270b3526a5a8ed6b09501d3af891daa2a9de7d6", 172 | "sha256:6209bb41dc692ddfee4942517c19ee81b86c864b626dbfca272ec0f7cff5d9fb", 173 | "sha256:673655af3eadf4df6b5457033f086e90299fdd7a47983a13827acf7459c15d94", 174 | "sha256:6c762a5b0997f5659a5ef2266abc1d8851ad7749ad9a6a5506eb23d314e4f46b", 175 | "sha256:7086cc1d5eebb91ad24ded9f58bec6c688e9f0ed7eb3dbbf1e4800280a896496", 176 | "sha256:73664fe514b34c8f02452ffb73b7a92c6774e39a647087f83d67f010eb9a0cf0", 177 | "sha256:76a911dfe51a36041f2e756b00f96ed84677cdeb75d25c767f296c1c1eda1319", 178 | "sha256:780c072c2e11c9b2c7ca37f9a2ee8ba66f44367ac3e5c7832afcfe5104fd6d1b", 179 | "sha256:7928ecbf1ece13956b95d9cbcfc77137652b02763ba384d9ab508099a2eca856", 180 | "sha256:7970285ab628a3779aecc35823296a7869f889b8329c16ad5a71e4901a3dc4ef", 181 | "sha256:7a8d4bade9952ea9a77d0c3e49cbd8b2890a399422258a77f357b9cc9be8d680", 182 | "sha256:7c1ee6f42250df403c5f103cbd2768a28fe1a0ea1f0f03fe151c8741e1469c8b", 183 | "sha256:7dfecdbad5c301d7b5bde160150b4db4c659cee2b69589705b6f8a0c509d9f42", 184 | "sha256:812f7342b0eee081eaec84d91423d1b4650bb9828eb53d8511bcef8ce5aecf1e", 185 | "sha256:866b6942a92f56300012f5fbac71f2d610312ee65e22f1aa2609e491284e5597", 186 | "sha256:86dcb5a1eb778d8b25659d5e4341269e8590ad6b4e8b44d9f4b07f8d136c414a", 187 | "sha256:87dd88ded2e6d74d31e1e0a99a726a6765cda32d00ba72dc37f0651f306daaa8", 188 | "sha256:8bc1a764ed8c957a2e9cacf97c8b2b053b70307cf2996aafd70e91a082e70df3", 189 | "sha256:8d4d5063501b6dd4024b8ac2f04962d661222d120381272deea52e3fc52d3736", 190 | "sha256:8f0aef4ef59694b12cadee839e2ba6afeab89c0f39a3adc02ed51d109117b8da", 191 | "sha256:930044bb7679ab003b14023138b50181899da3f25de50e9dbee23b61b4de2126", 192 | "sha256:950be4d8ba92aca4b2bb0741285a46bfae3ca699ef913ec8416c1b78eadd64cd", 193 | "sha256:961a7293b2457b405967af9c77dcaa43cc1a8cd50d23c532e62d48ab6cdd56f5", 194 | "sha256:9b885f89040bb8c4a1573566bbb2f44f5c505ef6e74cec7ab9068c900047f04b", 195 | "sha256:9f4727572e2918acaa9077c919cbbeb73bd2b3ebcfe033b72f858fc9fbef0026", 196 | "sha256:a02364621fe369e06200d4a16558e056fe2805d3468350df3aef21e00d26214b", 197 | "sha256:a985e028fc183bf12a77a8bbf36318db4238a3ded7fa9df1b9a133f1cb79f8fc", 198 | "sha256:ac1452d2fbe4978c2eec89fb5a23b8387aba707ac72810d9490118817d9c0b46", 199 | "sha256:b15e02e9bb4c21e39876698abf233c8c579127986f8207200bc8a8f6bb27acf2", 200 | "sha256:b2724fdb354a868ddf9a880cb84d102da914e99119211ef7ecbdc613b8c96b3c", 201 | "sha256:bbc527b519bd3aa9d7f429d152fea69f9ad37c95f0b02aebddff592688998abe", 202 | "sha256:bcd5e41a859bf2e84fdc42f4edb7d9aba0a13d29a2abadccafad99de3feff984", 203 | "sha256:bd2880a07482090a3bcb01f4265f1936a903d70bc740bfcb1fd4e8a2ffe5cf5a", 204 | "sha256:bee197b30783295d2eb680b311af15a20a8b24024a19c3a26431ff83eb8d1f70", 205 | "sha256:bf2342ac639c4cf38799a44950bbc2dfcb685f052b9e262f446482afaf4bffca", 206 | "sha256:c76e5786951e72ed3686e122d14c5d7012f16c8303a674d18cdcd6d89557fc5b", 207 | "sha256:cbed61494057c0f83b83eb3a310f0bf774b09513307c434d4366ed64f4128a91", 208 | "sha256:cfdd747216947628af7b259d274771d84db2268ca062dd5faf373639d00113a3", 209 | "sha256:d7480af14364494365e89d6fddc510a13e5a2c3584cb19ef65415ca57252fb84", 210 | "sha256:dbc6ae66518ab3c5847659e9988c3b60dc94ffb48ef9168656e0019a93dbf8a1", 211 | "sha256:dc3e2db6ba09ffd7d02ae9141cfa0ae23393ee7687248d46a7507b75d610f4f5", 212 | "sha256:dfe91cb65544a1321e631e696759491ae04a2ea11d36715eca01ce07284738be", 213 | "sha256:e4d49b85c4348ea0b31ea63bc75a9f3857869174e2bf17e7aba02945cd218e6f", 214 | "sha256:e4db64794ccdf6cb83a59d73405f63adbe2a1887012e308828596100a0b2f6cc", 215 | "sha256:e553cad5179a66ba15bb18b353a19020e73a7921296a7979c4a2b7f6a5cd57f9", 216 | "sha256:e88d5e6ad0d026fba7bdab8c3f225a69f063f116462c49892b0149e21b6c0a0e", 217 | "sha256:ecd85a8d3e79cd7158dec1c9e5808e821feea088e2f69a974db5edf84dc53141", 218 | "sha256:f5b92f4d70791b4a67157321c4e8225d60b119c5cc9aee8ecf153aace4aad4ef", 219 | "sha256:f5f0c3e969c8f12dd2bb7e0b15d5c468b51e5017e01e2e867335c81903046a22", 220 | "sha256:f7baece4ce06bade126fb84b8af1c33439a76d8a6fd818970215e0560ca28c27", 221 | "sha256:ff25afb18123cea58a591ea0244b92eb1e61a1fd497bf6d6384f09bc3262ec3e", 222 | "sha256:ff337c552345e95702c5fde3158acb0625111017d0e5f24bf3acdb9cc16b90d1" 223 | ], 224 | "index": "pypi", 225 | "markers": "python_version >= '3.8'", 226 | "version": "==10.4.0" 227 | }, 228 | "pytesseract": { 229 | "hashes": [ 230 | "sha256:4bf5f880c99406f52a3cfc2633e42d9dc67615e69d8a509d74867d3baddb5db9", 231 | "sha256:7a99c6c2ac598360693d83a416e36e0b33a67638bb9d77fdcac094a3589d4b34" 232 | ], 233 | "index": "pypi", 234 | "markers": "python_version >= '3.8'", 235 | "version": "==0.3.13" 236 | }, 237 | "requests": { 238 | "hashes": [ 239 | "sha256:55365417734eb18255590a9ff9eb97e9e1da868d4ccd6402399eaf68af20a760", 240 | "sha256:70761cfe03c773ceb22aa2f671b4757976145175cdfca038c02654d061d6dcc6" 241 | ], 242 | "index": "pypi", 243 | "markers": "python_version >= '3.8'", 244 | "version": "==2.32.3" 245 | }, 246 | "urllib3": { 247 | "hashes": [ 248 | "sha256:ca899ca043dcb1bafa3e262d73aa25c465bfb49e0bd9dd5d59f1d0acba2f8fac", 249 | "sha256:e7d814a81dad81e6caf2ec9fdedb284ecc9c73076b62654547cc64ccdcae26e9" 250 | ], 251 | "markers": "python_version >= '3.8'", 252 | "version": "==2.2.3" 253 | } 254 | }, 255 | "develop": {} 256 | } 257 | -------------------------------------------------------------------------------- /continous-integration/lambda-handlers/python/faust.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bweigel/aws-lambda-tesseract-layer/8f88da851a8f5cb45f168450977403e7743f5f6c/continous-integration/lambda-handlers/python/faust.png -------------------------------------------------------------------------------- /continous-integration/lambda-handlers/python/handler.py: -------------------------------------------------------------------------------- 1 | from pathlib import Path 2 | from PIL import Image 3 | import pytesseract 4 | 5 | def main(evt, ctx): 6 | img = Image.open(Path('faust.png')) 7 | txt = pytesseract.image_to_string(img, lang="deu") 8 | return txt 9 | 10 | -------------------------------------------------------------------------------- /continous-integration/lambda-handlers/python/requirements.txt: -------------------------------------------------------------------------------- 1 | -i https://pypi.org/simple 2 | certifi==2025.4.26; python_version >= '3.6' 3 | charset-normalizer==3.4.2; python_version >= '3.7' 4 | idna==3.10; python_version >= '3.6' 5 | packaging==25.0; python_version >= '3.8' 6 | pillow==10.4.0; python_version >= '3.8' 7 | pytesseract==0.3.13; python_version >= '3.8' 8 | requests==2.32.3; python_version >= '3.8' 9 | urllib3==2.2.3; python_version >= '3.8' 10 | -------------------------------------------------------------------------------- /continous-integration/main.ts: -------------------------------------------------------------------------------- 1 | import * as path from 'path'; 2 | import { App, DockerImage, Duration, Stack } from 'aws-cdk-lib'; 3 | import * as lambda from 'aws-cdk-lib/aws-lambda'; 4 | import { CfnLayerVersion, Code, Runtime } from 'aws-cdk-lib/aws-lambda'; 5 | import * as nodelambda from 'aws-cdk-lib/aws-lambda-nodejs'; 6 | 7 | const app = new App(); 8 | const stack = new Stack(app, 'tesseract-lambda-ci'); 9 | const pathToLayerSource = path.resolve(__dirname, '..'); 10 | /** 11 | * Test setup and artifacts for AL 2 12 | */ 13 | const al2Layer = new lambda.LayerVersion(stack, 'al2-layer', { 14 | code: Code.fromAsset(pathToLayerSource, { 15 | bundling: { 16 | image: DockerImage.fromBuild(pathToLayerSource, { file: 'Dockerfile.al2' }), 17 | command: ['/bin/bash', '-c', 'cp -r /opt/build-dist/. /asset-output/'], 18 | }, 19 | }), 20 | description: 'AL2 Tesseract Layer', 21 | }); 22 | stack.renameLogicalId(stack.getLogicalId(al2Layer.node.defaultChild as CfnLayerVersion), 'al2layer'); 23 | 24 | new lambda.Function(stack, 'python', { 25 | code: lambda.Code.fromAsset(path.resolve(__dirname, 'lambda-handlers/python'), { 26 | bundling: { 27 | image: DockerImage.fromRegistry('public.ecr.aws/sam/build-python3.10:latest'), 28 | command: [ 29 | '/bin/bash', 30 | '-c', 31 | ['pip install -r requirements.txt -t /asset-output/', 'cp faust.png /asset-output', 'cp handler.py /asset-output'].join(' && '), 32 | ], 33 | }, 34 | }), 35 | runtime: Runtime.PYTHON_3_10, 36 | layers: [al2Layer], 37 | functionName: `python`, 38 | memorySize: 512, 39 | timeout: Duration.seconds(30), 40 | handler: 'handler.main', 41 | }); 42 | 43 | new nodelambda.NodejsFunction(stack, 'node', { 44 | bundling: { 45 | nodeModules: ['tesseractocr'], 46 | commandHooks: { 47 | beforeInstall() { 48 | return []; 49 | }, 50 | beforeBundling(inputDir: string, outputDir: string): string[] { 51 | return [`cp ${inputDir}/faust.png ${outputDir}`]; 52 | }, 53 | afterBundling(): string[] { 54 | return []; 55 | }, 56 | }, 57 | }, 58 | depsLockFilePath: path.resolve(__dirname, 'lambda-handlers/node/yarn.lock'), 59 | 60 | runtime: Runtime.NODEJS_18_X, 61 | entry: path.resolve(__dirname, 'lambda-handlers/node/index.js'), 62 | layers: [al2Layer], 63 | functionName: `node`, 64 | memorySize: 512, 65 | timeout: Duration.seconds(30), 66 | handler: 'handler', 67 | }); 68 | -------------------------------------------------------------------------------- /create_release_assets.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | set -euxo 4 | 5 | pushd . 6 | cd ready-to-use/amazonlinux-1 7 | zip -r ../layer-al1.zip * 8 | popd 9 | pushd . 10 | cd ready-to-use/amazonlinux-2 11 | zip -r ../layer-al2.zip * 12 | popd 13 | -------------------------------------------------------------------------------- /example/README.md: -------------------------------------------------------------------------------- 1 | Examples 2 | === 3 | 4 | | Lambda Runtime | Amazon Linux | IaC framework | example | 5 | | :------------------- | :----------: | :------------------- | :----------------------------------- | 6 | | Python 3.8 | 2 | serverless framework | [`al2-serverless`](./al2-serverless) | 7 | | Python 3.8 | 2 | AWS CDK | [`al2-cdk`](./al2-cdk) | 8 | -------------------------------------------------------------------------------- /example/cdk/.eslintrc.json: -------------------------------------------------------------------------------- 1 | // ~~ Generated by projen. To modify, edit .projenrc.js and run "npx projen". 2 | { 3 | "env": { 4 | "jest": true, 5 | "node": true 6 | }, 7 | "root": true, 8 | "plugins": [ 9 | "@typescript-eslint", 10 | "import", 11 | "@stylistic" 12 | ], 13 | "parser": "@typescript-eslint/parser", 14 | "parserOptions": { 15 | "ecmaVersion": 2018, 16 | "sourceType": "module", 17 | "project": "./tsconfig.dev.json" 18 | }, 19 | "extends": [ 20 | "plugin:import/typescript" 21 | ], 22 | "settings": { 23 | "import/parsers": { 24 | "@typescript-eslint/parser": [ 25 | ".ts", 26 | ".tsx" 27 | ] 28 | }, 29 | "import/resolver": { 30 | "node": {}, 31 | "typescript": { 32 | "project": "./tsconfig.dev.json", 33 | "alwaysTryTypes": true 34 | } 35 | } 36 | }, 37 | "ignorePatterns": [ 38 | "*.js", 39 | "*.d.ts", 40 | "node_modules/", 41 | "*.generated.ts", 42 | "coverage" 43 | ], 44 | "rules": { 45 | "@stylistic/indent": [ 46 | "error", 47 | 2 48 | ], 49 | "@stylistic/quotes": [ 50 | "error", 51 | "single", 52 | { 53 | "avoidEscape": true 54 | } 55 | ], 56 | "@stylistic/comma-dangle": [ 57 | "error", 58 | "always-multiline" 59 | ], 60 | "@stylistic/comma-spacing": [ 61 | "error", 62 | { 63 | "before": false, 64 | "after": true 65 | } 66 | ], 67 | "@stylistic/no-multi-spaces": [ 68 | "error", 69 | { 70 | "ignoreEOLComments": false 71 | } 72 | ], 73 | "@stylistic/array-bracket-spacing": [ 74 | "error", 75 | "never" 76 | ], 77 | "@stylistic/array-bracket-newline": [ 78 | "error", 79 | "consistent" 80 | ], 81 | "@stylistic/object-curly-spacing": [ 82 | "error", 83 | "always" 84 | ], 85 | "@stylistic/object-curly-newline": [ 86 | "error", 87 | { 88 | "multiline": true, 89 | "consistent": true 90 | } 91 | ], 92 | "@stylistic/object-property-newline": [ 93 | "error", 94 | { 95 | "allowAllPropertiesOnSameLine": true 96 | } 97 | ], 98 | "@stylistic/keyword-spacing": [ 99 | "error" 100 | ], 101 | "@stylistic/brace-style": [ 102 | "error", 103 | "1tbs", 104 | { 105 | "allowSingleLine": true 106 | } 107 | ], 108 | "@stylistic/space-before-blocks": [ 109 | "error" 110 | ], 111 | "@stylistic/member-delimiter-style": [ 112 | "error" 113 | ], 114 | "@stylistic/semi": [ 115 | "error", 116 | "always" 117 | ], 118 | "@stylistic/max-len": [ 119 | "error", 120 | { 121 | "code": 150, 122 | "ignoreUrls": true, 123 | "ignoreStrings": true, 124 | "ignoreTemplateLiterals": true, 125 | "ignoreComments": true, 126 | "ignoreRegExpLiterals": true 127 | } 128 | ], 129 | "@stylistic/quote-props": [ 130 | "error", 131 | "consistent-as-needed" 132 | ], 133 | "@stylistic/key-spacing": [ 134 | "error" 135 | ], 136 | "@stylistic/no-multiple-empty-lines": [ 137 | "error" 138 | ], 139 | "@stylistic/no-trailing-spaces": [ 140 | "error" 141 | ], 142 | "curly": [ 143 | "error", 144 | "multi-line", 145 | "consistent" 146 | ], 147 | "@typescript-eslint/no-require-imports": "error", 148 | "import/no-extraneous-dependencies": [ 149 | "error", 150 | { 151 | "devDependencies": [ 152 | "**/test/**", 153 | "**/build-tools/**" 154 | ], 155 | "optionalDependencies": false, 156 | "peerDependencies": true 157 | } 158 | ], 159 | "import/no-unresolved": [ 160 | "error" 161 | ], 162 | "import/order": [ 163 | "warn", 164 | { 165 | "groups": [ 166 | "builtin", 167 | "external" 168 | ], 169 | "alphabetize": { 170 | "order": "asc", 171 | "caseInsensitive": true 172 | } 173 | } 174 | ], 175 | "import/no-duplicates": [ 176 | "error" 177 | ], 178 | "no-shadow": [ 179 | "off" 180 | ], 181 | "@typescript-eslint/no-shadow": "error", 182 | "@typescript-eslint/no-floating-promises": "error", 183 | "no-return-await": [ 184 | "off" 185 | ], 186 | "@typescript-eslint/return-await": "error", 187 | "dot-notation": [ 188 | "error" 189 | ], 190 | "no-bitwise": [ 191 | "error" 192 | ], 193 | "@typescript-eslint/member-ordering": [ 194 | "error", 195 | { 196 | "default": [ 197 | "public-static-field", 198 | "public-static-method", 199 | "protected-static-field", 200 | "protected-static-method", 201 | "private-static-field", 202 | "private-static-method", 203 | "field", 204 | "constructor", 205 | "method" 206 | ] 207 | } 208 | ] 209 | }, 210 | "overrides": [] 211 | } 212 | -------------------------------------------------------------------------------- /example/cdk/.gitattributes: -------------------------------------------------------------------------------- 1 | # ~~ Generated by projen. To modify, edit .projenrc.js and run "npx projen". 2 | 3 | * text=auto eol=lf 4 | /.eslintrc.json linguist-generated 5 | /.gitattributes linguist-generated 6 | /.gitignore linguist-generated 7 | /.npmignore linguist-generated 8 | /.projen/** linguist-generated 9 | /.projen/deps.json linguist-generated 10 | /.projen/files.json linguist-generated 11 | /.projen/tasks.json linguist-generated 12 | /cdk.json linguist-generated 13 | /package.json linguist-generated 14 | /tsconfig.dev.json linguist-generated 15 | /tsconfig.json linguist-generated 16 | /yarn.lock linguist-generated -------------------------------------------------------------------------------- /example/cdk/.gitignore: -------------------------------------------------------------------------------- 1 | # ~~ Generated by projen. To modify, edit .projenrc.js and run "npx projen". 2 | !/.gitattributes 3 | !/.projen/tasks.json 4 | !/.projen/deps.json 5 | !/.projen/files.json 6 | !/package.json 7 | !/.npmignore 8 | logs 9 | *.log 10 | npm-debug.log* 11 | yarn-debug.log* 12 | yarn-error.log* 13 | lerna-debug.log* 14 | report.[0-9]*.[0-9]*.[0-9]*.[0-9]*.json 15 | pids 16 | *.pid 17 | *.seed 18 | *.pid.lock 19 | lib-cov 20 | coverage 21 | *.lcov 22 | .nyc_output 23 | build/Release 24 | node_modules/ 25 | jspm_packages/ 26 | *.tsbuildinfo 27 | .eslintcache 28 | *.tgz 29 | .yarn-integrity 30 | .cache 31 | /test-reports/ 32 | junit.xml 33 | /coverage/ 34 | !/test/ 35 | !/tsconfig.json 36 | !/tsconfig.dev.json 37 | !/src/ 38 | /lib 39 | /dist/ 40 | !/.eslintrc.json 41 | /assets/ 42 | !/cdk.json 43 | /cdk.out/ 44 | .cdk.staging/ 45 | .parcel-cache/ 46 | -------------------------------------------------------------------------------- /example/cdk/.npmignore: -------------------------------------------------------------------------------- 1 | # ~~ Generated by projen. To modify, edit .projenrc.js and run "npx projen". 2 | /.projen/ 3 | /test-reports/ 4 | junit.xml 5 | /coverage/ 6 | /test/ 7 | /tsconfig.dev.json 8 | /src/ 9 | !/lib/ 10 | !/lib/**/*.js 11 | !/lib/**/*.d.ts 12 | dist 13 | /tsconfig.json 14 | /.github/ 15 | /.vscode/ 16 | /.idea/ 17 | /.projenrc.js 18 | tsconfig.tsbuildinfo 19 | /.eslintrc.json 20 | !/assets/ 21 | cdk.out/ 22 | .cdk.staging/ 23 | /.gitattributes 24 | -------------------------------------------------------------------------------- /example/cdk/.projen/deps.json: -------------------------------------------------------------------------------- 1 | { 2 | "dependencies": [ 3 | { 4 | "name": "@stylistic/eslint-plugin", 5 | "version": "^2", 6 | "type": "build" 7 | }, 8 | { 9 | "name": "@types/jest", 10 | "type": "build" 11 | }, 12 | { 13 | "name": "@types/node", 14 | "type": "build" 15 | }, 16 | { 17 | "name": "@typescript-eslint/eslint-plugin", 18 | "version": "^8", 19 | "type": "build" 20 | }, 21 | { 22 | "name": "@typescript-eslint/parser", 23 | "version": "^8", 24 | "type": "build" 25 | }, 26 | { 27 | "name": "aws-cdk", 28 | "version": "^2", 29 | "type": "build" 30 | }, 31 | { 32 | "name": "esbuild", 33 | "type": "build" 34 | }, 35 | { 36 | "name": "eslint-import-resolver-typescript", 37 | "type": "build" 38 | }, 39 | { 40 | "name": "eslint-plugin-import", 41 | "type": "build" 42 | }, 43 | { 44 | "name": "eslint", 45 | "version": "^9", 46 | "type": "build" 47 | }, 48 | { 49 | "name": "jest", 50 | "type": "build" 51 | }, 52 | { 53 | "name": "jest-junit", 54 | "version": "^16", 55 | "type": "build" 56 | }, 57 | { 58 | "name": "ts-jest", 59 | "type": "build" 60 | }, 61 | { 62 | "name": "ts-node", 63 | "type": "build" 64 | }, 65 | { 66 | "name": "typescript", 67 | "type": "build" 68 | }, 69 | { 70 | "name": "aws-cdk-lib", 71 | "version": "^2.55.0", 72 | "type": "runtime" 73 | }, 74 | { 75 | "name": "constructs", 76 | "version": "^10.0.5", 77 | "type": "runtime" 78 | } 79 | ], 80 | "//": "~~ Generated by projen. To modify, edit .projenrc.js and run \"npx projen\"." 81 | } 82 | -------------------------------------------------------------------------------- /example/cdk/.projen/files.json: -------------------------------------------------------------------------------- 1 | { 2 | "files": [ 3 | ".eslintrc.json", 4 | ".gitattributes", 5 | ".gitignore", 6 | ".npmignore", 7 | ".projen/deps.json", 8 | ".projen/files.json", 9 | ".projen/tasks.json", 10 | "cdk.json", 11 | "tsconfig.dev.json", 12 | "tsconfig.json" 13 | ], 14 | "//": "~~ Generated by projen. To modify, edit .projenrc.js and run \"npx projen\"." 15 | } 16 | -------------------------------------------------------------------------------- /example/cdk/.projen/tasks.json: -------------------------------------------------------------------------------- 1 | { 2 | "tasks": { 3 | "build": { 4 | "name": "build", 5 | "description": "Full release build", 6 | "steps": [ 7 | { 8 | "spawn": "pre-compile" 9 | }, 10 | { 11 | "spawn": "compile" 12 | }, 13 | { 14 | "spawn": "post-compile" 15 | }, 16 | { 17 | "spawn": "test" 18 | }, 19 | { 20 | "spawn": "package" 21 | } 22 | ] 23 | }, 24 | "bundle": { 25 | "name": "bundle", 26 | "description": "Prepare assets" 27 | }, 28 | "compile": { 29 | "name": "compile", 30 | "description": "Only compile" 31 | }, 32 | "default": { 33 | "name": "default", 34 | "description": "Synthesize project files", 35 | "steps": [ 36 | { 37 | "exec": "npx projen default", 38 | "cwd": "../.." 39 | } 40 | ] 41 | }, 42 | "deploy": { 43 | "name": "deploy", 44 | "description": "Deploys your CDK app to the AWS cloud", 45 | "steps": [ 46 | { 47 | "exec": "cdk deploy", 48 | "receiveArgs": true 49 | } 50 | ] 51 | }, 52 | "destroy": { 53 | "name": "destroy", 54 | "description": "Destroys your cdk app in the AWS cloud", 55 | "steps": [ 56 | { 57 | "exec": "cdk destroy", 58 | "receiveArgs": true 59 | } 60 | ] 61 | }, 62 | "diff": { 63 | "name": "diff", 64 | "description": "Diffs the currently deployed app against your code", 65 | "steps": [ 66 | { 67 | "exec": "cdk diff" 68 | } 69 | ] 70 | }, 71 | "eslint": { 72 | "name": "eslint", 73 | "description": "Runs eslint against the codebase", 74 | "env": { 75 | "ESLINT_USE_FLAT_CONFIG": "false" 76 | }, 77 | "steps": [ 78 | { 79 | "exec": "eslint --ext .ts,.tsx --fix --no-error-on-unmatched-pattern $@ src test build-tools", 80 | "receiveArgs": true 81 | } 82 | ] 83 | }, 84 | "install": { 85 | "name": "install", 86 | "description": "Install project dependencies and update lockfile (non-frozen)", 87 | "steps": [ 88 | { 89 | "exec": "yarn install --check-files" 90 | } 91 | ] 92 | }, 93 | "install:ci": { 94 | "name": "install:ci", 95 | "description": "Install project dependencies using frozen lockfile", 96 | "steps": [ 97 | { 98 | "exec": "yarn install --check-files --frozen-lockfile" 99 | } 100 | ] 101 | }, 102 | "package": { 103 | "name": "package", 104 | "description": "Creates the distribution package" 105 | }, 106 | "post-compile": { 107 | "name": "post-compile", 108 | "description": "Runs after successful compilation", 109 | "steps": [ 110 | { 111 | "spawn": "synth:silent" 112 | } 113 | ] 114 | }, 115 | "post-upgrade": { 116 | "name": "post-upgrade", 117 | "description": "Runs after upgrading dependencies" 118 | }, 119 | "pre-compile": { 120 | "name": "pre-compile", 121 | "description": "Prepare the project for compilation" 122 | }, 123 | "synth": { 124 | "name": "synth", 125 | "description": "Synthesizes your cdk app into cdk.out", 126 | "steps": [ 127 | { 128 | "exec": "cdk synth" 129 | } 130 | ] 131 | }, 132 | "synth:silent": { 133 | "name": "synth:silent", 134 | "description": "Synthesizes your cdk app into cdk.out and suppresses the template in stdout (part of \"yarn build\")", 135 | "steps": [ 136 | { 137 | "exec": "cdk synth -q" 138 | } 139 | ] 140 | }, 141 | "test": { 142 | "name": "test", 143 | "description": "Run tests", 144 | "steps": [ 145 | { 146 | "exec": "jest --passWithNoTests --updateSnapshot", 147 | "receiveArgs": true 148 | }, 149 | { 150 | "spawn": "eslint" 151 | } 152 | ] 153 | }, 154 | "test:watch": { 155 | "name": "test:watch", 156 | "description": "Run jest in watch mode", 157 | "steps": [ 158 | { 159 | "exec": "jest --watch" 160 | } 161 | ] 162 | }, 163 | "upgrade": { 164 | "name": "upgrade", 165 | "description": "upgrade dependencies", 166 | "env": { 167 | "CI": "0" 168 | }, 169 | "steps": [ 170 | { 171 | "exec": "npx npm-check-updates@16 --upgrade --target=minor --peer --no-deprecated --dep=dev,peer,prod,optional --filter=@types/jest,@types/node,esbuild,eslint-import-resolver-typescript,eslint-plugin-import,jest,ts-jest,ts-node,typescript" 172 | }, 173 | { 174 | "exec": "yarn install --check-files" 175 | }, 176 | { 177 | "exec": "yarn upgrade @stylistic/eslint-plugin @types/jest @types/node @typescript-eslint/eslint-plugin @typescript-eslint/parser aws-cdk esbuild eslint-import-resolver-typescript eslint-plugin-import eslint jest jest-junit ts-jest ts-node typescript aws-cdk-lib constructs" 178 | }, 179 | { 180 | "exec": "npx projen" 181 | }, 182 | { 183 | "spawn": "post-upgrade" 184 | } 185 | ] 186 | }, 187 | "watch": { 188 | "name": "watch", 189 | "description": "Watches changes in your source code and rebuilds and deploys to the current account", 190 | "steps": [ 191 | { 192 | "exec": "cdk deploy --hotswap" 193 | }, 194 | { 195 | "exec": "cdk watch" 196 | } 197 | ] 198 | } 199 | }, 200 | "env": { 201 | "PATH": "$(npx -c \"node --print process.env.PATH\")" 202 | }, 203 | "//": "~~ Generated by projen. To modify, edit .projenrc.js and run \"npx projen\"." 204 | } 205 | -------------------------------------------------------------------------------- /example/cdk/README.md: -------------------------------------------------------------------------------- 1 | Example: AWS Lambda with Tesseract layer (Amazon Linux 2 based runtime - Python 3.8) 2 | === 3 | 4 | ### Requirements 5 | 6 | - Docker 7 | - Node.Js 8 | 9 | ### Deploy Stack 10 | 11 | ```bash 12 | ## install dependencies 13 | yarn install 14 | ## deploy 15 | npx cdk deploy 16 | ``` 17 | 18 | ![Deployment](./deployment.png) 19 | 20 | ### Invoke your API with an URL to an Image 21 | 22 | ```bash 23 | curl -X POST \ 24 | https://16ary8rftd.execute-api.eu-central-1.amazonaws.com/prod/ocr \ 25 | -d https://upload.wikimedia.org/wikipedia/de/e/eb/Goethe_Faust_Textbeispiel_Grossschreibung.png 26 | ``` 27 | 28 | ### Remove Stack 29 | 30 | ``` 31 | npx cdk destroy 32 | ``` -------------------------------------------------------------------------------- /example/cdk/cdk.json: -------------------------------------------------------------------------------- 1 | { 2 | "app": "npx ts-node -P tsconfig.json --prefer-ts-exts src/main.ts", 3 | "output": "cdk.out", 4 | "build": "npx projen bundle", 5 | "watch": { 6 | "include": [ 7 | "src/**/*.ts", 8 | "test/**/*.ts" 9 | ], 10 | "exclude": [ 11 | "README.md", 12 | "cdk*.json", 13 | "**/*.d.ts", 14 | "**/*.js", 15 | "tsconfig.json", 16 | "package*.json", 17 | "yarn.lock", 18 | "node_modules" 19 | ] 20 | }, 21 | "//": "~~ Generated by projen. To modify, edit .projenrc.js and run \"npx projen\"." 22 | } 23 | -------------------------------------------------------------------------------- /example/cdk/deployment.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bweigel/aws-lambda-tesseract-layer/8f88da851a8f5cb45f168450977403e7743f5f6c/example/cdk/deployment.png -------------------------------------------------------------------------------- /example/cdk/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "aws-lambda-tesseract-layer-example", 3 | "scripts": { 4 | "build": "npx projen build", 5 | "bundle": "npx projen bundle", 6 | "compile": "npx projen compile", 7 | "default": "npx projen default", 8 | "deploy": "npx projen deploy", 9 | "destroy": "npx projen destroy", 10 | "diff": "npx projen diff", 11 | "eslint": "npx projen eslint", 12 | "package": "npx projen package", 13 | "post-compile": "npx projen post-compile", 14 | "post-upgrade": "npx projen post-upgrade", 15 | "pre-compile": "npx projen pre-compile", 16 | "synth": "npx projen synth", 17 | "synth:silent": "npx projen synth:silent", 18 | "test": "npx projen test", 19 | "test:watch": "npx projen test:watch", 20 | "upgrade": "npx projen upgrade", 21 | "watch": "npx projen watch", 22 | "projen": "npx projen" 23 | }, 24 | "devDependencies": { 25 | "@stylistic/eslint-plugin": "^2", 26 | "@types/jest": "^29.4.0", 27 | "@types/node": "^18", 28 | "@typescript-eslint/eslint-plugin": "^8", 29 | "@typescript-eslint/parser": "^8", 30 | "aws-cdk": "^2", 31 | "esbuild": "^0.17.5", 32 | "eslint": "^9", 33 | "eslint-import-resolver-typescript": "^3.5.3", 34 | "eslint-plugin-import": "^2.27.5", 35 | "jest": "^29.4.1", 36 | "jest-junit": "^16", 37 | "ts-jest": "^29.0.5", 38 | "ts-node": "^10.9.1", 39 | "typescript": "^4.9.5" 40 | }, 41 | "dependencies": { 42 | "aws-cdk-lib": "^2.55.0", 43 | "constructs": "^10.0.5" 44 | }, 45 | "license": "UNLICENSED", 46 | "publishConfig": { 47 | "access": "public" 48 | }, 49 | "version": "0.0.0", 50 | "jest": { 51 | "coverageProvider": "v8", 52 | "testMatch": [ 53 | "/@(src|test)/**/*(*.)@(spec|test).ts?(x)", 54 | "/@(src|test)/**/__tests__/**/*.ts?(x)" 55 | ], 56 | "clearMocks": true, 57 | "collectCoverage": true, 58 | "coverageReporters": [ 59 | "json", 60 | "lcov", 61 | "clover", 62 | "cobertura", 63 | "text" 64 | ], 65 | "coverageDirectory": "coverage", 66 | "coveragePathIgnorePatterns": [ 67 | "/node_modules/" 68 | ], 69 | "testPathIgnorePatterns": [ 70 | "/node_modules/" 71 | ], 72 | "watchPathIgnorePatterns": [ 73 | "/node_modules/" 74 | ], 75 | "reporters": [ 76 | "default", 77 | [ 78 | "jest-junit", 79 | { 80 | "outputDirectory": "test-reports" 81 | } 82 | ] 83 | ], 84 | "transform": { 85 | "^.+\\.[t]sx?$": [ 86 | "ts-jest", 87 | { 88 | "tsconfig": "tsconfig.dev.json" 89 | } 90 | ] 91 | } 92 | }, 93 | "//": "~~ Generated by projen. To modify, edit .projenrc.js and run \"npx projen\"." 94 | } 95 | -------------------------------------------------------------------------------- /example/cdk/src/lambda-handlers/handler.py: -------------------------------------------------------------------------------- 1 | from PIL import Image 2 | import requests 3 | import pytesseract 4 | from io import BytesIO 5 | 6 | 7 | def main(evt, ctx): 8 | url = evt["body"] 9 | res = requests.get(url) 10 | img = Image.open(BytesIO(res.content)) 11 | txt = pytesseract.image_to_string(img, lang="deu") 12 | return {"statusCode": 200, "body": txt} 13 | 14 | -------------------------------------------------------------------------------- /example/cdk/src/lambda-handlers/requirements.txt: -------------------------------------------------------------------------------- 1 | -i https://pypi.org/simple 2 | certifi==2025.4.26; python_version >= '3.6' 3 | charset-normalizer==3.4.2; python_version >= '3.7' 4 | idna==3.10; python_version >= '3.6' 5 | packaging==25.0; python_version >= '3.8' 6 | pillow==10.4.0; python_version >= '3.8' 7 | pytesseract==0.3.13; python_version >= '3.8' 8 | requests==2.32.3; python_version >= '3.8' 9 | urllib3==2.2.3; python_version >= '3.8' 10 | -------------------------------------------------------------------------------- /example/cdk/src/main.ts: -------------------------------------------------------------------------------- 1 | import * as lambda from 'aws-cdk-lib/aws-lambda'; 2 | import { Code, Runtime } from 'aws-cdk-lib/aws-lambda'; 3 | import { RestApi, LambdaIntegration } from 'aws-cdk-lib/aws-apigateway'; 4 | import * as path from 'path'; 5 | import { App, DockerImage, Duration, Stack } from 'aws-cdk-lib'; 6 | 7 | 8 | const app = new App(); 9 | const stack = new Stack(app, 'tesseract-ocr-example-cdk-py38'); 10 | 11 | /** 12 | * Artifacts for AL 2 13 | */ 14 | const al2Layer = new lambda.LayerVersion(stack, 'al2-layer', { 15 | code: Code.fromAsset(path.resolve(__dirname, '../../../ready-to-use/amazonlinux-2')), 16 | description: 'AL2 Tesseract Layer', 17 | }); 18 | 19 | const ocrFn = new lambda.Function(stack, 'python3.8', { 20 | code: lambda.Code.fromAsset(path.resolve(__dirname, 'lambda-handlers'), 21 | { 22 | bundling: { 23 | image: DockerImage.fromRegistry('lambci/lambda:build-python3.8'), 24 | command: ['/bin/bash', '-c', [ 25 | 'pip install -r requirements.txt -t /asset-output/', 26 | 'cp handler.py /asset-output', 27 | ].join(' && ')], 28 | } 29 | }), 30 | runtime: Runtime.PYTHON_3_8, 31 | layers: [al2Layer], 32 | memorySize: 1024, 33 | timeout: Duration.seconds(10), 34 | handler: 'handler.main', 35 | }); 36 | 37 | const api = new RestApi(stack, 'ocr-api'); 38 | const ocr = api.root.addResource('ocr'); 39 | ocr.addMethod('POST', new LambdaIntegration(ocrFn, {proxy: true})); 40 | 41 | 42 | -------------------------------------------------------------------------------- /example/cdk/tsconfig.dev.json: -------------------------------------------------------------------------------- 1 | // ~~ Generated by projen. To modify, edit .projenrc.js and run "npx projen". 2 | { 3 | "compilerOptions": { 4 | "alwaysStrict": true, 5 | "declaration": true, 6 | "esModuleInterop": true, 7 | "experimentalDecorators": true, 8 | "inlineSourceMap": true, 9 | "inlineSources": true, 10 | "lib": [ 11 | "es2022" 12 | ], 13 | "module": "NodeNext", 14 | "noEmitOnError": false, 15 | "noFallthroughCasesInSwitch": false, 16 | "noImplicitAny": true, 17 | "noImplicitReturns": true, 18 | "noImplicitThis": true, 19 | "noUnusedLocals": false, 20 | "noUnusedParameters": false, 21 | "resolveJsonModule": true, 22 | "strict": true, 23 | "strictNullChecks": true, 24 | "strictPropertyInitialization": false, 25 | "stripInternal": true, 26 | "target": "ES2022", 27 | "moduleResolution": "nodenext", 28 | "typeRoots": [ 29 | "./node_modules/@types" 30 | ] 31 | }, 32 | "include": [ 33 | "src/**/*.ts", 34 | "test/**/*.ts" 35 | ], 36 | "exclude": [ 37 | "node_modules", 38 | "cdk.out" 39 | ] 40 | } 41 | -------------------------------------------------------------------------------- /example/cdk/tsconfig.json: -------------------------------------------------------------------------------- 1 | // ~~ Generated by projen. To modify, edit .projenrc.js and run "npx projen". 2 | { 3 | "compilerOptions": { 4 | "rootDir": "src", 5 | "outDir": "lib", 6 | "alwaysStrict": true, 7 | "declaration": true, 8 | "esModuleInterop": true, 9 | "experimentalDecorators": true, 10 | "inlineSourceMap": true, 11 | "inlineSources": true, 12 | "lib": [ 13 | "es2022" 14 | ], 15 | "module": "NodeNext", 16 | "noEmitOnError": false, 17 | "noFallthroughCasesInSwitch": false, 18 | "noImplicitAny": true, 19 | "noImplicitReturns": true, 20 | "noImplicitThis": true, 21 | "noUnusedLocals": false, 22 | "noUnusedParameters": false, 23 | "resolveJsonModule": true, 24 | "strict": true, 25 | "strictNullChecks": true, 26 | "strictPropertyInitialization": false, 27 | "stripInternal": true, 28 | "target": "ES2022", 29 | "moduleResolution": "nodenext", 30 | "typeRoots": [ 31 | "./node_modules/@types" 32 | ] 33 | }, 34 | "include": [ 35 | "src/**/*.ts" 36 | ], 37 | "exclude": [ 38 | "node_modules", 39 | "cdk.out" 40 | ] 41 | } 42 | -------------------------------------------------------------------------------- /example/serverless/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM lambci/lambda:build-python3.8 -------------------------------------------------------------------------------- /example/serverless/README.md: -------------------------------------------------------------------------------- 1 | Example: AWS Lambda with Tesseract layer (Amazon Linux 2 based runtime - Python 3.8) 2 | === 3 | 4 | ### Requirements 5 | 6 | - Docker 7 | - Node.Js 8 | 9 | ### Deploy Stack 10 | 11 | ```bash 12 | ## install dependencies 13 | npm ci 14 | ## deploy 15 | npx sls deploy 16 | ``` 17 | 18 | ![Deployment](./deployment.png) 19 | 20 | ### Invoke your API with an URL to an Image 21 | 22 | ```bash 23 | curl -X POST \ 24 | https://i61tt4wbth.execute-api.eu-central-1.amazonaws.com/dev/ocr \ 25 | -d https://upload.wikimedia.org/wikipedia/de/e/eb/Goethe_Faust_Textbeispiel_Grossschreibung.png 26 | ``` 27 | 28 | ### Remove Stack 29 | 30 | ``` 31 | npx sls remove 32 | ``` -------------------------------------------------------------------------------- /example/serverless/deployment.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bweigel/aws-lambda-tesseract-layer/8f88da851a8f5cb45f168450977403e7743f5f6c/example/serverless/deployment.png -------------------------------------------------------------------------------- /example/serverless/handler.py: -------------------------------------------------------------------------------- 1 | from PIL import Image 2 | import requests 3 | import pytesseract 4 | from io import BytesIO 5 | 6 | 7 | def main(evt, ctx): 8 | url = evt["body"] 9 | res = requests.get(url) 10 | img = Image.open(BytesIO(res.content)) 11 | txt = pytesseract.image_to_string(img, lang="deu") 12 | return {"statusCode": 200, "body": txt} 13 | 14 | -------------------------------------------------------------------------------- /example/serverless/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "aws-lambda-tesseract-layer-example", 3 | "version": "1.0.0", 4 | "description": "Tesseract OCR Lambda Layer Example", 5 | "main": "index.js", 6 | "directories": { 7 | "example": "example" 8 | }, 9 | "dependencies": {}, 10 | "devDependencies": { 11 | "serverless": "^2.00.0", 12 | "serverless-python-requirements": "^5.1.0" 13 | }, 14 | "repository": { 15 | "type": "git", 16 | "url": "git+https://github.com/bweigel/aws-lambda-tesseract-layer.git" 17 | }, 18 | "author": "", 19 | "license": "Apache2.0", 20 | "bugs": { 21 | "url": "https://github.com/bweigel/aws-lambda-tesseract-layer/issues" 22 | }, 23 | "homepage": "https://github.com/bweigel/aws-lambda-tesseract-layer#readme" 24 | } 25 | -------------------------------------------------------------------------------- /example/serverless/requirements.txt: -------------------------------------------------------------------------------- 1 | -i https://pypi.org/simple 2 | certifi==2025.4.26; python_version >= '3.6' 3 | charset-normalizer==3.4.2; python_version >= '3.7' 4 | idna==3.10; python_version >= '3.6' 5 | packaging==25.0; python_version >= '3.8' 6 | pillow==10.4.0; python_version >= '3.8' 7 | pytesseract==0.3.13; python_version >= '3.8' 8 | requests==2.32.3; python_version >= '3.8' 9 | urllib3==2.2.3; python_version >= '3.8' 10 | -------------------------------------------------------------------------------- /example/serverless/serverless.yml: -------------------------------------------------------------------------------- 1 | service: tesseract-ocr-example-py38 2 | frameworkVersion: ">=2.0.0" 3 | 4 | plugins: 5 | - serverless-python-requirements 6 | 7 | provider: 8 | name: aws 9 | region: eu-central-1 10 | 11 | custom: 12 | pythonRequirements: 13 | dockerizePip: true 14 | dockerFile: Dockerfile 15 | 16 | layers: 17 | tesseractAl2: 18 | # specify path to layer content 19 | path: ../../ready-to-use/amazonlinux-2 20 | compatibleRuntimes: 21 | - python3.8 22 | 23 | functions: 24 | tesseract-ocr: 25 | handler: handler.main 26 | runtime: python3.8 27 | layers: 28 | - { Ref: TesseractAl2LambdaLayer } 29 | events: 30 | - http: 31 | path: ocr 32 | method: post -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "aws-lambda-tesseract-layer", 3 | "description": "A layer for AWS Lambda containing the tesseract C libraries and tesseract executable. ", 4 | "scripts": { 5 | "build": "npx projen build", 6 | "bump": "npx projen bump", 7 | "bundle": "npx projen bundle", 8 | "bundle:binary": "npx projen bundle:binary", 9 | "clobber": "npx projen clobber", 10 | "compile": "npx projen compile", 11 | "default": "npx projen default", 12 | "deploy": "npx projen deploy", 13 | "destroy": "npx projen destroy", 14 | "diff": "npx projen diff", 15 | "eject": "npx projen eject", 16 | "eslint": "npx projen eslint", 17 | "package": "npx projen package", 18 | "post-compile": "npx projen post-compile", 19 | "post-upgrade": "npx projen post-upgrade", 20 | "pre-compile": "npx projen pre-compile", 21 | "release": "npx projen release", 22 | "synth": "npx projen synth", 23 | "synth:silent": "npx projen synth:silent", 24 | "test": "npx projen test", 25 | "test:integration": "npx projen test:integration", 26 | "test:integration:node": "npx projen test:integration:node", 27 | "test:integration:python": "npx projen test:integration:python", 28 | "test:watch": "npx projen test:watch", 29 | "unbump": "npx projen unbump", 30 | "upgrade": "npx projen upgrade", 31 | "upgrade:ci:py": "npx projen upgrade:ci:py", 32 | "upgrade:subprojects": "npx projen upgrade:subprojects", 33 | "watch": "npx projen watch", 34 | "projen": "npx projen" 35 | }, 36 | "devDependencies": { 37 | "@types/jest": "^29.5.14", 38 | "@types/node": "^18", 39 | "@typescript-eslint/eslint-plugin": "^8", 40 | "@typescript-eslint/parser": "^8", 41 | "aws-cdk": "^2", 42 | "commit-and-tag-version": "^12", 43 | "esbuild": "^0.25.4", 44 | "eslint": "^9", 45 | "eslint-config-prettier": "^8.10.0", 46 | "eslint-import-resolver-typescript": "^3.10.1", 47 | "eslint-plugin-import": "^2.31.0", 48 | "eslint-plugin-prettier": "^4.2.1", 49 | "jest": "^29.7.0", 50 | "jest-junit": "^16", 51 | "prettier": "^2.8.8", 52 | "projen": "^0.92.3", 53 | "ts-jest": "^29.3.2", 54 | "ts-node": "^10.9.2", 55 | "typescript": "^4.9.5" 56 | }, 57 | "dependencies": { 58 | "aws-cdk-lib": "^2.95.0", 59 | "constructs": "^10.0.5" 60 | }, 61 | "license": "Apache-2.0", 62 | "publishConfig": { 63 | "access": "public" 64 | }, 65 | "version": "0.0.0", 66 | "jest": { 67 | "coverageProvider": "v8", 68 | "moduleNameMapper": { 69 | "^aws-cdk-lib/.warnings.jsii.js$": "/node_modules/aws-cdk-lib/.warnings.jsii.js" 70 | }, 71 | "testMatch": [ 72 | "/@(continous-integration|test)/**/*(*.)@(spec|test).ts?(x)", 73 | "/@(continous-integration|test)/**/__tests__/**/*.ts?(x)", 74 | "/@(projenrc)/**/*(*.)@(spec|test).ts?(x)", 75 | "/@(projenrc)/**/__tests__/**/*.ts?(x)" 76 | ], 77 | "clearMocks": true, 78 | "collectCoverage": true, 79 | "coverageReporters": [ 80 | "json", 81 | "lcov", 82 | "clover", 83 | "cobertura", 84 | "text" 85 | ], 86 | "coverageDirectory": "coverage", 87 | "coveragePathIgnorePatterns": [ 88 | "/node_modules/" 89 | ], 90 | "testPathIgnorePatterns": [ 91 | "/node_modules/" 92 | ], 93 | "watchPathIgnorePatterns": [ 94 | "/node_modules/" 95 | ], 96 | "reporters": [ 97 | "default", 98 | [ 99 | "jest-junit", 100 | { 101 | "outputDirectory": "test-reports" 102 | } 103 | ] 104 | ], 105 | "transform": { 106 | "^.+\\.[t]sx?$": [ 107 | "ts-jest", 108 | { 109 | "tsconfig": "tsconfig.dev.json" 110 | } 111 | ] 112 | } 113 | }, 114 | "//": "~~ Generated by projen. To modify, edit .projenrc.ts and run \"npx projen\"." 115 | } 116 | -------------------------------------------------------------------------------- /ready-to-use/README.md: -------------------------------------------------------------------------------- 1 | > Contains ready-to-use binaries for Tesseract for [Lambda runtimes](https://docs.aws.amazon.com/lambda/latest/dg/lambda-runtimes.html) using Amazon Linux 2 and X86 architecture. 2 | 3 | ## Supported Runtimes 4 | 5 | ### [Amazon Linux 2 (X86)](./amazonlinux-2) 6 | 7 | - Python 3.8 (:heavy_check_mark:) 8 | - NodeJS 12, 14, 16 (:heavy_check_mark:) 9 | - Ruby 2.7 10 | - Java 8 (Coretto), 11 (Coretto) 11 | - .NET Core 3.1 12 | 13 | :heavy_check_mark: verified working -------------------------------------------------------------------------------- /ready-to-use/amazonlinux-2/TESSERACT-README.md: -------------------------------------------------------------------------------- 1 | LEPTONICA_VERSION=1.84.1 2 | TESSERACT_VERSION=5.4.1 3 | TESSERACT_DATA_FILES=tessdata_fast/4.1.0 4 | TESSERACT_DATA_LANGUAGES=osd,eng,deu 5 | -------------------------------------------------------------------------------- /ready-to-use/amazonlinux-2/bin/tesseract: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bweigel/aws-lambda-tesseract-layer/8f88da851a8f5cb45f168450977403e7743f5f6c/ready-to-use/amazonlinux-2/bin/tesseract -------------------------------------------------------------------------------- /ready-to-use/amazonlinux-2/lib/libgomp.so.1: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bweigel/aws-lambda-tesseract-layer/8f88da851a8f5cb45f168450977403e7743f5f6c/ready-to-use/amazonlinux-2/lib/libgomp.so.1 -------------------------------------------------------------------------------- /ready-to-use/amazonlinux-2/lib/libjbig.so.2.0: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bweigel/aws-lambda-tesseract-layer/8f88da851a8f5cb45f168450977403e7743f5f6c/ready-to-use/amazonlinux-2/lib/libjbig.so.2.0 -------------------------------------------------------------------------------- /ready-to-use/amazonlinux-2/lib/libjpeg.so.62: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bweigel/aws-lambda-tesseract-layer/8f88da851a8f5cb45f168450977403e7743f5f6c/ready-to-use/amazonlinux-2/lib/libjpeg.so.62 -------------------------------------------------------------------------------- /ready-to-use/amazonlinux-2/lib/libleptonica.so.6: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bweigel/aws-lambda-tesseract-layer/8f88da851a8f5cb45f168450977403e7743f5f6c/ready-to-use/amazonlinux-2/lib/libleptonica.so.6 -------------------------------------------------------------------------------- /ready-to-use/amazonlinux-2/lib/libpng15.so.15: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bweigel/aws-lambda-tesseract-layer/8f88da851a8f5cb45f168450977403e7743f5f6c/ready-to-use/amazonlinux-2/lib/libpng15.so.15 -------------------------------------------------------------------------------- /ready-to-use/amazonlinux-2/lib/libtesseract.so.5: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bweigel/aws-lambda-tesseract-layer/8f88da851a8f5cb45f168450977403e7743f5f6c/ready-to-use/amazonlinux-2/lib/libtesseract.so.5 -------------------------------------------------------------------------------- /ready-to-use/amazonlinux-2/lib/libtiff.so.5: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bweigel/aws-lambda-tesseract-layer/8f88da851a8f5cb45f168450977403e7743f5f6c/ready-to-use/amazonlinux-2/lib/libtiff.so.5 -------------------------------------------------------------------------------- /ready-to-use/amazonlinux-2/lib/libwebp.so.4: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bweigel/aws-lambda-tesseract-layer/8f88da851a8f5cb45f168450977403e7743f5f6c/ready-to-use/amazonlinux-2/lib/libwebp.so.4 -------------------------------------------------------------------------------- /ready-to-use/amazonlinux-2/tesseract/share/tessdata/deu.traineddata: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bweigel/aws-lambda-tesseract-layer/8f88da851a8f5cb45f168450977403e7743f5f6c/ready-to-use/amazonlinux-2/tesseract/share/tessdata/deu.traineddata -------------------------------------------------------------------------------- /ready-to-use/amazonlinux-2/tesseract/share/tessdata/eng.traineddata: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bweigel/aws-lambda-tesseract-layer/8f88da851a8f5cb45f168450977403e7743f5f6c/ready-to-use/amazonlinux-2/tesseract/share/tessdata/eng.traineddata -------------------------------------------------------------------------------- /ready-to-use/amazonlinux-2/tesseract/share/tessdata/osd.traineddata: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bweigel/aws-lambda-tesseract-layer/8f88da851a8f5cb45f168450977403e7743f5f6c/ready-to-use/amazonlinux-2/tesseract/share/tessdata/osd.traineddata -------------------------------------------------------------------------------- /tsconfig.dev.json: -------------------------------------------------------------------------------- 1 | // ~~ Generated by projen. To modify, edit .projenrc.ts and run "npx projen". 2 | { 3 | "compilerOptions": { 4 | "alwaysStrict": true, 5 | "declaration": true, 6 | "esModuleInterop": true, 7 | "experimentalDecorators": true, 8 | "inlineSourceMap": true, 9 | "inlineSources": true, 10 | "lib": [ 11 | "es2022" 12 | ], 13 | "module": "NodeNext", 14 | "noEmitOnError": false, 15 | "noFallthroughCasesInSwitch": false, 16 | "noImplicitAny": true, 17 | "noImplicitReturns": true, 18 | "noImplicitThis": true, 19 | "noUnusedLocals": false, 20 | "noUnusedParameters": false, 21 | "resolveJsonModule": true, 22 | "strict": true, 23 | "strictNullChecks": true, 24 | "strictPropertyInitialization": false, 25 | "stripInternal": true, 26 | "target": "ES2022", 27 | "moduleResolution": "nodenext", 28 | "typeRoots": [ 29 | "./node_modules/@types" 30 | ] 31 | }, 32 | "include": [ 33 | "continous-integration/**/*.ts", 34 | "test/**/*.ts", 35 | ".projenrc.ts", 36 | "projenrc/**/*.ts" 37 | ], 38 | "exclude": [ 39 | "node_modules", 40 | "cdk.out" 41 | ] 42 | } 43 | -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | // ~~ Generated by projen. To modify, edit .projenrc.ts and run "npx projen". 2 | { 3 | "compilerOptions": { 4 | "rootDir": "continous-integration", 5 | "outDir": "lib", 6 | "alwaysStrict": true, 7 | "declaration": true, 8 | "esModuleInterop": true, 9 | "experimentalDecorators": true, 10 | "inlineSourceMap": true, 11 | "inlineSources": true, 12 | "lib": [ 13 | "es2022" 14 | ], 15 | "module": "NodeNext", 16 | "noEmitOnError": false, 17 | "noFallthroughCasesInSwitch": false, 18 | "noImplicitAny": true, 19 | "noImplicitReturns": true, 20 | "noImplicitThis": true, 21 | "noUnusedLocals": false, 22 | "noUnusedParameters": false, 23 | "resolveJsonModule": true, 24 | "strict": true, 25 | "strictNullChecks": true, 26 | "strictPropertyInitialization": false, 27 | "stripInternal": true, 28 | "target": "ES2022", 29 | "moduleResolution": "nodenext", 30 | "typeRoots": [ 31 | "./node_modules/@types" 32 | ] 33 | }, 34 | "include": [ 35 | "continous-integration/**/*.ts" 36 | ], 37 | "exclude": [ 38 | "node_modules", 39 | "cdk.out" 40 | ] 41 | } 42 | --------------------------------------------------------------------------------