@gjsify/resolve-npm 0.3.12 → 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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@gjsify/resolve-npm",
3
- "version": "0.3.12",
3
+ "version": "0.3.14",
4
4
  "description": "Resolve NPM package aliases",
5
5
  "type": "module",
6
6
  "main": "lib/index.mjs",
@@ -12,10 +12,6 @@
12
12
  "default": "./lib/index.mjs"
13
13
  },
14
14
  "./globals-map": "./lib/globals-map.mjs",
15
- "./pnp-relay": {
16
- "types": "./lib/pnp-relay.d.ts",
17
- "default": "./lib/pnp-relay.mjs"
18
- },
19
15
  "./package.json": "./package.json"
20
16
  },
21
17
  "scripts": {
@@ -29,8 +25,5 @@
29
25
  "node",
30
26
  "npm",
31
27
  "alias"
32
- ],
33
- "dependencies": {
34
- "@yarnpkg/esbuild-plugin-pnp": "^3.0.0-rc.15"
35
- }
28
+ ]
36
29
  }
@@ -1,32 +0,0 @@
1
- import type { Plugin, PluginBuild, OnLoadResult } from 'esbuild';
2
-
3
- export type TransformContents = (
4
- args: { path: string; namespace?: string },
5
- contents: string,
6
- ) => Promise<OnLoadResult | undefined> | OnLoadResult | undefined;
7
-
8
- export interface GetPnpPluginOptions {
9
- /**
10
- * Called once per esbuild `setup(build)` invocation. Returns the actual
11
- * per-file transformer that runs after the file is read but before
12
- * returning to esbuild. The factory pattern gives the transformer access
13
- * to `build.initialOptions` (e.g. for computing bundle-relative paths)
14
- * which isn't available at plugin-construction time.
15
- */
16
- transformContentsFactory?: (build: PluginBuild) => TransformContents;
17
-
18
- /**
19
- * `import.meta.url` of the caller. Used to anchor relay issuer resolution
20
- * on the caller's installation rather than `@gjsify/resolve-npm`'s.
21
- * Defaults to this module's own URL.
22
- */
23
- issuerUrl?: string;
24
- }
25
-
26
- /**
27
- * Build the gjsify-flavoured PnP plugin.
28
- *
29
- * Returns null when not running under Yarn PnP (no `.pnp.cjs` ancestor of cwd
30
- * or `@yarnpkg/esbuild-plugin-pnp` not installed).
31
- */
32
- export function getPnpPlugin(opts?: GetPnpPluginOptions): Promise<Plugin | null>;
package/lib/pnp-relay.mjs DELETED
@@ -1,181 +0,0 @@
1
- // PnP relay for @gjsify/* polyfills.
2
- //
3
- // Yarn PnP throws `UNDECLARED_DEPENDENCY` when esbuild's resolver asks for a
4
- // package that exists in the install graph but isn't a direct dep of the
5
- // importer. For external consumers of @gjsify/cli (e.g. ts-for-gir) this means
6
- // every transitive `@gjsify/<polyfill>` reached via the rewriter would have to
7
- // be declared as a direct devDep — defeating the point of having
8
- // `@gjsify/{node,web}-polyfills` as meta-packages.
9
- //
10
- // `getPnpPlugin()` returns a Plugin that catches `UNDECLARED_DEPENDENCY` errors
11
- // and re-resolves them through two relay issuers:
12
- // 1. The caller's own location (covers `@gjsify/*` that are direct deps of
13
- // cli's own deps — fast first-try)
14
- // 2. @gjsify/{node,web}-polyfills' package.json paths (covers everything
15
- // else, since those meta-packages depend on every individual polyfill)
16
- //
17
- // The plugin also accepts a `transformContents` factory: given the
18
- // `PluginBuild` it returns a per-build transformer that runs after the file
19
- // is read. esbuild stops at the first matching onLoad, so the rewriter MUST
20
- // run from inside this onLoad — not be registered as a separate onLoad
21
- // afterwards (that's the F5 bug).
22
-
23
- import { createRequire } from 'node:module';
24
- import { fileURLToPath } from 'node:url';
25
- import { dirname, join } from 'node:path';
26
- import { existsSync } from 'node:fs';
27
- import { readFile } from 'node:fs/promises';
28
-
29
- /** Walk up from dir until .pnp.cjs is found; return its directory or null. */
30
- function findPnpRoot(dir) {
31
- let current = dir;
32
- // eslint-disable-next-line no-constant-condition
33
- while (true) {
34
- if (existsSync(join(current, '.pnp.cjs'))) return current;
35
- const parent = dirname(current);
36
- if (parent === current) return null;
37
- current = parent;
38
- }
39
- }
40
-
41
- /**
42
- * @typedef {(args: { path: string, namespace?: string }, contents: string) =>
43
- * Promise<{contents: string, loader?: string, resolveDir?: string} | undefined>
44
- * | {contents: string, loader?: string, resolveDir?: string} | undefined} TransformContents
45
- *
46
- * @typedef {object} GetPnpPluginOptions
47
- * @property {(build: import('esbuild').PluginBuild) => TransformContents} [transformContentsFactory]
48
- * Optional: called once per esbuild `setup(build)` invocation. Returns the
49
- * actual per-file transformer that runs after the file is read but before
50
- * returning to esbuild. The factory pattern gives the transformer access to
51
- * `build.initialOptions` (e.g. for computing bundle-relative paths) which
52
- * isn't available at plugin-construction time.
53
- *
54
- * @property {string} [issuerUrl]
55
- * `import.meta.url` of the caller. Used to anchor relay issuer resolution
56
- * on the caller's installation rather than `@gjsify/resolve-npm`'s.
57
- * Defaults to this module's own URL.
58
- */
59
-
60
- /**
61
- * Build the gjsify-flavoured PnP plugin.
62
- *
63
- * Returns null when not running under Yarn PnP (no `.pnp.cjs` ancestor of cwd
64
- * or `@yarnpkg/esbuild-plugin-pnp` not installed).
65
- *
66
- * @param {GetPnpPluginOptions} [opts]
67
- * @returns {Promise<import('esbuild').Plugin | null>}
68
- */
69
- export async function getPnpPlugin(opts = {}) {
70
- const { transformContentsFactory, issuerUrl = import.meta.url } = opts;
71
- if (!findPnpRoot(process.cwd())) return null;
72
-
73
- let pnpPlugin;
74
- try {
75
- ({ pnpPlugin } = await import('@yarnpkg/esbuild-plugin-pnp'));
76
- } catch {
77
- return null;
78
- }
79
-
80
- // Anchor relay-issuer resolution on whoever called us. For external
81
- // consumers this is @gjsify/cli's own file path; node-polyfills + web-polyfills
82
- // are direct deps of @gjsify/cli, so requireFromIssuer.resolve() reaches them.
83
- const issuerPath = fileURLToPath(issuerUrl);
84
- const requireFromIssuer = createRequire(issuerPath);
85
- const relayIssuers = [];
86
- for (const pkg of ['@gjsify/node-polyfills', '@gjsify/web-polyfills']) {
87
- try {
88
- relayIssuers.push(requireFromIssuer.resolve(`${pkg}/package.json`));
89
- } catch {
90
- // polyfills package not in dep tree — relay won't cover it
91
- }
92
- }
93
-
94
- // pnpapi is a virtual CJS module injected by Yarn PnP. `await import()` of a
95
- // CJS module yields the ESM namespace `{ default, "module.exports" }`, NOT
96
- // the exports object — so unconditional `.resolveRequest` access is
97
- // `undefined`. Unwrap `.default` (the CJS exports) before use.
98
- let pnpApi = null;
99
- try {
100
- // eslint-disable-next-line @typescript-eslint/ban-ts-comment
101
- // @ts-expect-error pnpapi has no npm package
102
- const mod = await import('pnpapi');
103
- pnpApi = mod.default ?? mod;
104
- } catch {
105
- // Not in a PnP runtime (shouldn't happen since findPnpRoot passed).
106
- }
107
-
108
- return {
109
- name: '@gjsify/pnp-relay',
110
- async setup(build) {
111
- const transformContents = transformContentsFactory
112
- ? transformContentsFactory(build)
113
- : null;
114
-
115
- const inner = pnpPlugin({
116
- onResolve: async (args, { resolvedPath, error, watchFiles }) => {
117
- if (resolvedPath !== null) {
118
- return { namespace: 'pnp', path: resolvedPath, watchFiles };
119
- }
120
- if (error?.pnpCode === 'UNDECLARED_DEPENDENCY') {
121
- if (pnpApi !== null) {
122
- // Fast first-try: caller's own context.
123
- try {
124
- const rp = pnpApi.resolveRequest(args.path, issuerPath);
125
- if (rp !== null) return { namespace: 'pnp', path: rp, watchFiles };
126
- } catch { /* fall through to relay */ }
127
- // Two-hop relay: resolve from {node,web}-polyfills context.
128
- for (const relayIssuer of relayIssuers) {
129
- try {
130
- const rp = pnpApi.resolveRequest(args.path, relayIssuer);
131
- if (rp !== null) return { namespace: 'pnp', path: rp, watchFiles };
132
- } catch { /* try next issuer */ }
133
- }
134
- }
135
- // Fall through — bare aliases (`abort-controller`, `fetch/register/*`)
136
- // are handled by the gjsify alias plugin after this returns null;
137
- // the re-resolved `@gjsify/*` path then comes back through this hook.
138
- return null;
139
- }
140
- return {
141
- external: true,
142
- errors: error ? [{ text: error.message }] : [],
143
- watchFiles,
144
- };
145
- },
146
- onLoad: async (args) => {
147
- // @yarnpkg/esbuild-plugin-pnp invokes the user-provided onLoad
148
- // with just `args` (same shape as esbuild's standard onLoad —
149
- // not the (args, ctx) tuple of its onResolve). args.path is
150
- // already a resolved fs path; we only need to read it.
151
- let contents;
152
- try {
153
- contents = await readFile(args.path, 'utf8');
154
- } catch (readErr) {
155
- return {
156
- errors: [{ text: `gjsify pnp-relay: failed to read ${args.path}: ${readErr.message}` }],
157
- };
158
- }
159
-
160
- if (transformContents) {
161
- const transformed = await transformContents(
162
- { path: args.path, namespace: 'pnp' },
163
- contents,
164
- );
165
- if (transformed !== undefined) {
166
- return transformed;
167
- }
168
- }
169
-
170
- // `loader: 'default'` lets esbuild infer from the path extension.
171
- return {
172
- contents,
173
- loader: 'default',
174
- resolveDir: dirname(args.path),
175
- };
176
- },
177
- });
178
- await inner.setup(build);
179
- },
180
- };
181
- }