1tube 0.1.38 → 0.1.39

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": "1tube",
3
- "version": "0.1.38",
3
+ "version": "0.1.39",
4
4
  "private": false,
5
5
  "description": "Self-hosted Supabase Edge Functions gateway for Deno, plus an ESLint plugin for consumers",
6
6
  "license": "MIT",
@@ -19,7 +19,12 @@
19
19
 
20
20
  import * as esbuild from "npm:esbuild@^0.28.1";
21
21
  import type { BundleProfile } from "../../bundler/profile.ts";
22
- import { NODE_BUILTIN_MODULES, VERCEL_BANNER, VERCEL_FOOTER } from "./wrapper.ts";
22
+ import {
23
+ NODE_BUILTIN_MODULES,
24
+ VERCEL_BANNER,
25
+ VERCEL_FOOTER,
26
+ VERCEL_REQUIRE_SHIM,
27
+ } from "./wrapper.ts";
23
28
 
24
29
  const NODE_BUILTIN_SET = new Set<string>(NODE_BUILTIN_MODULES);
25
30
 
@@ -144,6 +149,7 @@ export const VERCEL_PROFILE: BundleProfile = {
144
149
  mainFields: ["module", "main"],
145
150
  banner: VERCEL_BANNER,
146
151
  footer: VERCEL_FOOTER,
152
+ outputPreamble: VERCEL_REQUIRE_SHIM,
147
153
  resolverPlugins: [
148
154
  // node-builtins first so `crypto`/`stream`/… short-circuit to `node:` and
149
155
  // never reach the optional-dependency probe.
@@ -87,6 +87,30 @@ export const NODE_BUILTIN_MODULES: readonly string[] = [
87
87
  "zlib",
88
88
  ];
89
89
 
90
+ /**
91
+ * Output preamble prepended to EVERY emitted file — entry points and the
92
+ * code-split chunks alike (see `BundleProfile.outputPreamble`).
93
+ *
94
+ * Why this can't live in the banner: esbuild only injects `banner` into entry
95
+ * points. When CJS dependencies `require()` at module-init time (e.g.
96
+ * `google-auth-library` → `require("node:child_process")`), esbuild hoists its
97
+ * `__require` helper into a *shared chunk*. That helper falls back to a real
98
+ * `require` only `if (typeof require !== "undefined")` — and an ESM module has
99
+ * no `require` in scope, so the chunk throws "Dynamic require of … is not
100
+ * supported" at runtime on Vercel.
101
+ *
102
+ * Defining a module-scoped `require` backed by `node:module`'s `createRequire`
103
+ * gives esbuild's `__require` a working delegate in whichever chunk it lands.
104
+ * The per-file minify pass renames our `require` (and the helper's `typeof
105
+ * require` checks) consistently, collapsing `__require` to the real delegate.
106
+ * The shim is kept in every file (minify can't prove `createRequire()` is
107
+ * side-effect-free) — a few harmless bytes where unused. `import.meta.url` is
108
+ * always valid because every output is ESM.
109
+ */
110
+ export const VERCEL_REQUIRE_SHIM =
111
+ `import { createRequire as __1tubeCreateRequire } from "node:module";
112
+ var require = __1tubeCreateRequire(import.meta.url);`;
113
+
90
114
  /**
91
115
  * Banner injected at the top of every Vercel bundle. Runs before the user
92
116
  * entrypoint import so top-level `Deno.env.get(...)` / `serve(...)` calls find
@@ -358,11 +358,19 @@ async function minifyOutputFile(
358
358
  path: string,
359
359
  sourcemap: boolean | "linked" | "inline",
360
360
  target: string | string[],
361
+ preamble?: string,
361
362
  ): Promise<{
362
363
  originalByteLength: number;
363
364
  byteLength: number;
364
365
  }> {
365
- const original = await Deno.readTextFile(path);
366
+ const raw = await Deno.readTextFile(path);
367
+ // Prepend the profile preamble (e.g. the Node createRequire shim) before the
368
+ // minify transform so it reaches the shared chunks where esbuild hoists
369
+ // helpers like `__require`. esbuild's own `banner` can't do this — it only
370
+ // injects into entry points, never chunks. The transform keeps the preamble
371
+ // in every file (it can't prove the initializer is side-effect-free), which
372
+ // is harmless where unused.
373
+ const original = preamble ? `${preamble}\n${raw}` : raw;
366
374
  const originalByteLength = new TextEncoder().encode(original).byteLength;
367
375
  const result = await esbuild.transform(original, {
368
376
  loader: "js",
@@ -616,7 +624,12 @@ export async function bundleAllChunked(
616
624
  emittedJs.map(async (file) => {
617
625
  minifiedSizesByFile.set(
618
626
  file,
619
- await minifyOutputFile(join(opts.outDir, file), sourcemap, target),
627
+ await minifyOutputFile(
628
+ join(opts.outDir, file),
629
+ sourcemap,
630
+ target,
631
+ profile.outputPreamble,
632
+ ),
620
633
  );
621
634
  }),
622
635
  );
@@ -725,7 +738,12 @@ export async function bundleSharedModule(opts: {
725
738
  mainFields: [...profile.mainFields],
726
739
  });
727
740
  await patchOutputFile(outfile);
728
- const sizes = await minifyOutputFile(outfile, false, target);
741
+ const sizes = await minifyOutputFile(
742
+ outfile,
743
+ false,
744
+ target,
745
+ profile.outputPreamble,
746
+ );
729
747
  return {
730
748
  id: opts.module.id,
731
749
  bundlePath: outfile,
@@ -56,4 +56,22 @@ export interface BundleProfile {
56
56
  * target). Most profiles need none.
57
57
  */
58
58
  readonly resolverPlugins?: readonly esbuild.Plugin[];
59
+ /**
60
+ * Source prepended to EVERY emitted output file (entry points AND
61
+ * code-split chunks) before the final minify pass. Unlike {@link banner},
62
+ * which esbuild only injects into entry points, this reaches chunks too.
63
+ *
64
+ * Needed when a runtime shim must be present in the chunk that esbuild
65
+ * happens to hoist a helper into — e.g. the Node target injects a
66
+ * `createRequire(import.meta.url)`-backed `require` so esbuild's `__require`
67
+ * shim (emitted into a shared chunk for CJS deps that `require()` at module
68
+ * init) works instead of throwing "Dynamic require of … is not supported".
69
+ *
70
+ * It is prepended to every file (the per-file minify pass keeps it even where
71
+ * unused, since it can't prove the initializer is side-effect-free — a few
72
+ * harmless bytes per chunk). In the chunk that defines the helper, esbuild's
73
+ * minifier rewrites the helper's `typeof require` checks to the injected
74
+ * binding, so the shim wires up automatically.
75
+ */
76
+ readonly outputPreamble?: string;
59
77
  }