@gjsify/rolldown-plugin-pnp 0.3.14
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/lib/index.d.ts +22 -0
- package/lib/index.js +165 -0
- package/package.json +50 -0
- package/src/index.ts +180 -0
- package/tsconfig.json +15 -0
package/lib/index.d.ts
ADDED
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import type { Plugin } from 'rolldown';
|
|
2
|
+
export interface PnpPluginOptions {
|
|
3
|
+
/**
|
|
4
|
+
* `import.meta.url` of the caller. Used to anchor relay-issuer resolution
|
|
5
|
+
* on the caller's installation rather than this package's own location.
|
|
6
|
+
* Defaults to this module's own URL.
|
|
7
|
+
*/
|
|
8
|
+
issuerUrl?: string;
|
|
9
|
+
/**
|
|
10
|
+
* Packages whose `package.json` paths serve as fallback relay issuers
|
|
11
|
+
* when a direct `pnpApi.resolveRequest` fails with `UNDECLARED_DEPENDENCY`.
|
|
12
|
+
* Defaults to gjsify's polyfill meta-packages.
|
|
13
|
+
*/
|
|
14
|
+
relayPackages?: string[];
|
|
15
|
+
}
|
|
16
|
+
/**
|
|
17
|
+
* Build the gjsify-flavoured PnP relay plugin for Rolldown.
|
|
18
|
+
*
|
|
19
|
+
* Returns null when not running under Yarn PnP. Callers can spread this into
|
|
20
|
+
* a plugin array and Rolldown will skip the null entry.
|
|
21
|
+
*/
|
|
22
|
+
export declare function pnpPlugin(opts?: PnpPluginOptions): Promise<Plugin | null>;
|
package/lib/index.js
ADDED
|
@@ -0,0 +1,165 @@
|
|
|
1
|
+
// Yarn PnP resolver plugin for Rolldown / Rollup / Vite.
|
|
2
|
+
//
|
|
3
|
+
// Replaces the esbuild-only `@yarnpkg/esbuild-plugin-pnp` wrapper that
|
|
4
|
+
// previously lived in `@gjsify/resolve-npm/lib/pnp-relay.mjs`. Same relay
|
|
5
|
+
// semantics, Rollup-shaped hooks instead of esbuild's `setup(build)`.
|
|
6
|
+
//
|
|
7
|
+
// The plugin behaves like a no-op when not running under Yarn PnP (no
|
|
8
|
+
// `.pnp.cjs` ancestor of cwd, or `module.findPnpApi` unavailable).
|
|
9
|
+
//
|
|
10
|
+
// Rolldown does NOT have esbuild's "first onLoad wins" rule — the path
|
|
11
|
+
// rewriter that used to run inside this plugin's onLoad now lives as an
|
|
12
|
+
// independent `transform(code, id)` plugin. See
|
|
13
|
+
// `@gjsify/rolldown-plugin-gjsify/src/import-meta-url.ts`.
|
|
14
|
+
import { createRequire } from 'node:module';
|
|
15
|
+
import { fileURLToPath } from 'node:url';
|
|
16
|
+
import { dirname, join } from 'node:path';
|
|
17
|
+
import { existsSync } from 'node:fs';
|
|
18
|
+
import { readFile } from 'node:fs/promises';
|
|
19
|
+
/** Walk up from dir until .pnp.cjs is found; return its directory or null. */
|
|
20
|
+
function findPnpRoot(dir) {
|
|
21
|
+
let current = dir;
|
|
22
|
+
while (true) {
|
|
23
|
+
if (existsSync(join(current, '.pnp.cjs')))
|
|
24
|
+
return current;
|
|
25
|
+
const parent = dirname(current);
|
|
26
|
+
if (parent === current)
|
|
27
|
+
return null;
|
|
28
|
+
current = parent;
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
/** Try to load the runtime PnP API for the cwd's PnP installation. */
|
|
32
|
+
async function loadPnpApi() {
|
|
33
|
+
try {
|
|
34
|
+
// `pnpapi` is a virtual CJS module Yarn injects when running under PnP.
|
|
35
|
+
// `await import()` of a CJS module yields `{ default, "module.exports" }`,
|
|
36
|
+
// not the exports object directly — unwrap `.default`.
|
|
37
|
+
// @ts-expect-error pnpapi has no npm package
|
|
38
|
+
const mod = await import('pnpapi');
|
|
39
|
+
return (mod.default ?? mod);
|
|
40
|
+
}
|
|
41
|
+
catch {
|
|
42
|
+
return null;
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
/**
|
|
46
|
+
* Build the gjsify-flavoured PnP relay plugin for Rolldown.
|
|
47
|
+
*
|
|
48
|
+
* Returns null when not running under Yarn PnP. Callers can spread this into
|
|
49
|
+
* a plugin array and Rolldown will skip the null entry.
|
|
50
|
+
*/
|
|
51
|
+
export async function pnpPlugin(opts = {}) {
|
|
52
|
+
const issuerUrl = opts.issuerUrl ?? import.meta.url;
|
|
53
|
+
if (!findPnpRoot(process.cwd()))
|
|
54
|
+
return null;
|
|
55
|
+
const pnpApi = await loadPnpApi();
|
|
56
|
+
if (pnpApi === null)
|
|
57
|
+
return null;
|
|
58
|
+
// Relay issuers — anchor resolution on whoever called us first, then fall
|
|
59
|
+
// back to the polyfill meta-packages (which depend on every individual
|
|
60
|
+
// polyfill, so transitive `@gjsify/*` lookups always reach them).
|
|
61
|
+
const issuerPath = fileURLToPath(issuerUrl);
|
|
62
|
+
const requireFromIssuer = createRequire(issuerPath);
|
|
63
|
+
const relayPackages = opts.relayPackages ?? ['@gjsify/node-polyfills', '@gjsify/web-polyfills'];
|
|
64
|
+
const relayIssuers = [];
|
|
65
|
+
for (const pkg of relayPackages) {
|
|
66
|
+
try {
|
|
67
|
+
relayIssuers.push(requireFromIssuer.resolve(`${pkg}/package.json`));
|
|
68
|
+
}
|
|
69
|
+
catch {
|
|
70
|
+
// not in dep tree — relay won't cover it
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
return {
|
|
74
|
+
name: 'gjsify-pnp',
|
|
75
|
+
// Per-hook `order: 'pre'` runs us before Rolldown's default resolver
|
|
76
|
+
// so we own resolution for every bare specifier under PnP. Rolldown
|
|
77
|
+
// uses Rollup's per-hook ordering (not Vite's top-level `enforce`).
|
|
78
|
+
resolveId: {
|
|
79
|
+
order: 'pre',
|
|
80
|
+
async handler(source, importer) {
|
|
81
|
+
// Skip relative / absolute paths — let Rolldown handle them.
|
|
82
|
+
if (source.startsWith('.') || source.startsWith('/'))
|
|
83
|
+
return null;
|
|
84
|
+
// GJS gi:// imports are externalised by the orchestrator's
|
|
85
|
+
// `external` predicate; we must not run them through PnP
|
|
86
|
+
// (which would error with `UNDECLARED_DEPENDENCY` because
|
|
87
|
+
// `@girs/*` packages don't list `gi:` as a dep).
|
|
88
|
+
if (source.startsWith('gi://'))
|
|
89
|
+
return { id: source, external: true };
|
|
90
|
+
if (!importer)
|
|
91
|
+
return null;
|
|
92
|
+
// Importer may be a file URL string or an absolute path.
|
|
93
|
+
const importerPath = importer.startsWith('file://')
|
|
94
|
+
? fileURLToPath(importer)
|
|
95
|
+
: importer;
|
|
96
|
+
// Fast path: resolve from the importer's own context.
|
|
97
|
+
try {
|
|
98
|
+
const resolved = pnpApi.resolveRequest(source, importerPath);
|
|
99
|
+
if (resolved !== null)
|
|
100
|
+
return { id: resolved };
|
|
101
|
+
// Yarn returns null for built-ins (`fs`, `path`, …) —
|
|
102
|
+
// leave them external; Rolldown picks them up downstream.
|
|
103
|
+
return null;
|
|
104
|
+
}
|
|
105
|
+
catch (err) {
|
|
106
|
+
if (!isUndeclaredDependency(err))
|
|
107
|
+
throw err;
|
|
108
|
+
// Relay through caller's anchor first, then polyfill meta-packages.
|
|
109
|
+
try {
|
|
110
|
+
const resolved = pnpApi.resolveRequest(source, issuerPath);
|
|
111
|
+
if (resolved !== null)
|
|
112
|
+
return { id: resolved };
|
|
113
|
+
}
|
|
114
|
+
catch (relayErr) {
|
|
115
|
+
if (!isUndeclaredDependency(relayErr))
|
|
116
|
+
throw relayErr;
|
|
117
|
+
}
|
|
118
|
+
for (const relayIssuer of relayIssuers) {
|
|
119
|
+
try {
|
|
120
|
+
const resolved = pnpApi.resolveRequest(source, relayIssuer);
|
|
121
|
+
if (resolved !== null)
|
|
122
|
+
return { id: resolved };
|
|
123
|
+
}
|
|
124
|
+
catch (relayErr) {
|
|
125
|
+
if (!isUndeclaredDependency(relayErr))
|
|
126
|
+
throw relayErr;
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
// Fall through — bare aliases (e.g. `abort-controller`,
|
|
130
|
+
// `fetch/register/*`) are handled by the gjsify alias
|
|
131
|
+
// layer after this returns null; the re-resolved
|
|
132
|
+
// `@gjsify/*` path then comes back through this hook on
|
|
133
|
+
// the second try.
|
|
134
|
+
return null;
|
|
135
|
+
}
|
|
136
|
+
},
|
|
137
|
+
},
|
|
138
|
+
async load(id) {
|
|
139
|
+
// Only handle paths that look like PnP-resolved zip-resident or
|
|
140
|
+
// cache-resident files. For everything else, defer to the
|
|
141
|
+
// default loader (returning null = pass-through).
|
|
142
|
+
if (!id.includes('/.yarn/') && !id.includes('.zip/'))
|
|
143
|
+
return null;
|
|
144
|
+
try {
|
|
145
|
+
// Yarn's PnP runtime patches Node's `fs` module so reads
|
|
146
|
+
// against zip-resident virtual paths transparently work.
|
|
147
|
+
// Rolldown's Rust core does NOT participate in that patch;
|
|
148
|
+
// delegating to Node fs from here is what makes the read
|
|
149
|
+
// succeed.
|
|
150
|
+
const code = await readFile(id, 'utf8');
|
|
151
|
+
return { code };
|
|
152
|
+
}
|
|
153
|
+
catch (err) {
|
|
154
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
155
|
+
this.error(`gjsify-pnp: failed to read ${id}: ${message}`);
|
|
156
|
+
}
|
|
157
|
+
},
|
|
158
|
+
};
|
|
159
|
+
}
|
|
160
|
+
function isUndeclaredDependency(err) {
|
|
161
|
+
return typeof err === 'object'
|
|
162
|
+
&& err !== null
|
|
163
|
+
&& 'pnpCode' in err
|
|
164
|
+
&& err.pnpCode === 'UNDECLARED_DEPENDENCY';
|
|
165
|
+
}
|
package/package.json
ADDED
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@gjsify/rolldown-plugin-pnp",
|
|
3
|
+
"version": "0.3.14",
|
|
4
|
+
"description": "Yarn PnP resolver plugin for Rolldown / Rollup / Vite",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"main": "lib/index.js",
|
|
7
|
+
"module": "lib/index.js",
|
|
8
|
+
"types": "lib/index.d.ts",
|
|
9
|
+
"exports": {
|
|
10
|
+
".": {
|
|
11
|
+
"types": "./lib/index.d.ts",
|
|
12
|
+
"default": "./lib/index.js"
|
|
13
|
+
}
|
|
14
|
+
},
|
|
15
|
+
"scripts": {
|
|
16
|
+
"clear": "rm -rf lib tsconfig.tsbuildinfo || exit 0",
|
|
17
|
+
"check": "tsc --noEmit",
|
|
18
|
+
"build": "tsc"
|
|
19
|
+
},
|
|
20
|
+
"repository": {
|
|
21
|
+
"type": "git",
|
|
22
|
+
"url": "git+https://github.com/gjsify/gjsify.git"
|
|
23
|
+
},
|
|
24
|
+
"bugs": {
|
|
25
|
+
"url": "https://github.com/gjsify/gjsify/issues"
|
|
26
|
+
},
|
|
27
|
+
"homepage": "https://github.com/gjsify/gjsify/tree/main/packages/infra/rolldown-plugin-pnp#readme",
|
|
28
|
+
"keywords": [
|
|
29
|
+
"rolldown",
|
|
30
|
+
"rollup",
|
|
31
|
+
"vite",
|
|
32
|
+
"yarn",
|
|
33
|
+
"pnp",
|
|
34
|
+
"resolver"
|
|
35
|
+
],
|
|
36
|
+
"license": "MIT",
|
|
37
|
+
"peerDependencies": {
|
|
38
|
+
"rolldown": "^1.0.0-rc.18"
|
|
39
|
+
},
|
|
40
|
+
"peerDependenciesMeta": {
|
|
41
|
+
"rolldown": {
|
|
42
|
+
"optional": true
|
|
43
|
+
}
|
|
44
|
+
},
|
|
45
|
+
"devDependencies": {
|
|
46
|
+
"@types/node": "^25.6.0",
|
|
47
|
+
"rolldown": "^1.0.0-rc.18",
|
|
48
|
+
"typescript": "^6.0.3"
|
|
49
|
+
}
|
|
50
|
+
}
|
package/src/index.ts
ADDED
|
@@ -0,0 +1,180 @@
|
|
|
1
|
+
// Yarn PnP resolver plugin for Rolldown / Rollup / Vite.
|
|
2
|
+
//
|
|
3
|
+
// Replaces the esbuild-only `@yarnpkg/esbuild-plugin-pnp` wrapper that
|
|
4
|
+
// previously lived in `@gjsify/resolve-npm/lib/pnp-relay.mjs`. Same relay
|
|
5
|
+
// semantics, Rollup-shaped hooks instead of esbuild's `setup(build)`.
|
|
6
|
+
//
|
|
7
|
+
// The plugin behaves like a no-op when not running under Yarn PnP (no
|
|
8
|
+
// `.pnp.cjs` ancestor of cwd, or `module.findPnpApi` unavailable).
|
|
9
|
+
//
|
|
10
|
+
// Rolldown does NOT have esbuild's "first onLoad wins" rule — the path
|
|
11
|
+
// rewriter that used to run inside this plugin's onLoad now lives as an
|
|
12
|
+
// independent `transform(code, id)` plugin. See
|
|
13
|
+
// `@gjsify/rolldown-plugin-gjsify/src/import-meta-url.ts`.
|
|
14
|
+
|
|
15
|
+
import { createRequire } from 'node:module';
|
|
16
|
+
import { fileURLToPath } from 'node:url';
|
|
17
|
+
import { dirname, join } from 'node:path';
|
|
18
|
+
import { existsSync } from 'node:fs';
|
|
19
|
+
import { readFile } from 'node:fs/promises';
|
|
20
|
+
import type { Plugin } from 'rolldown';
|
|
21
|
+
|
|
22
|
+
export interface PnpPluginOptions {
|
|
23
|
+
/**
|
|
24
|
+
* `import.meta.url` of the caller. Used to anchor relay-issuer resolution
|
|
25
|
+
* on the caller's installation rather than this package's own location.
|
|
26
|
+
* Defaults to this module's own URL.
|
|
27
|
+
*/
|
|
28
|
+
issuerUrl?: string;
|
|
29
|
+
/**
|
|
30
|
+
* Packages whose `package.json` paths serve as fallback relay issuers
|
|
31
|
+
* when a direct `pnpApi.resolveRequest` fails with `UNDECLARED_DEPENDENCY`.
|
|
32
|
+
* Defaults to gjsify's polyfill meta-packages.
|
|
33
|
+
*/
|
|
34
|
+
relayPackages?: string[];
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
/** PnP API exposed by Yarn at runtime. Subset we actually use. */
|
|
38
|
+
interface PnpApi {
|
|
39
|
+
resolveRequest(specifier: string, issuer: string): string | null;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
/** Walk up from dir until .pnp.cjs is found; return its directory or null. */
|
|
43
|
+
function findPnpRoot(dir: string): string | null {
|
|
44
|
+
let current = dir;
|
|
45
|
+
while (true) {
|
|
46
|
+
if (existsSync(join(current, '.pnp.cjs'))) return current;
|
|
47
|
+
const parent = dirname(current);
|
|
48
|
+
if (parent === current) return null;
|
|
49
|
+
current = parent;
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
/** Try to load the runtime PnP API for the cwd's PnP installation. */
|
|
54
|
+
async function loadPnpApi(): Promise<PnpApi | null> {
|
|
55
|
+
try {
|
|
56
|
+
// `pnpapi` is a virtual CJS module Yarn injects when running under PnP.
|
|
57
|
+
// `await import()` of a CJS module yields `{ default, "module.exports" }`,
|
|
58
|
+
// not the exports object directly — unwrap `.default`.
|
|
59
|
+
// @ts-expect-error pnpapi has no npm package
|
|
60
|
+
const mod = await import('pnpapi');
|
|
61
|
+
return (mod.default ?? mod) as PnpApi;
|
|
62
|
+
} catch {
|
|
63
|
+
return null;
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
/**
|
|
68
|
+
* Build the gjsify-flavoured PnP relay plugin for Rolldown.
|
|
69
|
+
*
|
|
70
|
+
* Returns null when not running under Yarn PnP. Callers can spread this into
|
|
71
|
+
* a plugin array and Rolldown will skip the null entry.
|
|
72
|
+
*/
|
|
73
|
+
export async function pnpPlugin(opts: PnpPluginOptions = {}): Promise<Plugin | null> {
|
|
74
|
+
const issuerUrl = opts.issuerUrl ?? import.meta.url;
|
|
75
|
+
if (!findPnpRoot(process.cwd())) return null;
|
|
76
|
+
|
|
77
|
+
const pnpApi = await loadPnpApi();
|
|
78
|
+
if (pnpApi === null) return null;
|
|
79
|
+
|
|
80
|
+
// Relay issuers — anchor resolution on whoever called us first, then fall
|
|
81
|
+
// back to the polyfill meta-packages (which depend on every individual
|
|
82
|
+
// polyfill, so transitive `@gjsify/*` lookups always reach them).
|
|
83
|
+
const issuerPath = fileURLToPath(issuerUrl);
|
|
84
|
+
const requireFromIssuer = createRequire(issuerPath);
|
|
85
|
+
const relayPackages = opts.relayPackages ?? ['@gjsify/node-polyfills', '@gjsify/web-polyfills'];
|
|
86
|
+
const relayIssuers: string[] = [];
|
|
87
|
+
for (const pkg of relayPackages) {
|
|
88
|
+
try {
|
|
89
|
+
relayIssuers.push(requireFromIssuer.resolve(`${pkg}/package.json`));
|
|
90
|
+
} catch {
|
|
91
|
+
// not in dep tree — relay won't cover it
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
return {
|
|
96
|
+
name: 'gjsify-pnp',
|
|
97
|
+
|
|
98
|
+
// Per-hook `order: 'pre'` runs us before Rolldown's default resolver
|
|
99
|
+
// so we own resolution for every bare specifier under PnP. Rolldown
|
|
100
|
+
// uses Rollup's per-hook ordering (not Vite's top-level `enforce`).
|
|
101
|
+
resolveId: {
|
|
102
|
+
order: 'pre' as const,
|
|
103
|
+
async handler(source, importer) {
|
|
104
|
+
// Skip relative / absolute paths — let Rolldown handle them.
|
|
105
|
+
if (source.startsWith('.') || source.startsWith('/')) return null;
|
|
106
|
+
// GJS gi:// imports are externalised by the orchestrator's
|
|
107
|
+
// `external` predicate; we must not run them through PnP
|
|
108
|
+
// (which would error with `UNDECLARED_DEPENDENCY` because
|
|
109
|
+
// `@girs/*` packages don't list `gi:` as a dep).
|
|
110
|
+
if (source.startsWith('gi://')) return { id: source, external: true };
|
|
111
|
+
if (!importer) return null;
|
|
112
|
+
|
|
113
|
+
// Importer may be a file URL string or an absolute path.
|
|
114
|
+
const importerPath = importer.startsWith('file://')
|
|
115
|
+
? fileURLToPath(importer)
|
|
116
|
+
: importer;
|
|
117
|
+
|
|
118
|
+
// Fast path: resolve from the importer's own context.
|
|
119
|
+
try {
|
|
120
|
+
const resolved = pnpApi.resolveRequest(source, importerPath);
|
|
121
|
+
if (resolved !== null) return { id: resolved };
|
|
122
|
+
// Yarn returns null for built-ins (`fs`, `path`, …) —
|
|
123
|
+
// leave them external; Rolldown picks them up downstream.
|
|
124
|
+
return null;
|
|
125
|
+
} catch (err) {
|
|
126
|
+
if (!isUndeclaredDependency(err)) throw err;
|
|
127
|
+
|
|
128
|
+
// Relay through caller's anchor first, then polyfill meta-packages.
|
|
129
|
+
try {
|
|
130
|
+
const resolved = pnpApi.resolveRequest(source, issuerPath);
|
|
131
|
+
if (resolved !== null) return { id: resolved };
|
|
132
|
+
} catch (relayErr) {
|
|
133
|
+
if (!isUndeclaredDependency(relayErr)) throw relayErr;
|
|
134
|
+
}
|
|
135
|
+
for (const relayIssuer of relayIssuers) {
|
|
136
|
+
try {
|
|
137
|
+
const resolved = pnpApi.resolveRequest(source, relayIssuer);
|
|
138
|
+
if (resolved !== null) return { id: resolved };
|
|
139
|
+
} catch (relayErr) {
|
|
140
|
+
if (!isUndeclaredDependency(relayErr)) throw relayErr;
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
// Fall through — bare aliases (e.g. `abort-controller`,
|
|
144
|
+
// `fetch/register/*`) are handled by the gjsify alias
|
|
145
|
+
// layer after this returns null; the re-resolved
|
|
146
|
+
// `@gjsify/*` path then comes back through this hook on
|
|
147
|
+
// the second try.
|
|
148
|
+
return null;
|
|
149
|
+
}
|
|
150
|
+
},
|
|
151
|
+
},
|
|
152
|
+
|
|
153
|
+
async load(id) {
|
|
154
|
+
// Only handle paths that look like PnP-resolved zip-resident or
|
|
155
|
+
// cache-resident files. For everything else, defer to the
|
|
156
|
+
// default loader (returning null = pass-through).
|
|
157
|
+
if (!id.includes('/.yarn/') && !id.includes('.zip/')) return null;
|
|
158
|
+
|
|
159
|
+
try {
|
|
160
|
+
// Yarn's PnP runtime patches Node's `fs` module so reads
|
|
161
|
+
// against zip-resident virtual paths transparently work.
|
|
162
|
+
// Rolldown's Rust core does NOT participate in that patch;
|
|
163
|
+
// delegating to Node fs from here is what makes the read
|
|
164
|
+
// succeed.
|
|
165
|
+
const code = await readFile(id, 'utf8');
|
|
166
|
+
return { code };
|
|
167
|
+
} catch (err) {
|
|
168
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
169
|
+
this.error(`gjsify-pnp: failed to read ${id}: ${message}`);
|
|
170
|
+
}
|
|
171
|
+
},
|
|
172
|
+
};
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
function isUndeclaredDependency(err: unknown): boolean {
|
|
176
|
+
return typeof err === 'object'
|
|
177
|
+
&& err !== null
|
|
178
|
+
&& 'pnpCode' in err
|
|
179
|
+
&& (err as { pnpCode?: unknown }).pnpCode === 'UNDECLARED_DEPENDENCY';
|
|
180
|
+
}
|
package/tsconfig.json
ADDED
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
{
|
|
2
|
+
"compilerOptions": {
|
|
3
|
+
"rootDir": "src",
|
|
4
|
+
"outDir": "lib",
|
|
5
|
+
"declaration": true,
|
|
6
|
+
"target": "ESNext",
|
|
7
|
+
"module": "ESNext",
|
|
8
|
+
"moduleResolution": "bundler",
|
|
9
|
+
"strict": true,
|
|
10
|
+
"esModuleInterop": true,
|
|
11
|
+
"skipLibCheck": true,
|
|
12
|
+
"types": ["node"]
|
|
13
|
+
},
|
|
14
|
+
"include": ["src/**/*"]
|
|
15
|
+
}
|