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 0000000..ae89dd3 Binary files /dev/null and b/bun.lockb differ 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