houdini 2.0.7 → 2.0.8
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/build/cmd/init.js +2 -2
- package/build/lib/codegen.js +10 -2
- package/build/package.json +1 -1
- package/build/runtime/cache/index.d.ts +1 -0
- package/build/runtime/cache/index.js +16 -0
- package/build/runtime/cache/subscription.d.ts +3 -0
- package/build/runtime/cache/subscription.js +23 -0
- package/build/runtime/types.d.ts +1 -0
- package/build/vite/hmr.d.ts +0 -2
- package/build/vite/hmr.js +24 -11
- package/build/vite/houdini.js +2 -0
- package/build/vite/index.d.ts +2 -1
- package/build/vite/index.js +3 -1
- package/build/vite/schema.d.ts +2 -2
- package/build/vite/schema.js +4 -3
- package/build/vite/session.d.ts +30 -0
- package/build/vite/session.js +29 -0
- package/package.json +2 -2
package/build/cmd/init.js
CHANGED
|
@@ -472,12 +472,12 @@ async function packageJSON(targetPath, frameworkInfo) {
|
|
|
472
472
|
}
|
|
473
473
|
packageJSON2.devDependencies = {
|
|
474
474
|
...packageJSON2.devDependencies,
|
|
475
|
-
houdini: "^2.0.
|
|
475
|
+
houdini: "^2.0.8"
|
|
476
476
|
};
|
|
477
477
|
if (frameworkInfo.framework === "svelte" || frameworkInfo.framework === "kit") {
|
|
478
478
|
packageJSON2.devDependencies = {
|
|
479
479
|
...packageJSON2.devDependencies,
|
|
480
|
-
"houdini-svelte": "^3.0.
|
|
480
|
+
"houdini-svelte": "^3.0.4"
|
|
481
481
|
};
|
|
482
482
|
} else {
|
|
483
483
|
throw new Error(`Unmanaged framework: "${JSON.stringify(frameworkInfo)}"`);
|
package/build/lib/codegen.js
CHANGED
|
@@ -196,8 +196,16 @@ async function codegen_setup(config, mode, db, db_file) {
|
|
|
196
196
|
};
|
|
197
197
|
spec_results[name] = spec;
|
|
198
198
|
_db.run(
|
|
199
|
-
`INSERT
|
|
200
|
-
VALUES (?, ?, ?, ?, ?, ?, ?, ?)
|
|
199
|
+
`INSERT INTO plugins (name, hooks, port, plugin_order, include_runtime, include_static_runtime, config_module, client_plugins)
|
|
200
|
+
VALUES (?, ?, ?, ?, ?, ?, ?, ?)
|
|
201
|
+
ON CONFLICT(name) DO UPDATE SET
|
|
202
|
+
hooks = excluded.hooks,
|
|
203
|
+
port = excluded.port,
|
|
204
|
+
plugin_order = excluded.plugin_order,
|
|
205
|
+
include_runtime = excluded.include_runtime,
|
|
206
|
+
include_static_runtime = excluded.include_static_runtime,
|
|
207
|
+
config_module = excluded.config_module,
|
|
208
|
+
client_plugins = excluded.client_plugins`,
|
|
201
209
|
[
|
|
202
210
|
spec.name,
|
|
203
211
|
JSON.stringify([...spec.hooks]),
|
package/build/package.json
CHANGED
|
@@ -153,6 +153,22 @@ class Cache {
|
|
|
153
153
|
}
|
|
154
154
|
}
|
|
155
155
|
}
|
|
156
|
+
// ask every active query document to refetch itself.
|
|
157
|
+
// this is used when global request context changes (for example, the
|
|
158
|
+
// SvelteKit session) and any query might resolve differently even if its
|
|
159
|
+
// cached records did not change. non-query artifacts are skipped because
|
|
160
|
+
// only queries can be refetched through this cache notification path.
|
|
161
|
+
refreshAll(session) {
|
|
162
|
+
const message = session === void 0 ? { kind: "refetch" } : { kind: "refetch", session };
|
|
163
|
+
for (const [spec] of this._internal_unstable.subscriptions.all({
|
|
164
|
+
includeMaskedParents: true
|
|
165
|
+
})) {
|
|
166
|
+
if (spec.kind !== ArtifactKind.Query) {
|
|
167
|
+
continue;
|
|
168
|
+
}
|
|
169
|
+
spec.onMessage(message);
|
|
170
|
+
}
|
|
171
|
+
}
|
|
156
172
|
markRecordStale(id, options) {
|
|
157
173
|
if (options.field) {
|
|
158
174
|
const key = computeKey({ field: options.field, args: options.when ?? {} });
|
|
@@ -49,6 +49,9 @@ export declare class InMemorySubscriptions {
|
|
|
49
49
|
getAll(id: string, { includeMaskedParents }?: {
|
|
50
50
|
includeMaskedParents?: boolean;
|
|
51
51
|
}): FieldSelection[];
|
|
52
|
+
all({ includeMaskedParents }?: {
|
|
53
|
+
includeMaskedParents?: boolean;
|
|
54
|
+
}): FieldSelection[];
|
|
52
55
|
remove(id: string, selection: SubscriptionSelection, targets: SubscriptionSpec[], variables: {}, visited?: string[], masked?: boolean): void;
|
|
53
56
|
reset(): Readonly<{
|
|
54
57
|
rootType: string;
|
|
@@ -209,6 +209,29 @@ class InMemorySubscriptions {
|
|
|
209
209
|
(fieldSub) => includeMaskedParents ? fieldSub.selections.concat(fieldSub.maskedParentSelections) : fieldSub.selections
|
|
210
210
|
);
|
|
211
211
|
}
|
|
212
|
+
all({ includeMaskedParents = false } = {}) {
|
|
213
|
+
const result = [];
|
|
214
|
+
const notified = /* @__PURE__ */ new Set();
|
|
215
|
+
for (const fields of this.subscribers.values()) {
|
|
216
|
+
for (const fieldSub of fields.values()) {
|
|
217
|
+
for (const selection of fieldSub.selections) {
|
|
218
|
+
if (!notified.has(selection[0].onMessage)) {
|
|
219
|
+
notified.add(selection[0].onMessage);
|
|
220
|
+
result.push(selection);
|
|
221
|
+
}
|
|
222
|
+
}
|
|
223
|
+
if (includeMaskedParents) {
|
|
224
|
+
for (const selection of fieldSub.maskedParentSelections) {
|
|
225
|
+
if (!notified.has(selection[0].onMessage)) {
|
|
226
|
+
notified.add(selection[0].onMessage);
|
|
227
|
+
result.push(selection);
|
|
228
|
+
}
|
|
229
|
+
}
|
|
230
|
+
}
|
|
231
|
+
}
|
|
232
|
+
}
|
|
233
|
+
return result;
|
|
234
|
+
}
|
|
212
235
|
remove(id, selection, targets, variables, visited = [], masked = false) {
|
|
213
236
|
visited.push(id);
|
|
214
237
|
const linkedIDs = [];
|
package/build/runtime/types.d.ts
CHANGED
package/build/vite/hmr.d.ts
CHANGED
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
import type { HmrContext, Plugin as VitePlugin } from 'vite';
|
|
2
|
-
import { type CompilerProxy } from '../lib/index.js';
|
|
3
2
|
import type { VitePluginContext } from './index.js';
|
|
4
3
|
/**
|
|
5
4
|
* Houdini Vite HMR Plugin
|
|
@@ -16,7 +15,6 @@ import type { VitePluginContext } from './index.js';
|
|
|
16
15
|
* The plugin uses the same dependency resolution logic for both scenarios, walking both up and down
|
|
17
16
|
* the dependency graph to ensure all related documents are properly regenerated.
|
|
18
17
|
*/
|
|
19
|
-
export declare let compiler: CompilerProxy;
|
|
20
18
|
export declare function document_hmr(ctx: VitePluginContext): VitePlugin;
|
|
21
19
|
type BatchCallback = (filesWithContent: Record<string, string>, deletedFiles: string[], batchId: string) => void | Promise<void>;
|
|
22
20
|
export declare function createDebounceHmr(debounceMs?: number): {
|
package/build/vite/hmr.js
CHANGED
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
import { readFileSync, writeFileSync } from "fs";
|
|
2
2
|
import { codegen_setup, get_config, path, run_pipeline } from "../lib/index.js";
|
|
3
|
-
|
|
3
|
+
import { dispose_active_session, register_session } from "./session.js";
|
|
4
4
|
function document_hmr(ctx) {
|
|
5
5
|
const debounceHmr = createDebounceHmr(50);
|
|
6
|
+
let compiler;
|
|
6
7
|
let config;
|
|
7
8
|
const ownWrites = /* @__PURE__ */ new Map();
|
|
8
9
|
let generatedDir;
|
|
@@ -62,17 +63,29 @@ function document_hmr(ctx) {
|
|
|
62
63
|
// this is called when the dev server starts
|
|
63
64
|
async configureServer(server) {
|
|
64
65
|
config = await get_config();
|
|
65
|
-
|
|
66
|
+
await dispose_active_session(ctx.db_file);
|
|
67
|
+
const ownedCompiler = await codegen_setup(config, "dev", ctx.db, ctx.db_file);
|
|
68
|
+
compiler = ownedCompiler;
|
|
69
|
+
ctx.compiler = ownedCompiler;
|
|
66
70
|
generatedDir = path.join(
|
|
67
71
|
server.config.root,
|
|
68
72
|
ctx.config.config_file.runtimeDir ?? ".houdini"
|
|
69
73
|
);
|
|
70
74
|
rootPrefix = server.config.root.endsWith("/") ? server.config.root : `${server.config.root}/`;
|
|
75
|
+
const dispose_session = register_session(ctx.db_file, async () => {
|
|
76
|
+
if (compiler === ownedCompiler) {
|
|
77
|
+
compiler = void 0;
|
|
78
|
+
}
|
|
79
|
+
if (ctx.compiler === ownedCompiler) {
|
|
80
|
+
ctx.compiler = void 0;
|
|
81
|
+
}
|
|
82
|
+
await ownedCompiler.close();
|
|
83
|
+
});
|
|
71
84
|
server.httpServer?.once("close", () => {
|
|
72
|
-
|
|
85
|
+
dispose_session();
|
|
73
86
|
});
|
|
74
87
|
try {
|
|
75
|
-
await
|
|
88
|
+
await ownedCompiler.run_pipeline({
|
|
76
89
|
// the pipeline through schema is run as part of codegen_setup
|
|
77
90
|
after: "Schema"
|
|
78
91
|
});
|
|
@@ -140,8 +153,9 @@ function document_hmr(ctx) {
|
|
|
140
153
|
return opts.modules.filter((mod) => mod.type === "js");
|
|
141
154
|
}
|
|
142
155
|
async function batchCallback(files, deletedFiles, task_id) {
|
|
143
|
-
|
|
144
|
-
|
|
156
|
+
const batchCompiler = compiler;
|
|
157
|
+
if (!batchCompiler) return;
|
|
158
|
+
await batchCompiler.pipeline_lock(async () => {
|
|
145
159
|
if (deletedFiles.length > 0) {
|
|
146
160
|
const delClause = deletedFiles.map(() => "filepath = ?").join(" OR ");
|
|
147
161
|
ctx.db.run(`DELETE FROM raw_documents WHERE ${delClause}`, deletedFiles);
|
|
@@ -196,7 +210,7 @@ function document_hmr(ctx) {
|
|
|
196
210
|
`);
|
|
197
211
|
});
|
|
198
212
|
try {
|
|
199
|
-
const results2 = await run_pipeline(
|
|
213
|
+
const results2 = await run_pipeline(batchCompiler.trigger_hook, {
|
|
200
214
|
after: "AfterExtract"
|
|
201
215
|
});
|
|
202
216
|
const updated_modules2 = [
|
|
@@ -240,7 +254,7 @@ function document_hmr(ctx) {
|
|
|
240
254
|
`);
|
|
241
255
|
});
|
|
242
256
|
try {
|
|
243
|
-
await
|
|
257
|
+
await batchCompiler.trigger_hook("ExtractDocuments", {
|
|
244
258
|
payload: { filepaths }
|
|
245
259
|
});
|
|
246
260
|
} catch (err) {
|
|
@@ -273,7 +287,7 @@ function document_hmr(ctx) {
|
|
|
273
287
|
if (changes === 0 && savedDocs.length === 0) {
|
|
274
288
|
if (!filepaths.some(isManifestFile)) return;
|
|
275
289
|
}
|
|
276
|
-
await
|
|
290
|
+
await batchCompiler.trigger_hook("AfterExtract", { task_id });
|
|
277
291
|
ctx.db.run(
|
|
278
292
|
`
|
|
279
293
|
WITH RECURSIVE
|
|
@@ -314,7 +328,7 @@ function document_hmr(ctx) {
|
|
|
314
328
|
);
|
|
315
329
|
let results;
|
|
316
330
|
try {
|
|
317
|
-
results = await run_pipeline(
|
|
331
|
+
results = await run_pipeline(batchCompiler.trigger_hook, {
|
|
318
332
|
task_id,
|
|
319
333
|
after: "AfterExtract"
|
|
320
334
|
});
|
|
@@ -437,7 +451,6 @@ function createDebounceHmr(debounceMs = 50) {
|
|
|
437
451
|
};
|
|
438
452
|
}
|
|
439
453
|
export {
|
|
440
|
-
compiler,
|
|
441
454
|
createDebounceHmr,
|
|
442
455
|
document_hmr
|
|
443
456
|
};
|
package/build/vite/houdini.js
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import path from "node:path";
|
|
2
2
|
import { codegen_setup, init_db } from "../lib/codegen.js";
|
|
3
3
|
import * as fs from "../lib/fs.js";
|
|
4
|
+
import { dispose_active_session } from "./session.js";
|
|
4
5
|
let compiler;
|
|
5
6
|
let alreadyBuilt = false;
|
|
6
7
|
function houdini(ctx) {
|
|
@@ -19,6 +20,7 @@ function houdini(ctx) {
|
|
|
19
20
|
return;
|
|
20
21
|
}
|
|
21
22
|
if (!ctx.db) {
|
|
23
|
+
await dispose_active_session(ctx.db_file);
|
|
22
24
|
const [db] = await init_db(ctx.config, false);
|
|
23
25
|
ctx.db = db;
|
|
24
26
|
}
|
package/build/vite/index.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import type { Db } from '../lib/db.js';
|
|
2
2
|
import type { PluginOption } from 'vite';
|
|
3
|
-
import { type Adapter, type ConfigFile, type Config } from '../lib/index.js';
|
|
3
|
+
import { type Adapter, type CompilerProxy, type ConfigFile, type Config } from '../lib/index.js';
|
|
4
4
|
export type PluginConfig = {
|
|
5
5
|
configPath?: string;
|
|
6
6
|
adapter?: Adapter;
|
|
@@ -9,5 +9,6 @@ export type VitePluginContext = PluginConfig & {
|
|
|
9
9
|
db: Db;
|
|
10
10
|
db_file: string;
|
|
11
11
|
config: Config;
|
|
12
|
+
compiler?: CompilerProxy;
|
|
12
13
|
};
|
|
13
14
|
export default function (opts?: PluginConfig): Promise<Array<PluginOption>>;
|
package/build/vite/index.js
CHANGED
|
@@ -2,7 +2,9 @@ import * as fs from "node:fs";
|
|
|
2
2
|
import { createRequire } from "node:module";
|
|
3
3
|
import * as path from "node:path";
|
|
4
4
|
import { pathToFileURL } from "node:url";
|
|
5
|
-
import {
|
|
5
|
+
import {
|
|
6
|
+
get_config
|
|
7
|
+
} from "../lib/index.js";
|
|
6
8
|
import { db_path } from "../router/conventions.js";
|
|
7
9
|
import { document_hmr } from "./hmr.js";
|
|
8
10
|
import { houdini } from "./houdini.js";
|
package/build/vite/schema.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import type { PluginOption } from 'vite';
|
|
2
2
|
import type { VitePluginContext } from './index.js';
|
|
3
|
-
export declare function refresh_on_schema(
|
|
3
|
+
export declare function refresh_on_schema(ctx: VitePluginContext): PluginOption;
|
|
4
4
|
export declare function poll_remote_schema(_ctx: VitePluginContext): PluginOption;
|
|
5
|
-
export declare function watch_local_schema(
|
|
5
|
+
export declare function watch_local_schema(ctx: VitePluginContext): PluginOption;
|
package/build/vite/schema.js
CHANGED
|
@@ -3,9 +3,8 @@ import * as graphql from "graphql";
|
|
|
3
3
|
import { fs, get_config, run_pipeline } from "../lib/index.js";
|
|
4
4
|
import { pull_schema } from "../lib/schema.js";
|
|
5
5
|
import { sleep } from "../lib/sleep.js";
|
|
6
|
-
import { compiler } from "./hmr.js";
|
|
7
6
|
const ownSchemaWrites = /* @__PURE__ */ new Set();
|
|
8
|
-
function refresh_on_schema(
|
|
7
|
+
function refresh_on_schema(ctx) {
|
|
9
8
|
return {
|
|
10
9
|
name: "houdini-refresh-on-schema",
|
|
11
10
|
async handleHotUpdate({ file, server }) {
|
|
@@ -17,6 +16,7 @@ function refresh_on_schema(_ctx) {
|
|
|
17
16
|
ownSchemaWrites.delete(file);
|
|
18
17
|
return;
|
|
19
18
|
}
|
|
19
|
+
const compiler = ctx.compiler;
|
|
20
20
|
if (!compiler) {
|
|
21
21
|
return;
|
|
22
22
|
}
|
|
@@ -89,7 +89,7 @@ function poll_remote_schema(_ctx) {
|
|
|
89
89
|
}
|
|
90
90
|
};
|
|
91
91
|
}
|
|
92
|
-
function watch_local_schema(
|
|
92
|
+
function watch_local_schema(ctx) {
|
|
93
93
|
return {
|
|
94
94
|
name: "houdini-watch-local-schema",
|
|
95
95
|
// Write the serialized schema at startup so houdini-core's Schema hook sees
|
|
@@ -120,6 +120,7 @@ function watch_local_schema(_ctx) {
|
|
|
120
120
|
ownSchemaWrites.add(write_target);
|
|
121
121
|
await serialize_and_write(schema, write_target);
|
|
122
122
|
setTimeout(() => ownSchemaWrites.delete(write_target), 2e3);
|
|
123
|
+
const compiler = ctx.compiler;
|
|
123
124
|
if (!compiler) return;
|
|
124
125
|
try {
|
|
125
126
|
await compiler.pipeline_lock(
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Coordinates the handoff between houdini dev sessions within one process.
|
|
3
|
+
*
|
|
4
|
+
* A vite restart creates the replacement server (and with it a fresh houdini
|
|
5
|
+
* session: plugin context, database connection, compiler, and Go plugin
|
|
6
|
+
* processes) *before* closing the old server. Without coordination the two
|
|
7
|
+
* sessions overlap on the shared orchestration database: the new session wipes
|
|
8
|
+
* the file and spawns its plugins while the old session's processes still hold
|
|
9
|
+
* it, so plugin registrations collide and the surviving session can end up
|
|
10
|
+
* pointing at plugin processes that no longer exist.
|
|
11
|
+
*
|
|
12
|
+
* This registry is deliberately module-level: its whole purpose is to pass
|
|
13
|
+
* ownership from one plugin-instance generation to the next, which no
|
|
14
|
+
* per-instance state can do. Each dev session registers a dispose callback
|
|
15
|
+
* keyed by its database file; the next session for that file (or the owning
|
|
16
|
+
* server's close event, whichever comes first) runs it exactly once.
|
|
17
|
+
*/
|
|
18
|
+
/**
|
|
19
|
+
* Register the active session for a database file. Returns a disposer bound to
|
|
20
|
+
* this registration: it runs the teardown at most once, and removes the
|
|
21
|
+
* registration only if it is still the active one (a replacement session may
|
|
22
|
+
* have already taken the slot).
|
|
23
|
+
*/
|
|
24
|
+
export declare function register_session(db_file: string, dispose: () => Promise<void>): () => Promise<void>;
|
|
25
|
+
/**
|
|
26
|
+
* Dispose whatever session currently owns the database file (no-op when none).
|
|
27
|
+
* A new session calls this before it recreates the database and spawns its own
|
|
28
|
+
* plugin processes.
|
|
29
|
+
*/
|
|
30
|
+
export declare function dispose_active_session(db_file: string): Promise<void>;
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
const sessions = /* @__PURE__ */ new Map();
|
|
2
|
+
function register_session(db_file, dispose) {
|
|
3
|
+
let running = null;
|
|
4
|
+
const entry = {
|
|
5
|
+
dispose: () => {
|
|
6
|
+
running ??= dispose();
|
|
7
|
+
return running;
|
|
8
|
+
}
|
|
9
|
+
};
|
|
10
|
+
sessions.set(db_file, entry);
|
|
11
|
+
return () => {
|
|
12
|
+
if (sessions.get(db_file) === entry) {
|
|
13
|
+
sessions.delete(db_file);
|
|
14
|
+
}
|
|
15
|
+
return entry.dispose();
|
|
16
|
+
};
|
|
17
|
+
}
|
|
18
|
+
async function dispose_active_session(db_file) {
|
|
19
|
+
const entry = sessions.get(db_file);
|
|
20
|
+
if (!entry) {
|
|
21
|
+
return;
|
|
22
|
+
}
|
|
23
|
+
sessions.delete(db_file);
|
|
24
|
+
await entry.dispose();
|
|
25
|
+
}
|
|
26
|
+
export {
|
|
27
|
+
dispose_active_session,
|
|
28
|
+
register_session
|
|
29
|
+
};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "houdini",
|
|
3
|
-
"version": "2.0.
|
|
3
|
+
"version": "2.0.8",
|
|
4
4
|
"description": "The disappearing GraphQL clients",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"typescript",
|
|
@@ -52,7 +52,7 @@
|
|
|
52
52
|
"recast": "^0.23.11",
|
|
53
53
|
"sql.js": "^1.14.1",
|
|
54
54
|
"ws": "^8.21.0",
|
|
55
|
-
"houdini-core": "^2.0.
|
|
55
|
+
"houdini-core": "^2.0.6"
|
|
56
56
|
},
|
|
57
57
|
"peerDependencies": {
|
|
58
58
|
"graphql": ">=16",
|