From fb93b708f74cc8afee29f82f72c61b4eab5ea83b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gr=C3=A9gory=20Houllier?= Date: Fri, 1 Dec 2023 22:38:20 +0000 Subject: [PATCH] Initial commit --- .devcontainer/devcontainer.json | 21 ++++++ .editorconfig | 10 +++ .gitattributes | 0 .github/actions/build/action.yaml | 10 +++ .github/actions/cache/action.yaml | 29 ++++++++ .../prevent-uncommit-changes/action.yaml | 13 ++++ .github/actions/setup-bun/action.yaml | 13 ++++ .github/dependabot.yml | 15 ++++ .github/workflows/ci.yml | 44 ++++++++++++ .github/workflows/dependabot.yml | 66 ++++++++++++++++++ .github/workflows/semantic-release.yml | 40 +++++++++++ .gitignore | 7 ++ .vscode/settings.json | 10 +++ README.md | 23 ++++++ bun.lockb | Bin 0 -> 64659 bytes package.json | 60 ++++++++++++++++ src/index.ts | 1 + tsconfig.build.json | 5 ++ tsconfig.json | 18 +++++ 19 files changed, 385 insertions(+) create mode 100644 .devcontainer/devcontainer.json create mode 100644 .editorconfig create mode 100644 .gitattributes create mode 100644 .github/actions/build/action.yaml create mode 100644 .github/actions/cache/action.yaml create mode 100644 .github/actions/prevent-uncommit-changes/action.yaml create mode 100644 .github/actions/setup-bun/action.yaml create mode 100644 .github/dependabot.yml create mode 100644 .github/workflows/ci.yml create mode 100644 .github/workflows/dependabot.yml create mode 100644 .github/workflows/semantic-release.yml create mode 100644 .gitignore create mode 100644 .vscode/settings.json create mode 100644 README.md create mode 100755 bun.lockb create mode 100644 package.json create mode 100644 src/index.ts create mode 100644 tsconfig.build.json create mode 100644 tsconfig.json diff --git a/.devcontainer/devcontainer.json b/.devcontainer/devcontainer.json new file mode 100644 index 0000000..5734239 --- /dev/null +++ b/.devcontainer/devcontainer.json @@ -0,0 +1,21 @@ +{ + "name": "Node.js", + // Image definition + "image": "mcr.microsoft.com/devcontainers/typescript-node:20", + // Configure tool-specific properties. + "customizations": { + // Configure properties specific to VS Code. + "vscode": { + // Set *default* container specific settings.json values on container create. + "settings": {}, + + // Add the IDs of extensions you want installed when the container is created. + "extensions": [ + "github.vscode-github-actions", + "oven.bun-vscode" + ] + } + }, + "postCreateCommand": "curl -fsSL https://bun.sh/install | bash" + } + \ No newline at end of file diff --git a/.editorconfig b/.editorconfig new file mode 100644 index 0000000..1ed453a --- /dev/null +++ b/.editorconfig @@ -0,0 +1,10 @@ +root = true + +[*] +end_of_line = lf +insert_final_newline = true + +[*.{js,json,yml}] +charset = utf-8 +indent_style = space +indent_size = 2 diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 0000000..e69de29 diff --git a/.github/actions/build/action.yaml b/.github/actions/build/action.yaml new file mode 100644 index 0000000..5497c63 --- /dev/null +++ b/.github/actions/build/action.yaml @@ -0,0 +1,10 @@ +name: Build + +runs: + using: "composite" + steps: + - uses: ./.github/actions/cache + with: + scope: build + - run: bun --bun run build + shell: bash \ No newline at end of file diff --git a/.github/actions/cache/action.yaml b/.github/actions/cache/action.yaml new file mode 100644 index 0000000..4d21181 --- /dev/null +++ b/.github/actions/cache/action.yaml @@ -0,0 +1,29 @@ +name: Cache + +inputs: + scope: + required: true + description: Scope of files to cache + Example => 'dependencies,build' + Possible values for the scope => [dependencies, build] + +runs: + using: composite + steps: + - name: Store dependencies cache + id: dependencies + if: ${{ contains(inputs.scope, 'dependencies') }} + uses: actions/cache@v3 + with: + key: dependencies-${{ hashFiles('./bun.lockb') }} + path: | + ./node_modules/** + + - name: Store build cache + id: build + if: ${{ contains(inputs.scope, 'build') }} + uses: actions/cache@v3 + with: + key: build-${{ hashFiles('./src/**') }} + path: | + ./dist/** \ No newline at end of file diff --git a/.github/actions/prevent-uncommit-changes/action.yaml b/.github/actions/prevent-uncommit-changes/action.yaml new file mode 100644 index 0000000..dfe91d1 --- /dev/null +++ b/.github/actions/prevent-uncommit-changes/action.yaml @@ -0,0 +1,13 @@ +name: Prevent uncommit changes + +runs: + using: "composite" + steps: + - shell: bash + run: | + if [ "$(git status --porcelain | wc -l)" -gt "0" ]; then + echo "Detected uncommitted changes after build. See status below:" + git status --porcelain + exit 1 + fi + diff --git a/.github/actions/setup-bun/action.yaml b/.github/actions/setup-bun/action.yaml new file mode 100644 index 0000000..8c99923 --- /dev/null +++ b/.github/actions/setup-bun/action.yaml @@ -0,0 +1,13 @@ +name: Setup Bun + +runs: + using: "composite" + steps: + - uses: ./.github/actions/cache + with: + scope: dependencies + - uses: oven-sh/setup-bun@v1 + with: + bun-version: latest + - run: bun install + shell: bash diff --git a/.github/dependabot.yml b/.github/dependabot.yml new file mode 100644 index 0000000..7ddf791 --- /dev/null +++ b/.github/dependabot.yml @@ -0,0 +1,15 @@ +version: 2 +updates: + - package-ecosystem: "npm" + directory: "/" + groups: + eslint: + patterns: + - "@typescript-eslint/*" + - "eslint" + schedule: + interval: "daily" + labels: ["dependencies"] + commit-message: + prefix: "chore" + include: "scope" \ No newline at end of file diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml new file mode 100644 index 0000000..28ce66f --- /dev/null +++ b/.github/workflows/ci.yml @@ -0,0 +1,44 @@ +on: + push: + branches: [ main ] + pull_request: + branches: [ main ] + types: [ opened, synchronize, reopened, labeled ] + +name: CI + +concurrency: + group: ${{ github.ref }} + cancel-in-progress: true + +permissions: + contents: read # to fetch code (actions/checkout) + packages: write # to publish packages (npm publish) + +jobs: + ci-setup: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + - uses: ./.github/actions/setup-bun + - uses: ./.github/actions/build + - uses: ./.github/actions/prevent-uncommit-changes + - run: bun test + - run: bun run lint + + ci-canary-release: + runs-on: ubuntu-latest + needs: [ci-setup] + steps: + - uses: actions/checkout@v4 + - uses: ./.github/actions/setup-bun + - uses: actions/setup-node@v3 + with: + registry-url: "https://npm.pkg.github.com" + - uses: ./.github/actions/cache + with: + scope: build + - run: npm version prerelease --preid=canary.$(git rev-parse --short HEAD) --no-git-tag-version + - run: npm publish --tag canary + env: + NODE_AUTH_TOKEN: ${{secrets.GITHUB_TOKEN}} diff --git a/.github/workflows/dependabot.yml b/.github/workflows/dependabot.yml new file mode 100644 index 0000000..05b079e --- /dev/null +++ b/.github/workflows/dependabot.yml @@ -0,0 +1,66 @@ +on: pull_request_target + +name: Dependabot + +concurrency: + group: ${{ github.ref }} + cancel-in-progress: true + +permissions: + contents: write + pull-requests: write + +jobs: + dependabot-update-lockfile: + runs-on: ubuntu-latest + if: ${{ github.actor == 'dependabot[bot]' }} + steps: + - uses: actions/checkout@v4 + with: + ref: ${{ github.event.pull_request.head.ref }} + - uses: ./.github/actions/setup-bun + - name: Set @github-actions[bot] as committer + run: | + git config --global user.name 'github-actions[bot]' + git config --global user.email 'github-actions[bot]@users.noreply.github.com' + - run: git status + - run: git add -A + - run: | + git commit -m "chore(deps-dev): bump bun lockfile" + - run: git push + dependabot-build: + runs-on: ubuntu-latest + if: ${{ github.actor == 'dependabot[bot]' }} + needs: [dependabot-update-lockfile] + steps: + - uses: actions/checkout@v4 + with: + ref: ${{ github.event.pull_request.head.ref }} + - uses: ./.github/actions/setup-bun + - uses: ./.github/actions/build + - uses: ./.github/actions/prevent-uncommit-changes + - run: bun test + - run: bun run lint + dependabot-automerge: + runs-on: ubuntu-latest + if: ${{ github.actor == 'dependabot[bot]' }} + needs: [dependabot-build] + steps: + - uses: actions/checkout@v4 + with: + ref: ${{ github.event.pull_request.head.ref }} + - name: Dependabot metadata + id: metadata + uses: dependabot/fetch-metadata@v1 + - name: Approve a PR + if: ${{contains(fromJSON('["version-update:semver-patch", "version-update:semver-minor"]'), steps.metadata.outputs.update-type)}} + run: gh pr review --approve "$PR_URL" -b "**Automatically approving** pull request because **it includes a minor/patch update**" + env: + PR_URL: ${{github.event.pull_request.html_url}} + GITHUB_TOKEN: ${{secrets.DEPENDABOT_AUTOMERGE_TOKEN}} + - name: Enable auto-merge for Dependabot PRs + if: ${{contains(fromJSON('["version-update:semver-patch", "version-update:semver-minor"]'), steps.metadata.outputs.update-type)}} + run: gh pr merge --auto --squash "$PR_URL" + env: + PR_URL: ${{github.event.pull_request.html_url}} + GITHUB_TOKEN: ${{secrets.DEPENDABOT_AUTOMERGE_TOKEN}} diff --git a/.github/workflows/semantic-release.yml b/.github/workflows/semantic-release.yml new file mode 100644 index 0000000..65335bd --- /dev/null +++ b/.github/workflows/semantic-release.yml @@ -0,0 +1,40 @@ +on: + push: + branches: + - main + +name: Semantic Release + +permissions: + contents: read # For Checkout + +jobs: + release: + permissions: + contents: write # to create release commit (google-github-actions/release-please-action) + pull-requests: write # to create release PR (google-github-actions/release-please-action) + packages: write # to publish to GitHub Packages (actions/setup-node) + + runs-on: ubuntu-latest + steps: + - uses: google-github-actions/release-please-action@v3 + id: release + with: + token: ${{ secrets.GITHUB_TOKEN }} + release-type: node + changelog-types: '[{"type":"feat","section":"Features","hidden":false},{"type":"fix","section":"Bug Fixes","hidden":false},{"type":"chore","section":"Miscellaneous","hidden":false}]' + - uses: actions/checkout@v4 + - uses: oven-sh/setup-bun@v1 + with: + bun-version: latest + - run: bun install + - run: bun --bun run build + - run: bun test + - uses: actions/setup-node@v3 + with: + registry-url: 'https://npm.pkg.github.com' + if: ${{ steps.release.outputs.release_created }} + - run: npm publish + env: + NODE_AUTH_TOKEN: ${{secrets.GITHUB_TOKEN}} + if: ${{ steps.release.outputs.release_created }} diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..74f901e --- /dev/null +++ b/.gitignore @@ -0,0 +1,7 @@ +# Dependency directories + +node_modules/ + +# Generate output + +dist/ \ No newline at end of file diff --git a/.vscode/settings.json b/.vscode/settings.json new file mode 100644 index 0000000..5f17ce4 --- /dev/null +++ b/.vscode/settings.json @@ -0,0 +1,10 @@ +{ + "typescript.enablePromptUseWorkspaceTsdk": true, + "typescript.inlayHints.variableTypes.enabled": true, + "typescript.inlayHints.variableTypes.suppressWhenTypeMatchesName": true, + "typescript.inlayHints.parameterTypes.enabled": true, + "typescript.inlayHints.parameterNames.suppressWhenArgumentMatchesName": true, + "typescript.inlayHints.parameterNames.enabled": "all", + "typescript.preferences.preferTypeOnlyAutoImports": true, + "typescript.tsdk": "./node_modules/typescript/lib" +} diff --git a/README.md b/README.md new file mode 100644 index 0000000..322ff14 --- /dev/null +++ b/README.md @@ -0,0 +1,23 @@ +# bun-typescript-template + +Provide a modern and ready to use template to setup a typescript project + +> This Project rely on [bun](https://bun.sh) toolchain + +## Install project + +```sh +bun install +``` + +## Run test + +```sh +bun test +``` + +## Build the project + +```sh +bun --bun run build +``` diff --git a/bun.lockb b/bun.lockb new file mode 100755 index 0000000000000000000000000000000000000000..ae89dd3ee5d9361ab22383115240826b8e01006a GIT binary patch literal 64659 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 E03xv9!vFvP literal 0 HcmV?d00001 diff --git a/package.json b/package.json new file mode 100644 index 0000000..f03ff8e --- /dev/null +++ b/package.json @@ -0,0 +1,60 @@ +{ + "name": "@ghoullier/bun-typescript-template", + "description": "Provide a modern and ready to use template to setup a typescript project", + "version": "0.0.0", + "type": "module", + "scripts": { + "build:lib": "bun build --minify --outdir=dist src/index.ts", + "build:types": "tsc -p tsconfig.build.json", + "build": "bun build:lib && bun build:types", + "lint": "npm run lint:lib && npm run lint:exports && npm run lint:package", + "lint:lib": "eslint --ext .ts src", + "lint:exports": "attw --pack . --ignore-rules no-resolution cjs-resolves-to-esm", + "lint:package": "publint ." + }, + "files": [ + "dist", + "package.json" + ], + "exports": { + ".": { + "types": "./dist/index.d.ts", + "import": "./dist/index.js", + "default": "./dist/index.js" + }, + "./package.json": "./package.json" + }, + "devDependencies": { + "@arethetypeswrong/cli": "0.13.2", + "@tsconfig/strictest": "2.0.2", + "@typescript-eslint/eslint-plugin": "6.13.1", + "@typescript-eslint/parser": "6.13.1", + "bun-types": "1.0.14", + "eslint": "8.54.0", + "publint": "0.2.6", + "typescript": "5.3.2" + }, + "publishConfig": { + "registry": "https://npm.pkg.github.com" + }, + "eslintConfig": { + "extends": [ + "eslint:recommended", + "plugin:@typescript-eslint/recommended-type-checked", + "plugin:@typescript-eslint/stylistic-type-checked" + ], + "plugins": [ + "@typescript-eslint" + ], + "parser": "@typescript-eslint/parser", + "parserOptions": { + "project": true, + "tsconfigRootDir": "." + }, + "root": true, + "rules": { + "@typescript-eslint/no-empty-interface": "off" + } + } + } + \ No newline at end of file diff --git a/src/index.ts b/src/index.ts new file mode 100644 index 0000000..693da49 --- /dev/null +++ b/src/index.ts @@ -0,0 +1 @@ +export {} \ No newline at end of file diff --git a/tsconfig.build.json b/tsconfig.build.json new file mode 100644 index 0000000..ff49a63 --- /dev/null +++ b/tsconfig.build.json @@ -0,0 +1,5 @@ +{ + "extends": "./tsconfig.json", + "exclude": ["node_modules", "dist", "src/*.test.ts"] + } + \ No newline at end of file diff --git a/tsconfig.json b/tsconfig.json new file mode 100644 index 0000000..2ed678f --- /dev/null +++ b/tsconfig.json @@ -0,0 +1,18 @@ +{ + "extends": "@tsconfig/strictest/tsconfig.json", + "compilerOptions": { + "lib": ["ESNext"], + "module": "esnext", + "target": "esnext", + "moduleResolution": "bundler", + "moduleDetection": "force", + "allowSyntheticDefaultImports": true, + "declaration": true, + "emitDeclarationOnly": true, + "outDir": "dist", + "types": ["bun-types"] + }, + "include": ["src/**/*"], + "exclude": ["node_modules", "dist"] + } + \ No newline at end of file