byte-codec 1.0.0 → 1.0.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index-DCdK98vS.d.cts +81 -0
- package/dist/index-DCdK98vS.d.ts +81 -0
- package/dist/index.cjs +563 -0
- package/dist/index.d.cts +81 -0
- package/dist/index.d.ts +81 -0
- package/dist/index.js +549 -0
- package/package.json +7 -3
- package/.github/workflows/ci.yml +0 -254
- package/.github/workflows/dependabot-auto-merge.yml +0 -64
- package/.github/workflows/sibling-dependency-update.yml +0 -174
- package/.husky/commit-msg +0 -1
- package/.husky/pre-commit +0 -2
- package/.husky/pre-push +0 -2
- package/CHANGELOG.md +0 -12
- package/commitlint.config.ts +0 -8
- package/eslint.config.ts +0 -19
- package/release.config.ts +0 -65
- package/src/bytes/crc32.ts +0 -24
- package/src/bytes/flate.ts +0 -69
- package/src/bytes/reader.ts +0 -73
- package/src/bytes/writer.ts +0 -45
- package/src/image/jpeg-info.ts +0 -90
- package/src/image/png-decode.ts +0 -263
- package/src/image/png-encode.ts +0 -74
- package/src/image/png-filter.ts +0 -142
- package/src/index.test.ts +0 -33
- package/src/index.ts +0 -9
- package/tsconfig.json +0 -18
- package/tsdown.config.ts +0 -10
package/.github/workflows/ci.yml
DELETED
|
@@ -1,254 +0,0 @@
|
|
|
1
|
-
name: CI
|
|
2
|
-
|
|
3
|
-
on:
|
|
4
|
-
push:
|
|
5
|
-
branches: [main]
|
|
6
|
-
pull_request:
|
|
7
|
-
workflow_dispatch:
|
|
8
|
-
|
|
9
|
-
permissions:
|
|
10
|
-
contents: read
|
|
11
|
-
|
|
12
|
-
jobs:
|
|
13
|
-
commitlint:
|
|
14
|
-
name: Commitlint
|
|
15
|
-
runs-on: ubuntu-latest
|
|
16
|
-
timeout-minutes: 10
|
|
17
|
-
steps:
|
|
18
|
-
- uses: actions/checkout@v7
|
|
19
|
-
with:
|
|
20
|
-
fetch-depth: 0
|
|
21
|
-
- uses: wagoid/commitlint-github-action@v6
|
|
22
|
-
|
|
23
|
-
lint:
|
|
24
|
-
name: Lint
|
|
25
|
-
runs-on: ubuntu-latest
|
|
26
|
-
timeout-minutes: 10
|
|
27
|
-
steps:
|
|
28
|
-
- uses: actions/checkout@v7
|
|
29
|
-
- uses: pnpm/action-setup@v6
|
|
30
|
-
- uses: actions/setup-node@v7
|
|
31
|
-
with:
|
|
32
|
-
node-version: '22'
|
|
33
|
-
cache: pnpm
|
|
34
|
-
- run: pnpm install --frozen-lockfile
|
|
35
|
-
- run: pnpm lint
|
|
36
|
-
|
|
37
|
-
typecheck:
|
|
38
|
-
name: Typecheck
|
|
39
|
-
runs-on: ubuntu-latest
|
|
40
|
-
timeout-minutes: 10
|
|
41
|
-
steps:
|
|
42
|
-
- uses: actions/checkout@v7
|
|
43
|
-
- uses: pnpm/action-setup@v6
|
|
44
|
-
- uses: actions/setup-node@v7
|
|
45
|
-
with:
|
|
46
|
-
node-version: '22'
|
|
47
|
-
cache: pnpm
|
|
48
|
-
- run: pnpm install --frozen-lockfile
|
|
49
|
-
- run: pnpm typecheck
|
|
50
|
-
|
|
51
|
-
test:
|
|
52
|
-
name: Test
|
|
53
|
-
runs-on: ubuntu-latest
|
|
54
|
-
timeout-minutes: 10
|
|
55
|
-
permissions:
|
|
56
|
-
contents: read
|
|
57
|
-
code-quality: write # to upload the cobertura coverage report below
|
|
58
|
-
steps:
|
|
59
|
-
- uses: actions/checkout@v7
|
|
60
|
-
- uses: pnpm/action-setup@v6
|
|
61
|
-
- uses: actions/setup-node@v7
|
|
62
|
-
with:
|
|
63
|
-
node-version: '22'
|
|
64
|
-
cache: pnpm
|
|
65
|
-
- run: pnpm install --frozen-lockfile
|
|
66
|
-
- run: pnpm test
|
|
67
|
-
|
|
68
|
-
test-smoke:
|
|
69
|
-
name: Smoke test
|
|
70
|
-
runs-on: ubuntu-latest
|
|
71
|
-
timeout-minutes: 10
|
|
72
|
-
steps:
|
|
73
|
-
- uses: actions/checkout@v7
|
|
74
|
-
- uses: pnpm/action-setup@v6
|
|
75
|
-
- uses: actions/setup-node@v7
|
|
76
|
-
with:
|
|
77
|
-
node-version: '22'
|
|
78
|
-
cache: pnpm
|
|
79
|
-
- run: pnpm install --frozen-lockfile
|
|
80
|
-
- run: pnpm build && node -e "require('./dist/index.cjs')" && node --input-type=module -e "import('./dist/index.js').then(m => console.log(Object.keys(m).length + ' exports'))"
|
|
81
|
-
|
|
82
|
-
release:
|
|
83
|
-
name: Release
|
|
84
|
-
needs: [commitlint, lint, typecheck, test, test-smoke]
|
|
85
|
-
if: github.ref == 'refs/heads/main' && github.event_name == 'push'
|
|
86
|
-
runs-on: ubuntu-latest
|
|
87
|
-
timeout-minutes: 15
|
|
88
|
-
permissions:
|
|
89
|
-
contents: write # to push the release commit/tag and create the GitHub Release
|
|
90
|
-
issues: write # to comment on released issues
|
|
91
|
-
pull-requests: write # to comment on released pull requests
|
|
92
|
-
id-token: write # OIDC identity for npm trusted publishing (no NPM_TOKEN)
|
|
93
|
-
outputs:
|
|
94
|
-
published: ${{ steps.before.outputs.version != steps.after.outputs.version }}
|
|
95
|
-
version: ${{ steps.after.outputs.version }}
|
|
96
|
-
steps:
|
|
97
|
-
- uses: actions/checkout@v7
|
|
98
|
-
with:
|
|
99
|
-
# semantic-release analyses the full commit history since the last release.
|
|
100
|
-
fetch-depth: 0
|
|
101
|
-
- uses: pnpm/action-setup@v6
|
|
102
|
-
- uses: actions/setup-node@v7
|
|
103
|
-
with:
|
|
104
|
-
node-version: '22'
|
|
105
|
-
cache: pnpm
|
|
106
|
-
# registry-url is deliberately absent. Setting it makes setup-node write an .npmrc containing an _authToken line, and that line wins over the OIDC token exchange -- so the setting that looks like it configures the registry is exactly the one that would stop trusted publishing working.
|
|
107
|
-
- run: pnpm install --frozen-lockfile
|
|
108
|
-
- name: Read pre-release version
|
|
109
|
-
id: before
|
|
110
|
-
run: echo "version=$(node -p "require('./package.json').version")" >> "$GITHUB_OUTPUT"
|
|
111
|
-
- name: Upgrade npm for OIDC trusted publishing (needs npm CLI >=11.5.1)
|
|
112
|
-
run: npm install -g npm@latest
|
|
113
|
-
- name: Release
|
|
114
|
-
# HUSKY=0 so the commit-msg hook never fires against the automated release commit.
|
|
115
|
-
run: HUSKY=0 pnpm exec semantic-release
|
|
116
|
-
env:
|
|
117
|
-
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
|
118
|
-
# Blanked, not omitted -- an inherited NPM_TOKEN/NODE_AUTH_TOKEN from a workflow-level env block, reusable workflow, or composite action would otherwise be used in preference to the OIDC exchange.
|
|
119
|
-
NPM_TOKEN: ''
|
|
120
|
-
NODE_AUTH_TOKEN: ''
|
|
121
|
-
- name: Read post-release version
|
|
122
|
-
id: after
|
|
123
|
-
run: echo "version=$(node -p "require('./package.json').version")" >> "$GITHUB_OUTPUT"
|
|
124
|
-
|
|
125
|
-
notify-downstream:
|
|
126
|
-
name: Notify downstream repositories
|
|
127
|
-
needs: release
|
|
128
|
-
if: needs.release.outputs.published == 'true'
|
|
129
|
-
runs-on: ubuntu-latest
|
|
130
|
-
timeout-minutes: 5
|
|
131
|
-
permissions:
|
|
132
|
-
contents: read
|
|
133
|
-
steps:
|
|
134
|
-
- name: Generate a token for cross-repo dispatch
|
|
135
|
-
id: app-token
|
|
136
|
-
uses: actions/create-github-app-token@v2
|
|
137
|
-
with:
|
|
138
|
-
app-id: '4473709'
|
|
139
|
-
private-key: ${{ secrets.AUTOMERGE_APP_PRIVATE_KEY }}
|
|
140
|
-
repositories: |
|
|
141
|
-
documents.js
|
|
142
|
-
- name: Dispatch sibling-released event to downstream repos
|
|
143
|
-
env:
|
|
144
|
-
GH_TOKEN: ${{ steps.app-token.outputs.token }}
|
|
145
|
-
run: |
|
|
146
|
-
version="${{ needs.release.outputs.version }}"
|
|
147
|
-
for repo in documents.js; do
|
|
148
|
-
gh api "repos/ExaDev/$repo/dispatches" \
|
|
149
|
-
-f event_type=sibling-released \
|
|
150
|
-
-F "client_payload[package]=byte-codec" \
|
|
151
|
-
-F "client_payload[version]=$version"
|
|
152
|
-
done
|
|
153
|
-
|
|
154
|
-
publish-github-packages:
|
|
155
|
-
name: Publish alias to GitHub Packages
|
|
156
|
-
needs: release
|
|
157
|
-
if: needs.release.outputs.published == 'true'
|
|
158
|
-
runs-on: ubuntu-latest
|
|
159
|
-
timeout-minutes: 10
|
|
160
|
-
permissions:
|
|
161
|
-
contents: read
|
|
162
|
-
packages: write
|
|
163
|
-
steps:
|
|
164
|
-
- uses: actions/checkout@v7
|
|
165
|
-
with:
|
|
166
|
-
ref: main # the release commit semantic-release just pushed
|
|
167
|
-
- uses: pnpm/action-setup@v6
|
|
168
|
-
- uses: actions/setup-node@v7
|
|
169
|
-
with:
|
|
170
|
-
node-version: '22'
|
|
171
|
-
cache: pnpm
|
|
172
|
-
registry-url: 'https://npm.pkg.github.com'
|
|
173
|
-
# Explicit, not inferred: setup-node's scope default only matches the scoped package.json name if package.json is already scoped by the time this step runs, and the rewrite below happens after it.
|
|
174
|
-
scope: '@exadev'
|
|
175
|
-
# GitHub Packages has no OIDC trusted-publishing exchange, so this job (unlike release above) authenticates with a token -- GITHUB_TOKEN is sufficient and needs no separate secret.
|
|
176
|
-
- run: pnpm install --frozen-lockfile
|
|
177
|
-
- run: pnpm build
|
|
178
|
-
- name: Rewrite package name and registry for the GitHub Packages scope
|
|
179
|
-
# GitHub Packages requires the npm package name to be scoped to the repo owner. Rewriting the fields rather than keeping a second package.json means this alias cannot drift away from the real package's metadata. publishConfig.registry has to be overridden too: it takes precedence over the .npmrc registry-url set by setup-node above, so without this the publish silently targets registry.npmjs.org instead -- confirmed failure mode, not a hypothetical (404 on the npmjs.org registry, since GITHUB_TOKEN isn't a credential it recognises).
|
|
180
|
-
run: |
|
|
181
|
-
npm pkg set name="@exadev/byte-codec"
|
|
182
|
-
npm pkg set publishConfig.registry="https://npm.pkg.github.com"
|
|
183
|
-
- run: pnpm publish --access public --no-git-checks
|
|
184
|
-
env:
|
|
185
|
-
NODE_AUTH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
|
186
|
-
|
|
187
|
-
publish-aliases:
|
|
188
|
-
name: Publish aliases (${{ matrix.name }})
|
|
189
|
-
needs: release
|
|
190
|
-
if: needs.release.outputs.published == 'true'
|
|
191
|
-
runs-on: ubuntu-latest
|
|
192
|
-
timeout-minutes: 10
|
|
193
|
-
permissions:
|
|
194
|
-
contents: read
|
|
195
|
-
id-token: write # OIDC identity for npm trusted publishing -- every leg in this job targets npmjs.org. The GitHub Packages alias is a separate job above specifically so it never holds this permission: pnpm attempts an OIDC exchange whenever id-token: write is available regardless of target registry, and GitHub Packages has no such exchange to attempt -- confirmed the hard way in a sibling repo when this leg used to share that job and failed with "401 Unauthorized - authentication token not provided" even with GITHUB_TOKEN correctly set, because the failed OIDC attempt never fell through to it.
|
|
196
|
-
strategy:
|
|
197
|
-
fail-fast: false
|
|
198
|
-
matrix:
|
|
199
|
-
include:
|
|
200
|
-
- { name: document-bytes, registry: 'https://registry.npmjs.org' }
|
|
201
|
-
steps:
|
|
202
|
-
- uses: actions/checkout@v7
|
|
203
|
-
with:
|
|
204
|
-
ref: main # the release commit semantic-release just pushed
|
|
205
|
-
- uses: pnpm/action-setup@v6
|
|
206
|
-
- uses: actions/setup-node@v7
|
|
207
|
-
with:
|
|
208
|
-
node-version: '22'
|
|
209
|
-
cache: pnpm
|
|
210
|
-
# registry-url is deliberately absent. Setting it makes setup-node write an .npmrc containing an _authToken line, and that line wins over the OIDC exchange -- so the setting that looks like it configures the registry is exactly the one that would break trusted publishing.
|
|
211
|
-
- run: pnpm install --frozen-lockfile
|
|
212
|
-
- run: pnpm build
|
|
213
|
-
- name: Rewrite package name for this alias
|
|
214
|
-
# Rewriting the checked-out package.json rather than keeping a package.json per alias means no alias can drift away from the real package's metadata -- each matrix leg gets its own fresh runner and checkout, so there is no cross-contamination between legs.
|
|
215
|
-
run: npm pkg set name="${{ matrix.name }}"
|
|
216
|
-
- run: pnpm publish --access public --no-git-checks
|
|
217
|
-
env:
|
|
218
|
-
# Blanked, not omitted -- an inherited NODE_AUTH_TOKEN would otherwise be used in preference to the OIDC exchange, matching the release job's own convention above.
|
|
219
|
-
NODE_AUTH_TOKEN: ''
|
|
220
|
-
|
|
221
|
-
attest:
|
|
222
|
-
name: Attest SBOM and build provenance
|
|
223
|
-
needs: release
|
|
224
|
-
if: needs.release.outputs.published == 'true'
|
|
225
|
-
runs-on: ubuntu-latest
|
|
226
|
-
timeout-minutes: 10
|
|
227
|
-
permissions:
|
|
228
|
-
contents: read
|
|
229
|
-
id-token: write
|
|
230
|
-
attestations: write
|
|
231
|
-
steps:
|
|
232
|
-
- uses: actions/checkout@v7
|
|
233
|
-
with:
|
|
234
|
-
ref: main # the release commit semantic-release just pushed
|
|
235
|
-
- uses: pnpm/action-setup@v6
|
|
236
|
-
- uses: actions/setup-node@v7
|
|
237
|
-
with:
|
|
238
|
-
node-version: '22'
|
|
239
|
-
cache: pnpm
|
|
240
|
-
- run: pnpm install --frozen-lockfile
|
|
241
|
-
- run: pnpm build
|
|
242
|
-
# Pack into a directory of its own, separate from dist/ (tsdown's raw build output). The attestation subject has to be the artefact that actually ships -- attesting dist/ itself would mix in files that never leave the repo, producing digests that match nothing a consumer can download.
|
|
243
|
-
- run: pnpm pack --pack-destination release-artifact
|
|
244
|
-
- run: pnpm sbom --sbom-format spdx --prod > release-artifact/sbom.spdx.json
|
|
245
|
-
# attest-sbom/attest-build-provenance are deprecated wrappers around actions/attest; called as two steps (sbom-path present vs. absent) rather than one, since actions/attest's docs don't clearly state whether passing both together attests SBOM and provenance in a single call or SBOM only -- two steps is the unambiguous equivalent of what this replaced.
|
|
246
|
-
- name: Attest SBOM
|
|
247
|
-
uses: actions/attest@v4
|
|
248
|
-
with:
|
|
249
|
-
subject-path: release-artifact/*.tgz
|
|
250
|
-
sbom-path: release-artifact/sbom.spdx.json
|
|
251
|
-
- name: Attest build provenance
|
|
252
|
-
uses: actions/attest@v4
|
|
253
|
-
with:
|
|
254
|
-
subject-path: release-artifact/*.tgz
|
|
@@ -1,64 +0,0 @@
|
|
|
1
|
-
name: Dependabot auto-merge
|
|
2
|
-
|
|
3
|
-
# Two auto-merge policies in one workflow. Sibling ExaDev packages (document-schema.js) merge unconditionally once green -- no cooldown, matching this family's existing convention. Every other (third-party) dependency merges only for a minor or patch bump; a major bump still opens a PR via Dependabot but is left for manual review. Third-party updates additionally carry dependabot.yml's own 7-day cooldown before Dependabot proposes them at all. Auto-merge is enforced by main's own CI actually passing on the PR's head commit -- this workflow only requests the merge, GitHub itself withholds it until checks conclude. The merge itself authenticates via a GitHub App installation token rather than GITHUB_TOKEN, so the resulting push to main triggers downstream workflow runs (ci.yml, release) instead of being silently skipped by GitHub's anti-recursion protection.
|
|
4
|
-
|
|
5
|
-
on:
|
|
6
|
-
# pull_request_target, not pull_request -- a workflow run triggered by dependabot[bot]'s own pull_request
|
|
7
|
-
# event gets NO secret access at all (a hard GitHub Actions security restriction against a compromised
|
|
8
|
-
# dependency update exfiltrating secrets), so secrets.AUTOMERGE_APP_PRIVATE_KEY would resolve empty
|
|
9
|
-
# regardless of how correctly the secret itself is configured. pull_request_target runs using the base
|
|
10
|
-
# branch's own workflow file and normal secret access instead. Safe here specifically because this job
|
|
11
|
-
# never checks out or executes the PR's own code -- it only calls the GitHub API (fetch-metadata, gh pr
|
|
12
|
-
# merge), which is exactly the case pull_request_target's own security guidance calls out as safe.
|
|
13
|
-
pull_request_target:
|
|
14
|
-
|
|
15
|
-
permissions:
|
|
16
|
-
contents: write
|
|
17
|
-
pull-requests: write
|
|
18
|
-
|
|
19
|
-
jobs:
|
|
20
|
-
auto-merge:
|
|
21
|
-
if: github.actor == 'dependabot[bot]'
|
|
22
|
-
runs-on: ubuntu-latest
|
|
23
|
-
timeout-minutes: 10
|
|
24
|
-
steps:
|
|
25
|
-
- name: Fetch Dependabot metadata
|
|
26
|
-
id: metadata
|
|
27
|
-
uses: dependabot/fetch-metadata@v2
|
|
28
|
-
with:
|
|
29
|
-
github-token: "${{ secrets.GITHUB_TOKEN }}"
|
|
30
|
-
- name: Decide whether to auto-merge
|
|
31
|
-
id: decide
|
|
32
|
-
env:
|
|
33
|
-
DEPENDENCY_NAMES: ${{ steps.metadata.outputs.dependency-names }}
|
|
34
|
-
UPDATE_TYPE: ${{ steps.metadata.outputs.update-type }}
|
|
35
|
-
run: |
|
|
36
|
-
siblings="document-schema.js"
|
|
37
|
-
is_sibling=false
|
|
38
|
-
for name in $(echo "$DEPENDENCY_NAMES" | tr ',' ' '); do
|
|
39
|
-
name=$(echo "$name" | xargs)
|
|
40
|
-
for sib in $siblings; do
|
|
41
|
-
if [ "$name" = "$sib" ]; then
|
|
42
|
-
is_sibling=true
|
|
43
|
-
fi
|
|
44
|
-
done
|
|
45
|
-
done
|
|
46
|
-
if [ "$is_sibling" = "true" ]; then
|
|
47
|
-
echo "merge=true" >> "$GITHUB_OUTPUT"
|
|
48
|
-
elif [ "$UPDATE_TYPE" = "version-update:semver-minor" ] || [ "$UPDATE_TYPE" = "version-update:semver-patch" ]; then
|
|
49
|
-
echo "merge=true" >> "$GITHUB_OUTPUT"
|
|
50
|
-
else
|
|
51
|
-
echo "merge=false" >> "$GITHUB_OUTPUT"
|
|
52
|
-
fi
|
|
53
|
-
- name: Generate a token for the merge
|
|
54
|
-
id: app-token
|
|
55
|
-
uses: actions/create-github-app-token@v2
|
|
56
|
-
with:
|
|
57
|
-
app-id: "4473709"
|
|
58
|
-
private-key: ${{ secrets.AUTOMERGE_APP_PRIVATE_KEY }}
|
|
59
|
-
- name: Enable auto-merge
|
|
60
|
-
if: steps.decide.outputs.merge == 'true'
|
|
61
|
-
run: gh pr merge --auto --rebase "$PR_URL"
|
|
62
|
-
env:
|
|
63
|
-
PR_URL: ${{ github.event.pull_request.html_url }}
|
|
64
|
-
GH_TOKEN: ${{ steps.app-token.outputs.token }}
|
|
@@ -1,174 +0,0 @@
|
|
|
1
|
-
name: Sibling dependency instant update
|
|
2
|
-
|
|
3
|
-
# Triggered the moment a sibling ExaDev package this repo depends on publishes a new version -- the publishing repo own ci.yml sends this repository_dispatch event right after semantic-release completes, instead of waiting for Dependabot own daily scheduled scan to notice. Bumps the named dependency, opens a PR, and requests auto-merge. The branch push and the PR-open call both authenticate via a freshly-minted GitHub App installation token, not the default GITHUB_TOKEN -- GITHUB_TOKEN-authenticated actions (a push OR opening a PR) do not cascade into further workflow runs, so a GITHUB_TOKEN-created PR would never trigger this repo own ci.yml pull_request checks at all, leaving nothing for auto-merge to wait on and letting GitHub treat the PR as already mergeable the instant it opens. Even with the App token making that cascade happen for real, there is a second, narrower race: GitHub can take a few seconds to actually register ci.yml own check-runs against the new PR, and calling gh pr merge --auto before any check has registered gets rejected with "Pull request is in clean status" -- confirmed happening in production even after the App-token fix landed. The wait step below polls for ci.yml own Test check-run to actually appear before requesting auto-merge, closing that race. This workflow never pushes directly to main -- the PR still only merges once this repo own CI genuinely passes on it. Note: every repo in this family also enforces a minimumReleaseAge pnpm supply-chain gate (see pnpm-workspace.yaml); pnpm add itself can refuse to install a version published within that window, in which case this workflow run fails cleanly and the bump is left for Dependabot own next daily scan to pick up once the window has passed -- a neutral fallback, not a regression, since that scan would have handled it anyway.
|
|
4
|
-
|
|
5
|
-
on:
|
|
6
|
-
repository_dispatch:
|
|
7
|
-
types: [sibling-released]
|
|
8
|
-
push:
|
|
9
|
-
branches: [main]
|
|
10
|
-
workflow_dispatch: {}
|
|
11
|
-
|
|
12
|
-
permissions:
|
|
13
|
-
contents: write
|
|
14
|
-
pull-requests: write
|
|
15
|
-
|
|
16
|
-
jobs:
|
|
17
|
-
bump-and-open-pr:
|
|
18
|
-
if: github.event_name == 'repository_dispatch'
|
|
19
|
-
runs-on: ubuntu-latest
|
|
20
|
-
timeout-minutes: 10
|
|
21
|
-
steps:
|
|
22
|
-
- uses: actions/checkout@v7
|
|
23
|
-
- uses: pnpm/action-setup@v6
|
|
24
|
-
- uses: actions/setup-node@v7
|
|
25
|
-
with:
|
|
26
|
-
node-version: '22'
|
|
27
|
-
cache: pnpm
|
|
28
|
-
- name: Bump the released dependency
|
|
29
|
-
env:
|
|
30
|
-
PACKAGE: ${{ github.event.client_payload.package }}
|
|
31
|
-
VERSION: ${{ github.event.client_payload.version }}
|
|
32
|
-
run: pnpm add "$PACKAGE@$VERSION"
|
|
33
|
-
- name: Check whether anything actually changed
|
|
34
|
-
id: diff
|
|
35
|
-
run: |
|
|
36
|
-
if git diff --quiet -- package.json pnpm-lock.yaml; then
|
|
37
|
-
echo "changed=false" >> "$GITHUB_OUTPUT"
|
|
38
|
-
else
|
|
39
|
-
echo "changed=true" >> "$GITHUB_OUTPUT"
|
|
40
|
-
fi
|
|
41
|
-
- name: Generate a token for the branch push and PR
|
|
42
|
-
if: steps.diff.outputs.changed == 'true'
|
|
43
|
-
id: app-token
|
|
44
|
-
uses: actions/create-github-app-token@v2
|
|
45
|
-
with:
|
|
46
|
-
app-id: '4473709'
|
|
47
|
-
private-key: ${{ secrets.AUTOMERGE_APP_PRIVATE_KEY }}
|
|
48
|
-
- name: Commit and open a PR
|
|
49
|
-
if: steps.diff.outputs.changed == 'true'
|
|
50
|
-
id: pr
|
|
51
|
-
env:
|
|
52
|
-
GH_TOKEN: ${{ steps.app-token.outputs.token }}
|
|
53
|
-
PACKAGE: ${{ github.event.client_payload.package }}
|
|
54
|
-
VERSION: ${{ github.event.client_payload.version }}
|
|
55
|
-
run: |
|
|
56
|
-
git config user.name "github-actions[bot]"
|
|
57
|
-
git config user.email "github-actions[bot]@users.noreply.github.com"
|
|
58
|
-
branch="sibling-update/${PACKAGE}-${VERSION}"
|
|
59
|
-
git checkout -b "$branch"
|
|
60
|
-
git add package.json pnpm-lock.yaml
|
|
61
|
-
body=$(printf 'Triggered instantly via repository_dispatch when %s published its own release,\nrather than waiting for the next scheduled Dependabot scan.' "$PACKAGE")
|
|
62
|
-
git commit -m "build(deps): bump ${PACKAGE} to ${VERSION}" -m "$body"
|
|
63
|
-
git remote set-url origin "https://x-access-token:${GH_TOKEN}@github.com/${{ github.repository }}.git"
|
|
64
|
-
git push origin "$branch"
|
|
65
|
-
pr_url=$(gh pr create --title "build(deps): bump ${PACKAGE} to ${VERSION}" --body "Automatic dependency bump triggered instantly by the ${PACKAGE} release." --base main --head "$branch")
|
|
66
|
-
echo "pr_url=$pr_url" >> "$GITHUB_OUTPUT"
|
|
67
|
-
echo "head_sha=$(git rev-parse HEAD)" >> "$GITHUB_OUTPUT"
|
|
68
|
-
- name: Wait for this repo own real CI to register on the PR
|
|
69
|
-
if: steps.diff.outputs.changed == 'true'
|
|
70
|
-
env:
|
|
71
|
-
GH_TOKEN: ${{ steps.app-token.outputs.token }}
|
|
72
|
-
run: |
|
|
73
|
-
for i in $(seq 1 30); do
|
|
74
|
-
found=$(gh api "repos/${{ github.repository }}/commits/${{ steps.pr.outputs.head_sha }}/check-runs" --jq '[.check_runs[] | select(.name == "Test")] | length')
|
|
75
|
-
if [ "$found" -gt 0 ]; then
|
|
76
|
-
echo "ci.yml own Test check has registered after $((i * 3))s"
|
|
77
|
-
exit 0
|
|
78
|
-
fi
|
|
79
|
-
sleep 3
|
|
80
|
-
done
|
|
81
|
-
echo "::warning::ci.yml own Test check never registered after 90s -- proceeding anyway, but auto-merge may reject the PR as already clean or merge it immediately" >&2
|
|
82
|
-
- name: Enable auto-merge
|
|
83
|
-
if: steps.diff.outputs.changed == 'true'
|
|
84
|
-
env:
|
|
85
|
-
GH_TOKEN: ${{ steps.app-token.outputs.token }}
|
|
86
|
-
run: gh pr merge --auto --rebase "${{ steps.pr.outputs.pr_url }}"
|
|
87
|
-
|
|
88
|
-
heal-stranded-prs:
|
|
89
|
-
# gh pr merge --auto above only ever fires once, right after a PR opens. If enough other commits land on main before this repo's own CI finishes on that PR, the PR's branch falls behind and GitHub marks it CONFLICTING -- and a conflicting PR can never auto-merge, no matter how green its own CI is, with nothing to ever retry it. This job runs on every push to main (the only time a previously-clean PR can newly become conflicting) and regenerates any bump PR this same workflow opened that is now stuck: closes the stale PR/branch and re-runs the identical bump against the new main, rather than attempting a real git rebase -- a plain `pnpm add <package>@<version>` is fully idempotent and deterministic, so there is no conflict to resolve, only a fresh diff to produce.
|
|
90
|
-
if: github.event_name == 'push' || github.event_name == 'workflow_dispatch'
|
|
91
|
-
runs-on: ubuntu-latest
|
|
92
|
-
timeout-minutes: 15
|
|
93
|
-
steps:
|
|
94
|
-
- uses: actions/checkout@v7
|
|
95
|
-
- uses: pnpm/action-setup@v6
|
|
96
|
-
- uses: actions/setup-node@v7
|
|
97
|
-
with:
|
|
98
|
-
node-version: '22'
|
|
99
|
-
cache: pnpm
|
|
100
|
-
- name: Generate a token
|
|
101
|
-
id: app-token
|
|
102
|
-
uses: actions/create-github-app-token@v2
|
|
103
|
-
with:
|
|
104
|
-
app-id: '4473709'
|
|
105
|
-
private-key: ${{ secrets.AUTOMERGE_APP_PRIVATE_KEY }}
|
|
106
|
-
- name: Regenerate every conflicting sibling-update PR
|
|
107
|
-
env:
|
|
108
|
-
GH_TOKEN: ${{ steps.app-token.outputs.token }}
|
|
109
|
-
run: |
|
|
110
|
-
git config user.name "github-actions[bot]"
|
|
111
|
-
git config user.email "github-actions[bot]@users.noreply.github.com"
|
|
112
|
-
git remote set-url origin "https://x-access-token:${GH_TOKEN}@github.com/${{ github.repository }}.git"
|
|
113
|
-
|
|
114
|
-
# gh pr list's own `mergeable` field never computes a real value (always reports UNKNOWN) -- only a per-PR `gh pr view` triggers GitHub's own mergeable-status computation, and even that is asynchronous. So list candidates in bulk (reliable), then poll each one individually until its real status resolves.
|
|
115
|
-
candidates=$(gh pr list --state open --json number,headRefName \
|
|
116
|
-
--jq '[.[] | select(.headRefName | startswith("sibling-update/"))] | .[]')
|
|
117
|
-
if [ -z "$candidates" ]; then
|
|
118
|
-
echo "No open sibling-update PRs found."
|
|
119
|
-
exit 0
|
|
120
|
-
fi
|
|
121
|
-
|
|
122
|
-
echo "$candidates" | jq -c '.' | while read -r entry; do
|
|
123
|
-
number=$(echo "$entry" | jq -r '.number')
|
|
124
|
-
branch=$(echo "$entry" | jq -r '.headRefName')
|
|
125
|
-
|
|
126
|
-
mergeable="UNKNOWN"
|
|
127
|
-
for _attempt in $(seq 1 10); do
|
|
128
|
-
mergeable=$(gh pr view "$number" --json mergeable --jq '.mergeable')
|
|
129
|
-
if [ "$mergeable" != "UNKNOWN" ]; then
|
|
130
|
-
break
|
|
131
|
-
fi
|
|
132
|
-
sleep 3
|
|
133
|
-
done
|
|
134
|
-
|
|
135
|
-
if [ "$mergeable" != "CONFLICTING" ]; then
|
|
136
|
-
echo "PR #${number} (${branch}) is ${mergeable}, not stranded -- skipping."
|
|
137
|
-
continue
|
|
138
|
-
fi
|
|
139
|
-
|
|
140
|
-
package_version="${branch#sibling-update/}"
|
|
141
|
-
package="${package_version%-*}"
|
|
142
|
-
version="${package_version##*-}"
|
|
143
|
-
echo "Regenerating stranded PR #${number} (${branch}) for ${package}@${version}"
|
|
144
|
-
|
|
145
|
-
gh pr close "$number" --comment "Regenerating -- this branch fell behind main and could no longer auto-merge."
|
|
146
|
-
|
|
147
|
-
git fetch origin main
|
|
148
|
-
git checkout -B "$branch" origin/main
|
|
149
|
-
pnpm add "${package}@${version}"
|
|
150
|
-
|
|
151
|
-
if git diff --quiet -- package.json pnpm-lock.yaml; then
|
|
152
|
-
echo "main already has ${package}@${version} or newer -- nothing left to bump."
|
|
153
|
-
continue
|
|
154
|
-
fi
|
|
155
|
-
|
|
156
|
-
git add package.json pnpm-lock.yaml
|
|
157
|
-
git commit -m "build(deps): bump ${package} to ${version}"
|
|
158
|
-
git push --force origin "$branch"
|
|
159
|
-
pr_url=$(gh pr create --title "build(deps): bump ${package} to ${version}" \
|
|
160
|
-
--body "Regenerated automatically after the original PR fell behind main." \
|
|
161
|
-
--base main --head "$branch")
|
|
162
|
-
head_sha=$(git rev-parse HEAD)
|
|
163
|
-
|
|
164
|
-
for _attempt in $(seq 1 30); do
|
|
165
|
-
found=$(gh api "repos/${{ github.repository }}/commits/${head_sha}/check-runs" \
|
|
166
|
-
--jq '[.check_runs[] | select(.name == "Test")] | length')
|
|
167
|
-
if [ "$found" -gt 0 ]; then
|
|
168
|
-
break
|
|
169
|
-
fi
|
|
170
|
-
sleep 3
|
|
171
|
-
done
|
|
172
|
-
|
|
173
|
-
gh pr merge --auto --rebase "$pr_url"
|
|
174
|
-
done
|
package/.husky/commit-msg
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
pnpm exec commitlint --edit "$1"
|
package/.husky/pre-commit
DELETED
package/.husky/pre-push
DELETED
package/CHANGELOG.md
DELETED
|
@@ -1,12 +0,0 @@
|
|
|
1
|
-
# 1.0.0 (2026-08-05)
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
### Bug Fixes
|
|
5
|
-
|
|
6
|
-
* ci test and smoke steps for byte-codec's script set ([a64531d](https://github.com/ExaDev/byte-codec/commit/a64531df7cec8969ffe2f99cb4b100020b549ad4))
|
|
7
|
-
* ci yaml — remove stray key, fix job name, correct alias ([c1c6291](https://github.com/ExaDev/byte-codec/commit/c1c629166831899be2b07f761fafdd130babbe78))
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
### Features
|
|
11
|
-
|
|
12
|
-
* initial byte-codec package — generic byte/image utilities ([698c6ab](https://github.com/ExaDev/byte-codec/commit/698c6abd755e72e40759569a3ffa6b0f2f5d9f21))
|
package/commitlint.config.ts
DELETED
package/eslint.config.ts
DELETED
|
@@ -1,19 +0,0 @@
|
|
|
1
|
-
import js from '@eslint/js';
|
|
2
|
-
import tseslint from 'typescript-eslint';
|
|
3
|
-
import globals from 'globals';
|
|
4
|
-
|
|
5
|
-
export default tseslint.config(
|
|
6
|
-
js.configs.recommended,
|
|
7
|
-
...tseslint.configs.recommended,
|
|
8
|
-
{
|
|
9
|
-
languageOptions: {
|
|
10
|
-
globals: { ...globals.node },
|
|
11
|
-
},
|
|
12
|
-
rules: {
|
|
13
|
-
'@typescript-eslint/no-unused-vars': ['error', { argsIgnorePattern: '^_' }],
|
|
14
|
-
},
|
|
15
|
-
},
|
|
16
|
-
{
|
|
17
|
-
ignores: ['dist/**', 'node_modules/**'],
|
|
18
|
-
},
|
|
19
|
-
);
|
package/release.config.ts
DELETED
|
@@ -1,65 +0,0 @@
|
|
|
1
|
-
import type { Options } from 'semantic-release';
|
|
2
|
-
|
|
3
|
-
type ReleaseLevel = 'major' | 'minor' | 'patch' | false;
|
|
4
|
-
|
|
5
|
-
interface CommitType {
|
|
6
|
-
readonly type: string;
|
|
7
|
-
readonly release: ReleaseLevel;
|
|
8
|
-
}
|
|
9
|
-
|
|
10
|
-
/**
|
|
11
|
-
* Single source of truth for the conventional-commit types this project uses. commitlint's allowed type-enum (commitlint.config.ts imports this) and commit-analyzer's releaseRules below both derive from it, so a type can't trigger a release without also being accepted by commit-msg validation, or the reverse.
|
|
12
|
-
*
|
|
13
|
-
* Defined here rather than in a shared commit-types.ts: semantic-release loads this file via cosmiconfig, which transpiles only this one file to ESM, so a sibling .ts module would not resolve. commitlint's jiti loader has no such limit, so it imports commitTypes from here.
|
|
14
|
-
*/
|
|
15
|
-
export const commitTypes: readonly CommitType[] = [
|
|
16
|
-
{ type: 'feat', release: 'minor' },
|
|
17
|
-
{ type: 'fix', release: 'patch' },
|
|
18
|
-
{ type: 'perf', release: 'patch' },
|
|
19
|
-
{ type: 'revert', release: 'patch' },
|
|
20
|
-
{ type: 'refactor', release: 'patch' },
|
|
21
|
-
{ type: 'docs', release: 'patch' },
|
|
22
|
-
{ type: 'style', release: 'patch' },
|
|
23
|
-
{ type: 'test', release: 'patch' },
|
|
24
|
-
{ type: 'build', release: 'patch' },
|
|
25
|
-
{ type: 'ci', release: 'patch' },
|
|
26
|
-
{ type: 'chore', release: 'patch' },
|
|
27
|
-
];
|
|
28
|
-
|
|
29
|
-
/**
|
|
30
|
-
* Runs on `main`. Analyses commits since the last tag, bumps the version, publishes to npmjs.org (trusted OIDC publishing, no stored token -- see .github/workflows/ci.yml), creates a versioned tag and GitHub Release with generated notes, and commits CHANGELOG.md + package.json back to main. The release commit's [skip ci] message avoids a redundant CI run.
|
|
31
|
-
*/
|
|
32
|
-
const config: Options = {
|
|
33
|
-
branches: ['main'],
|
|
34
|
-
plugins: [
|
|
35
|
-
[
|
|
36
|
-
'@semantic-release/commit-analyzer',
|
|
37
|
-
{
|
|
38
|
-
preset: 'conventionalcommits',
|
|
39
|
-
releaseRules: [
|
|
40
|
-
{ breaking: true, release: 'major' },
|
|
41
|
-
...commitTypes.map((t) => ({ type: t.type, release: t.release })),
|
|
42
|
-
],
|
|
43
|
-
},
|
|
44
|
-
],
|
|
45
|
-
[
|
|
46
|
-
'@semantic-release/release-notes-generator',
|
|
47
|
-
{
|
|
48
|
-
// Deliberately angular, not conventionalcommits, despite commit-analyzer above using conventionalcommits without issue. conventional-changelog-conventionalcommits@10.2.1 exports its changelog body under the key `template`, but the conventional-changelog-writer version release-notes-generator@14.1.1 bundles only reads `options.mainTemplate` -- so the body silently falls back to the writer's own generic default, whose commit partial doesn't match conventionalcommits' function-based partial signature either. The result is a changelog with a version header and nothing under it, for every commit, with zero custom configuration: confirmed with `preset: 'conventionalcommits'` and no presetConfig at all. angular is release-notes-generator's own tested default and renders correctly. commitTypes above still drives commit-analyzer's releaseRules and commitlint's type-enum; it just can't also drive per-type changelog sections until this is fixed upstream, so there is no per-type `section` field here to go unused.
|
|
49
|
-
preset: 'angular',
|
|
50
|
-
},
|
|
51
|
-
],
|
|
52
|
-
'@semantic-release/changelog',
|
|
53
|
-
['@semantic-release/npm', { npmPublish: true }],
|
|
54
|
-
'@semantic-release/github',
|
|
55
|
-
[
|
|
56
|
-
'@semantic-release/git',
|
|
57
|
-
{
|
|
58
|
-
assets: ['CHANGELOG.md', 'package.json'],
|
|
59
|
-
message: 'chore(release): ${nextRelease.version} [skip ci]',
|
|
60
|
-
},
|
|
61
|
-
],
|
|
62
|
-
],
|
|
63
|
-
};
|
|
64
|
-
|
|
65
|
-
export default config;
|
package/src/bytes/crc32.ts
DELETED
|
@@ -1,24 +0,0 @@
|
|
|
1
|
-
// Table-driven CRC32 (polynomial 0xEDB88320, the standard IEEE 802.3 / ZIP / PNG polynomial). fflate exports no CRC32 of its own (only an internal one used by its ZIP writer), and PNG's chunk format requires one per chunk, so this is genuinely new code, not a duplicate of anything already in the tree.
|
|
2
|
-
const CRC32_POLYNOMIAL = 0xedb88320;
|
|
3
|
-
const BYTE_VALUES = 256;
|
|
4
|
-
const BITS_PER_BYTE = 8;
|
|
5
|
-
|
|
6
|
-
const CRC32_TABLE: Uint32Array = (() => {
|
|
7
|
-
const table = new Uint32Array(BYTE_VALUES);
|
|
8
|
-
for (let n = 0; n < BYTE_VALUES; n++) {
|
|
9
|
-
let c = n;
|
|
10
|
-
for (let k = 0; k < BITS_PER_BYTE; k++) {
|
|
11
|
-
c = (c & 1) === 1 ? CRC32_POLYNOMIAL ^ (c >>> 1) : c >>> 1;
|
|
12
|
-
}
|
|
13
|
-
table[n] = c >>> 0;
|
|
14
|
-
}
|
|
15
|
-
return table;
|
|
16
|
-
})();
|
|
17
|
-
|
|
18
|
-
export function crc32(bytes: Uint8Array<ArrayBuffer>): number {
|
|
19
|
-
let crc = 0xffffffff;
|
|
20
|
-
for (const byte of bytes) {
|
|
21
|
-
crc = CRC32_TABLE[(crc ^ byte) & 0xff]! ^ (crc >>> 8);
|
|
22
|
-
}
|
|
23
|
-
return (crc ^ 0xffffffff) >>> 0;
|
|
24
|
-
}
|