1tube 0.1.21 → 0.1.23

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.
@@ -1,159 +0,0 @@
1
- /**
2
- * Deno backend HMR snapshotting.
3
- *
4
- * Deno's in-process module cache is keyed by module URL and cannot be
5
- * invalidated. Importing `index.ts?v=...` refreshes only the entrypoint;
6
- * relative children such as `./types.ts` keep their old file URLs. HMR reloads
7
- * therefore import from a fresh snapshot path per generation, which gives the
8
- * entire relative dependency graph new module identities.
9
- */
10
-
11
- import { basename, dirname, join, resolve as resolvePath } from "node:path";
12
-
13
- const DEFAULT_KEEP_GENERATIONS = 3;
14
-
15
- export type SnapshotChanged = ReadonlySet<string> | "all";
16
-
17
- export interface DenoHmrSnapshotOptions {
18
- /** Real functions directory, e.g. `supabase/functions`. */
19
- functionsDir: string;
20
- /** Changed function names, or `"all"` for shared/full reloads. */
21
- changed: SnapshotChanged;
22
- /** Monotonic generation number owned by the caller. */
23
- generation: number;
24
- /** Cache root; defaults to `<cwd>/.1tube-cache/deno-hmr`. */
25
- cacheDir?: string;
26
- /** Number of newest generations to keep on disk. */
27
- keepGenerations?: number;
28
- }
29
-
30
- export interface DenoHmrSnapshot {
31
- /** Generation root, e.g. `.1tube-cache/deno-hmr/gen-4`. */
32
- root: string;
33
- /** Snapshot functions root passed to the discovery importer. */
34
- functionsDir: string;
35
- /** Names of top-level directories materialized into this snapshot. */
36
- copiedDirs: string[];
37
- }
38
-
39
- function defaultCacheDir(): string {
40
- return join(Deno.cwd(), ".1tube-cache", "deno-hmr");
41
- }
42
-
43
- function isSharedDir(name: string): boolean {
44
- return name.startsWith("_") || name.endsWith("_shared");
45
- }
46
-
47
- async function copyEntry(src: string, dest: string): Promise<void> {
48
- const info = await Deno.lstat(src);
49
-
50
- if (info.isSymlink) {
51
- const target = await Deno.readLink(src);
52
- try {
53
- await Deno.symlink(target, dest);
54
- return;
55
- } catch {
56
- // Windows often disallows symlink creation for normal users. Fall
57
- // through to copying the resolved target so the snapshot remains usable.
58
- const stat = await Deno.stat(src);
59
- if (stat.isDirectory) {
60
- await copyDirectory(src, dest);
61
- } else {
62
- await Deno.copyFile(src, dest);
63
- }
64
- return;
65
- }
66
- }
67
-
68
- if (info.isDirectory) {
69
- await copyDirectory(src, dest);
70
- return;
71
- }
72
-
73
- if (info.isFile) {
74
- await Deno.mkdir(dirname(dest), { recursive: true });
75
- await Deno.copyFile(src, dest);
76
- }
77
- }
78
-
79
- async function copyDirectory(src: string, dest: string): Promise<void> {
80
- await Deno.mkdir(dest, { recursive: true });
81
- for await (const entry of Deno.readDir(src)) {
82
- await copyEntry(join(src, entry.name), join(dest, entry.name));
83
- }
84
- }
85
-
86
- async function existingTopLevelDirs(functionsDir: string): Promise<string[]> {
87
- const dirs: string[] = [];
88
- for await (const entry of Deno.readDir(functionsDir)) {
89
- if (entry.isDirectory) dirs.push(entry.name);
90
- }
91
- dirs.sort();
92
- return dirs;
93
- }
94
-
95
- async function pruneGenerations(
96
- cacheDir: string,
97
- keepGenerations: number,
98
- ): Promise<void> {
99
- const generations: Array<{ name: string; n: number }> = [];
100
- try {
101
- for await (const entry of Deno.readDir(cacheDir)) {
102
- if (!entry.isDirectory) continue;
103
- const match = /^gen-(\d+)$/.exec(entry.name);
104
- if (match) generations.push({ name: entry.name, n: Number(match[1]) });
105
- }
106
- } catch (err) {
107
- if (err instanceof Deno.errors.NotFound) return;
108
- throw err;
109
- }
110
-
111
- generations.sort((a, b) => b.n - a.n);
112
- for (const old of generations.slice(Math.max(1, keepGenerations))) {
113
- await Deno.remove(join(cacheDir, old.name), { recursive: true }).catch(
114
- () => {},
115
- );
116
- }
117
- }
118
-
119
- export async function createDenoHmrSnapshot(
120
- options: DenoHmrSnapshotOptions,
121
- ): Promise<DenoHmrSnapshot> {
122
- const sourceRoot = await Deno.realPath(options.functionsDir);
123
- const cacheDir = resolvePath(options.cacheDir ?? defaultCacheDir());
124
- const keepGenerations = Math.max(
125
- 1,
126
- options.keepGenerations ?? DEFAULT_KEEP_GENERATIONS,
127
- );
128
- const root = join(cacheDir, `gen-${options.generation}`);
129
- const snapshotFunctionsDir = join(root, basename(sourceRoot));
130
-
131
- await Deno.remove(root, { recursive: true }).catch((err) => {
132
- if (!(err instanceof Deno.errors.NotFound)) throw err;
133
- });
134
- await Deno.mkdir(snapshotFunctionsDir, { recursive: true });
135
-
136
- const topLevelDirs = await existingTopLevelDirs(sourceRoot);
137
- const selected = (() => {
138
- if (options.changed === "all") return topLevelDirs;
139
- const changed = options.changed;
140
- return topLevelDirs.filter((name) =>
141
- isSharedDir(name) || changed.has(name)
142
- );
143
- })();
144
-
145
- for (const name of selected) {
146
- await copyDirectory(
147
- join(sourceRoot, name),
148
- join(snapshotFunctionsDir, name),
149
- );
150
- }
151
-
152
- await pruneGenerations(cacheDir, keepGenerations);
153
-
154
- return {
155
- root,
156
- functionsDir: snapshotFunctionsDir,
157
- copiedDirs: selected,
158
- };
159
- }