@_linked/server 2.24.2 → 2.24.3
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/CHANGELOG.md +6 -0
- package/package.json +6 -1
- package/.changeset/README.md +0 -20
- package/.changeset/config.json +0 -14
- package/.gitattributes +0 -1
- package/.github/workflows/pr.yml +0 -18
- package/.github/workflows/publish.yml +0 -30
- package/docs/architecture/01-server-only-surface.md +0 -58
- package/docs/backlog/001-resize-by-store-key.md +0 -104
- package/docs/reports/001-vite-release-serving.md +0 -100
- package/jest.config.cjs +0 -23
- package/renovate.json +0 -4
- package/tsconfig-cjs.json +0 -8
- package/tsconfig-esm.json +0 -9
- package/tsconfig-tests.json +0 -11
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,11 @@
|
|
|
1
1
|
# @\_linked/server
|
|
2
2
|
|
|
3
|
+
## 2.24.3
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- [#155](https://github.com/linked-fw/server/pull/155) [`c0fcc6f`](https://github.com/linked-fw/server/commit/c0fcc6f42c8ef611ceca5ee997d3f09b3aa890bd) Thanks [@flyon](https://github.com/flyon)! - Publish only the files consumers need; the tarball no longer includes `.changeset/`, `.gitattributes`, `.github/`, `docs/`, `jest.config.cjs`, `renovate.json` or tsconfig files.
|
|
8
|
+
|
|
3
9
|
## 2.24.2
|
|
4
10
|
|
|
5
11
|
### Patch Changes
|
package/package.json
CHANGED
|
@@ -10,13 +10,18 @@
|
|
|
10
10
|
"type": "git",
|
|
11
11
|
"url": "git+https://github.com/linked-fw/server.git"
|
|
12
12
|
},
|
|
13
|
-
"version": "2.24.
|
|
13
|
+
"version": "2.24.3",
|
|
14
14
|
"packageManager": "npm@11.21.0",
|
|
15
15
|
"linkedPackage": true,
|
|
16
16
|
"type": "module",
|
|
17
17
|
"main": "lib/esm/index.js",
|
|
18
18
|
"types": "index.d.ts",
|
|
19
19
|
"license": "ISC",
|
|
20
|
+
"files": [
|
|
21
|
+
"lib",
|
|
22
|
+
"styles",
|
|
23
|
+
"CHANGELOG.md"
|
|
24
|
+
],
|
|
20
25
|
"scripts": {
|
|
21
26
|
"start": "npm exec linked dev",
|
|
22
27
|
"test": "NODE_OPTIONS=--experimental-vm-modules npx jest --config jest.config.cjs",
|
package/.changeset/README.md
DELETED
|
@@ -1,20 +0,0 @@
|
|
|
1
|
-
# Changesets
|
|
2
|
-
|
|
3
|
-
This package uses [changesets](https://github.com/changesets/changesets) for version management and publishing.
|
|
4
|
-
|
|
5
|
-
## Adding a changeset
|
|
6
|
-
|
|
7
|
-
When making a change that should trigger a new release, run:
|
|
8
|
-
|
|
9
|
-
```bash
|
|
10
|
-
npx changeset
|
|
11
|
-
```
|
|
12
|
-
|
|
13
|
-
This generates a markdown file in `.changeset/` describing the change. Commit it with your PR.
|
|
14
|
-
|
|
15
|
-
On merge to `main`, the publish workflow either:
|
|
16
|
-
|
|
17
|
-
1. Creates (or updates) a **Release PR** that bumps the version + updates `CHANGELOG.md`, or
|
|
18
|
-
2. If the Release PR is already merged, publishes the new version to npm.
|
|
19
|
-
|
|
20
|
-
Changes that don't need a release (docs, CI config, tooling) can skip the changeset — the check is a warning, not a block.
|
package/.changeset/config.json
DELETED
|
@@ -1,14 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"$schema": "https://unpkg.com/@changesets/config@3.1.1/schema.json",
|
|
3
|
-
"changelog": [
|
|
4
|
-
"@changesets/changelog-github",
|
|
5
|
-
{ "repo": "linked-fw/server" }
|
|
6
|
-
],
|
|
7
|
-
"commit": false,
|
|
8
|
-
"fixed": [],
|
|
9
|
-
"linked": [],
|
|
10
|
-
"access": "public",
|
|
11
|
-
"baseBranch": "main",
|
|
12
|
-
"updateInternalDependencies": "patch",
|
|
13
|
-
"ignore": []
|
|
14
|
-
}
|
package/.gitattributes
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
package-lock.json linguist-generated=true -diff merge=ours
|
package/.github/workflows/pr.yml
DELETED
|
@@ -1,18 +0,0 @@
|
|
|
1
|
-
name: PR
|
|
2
|
-
|
|
3
|
-
on:
|
|
4
|
-
pull_request:
|
|
5
|
-
branches:
|
|
6
|
-
- main
|
|
7
|
-
|
|
8
|
-
jobs:
|
|
9
|
-
checks:
|
|
10
|
-
uses: linked-fw/.github/.github/workflows/pr.yml@v1
|
|
11
|
-
# The changeset reminder posts a PR comment. A reusable workflow only holds what its
|
|
12
|
-
# caller granted, and the org default is read-only.
|
|
13
|
-
permissions:
|
|
14
|
-
contents: read
|
|
15
|
-
pull-requests: write
|
|
16
|
-
with:
|
|
17
|
-
require-tests: true
|
|
18
|
-
run-e2e: false
|
|
@@ -1,30 +0,0 @@
|
|
|
1
|
-
# Calls the shared workflow in linked-fw/.github.
|
|
2
|
-
#
|
|
3
|
-
# This FILENAME is what npm's trusted-publisher check validates — not the shared workflow's.
|
|
4
|
-
# Renaming this file invalidates this package's trusted publisher, and the only symptom is
|
|
5
|
-
# that releases quietly start needing manual approval again.
|
|
6
|
-
name: Publish
|
|
7
|
-
|
|
8
|
-
on:
|
|
9
|
-
push:
|
|
10
|
-
branches:
|
|
11
|
-
- main
|
|
12
|
-
|
|
13
|
-
concurrency: ${{ github.workflow }}-${{ github.ref }}
|
|
14
|
-
|
|
15
|
-
jobs:
|
|
16
|
-
release:
|
|
17
|
-
uses: linked-fw/.github/.github/workflows/publish.yml@v1
|
|
18
|
-
permissions:
|
|
19
|
-
contents: write
|
|
20
|
-
pull-requests: write
|
|
21
|
-
# Needed HERE as well as in the shared workflow: a reusable workflow cannot widen the
|
|
22
|
-
# permissions its caller was granted, and without this npm never gets an id-token and
|
|
23
|
-
# every release silently falls back to the approval queue.
|
|
24
|
-
id-token: write
|
|
25
|
-
# Named rather than `inherit`: `inherit` forwards everything this repo can see, which is
|
|
26
|
-
# how a community repo would end up forwarding a first-party token.
|
|
27
|
-
secrets:
|
|
28
|
-
NPM_TOKEN: ${{ secrets.NPM_AUTH_TOKEN }}
|
|
29
|
-
RELEASE_APP_ID: ${{ secrets.RELEASE_APP_ID }}
|
|
30
|
-
RELEASE_APP_PRIVATE_KEY: ${{ secrets.RELEASE_APP_PRIVATE_KEY }}
|
|
@@ -1,58 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
summary: Why this package declares its own server-only surface rather than being named by
|
|
3
|
-
consumers, what the declaration means, and the one part of this package that is not server-only
|
|
4
|
-
and should not live here.
|
|
5
|
-
---
|
|
6
|
-
|
|
7
|
-
# This package's server-only surface
|
|
8
|
-
|
|
9
|
-
This package is a **replaceable module**. An application may swap it for another implementation,
|
|
10
|
-
and anything that depends on knowing it by name breaks the moment someone does.
|
|
11
|
-
|
|
12
|
-
That matters for one specific rule: **a frontend bundle must not contain this package.** Almost
|
|
13
|
-
everything here touches a filesystem, a process or a socket, and a `ShapeProvider` extends
|
|
14
|
-
`BackendProvider`, which imports node's `path`. Pull any of it into a client graph and the bundler
|
|
15
|
-
resolves `path` to the abandoned npm shim of the same name, the shim references `process`, and the
|
|
16
|
-
application hydrates into an empty shell with `ReferenceError: process is not defined` — an error
|
|
17
|
-
naming nothing that would lead you back to the import.
|
|
18
|
-
|
|
19
|
-
## The declaration
|
|
20
|
-
|
|
21
|
-
```jsonc
|
|
22
|
-
"linked": {
|
|
23
|
-
"serverOnly": [".", "./shapes/*", "./server/*", "./utils/*"]
|
|
24
|
-
}
|
|
25
|
-
```
|
|
26
|
-
|
|
27
|
-
A consuming application's client/server boundary check reads this, rather than hardcoding
|
|
28
|
-
`@_linked/server`. The difference is not stylistic: a check that names this package protects one
|
|
29
|
-
arrangement of the framework, and a replacement inherits none of it. A check that reads
|
|
30
|
-
declarations protects whatever is installed.
|
|
31
|
-
|
|
32
|
-
It is purely declarative. No code, no exports, and no resolution behaviour depends on it.
|
|
33
|
-
|
|
34
|
-
## The convention it complements
|
|
35
|
-
|
|
36
|
-
A consumer also treats anything under `<pkg>/backend/**` as server-only, in **any** package, with
|
|
37
|
-
no declaration needed. Between the two, no application has to know a package by name.
|
|
38
|
-
|
|
39
|
-
A package whose server-only code all lives under `backend/` therefore needs no `linked.serverOnly`
|
|
40
|
-
at all. This package declares one because its server-only surface predates that convention and is
|
|
41
|
-
spread across several subpaths.
|
|
42
|
-
|
|
43
|
-
## What is not server-only, and should move
|
|
44
|
-
|
|
45
|
-
Three exports are client-safe and are published from here anyway:
|
|
46
|
-
|
|
47
|
-
| Export | Who uses it |
|
|
48
|
-
|---|---|
|
|
49
|
-
| `BackendAPIStore` | the store a **browser** uses to talk to the backend; constructed by an app's frontend storage config |
|
|
50
|
-
| `getAccessUrlLocalFileStore` | the same frontend config |
|
|
51
|
-
| `LincdWebApp` | constructed in a React hook |
|
|
52
|
-
|
|
53
|
-
They belong in `@_linked/server-utils`, which exists for exactly the isomorphic half of the
|
|
54
|
-
framework. Until they move, every consuming application must carry a standing exception in its
|
|
55
|
-
boundary check — and a boundary with permanent exceptions stops being one.
|
|
56
|
-
|
|
57
|
-
Tracked as follow-up work; noted here so the next person to wonder why an app imports
|
|
58
|
-
`@_linked/server` from its frontend finds the answer.
|
|
@@ -1,104 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
summary: >
|
|
3
|
-
DONE. /resized/* no longer fetches anything: both branches read and write
|
|
4
|
-
through LinkedFileStorage. The `?src=` parameter still accepts a full URL, so
|
|
5
|
-
nothing broke -- the URL is resolved to a store key and the bytes are read
|
|
6
|
-
directly, which turned out not to need the major release this item assumed.
|
|
7
|
-
Kept as the record of why the route looks the way it does.
|
|
8
|
-
---
|
|
9
|
-
|
|
10
|
-
# 001 — Resize by store key instead of fetching a URL
|
|
11
|
-
|
|
12
|
-
> **Done.** Delivered without the breaking change this item expected: see *Resolution* at the end.
|
|
13
|
-
|
|
14
|
-
## Where this came from
|
|
15
|
-
|
|
16
|
-
`?src=` used to be handed straight to `fetch`, which made every deployment an
|
|
17
|
-
open proxy into its own network — and because the fetched bytes were written
|
|
18
|
-
into the *public* file store and the caller redirected to them, a reachable
|
|
19
|
-
internal resource was persisted rather than merely leaked.
|
|
20
|
-
|
|
21
|
-
That was fixed by restricting `src` to the configured file store: parsed-origin
|
|
22
|
-
comparison against `LinkedFileStorage.accessURL`, a `fileExists` check on the
|
|
23
|
-
derived key, a fetch of a URL rebuilt from that key, and `redirect: 'error'`
|
|
24
|
-
plus a timeout and a size cap. See `src/utils/resizeSource.ts`.
|
|
25
|
-
|
|
26
|
-
That fix was deliberately the conservative one, because it is backward
|
|
27
|
-
compatible. This item is the version that is actually correct.
|
|
28
|
-
|
|
29
|
-
## The problem with what is there now
|
|
30
|
-
|
|
31
|
-
Once `src` is guaranteed to name an image in the store, the URL is a store key
|
|
32
|
-
with extra steps:
|
|
33
|
-
|
|
34
|
-
- **The fetch is pointless.** `resizeImage` calls
|
|
35
|
-
`LinkedFileStorage.fileExists(key)` and then performs an HTTP request to
|
|
36
|
-
retrieve bytes that `LinkedFileStorage.getFile(key)` would return directly.
|
|
37
|
-
For a local store that is a loopback request to read a file already on disk.
|
|
38
|
-
- **It keeps a fetch that has to stay correct.** Origin comparison, redirect
|
|
39
|
-
refusal, credential rejection, the size cap and the timeout all exist to make
|
|
40
|
-
an outbound request safe. None of that code needs to exist if there is no
|
|
41
|
-
outbound request.
|
|
42
|
-
- **The API lies about what it accepts.** Callers pass a full URL, but only one
|
|
43
|
-
origin's URLs are valid. A key says what is meant.
|
|
44
|
-
|
|
45
|
-
## What the change looks like
|
|
46
|
-
|
|
47
|
-
Replace the `src`-fetch branch with a key lookup:
|
|
48
|
-
|
|
49
|
-
```ts
|
|
50
|
-
const bytes = await LinkedFileStorage.getFile(key);
|
|
51
|
-
```
|
|
52
|
-
|
|
53
|
-
`resolveResizeSource` still has a job during a deprecation window — turning a
|
|
54
|
-
legacy full URL into a key — but `fetchStoredImage`, and with it the timeout,
|
|
55
|
-
the size cap and the redirect handling, can go.
|
|
56
|
-
|
|
57
|
-
## Why it is not done yet
|
|
58
|
-
|
|
59
|
-
It is a breaking change to the route's contract. Anything passing
|
|
60
|
-
`?src=<full URL>` keeps working only if the URL-to-key translation is retained,
|
|
61
|
-
and anything passing a third-party URL — which no longer works anyway after the
|
|
62
|
-
SSRF fix — breaks visibly rather than silently.
|
|
63
|
-
|
|
64
|
-
## First open questions
|
|
65
|
-
|
|
66
|
-
1. Is `?src=` as a full URL used by real consumers, or is the local branch
|
|
67
|
-
(`/resized/<path>`) the only one anyone uses? That decides whether this needs
|
|
68
|
-
a deprecation window at all.
|
|
69
|
-
2. Should the key form be a new parameter (`?key=`) so both can coexist for a
|
|
70
|
-
release, or should `src` simply start accepting a key as well as a URL?
|
|
71
|
-
3. ~~The other branch of the same route reads from `<cwd>/data/uploads`
|
|
72
|
-
directly~~ — **done.** Both branches now read and write through
|
|
73
|
-
`LinkedFileStorage`, the derivative cache has its own purpose
|
|
74
|
-
(`resizedImagesPurpose`), and the hand-rolled directory creation is gone
|
|
75
|
-
because `LocalFileStore` makes its own parents. That was the larger half of
|
|
76
|
-
"the route reads and writes through the store"; what is left here is only
|
|
77
|
-
the remote branch's needless HTTP hop.
|
|
78
|
-
|
|
79
|
-
## Related
|
|
80
|
-
|
|
81
|
-
- `src/utils/resizeSource.ts` — the guard this would let go.
|
|
82
|
-
- `src/tests/resized-images.test.ts` — the behaviour that must keep passing.
|
|
83
|
-
|
|
84
|
-
## Resolution
|
|
85
|
-
|
|
86
|
-
Done, and the "why it is not done yet" above turned out to be wrong.
|
|
87
|
-
|
|
88
|
-
The assumption was that dropping the fetch meant dropping `?src=<full URL>`,
|
|
89
|
-
which would break callers and need a major. It does not. The URL form still
|
|
90
|
-
works: `resolveResizeSource` turns it into a store key, and the bytes are then
|
|
91
|
-
read with `LinkedFileStorage.getFile(key)` instead of being fetched over HTTP.
|
|
92
|
-
The request contract is unchanged, so this shipped as a minor.
|
|
93
|
-
|
|
94
|
-
What went with the fetch: `fetchStoredImage`, the 10s timeout, the 25MB
|
|
95
|
-
streaming cap and `redirect: 'error'`. All of that existed to make an outbound
|
|
96
|
-
request safe, and there is no outbound request any more — the route cannot be
|
|
97
|
-
pointed at anything, rather than being guarded against it.
|
|
98
|
-
|
|
99
|
-
The local branch had already moved to the store, so both halves now read and
|
|
100
|
-
write the same way.
|
|
101
|
-
|
|
102
|
-
Open question 2 — whether to add a `?key=` parameter — was not needed and is
|
|
103
|
-
dropped. Question 1, whether anyone passes a full URL, no longer matters either
|
|
104
|
-
way, since both forms cost the same now.
|
|
@@ -1,100 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
summary: Two fixes that stood between a Vite-built application and a release it could actually
|
|
3
|
-
serve — the entry tag was rendered as a classic script, and LocalFileStore rewrote the object
|
|
4
|
-
keys a release is addressed by. Records what was wrong, why neither surfaced earlier, and the
|
|
5
|
-
contracts they establish.
|
|
6
|
-
---
|
|
7
|
-
|
|
8
|
-
# Serving a Vite-built release
|
|
9
|
-
|
|
10
|
-
Two independent defects, both on the path from "a release exists" to "a browser runs it". Neither
|
|
11
|
-
could be seen from inside this package: the first needs a real Vite bundle, the second needs a
|
|
12
|
-
release actually published to a local store.
|
|
13
|
-
|
|
14
|
-
## 1. The entry tag was a classic script
|
|
15
|
-
|
|
16
|
-
**`LinkedServer.tsx` — [#51](https://github.com/linked-fw/server/pull/51)**
|
|
17
|
-
|
|
18
|
-
The SSR render passed the client entry to React as `bootstrapScripts`, which emits
|
|
19
|
-
|
|
20
|
-
```html
|
|
21
|
-
<script src="…/assets/index-abc123.js" async></script>
|
|
22
|
-
```
|
|
23
|
-
|
|
24
|
-
Vite always emits the client entry as an **ES module**. A browser handed module syntax in a
|
|
25
|
-
classic script refuses the file outright:
|
|
26
|
-
|
|
27
|
-
```
|
|
28
|
-
Uncaught SyntaxError: Cannot use import statement outside a module
|
|
29
|
-
```
|
|
30
|
-
|
|
31
|
-
So **no Vite production build could hydrate at all** — the server rendered correct HTML, every
|
|
32
|
-
asset returned 200, and the page stayed inert.
|
|
33
|
-
|
|
34
|
-
The dev branch immediately above this code already used `bootstrapModules`, for exactly this
|
|
35
|
-
reason. Only the production branch was wrong.
|
|
36
|
-
|
|
37
|
-
### What it does now
|
|
38
|
-
|
|
39
|
-
`start()` records whether `assets['main.js']` was resolved from a Vite manifest
|
|
40
|
-
(`mainEntryIsModule`), and the SSR render passes `bootstrapModules` when it was.
|
|
41
|
-
|
|
42
|
-
This is deliberately **not** unconditional. A legacy webpack bundle is a classic script and a
|
|
43
|
-
module tag would break it, so the decision follows the manifest the entry actually came from
|
|
44
|
-
rather than a global setting.
|
|
45
|
-
|
|
46
|
-
### Why it survived
|
|
47
|
-
|
|
48
|
-
Dev never takes this path — `config.server.vite` routes to `bootstrapScriptContent` with the
|
|
49
|
-
React-refresh preamble. And no consuming application had completed a production build, because
|
|
50
|
-
the release pipeline itself was still being finished. The first app to get that far hit this
|
|
51
|
-
immediately.
|
|
52
|
-
|
|
53
|
-
## 2. `LocalFileStore` rewrote release object keys
|
|
54
|
-
|
|
55
|
-
**`shapes/filestores/LocalFileStore.ts` — [#52](https://github.com/linked-fw/server/pull/52)**
|
|
56
|
-
|
|
57
|
-
`resolveTarget`'s preserved character class was `[A-Za-z0-9._/]` — no `-` — so a run of dashes
|
|
58
|
-
collapsed to one:
|
|
59
|
-
|
|
60
|
-
```
|
|
61
|
-
asked for: shapeCodeGenerator--2JmNvrO.js
|
|
62
|
-
stored as: shapeCodeGenerator-2JmNvrO.js
|
|
63
|
-
```
|
|
64
|
-
|
|
65
|
-
Rollup's default base64 hash alphabet includes `-`, so an entry whose hash begins with one meets
|
|
66
|
-
the separator as `--`. The stored key is then neither what the caller asked for nor what the
|
|
67
|
-
bundle's own URLs point at.
|
|
68
|
-
|
|
69
|
-
`publish-app` requires a release store to keep keys verbatim and caught it — but only after 125 of
|
|
70
|
-
158 objects had uploaded, leaving an incomplete release.
|
|
71
|
-
|
|
72
|
-
### What it does now
|
|
73
|
-
|
|
74
|
-
`-` joins the preserved set. The method's own doc comment already stated the intent — not to
|
|
75
|
-
corrupt "a key a program chose on purpose, such as a Vite content hash: `main-hwqwrAvA.css`" — so
|
|
76
|
-
this makes the character class match what it says. Everything else is unchanged: `My File (2).TXT`
|
|
77
|
-
still becomes `My-File-2-.TXT`.
|
|
78
|
-
|
|
79
|
-
A regression test in `src/tests/local-file-store.test.ts` covers the doubled dash specifically, and
|
|
80
|
-
was confirmed to fail without the change.
|
|
81
|
-
|
|
82
|
-
## The contract both establish
|
|
83
|
-
|
|
84
|
-
**A release object must be addressable by exactly the key it was given.** The bundle's own chunk
|
|
85
|
-
URLs are baked in at build time and nothing rewrites them at request time, so a store that alters a
|
|
86
|
-
key — or a server that renders the entry in a form the browser rejects — breaks the release with no
|
|
87
|
-
useful error.
|
|
88
|
-
|
|
89
|
-
Anything implementing `IFileStore` for release assets inherits that requirement.
|
|
90
|
-
|
|
91
|
-
## Known limitation, not fixed here
|
|
92
|
-
|
|
93
|
-
`LocalFileStore.accessURL` is bare `SITE_ROOT`, while the store writes to `data/uploads/<key>` and
|
|
94
|
-
`LinkedServer` serves that tree at `/uploads` — the `/uploads` segment is appended inside
|
|
95
|
-
`publicURL` instead. `build-app` bakes the bundle's base URL from `accessURL`, so publishing to the
|
|
96
|
-
default store produces chunk URLs missing that segment, and every chunk 404s.
|
|
97
|
-
|
|
98
|
-
An application can work around it by registering a dedicated `appAssets` store whose `accessURL`
|
|
99
|
-
carries the segment. Moving it into `accessURL` here would be the real fix, but it changes that
|
|
100
|
-
field for every existing consumer and warrants its own assessment.
|
package/jest.config.cjs
DELETED
|
@@ -1,23 +0,0 @@
|
|
|
1
|
-
/** @type {import('ts-jest/dist/types').JestConfigWithTsJest} */
|
|
2
|
-
module.exports = {
|
|
3
|
-
preset: 'ts-jest/presets/default-esm',
|
|
4
|
-
testEnvironment: 'node',
|
|
5
|
-
rootDir: '.',
|
|
6
|
-
roots: ['<rootDir>/src/tests'],
|
|
7
|
-
testMatch: ['<rootDir>/src/tests/*.test.ts'],
|
|
8
|
-
extensionsToTreatAsEsm: ['.ts', '.tsx'],
|
|
9
|
-
transform: {
|
|
10
|
-
'^.+\\.(ts|tsx)$': [
|
|
11
|
-
'ts-jest',
|
|
12
|
-
{
|
|
13
|
-
useESM: true,
|
|
14
|
-
tsconfig: '<rootDir>/tsconfig-tests.json',
|
|
15
|
-
},
|
|
16
|
-
],
|
|
17
|
-
},
|
|
18
|
-
// Strip the `.js` extension from relative ESM imports so ts-jest resolves the
|
|
19
|
-
// `.ts` source (NodeNext-style specifiers carry `.js`; jest maps back to src).
|
|
20
|
-
moduleNameMapper: {
|
|
21
|
-
'^(\\.{1,2}/.*)\\.js$': '$1',
|
|
22
|
-
},
|
|
23
|
-
};
|
package/renovate.json
DELETED
package/tsconfig-cjs.json
DELETED
package/tsconfig-esm.json
DELETED
package/tsconfig-tests.json
DELETED