houdini 2.0.0-next.40 → 2.0.0-next.45

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 CHANGED
@@ -472,12 +472,12 @@ async function packageJSON(targetPath, frameworkInfo) {
472
472
  }
473
473
  packageJSON2.devDependencies = {
474
474
  ...packageJSON2.devDependencies,
475
- houdini: "^2.0.0-next.40"
475
+ houdini: "^2.0.0-next.45"
476
476
  };
477
477
  if (frameworkInfo.framework === "svelte" || frameworkInfo.framework === "kit") {
478
478
  packageJSON2.devDependencies = {
479
479
  ...packageJSON2.devDependencies,
480
- "houdini-svelte": "^3.0.0-next.35"
480
+ "houdini-svelte": "^3.0.0-next.37"
481
481
  };
482
482
  } else {
483
483
  throw new Error(`Unmanaged framework: "${JSON.stringify(frameworkInfo)}"`);
@@ -50,7 +50,7 @@ process.exit(0);}
50
50
  `
51
51
  );
52
52
  import * as conventions from "../router/conventions.js";
53
- import { create_schema, write_config } from "./database.js";
53
+ import { create_schema, schema_version, write_config } from "./database.js";
54
54
  import { openDb } from "./db.js";
55
55
  import { format_hook_error } from "./error.js";
56
56
  import * as fs from "./fs.js";
@@ -58,8 +58,27 @@ import { Logger } from "./logger.js";
58
58
  import { LogLevel } from "./types.js";
59
59
  async function connect_db(config) {
60
60
  const filepath = conventions.db_path(config);
61
- const db = await openDb(filepath);
61
+ let db = await openDb(filepath);
62
+ const stamped = db.get("PRAGMA user_version")?.user_version ?? 0;
63
+ const existing = db.get(`SELECT 1 FROM sqlite_master WHERE type = 'table' LIMIT 1`);
64
+ if (existing && stamped !== schema_version) {
65
+ db.close();
66
+ try {
67
+ await fs.remove(filepath);
68
+ } catch (_e) {
69
+ }
70
+ try {
71
+ await fs.remove(`${filepath}-shm`);
72
+ } catch (_e) {
73
+ }
74
+ try {
75
+ await fs.remove(`${filepath}-wal`);
76
+ } catch (_e) {
77
+ }
78
+ db = await openDb(filepath);
79
+ }
62
80
  db.exec(create_schema);
81
+ db.exec(`PRAGMA user_version = ${schema_version}`);
63
82
  db.flush();
64
83
  return [db, filepath];
65
84
  }
@@ -293,9 +312,7 @@ async function codegen_setup(config, mode, db, db_file) {
293
312
  }
294
313
  logger.time(`Spawn ${plugin.name}`);
295
314
  const child = spawn(executable, args, {
296
- // [stdin, stdout, stderr]: stdio plugins need piped stdin/stdout for the
297
- // message protocol; stderr is always inherited so plugin logs reach the terminal.
298
- stdio: pluginUsesStdio ? ["pipe", "pipe", "inherit"] : ["inherit", "inherit", "inherit"],
315
+ stdio: ["pipe", "pipe", "inherit"],
299
316
  detached: process.platform !== "win32"
300
317
  });
301
318
  if (pluginUsesStdio) {
@@ -2,5 +2,6 @@ import type { PluginSpec } from './codegen.js';
2
2
  import type { Db } from './db.js';
3
3
  import type { Config } from './config.js';
4
4
  import { Logger } from './logger.js';
5
- export declare const create_schema = "\nCREATE TABLE IF NOT EXISTS plugins (\n name TEXT NOT NULL PRIMARY KEY UNIQUE,\n port INTEGER NOT NULL,\n hooks JSON NOT NULL,\n plugin_order TEXT CHECK (plugin_order IS NULL OR plugin_order IN ('before', 'after', 'core')),\n include_runtime TEXT,\n include_static_runtime TEXT,\n config JSON,\n\t config_module TEXT,\n\t\tclient_plugins JSON\n);\n\n-- Watch Schema Config\nCREATE TABLE IF NOT EXISTS watch_schema_config (\n url TEXT NOT NULL,\n headers JSON,\n interval INTEGER,\n timeout INTEGER\n);\n\n-- Router Config\nCREATE TABLE IF NOT EXISTS router_config (\n api_endpoint TEXT,\n redirect TEXT UNIQUE,\n session_keys TEXT NOT NULL UNIQUE,\n url TEXT,\n mutation TEXT UNIQUE\n);\n\n-- Runtime Scalar Definition\nCREATE TABLE IF NOT EXISTS runtime_scalar_definitions (\n name TEXT NOT NULL PRIMARY KEY UNIQUE,\n type TEXT NOT NULL\n);\n\nCREATE TABLE IF NOT EXISTS component_fields (\n\tid INTEGER PRIMARY KEY AUTOINCREMENT,\n\tdocument INTEGER NOT NULL,\n type TEXT,\n\tprop TEXT,\n field TEXT,\n\tinline BOOLEAN default false,\n type_field TEXT,\n fragment TEXT,\n\tUNIQUE (document),\n\tFOREIGN KEY (document) REFERENCES raw_documents(id) ON DELETE CASCADE\n);\n\n-- Static Config (main config table)\nCREATE TABLE IF NOT EXISTS config (\n include JSON NOT NULL,\n exclude JSON NOT NULL,\n schema_path TEXT NOT NULL,\n definitions_path TEXT,\n cache_buffer_size INTEGER,\n default_cache_policy TEXT,\n default_partial BOOLEAN,\n default_lifetime INTEGER,\n default_list_position TEXT CHECK (default_list_position IN ('APPEND', 'PREPEND')),\n default_list_target TEXT CHECK (default_list_target IN ('ALL', 'NULL')),\n default_paginate_mode TEXT CHECK (default_paginate_mode IN ('Infinite', 'SinglePage')),\n suppress_pagination_deduplication BOOLEAN,\n log_level TEXT CHECK (log_level IN ('QUIET', 'FULL', 'SUMMARY', 'SHORT_SUMMARY')),\n default_fragment_masking BOOLEAN,\n default_keys JSON,\n persisted_queries_path TEXT NOT NULL,\n project_root TEXT,\n runtime_dir TEXT,\n\t\tpath TEXT\n);\n\nCREATE TABLE IF NOT EXISTS scalar_config (\n name TEXT NOT NULL PRIMARY KEY UNIQUE,\n type TEXT NOT NULL,\n\tinput_types JSON,\n\tmodule TEXT,\n\tdefault_import BOOLEAN\n);\n\n-- Types configuration\nCREATE TABLE IF NOT EXISTS type_configs (\n name TEXT NOT NULL,\n keys JSON NOT NULL,\n\tresolve_query TEXT\n);\n\n-- A table of original document contents (to be populated by plugins)\nCREATE TABLE IF NOT EXISTS raw_documents (\n id INTEGER PRIMARY KEY AUTOINCREMENT,\n offset_line INTEGER,\n offset_column INTEGER,\n filepath TEXT NOT NULL,\n content TEXT NOT NULL,\n current_task TEXT,\n loaded_with TEXT\n);\n\n-----------------------------------------------------------\n-- Schema Definition Tables\n-----------------------------------------------------------\n\nCREATE TABLE IF NOT EXISTS types (\n name TEXT NOT NULL PRIMARY KEY UNIQUE,\n kind TEXT NOT NULL CHECK (kind IN ('OBJECT', 'INTERFACE', 'UNION', 'ENUM', 'SCALAR', 'INPUT')),\n operation TEXT,\n\tdescription TEXT,\n\tinternal BOOLEAN default false,\n\tbuilt_in BOOLEAN default false\n);\n\nCREATE TABLE IF NOT EXISTS type_fields (\n id TEXT PRIMARY KEY, -- will be something like User.name so we don't have to look up the generated id\n parent TEXT NOT NULL, -- will be User\n name TEXT NOT NULL,\n type TEXT NOT NULL,\n\t type_modifiers TEXT,\n default_value TEXT,\n description TEXT,\n\t internal BOOLEAN default false,\n document INT,\n\n FOREIGN KEY (document) REFERENCES raw_documents(id) ON DELETE CASCADE,\n FOREIGN KEY (parent) REFERENCES types(name) ON DELETE CASCADE,\n FOREIGN KEY (type) REFERENCES types(name) ON DELETE CASCADE,\n UNIQUE (parent, name)\n);\n\nCREATE TABLE IF NOT EXISTS type_field_arguments (\n id TEXT PRIMARY KEY,\n field TEXT NOT NULL,\n name TEXT NOT NULL,\n type TEXT NOT NULL,\n type_modifiers TEXT,\n default_value TEXT,\n FOREIGN KEY (field) REFERENCES type_fields(id) ON DELETE CASCADE,\n UNIQUE (field, name)\n);\n\n\nCREATE TABLE IF NOT EXISTS enum_values (\n id INTEGER PRIMARY KEY AUTOINCREMENT,\n parent TEXT NOT NULL,\n value TEXT NOT NULL,\n description TEXT,\n FOREIGN KEY (parent) REFERENCES types(name) ON DELETE CASCADE,\n UNIQUE (parent, value)\n);\n\nCREATE TABLE IF NOT EXISTS possible_types (\n type TEXT NOT NULL,\n member TEXT NOT NULL,\n FOREIGN KEY (type) REFERENCES types(name) ON DELETE CASCADE,\n FOREIGN KEY (member) REFERENCES types(name) ON DELETE CASCADE,\n PRIMARY KEY (type, member)\n);\n\nCREATE TABLE IF NOT EXISTS directives (\n name TEXT NOT NULL UNIQUE PRIMARY KEY,\n\tinternal BOOLEAN default false,\n visible BOOLEAN default true,\n repeatable BOOLEAN default false,\n\tdescription TEXT\n);\n\nCREATE TABLE IF NOT EXISTS directive_arguments (\n parent TEXT NOT NULL,\n name TEXT NOT NULL,\n type TEXT NOT NULL,\n\ttype_modifiers TEXT,\n default_value TEXT,\n FOREIGN KEY (parent) REFERENCES directives(name),\n PRIMARY KEY (parent, name),\n UNIQUE (parent, name)\n);\n\nCREATE TABLE IF NOT EXISTS directive_locations (\n directive TEXT NOT NULL,\n location TEXT NOT NULL CHECK (location IN ('QUERY', 'MUTATION', 'SUBSCRIPTION', 'FIELD', 'FRAGMENT_DEFINITION', 'FRAGMENT_SPREAD', 'INLINE_FRAGMENT', 'SCHEMA', 'SCALAR', 'OBJECT', 'FIELD_DEFINITION', 'ARGUMENT_DEFINITION', 'INTERFACE', 'UNION', 'ENUM', 'ENUM_VALUE', 'INPUT_OBJECT', 'INPUT_FIELD_DEFINITION')),\n FOREIGN KEY (directive) REFERENCES directives(name),\n PRIMARY KEY (directive, location)\n);\n\nCREATE TABLE IF NOT EXISTS document_variable_directives (\n\tid INTEGER PRIMARY KEY AUTOINCREMENT,\n\tparent INTEGER NOT NULL,\n\tdirective TEXT NOT NULL,\n row INTEGER NOT NULL,\n column INTEGER NOT NULL,\n\tFOREIGN KEY (parent) REFERENCES document_variables(id) ON DELETE CASCADE,\n\tFOREIGN KEY (directive) REFERENCES directives(name) ON DELETE CASCADE\n);\n\nCREATE TABLE IF NOT EXISTS document_variable_directive_arguments (\n id INTEGER PRIMARY KEY AUTOINCREMENT,\n parent INTEGER NOT NULL,\n name TEXT NOT NULL,\n value INTEGER NOT NULL,\n\n FOREIGN KEY (value) REFERENCES argument_values(id) ON DELETE CASCADE,\n FOREIGN KEY (parent) REFERENCES document_variable_directives(id) ON DELETE CASCADE\n);\n\n-----------------------------------------------------------\n-- Document Tables\n-----------------------------------------------------------\n\nCREATE TABLE IF NOT EXISTS document_variables (\n \tid INTEGER PRIMARY KEY AUTOINCREMENT,\n document TEXT NOT NULL,\n name TEXT NOT NULL,\n type TEXT NOT NULL,\n type_modifiers TEXT,\n default_value INT,\n row INTEGER NOT NULL,\n column INTEGER NOT NULL,\n\n FOREIGN KEY (default_value) REFERENCES argument_values(id) ON DELETE CASCADE,\n FOREIGN KEY (document) REFERENCES documents(id) ON DELETE CASCADE,\n UNIQUE (document, name)\n);\n\n-- this is pulled out separately from operations and fragments so foreign keys can be used\nCREATE TABLE IF NOT EXISTS documents (\n id INTEGER PRIMARY KEY AUTOINCREMENT,\n name TEXT NOT NULL,\n kind TEXT NOT NULL CHECK (kind IN ('query', 'mutation', 'subscription', 'fragment')),\n raw_document INTEGER,\n type_condition TEXT,\n hash TEXT,\n printed TEXT,\n\t\tinternal boolean default false,\n\t\tvisible boolean default true,\n\t\tprocessed boolean default false,\n FOREIGN KEY (type_condition) REFERENCES types(name) ON DELETE CASCADE,\n FOREIGN KEY (raw_document) REFERENCES raw_documents(id) ON DELETE CASCADE\n);\n\nCREATE TABLE IF NOT EXISTS selections (\n id INTEGER PRIMARY KEY AUTOINCREMENT,\n field_name TEXT NOT NULL,\n\tkind TEXT NOT NULL CHECK (kind IN ('field', 'fragment', 'inline_fragment')),\n alias TEXT,\n type TEXT, -- should be something like User.Avatar\n fragment_ref TEXT, -- used when fragment arguments cause a hash to be inlined (removing the ability to track what the original fragment is)\n\t\tfragment_args JSON -- used to store the arguments that are used when fragment variables are expanded\n);\n\nCREATE TABLE IF NOT EXISTS selection_directives (\n id INTEGER PRIMARY KEY AUTOINCREMENT,\n selection_id INTEGER NOT NULL,\n directive TEXT NOT NULL,\n row INTEGER NOT NULL,\n column INTEGER NOT NULL,\n FOREIGN KEY (selection_id) REFERENCES selections(id) ON DELETE CASCADE,\n FOREIGN KEY (directive) REFERENCES directives(name) ON DELETE CASCADE\n);\n\nCREATE TABLE IF NOT EXISTS selection_directive_arguments (\n id INTEGER PRIMARY KEY AUTOINCREMENT,\n parent INTEGER NOT NULL,\n name TEXT NOT NULL,\n value INTEGER NOT NULL,\n document INTEGER NOT NULL,\n\n FOREIGN KEY (value) REFERENCES argument_values(id) ON DELETE CASCADE,\n FOREIGN KEY (parent) REFERENCES selection_directives(id) ON DELETE CASCADE,\n FOREIGN KEY (document) REFERENCES documents(id) ON DELETE CASCADE\n);\n\nCREATE TABLE IF NOT EXISTS document_directives (\n\tid INTEGER PRIMARY KEY AUTOINCREMENT,\n\tdocument int NOT NULL,\n\tdirective TEXT NOT NULL,\n\trow INTEGER NOT NULL,\n\tcolumn INTEGER NOT NULL,\n\tFOREIGN KEY (document) REFERENCES documents(id) ON DELETE CASCADE,\n\tFOREIGN KEY (directive) REFERENCES directives(name) ON DELETE CASCADE\n);\n\nCREATE TABLE IF NOT EXISTS document_directive_arguments (\n id INTEGER PRIMARY KEY AUTOINCREMENT,\n parent INTEGER NOT NULL,\n name TEXT NOT NULL,\n value INTEGER NOT NULL,\n\n FOREIGN KEY (value) REFERENCES argument_values(id) ON DELETE CASCADE,\n FOREIGN KEY (parent) REFERENCES document_directives(id) ON DELETE CASCADE\n);\n\nCREATE TABLE IF NOT EXISTS selection_refs (\n id INTEGER PRIMARY KEY AUTOINCREMENT,\n parent_id INTEGER,\n child_id INTEGER NOT NULL,\n path_index INTEGER NOT NULL,\n document INTEGER NOT NULL,\n\trow INTEGER NOT NULL,\n\tcolumn INTEGER NOT NULL,\n\tinternal BOOLEAN NOT NULL DEFAULT false,\n FOREIGN KEY (parent_id) REFERENCES selections(id) ON DELETE CASCADE,\n FOREIGN KEY (child_id) REFERENCES selections(id) ON DELETE CASCADE,\n FOREIGN KEY (document) REFERENCES documents(id) ON DELETE CASCADE\n);\n\nCREATE TABLE IF NOT EXISTS selection_arguments (\n id INTEGER PRIMARY KEY AUTOINCREMENT,\n selection_id INTEGER NOT NULL,\n document INTEGER NOT NULL,\n name TEXT NOT NULL,\n value INTEGER NOT NULL,\n row INTEGER NOT NULL,\n column INTEGER NOT NULL,\n field_argument TEXT NOT NULL,\n\n FOREIGN KEY (value) REFERENCES argument_values(id) ON DELETE CASCADE,\n FOREIGN KEY (selection_id) REFERENCES selections(id) ON DELETE CASCADE,\n FOREIGN KEY (document) REFERENCES documents(id) ON DELETE CASCADE\n);\n\n\nCREATE TABLE IF NOT EXISTS argument_values (\n id INTEGER PRIMARY KEY AUTOINCREMENT,\n kind TEXT NOT NULL CHECK (kind IN ('Variable', 'Int', 'Float', 'String', 'Block', 'Boolean', 'Null', 'Enum', 'List', 'Object')),\n raw TEXT NOT NULL,\n row INTEGER NOT NULL,\n column INTEGER NOT NULL,\n expected_type TEXT NOT NULL,\n expected_type_modifiers TEXT,\n document INTEGER NOT NULL,\n\n FOREIGN KEY (document) REFERENCES documents(id) ON DELETE CASCADE\n);\n\nCREATE TABLE IF NOT EXISTS argument_value_children (\n id INTEGER PRIMARY KEY AUTOINCREMENT,\n name TEXT,\n parent INTEGER NOT NULL,\n value INTEGER NOT NULL,\n row INTEGER NOT NULL,\n column INTEGER NOT NULL,\n document INTEGER NOT NULL,\n\n FOREIGN KEY (document) REFERENCES documents(id) ON DELETE CASCADE,\n FOREIGN KEY (parent) REFERENCES argument_values(id) ON DELETE CASCADE,\n FOREIGN KEY (value) REFERENCES argument_values(id) ON DELETE CASCADE\n);\n\nCREATE TABLE IF NOT EXISTS discovered_lists (\n id INTEGER PRIMARY KEY AUTOINCREMENT,\n name TEXT,\n node_type TEXT NOT NULL,\n edge_type TEXT,\n connection_type TEXT NOT NULL,\n node INTEGER NOT NULL,\n page_size INTEGER NOT NULL,\n document INTEGER NOT NULL,\n mode TEXT NOT NULL,\n embedded BOOLEAN NOT NULL,\n target_type TEXT NOT NULL,\n connection BOOLEAN default false,\n list_field INTEGER NOT NULL,\n paginate TEXT,\n supports_forward BOOLEAN default false,\n supports_backward BOOLEAN default false,\n cursor_type TEXT,\n\n FOREIGN KEY (list_field) REFERENCES selections(id) ON DELETE CASCADE,\n\t FOREIGN KEY (node) REFERENCES selections(id) ON DELETE CASCADE,\n FOREIGN KEY (node_type) REFERENCES types(name) ON DELETE CASCADE,\n FOREIGN KEY (document) REFERENCES documents(id) ON DELETE CASCADE\n);\n\nCREATE TABLE IF NOT EXISTS document_dependencies (\n document INTEGER NOT NULL,\n depends_on TEXT NOT NULL,\n\n FOREIGN KEY (document) REFERENCES documents(id) ON DELETE CASCADE,\n UNIQUE (document, depends_on)\n);\n\n-----------------------------------------------------------\n-- Indices\n-----------------------------------------------------------\n\n-- component_fields\nCREATE INDEX IF NOT EXISTS idx_component_fields_type_fields ON component_fields(type_field);\n\n-- discovered_lists\nCREATE INDEX IF NOT EXISTS idx_discovered_lists_document ON discovered_lists(document);\nCREATE INDEX IF NOT EXISTS idx_discovered_lists_node ON discovered_lists(node);\nCREATE INDEX IF NOT EXISTS idx_discovered_lists_list_field ON discovered_lists(list_field);\n-- note: no index on discovered_lists(connection) \u2014 boolean column, ~2 distinct values\n\n-- types\nCREATE INDEX IF NOT EXISTS idx_types_kind_operation ON types(kind, operation);\n-- note: no index on types(name) \u2014 covered by PRIMARY KEY UNIQUE\n\n-- documents\nCREATE INDEX IF NOT EXISTS idx_documents_kind ON documents(kind);\nCREATE INDEX IF NOT EXISTS idx_documents_type_condition ON documents(type_condition);\nCREATE INDEX IF NOT EXISTS idx_documents_raw_document ON documents(raw_document);\nCREATE INDEX IF NOT EXISTS idx_documents_name_kind ON documents(name, kind);\n\n-- raw_documents\nCREATE INDEX IF NOT EXISTS idx_raw_documents_current_task ON raw_documents(current_task);\nCREATE INDEX IF NOT EXISTS idx_raw_documents_filepath ON raw_documents(filepath);\n\n-- selections\nCREATE INDEX IF NOT EXISTS idx_selections_type ON selections(type);\nCREATE INDEX IF NOT EXISTS idx_selections_alias ON selections(alias);\nCREATE INDEX IF NOT EXISTS idx_selections_field_name_kind ON selections(field_name, kind);\n\n-- selection_refs: composite covers document-only lookups, so no separate single-column index needed\nCREATE INDEX IF NOT EXISTS idx_selection_refs_parent_id ON selection_refs(parent_id);\n\nCREATE INDEX IF NOT EXISTS idx_selection_refs_child_id ON selection_refs(child_id);\nCREATE INDEX IF NOT EXISTS idx_selection_refs_document_parent_id ON selection_refs(document, parent_id);\n\n-- selection_directives / selection_directive_arguments / selection_arguments\nCREATE INDEX IF NOT EXISTS idx_selection_directives_selection ON selection_directives(selection_id);\nCREATE INDEX IF NOT EXISTS idx_selection_directives_directive ON selection_directives(directive);\nCREATE INDEX IF NOT EXISTS idx_selection_directive_arguments_parent_name ON selection_directive_arguments(parent, name);\n-- note: no index on selection_directive_arguments(parent) alone \u2014 covered by (parent,name) composite\nCREATE INDEX IF NOT EXISTS idx_selection_directive_arguments_value ON selection_directive_arguments(value);\n-- document FK on selection_directive_arguments and selection_arguments: used in WHERE/JOIN in CollectDocuments\nCREATE INDEX IF NOT EXISTS idx_selection_directive_arguments_document ON selection_directive_arguments(document);\nCREATE INDEX IF NOT EXISTS idx_selection_arguments_document ON selection_arguments(document);\nCREATE INDEX IF NOT EXISTS idx_selection_arguments_selection ON selection_arguments(selection_id);\nCREATE INDEX IF NOT EXISTS idx_selection_arguments_value ON selection_arguments(value);\n\n-- type_fields / type_field_arguments\n-- note: no index on type_fields(id) or type_field_arguments(id) \u2014 covered by their TEXT PRIMARY KEYs\nCREATE INDEX IF NOT EXISTS idx_type_fields_parent ON type_fields(parent);\nCREATE INDEX IF NOT EXISTS idx_type_fields_name ON type_fields(name);\nCREATE INDEX IF NOT EXISTS idx_type_configs_name ON type_configs(name);\n\n-- possible_types\n-- note: no index on possible_types(type) \u2014 covered by PRIMARY KEY(type,member) leading column\nCREATE INDEX IF NOT EXISTS idx_possible_types_member ON possible_types(member);\n\n-- type_fields: type and document FK columns have no implicit index\nCREATE INDEX IF NOT EXISTS idx_type_fields_type ON type_fields(type);\nCREATE INDEX IF NOT EXISTS idx_type_fields_document ON type_fields(document);\n\n-- enum_values\n-- note: no index on enum_values(parent) or (parent,value) \u2014 both covered by UNIQUE(parent,value)\n\n-- document_directives / document_directive_arguments\nCREATE INDEX IF NOT EXISTS idx_document_directives_document ON document_directives(document);\nCREATE INDEX IF NOT EXISTS idx_document_directives_directive ON document_directives(directive);\nCREATE INDEX IF NOT EXISTS idx_document_directive_arguments_parent_name ON document_directive_arguments(parent, name);\n-- note: no index on document_directive_arguments(parent) alone \u2014 covered by (parent,name) composite\nCREATE INDEX IF NOT EXISTS idx_document_directive_arguments_value on document_directive_arguments(value);\n\n-- document_variables\n-- note: no index on document_variables(document,name) \u2014 covered by UNIQUE(document,name)\n-- default_value FK is used as a JOIN column in validate and fragmentArguments transforms\nCREATE INDEX IF NOT EXISTS idx_document_variables_default_value ON document_variables(default_value);\nCREATE INDEX IF NOT EXISTS idx_document_variables_document_id ON document_variables(document, id);\nCREATE INDEX IF NOT EXISTS idx_document_variables_document_type_modifiers_default ON document_variables(document, type_modifiers, default_value);\n\n-- document_variable_directives / document_variable_directive_arguments\nCREATE INDEX IF NOT EXISTS idx_document_variable_directives_parent ON document_variable_directives(parent);\nCREATE INDEX IF NOT EXISTS idx_document_variable_directives_directive ON document_variable_directives(directive);\nCREATE INDEX IF NOT EXISTS idx_document_variable_directive_arguments_parent ON document_variable_directive_arguments(parent);\n\n-- document_dependencies\n-- note: no index on document_dependencies(document) \u2014 covered by UNIQUE(document,depends_on) leading column\nCREATE INDEX IF NOT EXISTS idx_document_dependency_depends_on on document_dependencies(depends_on);\n\n-- argument_values: composite (document,id) covers document-only lookups\n-- note: no separate index on argument_values(document) alone\nCREATE INDEX IF NOT EXISTS idx_argument_values_kind_raw ON argument_values(kind, raw);\nCREATE INDEX IF NOT EXISTS idx_argument_values_document_id ON argument_values(document, id);\nCREATE INDEX IF NOT EXISTS idx_argument_values_expected_type_document ON argument_values(expected_type, document);\n\n-- argument_value_children: composite (parent,value) covers parent-only lookups\n-- note: no separate index on argument_value_children(parent) alone\nCREATE INDEX IF NOT EXISTS idx_argument_value_children_parent_value ON argument_value_children(parent, value);\nCREATE INDEX IF NOT EXISTS idx_argument_value_children_value ON argument_value_children(value);\n-- document FK: large table; index needed for efficient CASCADE DELETE from documents\nCREATE INDEX IF NOT EXISTS idx_argument_value_children_document ON argument_value_children(document);\n";
5
+ export declare const create_schema = "\nCREATE TABLE IF NOT EXISTS plugins (\n name TEXT NOT NULL PRIMARY KEY UNIQUE,\n port INTEGER NOT NULL,\n hooks JSON NOT NULL,\n plugin_order TEXT CHECK (plugin_order IS NULL OR plugin_order IN ('before', 'after', 'core')),\n include_runtime TEXT,\n include_static_runtime TEXT,\n config JSON,\n\t config_module TEXT,\n\t\tclient_plugins JSON\n);\n\n-- Watch Schema Config\nCREATE TABLE IF NOT EXISTS watch_schema_config (\n url TEXT NOT NULL,\n headers JSON,\n interval INTEGER,\n timeout INTEGER\n);\n\n-- Router Config\nCREATE TABLE IF NOT EXISTS router_config (\n api_endpoint TEXT,\n redirect TEXT UNIQUE,\n session_keys TEXT NOT NULL UNIQUE,\n url TEXT,\n mutation TEXT UNIQUE\n);\n\n-- Runtime Scalar Definition\nCREATE TABLE IF NOT EXISTS runtime_scalar_definitions (\n name TEXT NOT NULL PRIMARY KEY UNIQUE,\n type TEXT NOT NULL\n);\n\nCREATE TABLE IF NOT EXISTS component_fields (\n\tid INTEGER PRIMARY KEY AUTOINCREMENT,\n\tdocument INTEGER NOT NULL,\n type TEXT,\n\tprop TEXT,\n field TEXT,\n\tinline BOOLEAN default false,\n type_field TEXT,\n fragment TEXT,\n\tUNIQUE (document),\n\tFOREIGN KEY (document) REFERENCES raw_documents(id) ON DELETE CASCADE\n);\n\n-- Static Config (main config table)\nCREATE TABLE IF NOT EXISTS config (\n include JSON NOT NULL,\n exclude JSON NOT NULL,\n schema_path TEXT NOT NULL,\n definitions_path TEXT,\n cache_buffer_size INTEGER,\n default_cache_policy TEXT,\n default_partial BOOLEAN,\n default_lifetime INTEGER,\n default_list_position TEXT CHECK (default_list_position IN ('APPEND', 'PREPEND')),\n default_list_target TEXT CHECK (default_list_target IN ('ALL', 'NULL')),\n default_paginate_mode TEXT CHECK (default_paginate_mode IN ('Infinite', 'SinglePage')),\n suppress_pagination_deduplication BOOLEAN,\n log_level TEXT CHECK (log_level IN ('QUIET', 'FULL', 'SUMMARY', 'SHORT_SUMMARY')),\n default_fragment_masking BOOLEAN,\n default_keys JSON,\n persisted_queries_path TEXT NOT NULL,\n project_root TEXT,\n runtime_dir TEXT,\n\t\tpath TEXT\n);\n\nCREATE TABLE IF NOT EXISTS scalar_config (\n name TEXT NOT NULL PRIMARY KEY UNIQUE,\n type TEXT NOT NULL,\n\tinput_types JSON,\n\tmodule TEXT,\n\tdefault_import BOOLEAN\n);\n\n-- Types configuration\nCREATE TABLE IF NOT EXISTS type_configs (\n name TEXT NOT NULL,\n keys JSON NOT NULL,\n\tresolve_query TEXT\n);\n\n-- A table of original document contents (to be populated by plugins)\nCREATE TABLE IF NOT EXISTS raw_documents (\n id INTEGER PRIMARY KEY AUTOINCREMENT,\n offset_line INTEGER,\n offset_column INTEGER,\n filepath TEXT NOT NULL,\n content TEXT NOT NULL,\n current_task TEXT,\n loaded_with TEXT\n);\n\n-----------------------------------------------------------\n-- Schema Definition Tables\n-----------------------------------------------------------\n\nCREATE TABLE IF NOT EXISTS types (\n name TEXT NOT NULL PRIMARY KEY UNIQUE,\n kind TEXT NOT NULL CHECK (kind IN ('OBJECT', 'INTERFACE', 'UNION', 'ENUM', 'SCALAR', 'INPUT')),\n operation TEXT,\n\tdescription TEXT,\n\tinternal BOOLEAN default false,\n\tbuilt_in BOOLEAN default false\n);\n\nCREATE TABLE IF NOT EXISTS type_fields (\n id TEXT PRIMARY KEY, -- will be something like User.name so we don't have to look up the generated id\n parent TEXT NOT NULL, -- will be User\n name TEXT NOT NULL,\n type TEXT NOT NULL,\n\t type_modifiers TEXT,\n default_value TEXT,\n description TEXT,\n\t internal BOOLEAN default false,\n document INT,\n\n FOREIGN KEY (document) REFERENCES raw_documents(id) ON DELETE CASCADE,\n FOREIGN KEY (parent) REFERENCES types(name) ON DELETE CASCADE,\n FOREIGN KEY (type) REFERENCES types(name) ON DELETE CASCADE,\n UNIQUE (parent, name)\n);\n\nCREATE TABLE IF NOT EXISTS type_field_arguments (\n id TEXT PRIMARY KEY,\n field TEXT NOT NULL,\n name TEXT NOT NULL,\n type TEXT NOT NULL,\n type_modifiers TEXT,\n default_value TEXT,\n FOREIGN KEY (field) REFERENCES type_fields(id) ON DELETE CASCADE,\n UNIQUE (field, name)\n);\n\n\nCREATE TABLE IF NOT EXISTS enum_values (\n id INTEGER PRIMARY KEY AUTOINCREMENT,\n parent TEXT NOT NULL,\n value TEXT NOT NULL,\n description TEXT,\n FOREIGN KEY (parent) REFERENCES types(name) ON DELETE CASCADE,\n UNIQUE (parent, value)\n);\n\nCREATE TABLE IF NOT EXISTS possible_types (\n type TEXT NOT NULL,\n member TEXT NOT NULL,\n FOREIGN KEY (type) REFERENCES types(name) ON DELETE CASCADE,\n FOREIGN KEY (member) REFERENCES types(name) ON DELETE CASCADE,\n PRIMARY KEY (type, member)\n);\n\nCREATE TABLE IF NOT EXISTS directives (\n name TEXT NOT NULL UNIQUE PRIMARY KEY,\n\tinternal BOOLEAN default false,\n visible BOOLEAN default true,\n repeatable BOOLEAN default false,\n\tdescription TEXT\n);\n\nCREATE TABLE IF NOT EXISTS directive_arguments (\n parent TEXT NOT NULL,\n name TEXT NOT NULL,\n type TEXT NOT NULL,\n\ttype_modifiers TEXT,\n default_value TEXT,\n FOREIGN KEY (parent) REFERENCES directives(name),\n PRIMARY KEY (parent, name),\n UNIQUE (parent, name)\n);\n\nCREATE TABLE IF NOT EXISTS directive_locations (\n directive TEXT NOT NULL,\n location TEXT NOT NULL CHECK (location IN ('QUERY', 'MUTATION', 'SUBSCRIPTION', 'FIELD', 'FRAGMENT_DEFINITION', 'FRAGMENT_SPREAD', 'INLINE_FRAGMENT', 'SCHEMA', 'SCALAR', 'OBJECT', 'FIELD_DEFINITION', 'ARGUMENT_DEFINITION', 'INTERFACE', 'UNION', 'ENUM', 'ENUM_VALUE', 'INPUT_OBJECT', 'INPUT_FIELD_DEFINITION')),\n FOREIGN KEY (directive) REFERENCES directives(name),\n PRIMARY KEY (directive, location)\n);\n\nCREATE TABLE IF NOT EXISTS document_variable_directives (\n\tid INTEGER PRIMARY KEY AUTOINCREMENT,\n\tparent INTEGER NOT NULL,\n\tdirective TEXT NOT NULL,\n row INTEGER NOT NULL,\n column INTEGER NOT NULL,\n\tFOREIGN KEY (parent) REFERENCES document_variables(id) ON DELETE CASCADE,\n\tFOREIGN KEY (directive) REFERENCES directives(name) ON DELETE CASCADE\n);\n\nCREATE TABLE IF NOT EXISTS document_variable_directive_arguments (\n id INTEGER PRIMARY KEY AUTOINCREMENT,\n parent INTEGER NOT NULL,\n name TEXT NOT NULL,\n value INTEGER NOT NULL,\n\n FOREIGN KEY (value) REFERENCES argument_values(id) ON DELETE CASCADE,\n FOREIGN KEY (parent) REFERENCES document_variable_directives(id) ON DELETE CASCADE\n);\n\n-----------------------------------------------------------\n-- Document Tables\n-----------------------------------------------------------\n\nCREATE TABLE IF NOT EXISTS document_variables (\n \tid INTEGER PRIMARY KEY AUTOINCREMENT,\n document TEXT NOT NULL,\n name TEXT NOT NULL,\n type TEXT NOT NULL,\n type_modifiers TEXT,\n default_value INT,\n row INTEGER NOT NULL,\n column INTEGER NOT NULL,\n\n FOREIGN KEY (default_value) REFERENCES argument_values(id) ON DELETE CASCADE,\n FOREIGN KEY (document) REFERENCES documents(id) ON DELETE CASCADE,\n UNIQUE (document, name)\n);\n\n-- this is pulled out separately from operations and fragments so foreign keys can be used\nCREATE TABLE IF NOT EXISTS documents (\n id INTEGER PRIMARY KEY AUTOINCREMENT,\n name TEXT NOT NULL,\n kind TEXT NOT NULL CHECK (kind IN ('query', 'mutation', 'subscription', 'fragment')),\n raw_document INTEGER,\n type_condition TEXT,\n hash TEXT,\n printed TEXT,\n\t\tinternal boolean default false,\n\t\tvisible boolean default true,\n\t\tprocessed boolean default false,\n FOREIGN KEY (type_condition) REFERENCES types(name) ON DELETE CASCADE,\n FOREIGN KEY (raw_document) REFERENCES raw_documents(id) ON DELETE CASCADE\n);\n\nCREATE TABLE IF NOT EXISTS selections (\n id INTEGER PRIMARY KEY AUTOINCREMENT,\n field_name TEXT NOT NULL,\n\tkind TEXT NOT NULL CHECK (kind IN ('field', 'fragment', 'inline_fragment')),\n alias TEXT,\n type TEXT, -- should be something like User.Avatar\n fragment_ref TEXT, -- used when fragment arguments cause a hash to be inlined (removing the ability to track what the original fragment is)\n\t\tfragment_args JSON -- used to store the arguments that are used when fragment variables are expanded\n);\n\nCREATE TABLE IF NOT EXISTS selection_directives (\n id INTEGER PRIMARY KEY AUTOINCREMENT,\n selection_id INTEGER NOT NULL,\n directive TEXT NOT NULL,\n row INTEGER NOT NULL,\n column INTEGER NOT NULL,\n FOREIGN KEY (selection_id) REFERENCES selections(id) ON DELETE CASCADE,\n FOREIGN KEY (directive) REFERENCES directives(name) ON DELETE CASCADE\n);\n\nCREATE TABLE IF NOT EXISTS selection_directive_arguments (\n id INTEGER PRIMARY KEY AUTOINCREMENT,\n parent INTEGER NOT NULL,\n name TEXT NOT NULL,\n value INTEGER NOT NULL,\n document INTEGER NOT NULL,\n\n FOREIGN KEY (value) REFERENCES argument_values(id) ON DELETE CASCADE,\n FOREIGN KEY (parent) REFERENCES selection_directives(id) ON DELETE CASCADE,\n FOREIGN KEY (document) REFERENCES documents(id) ON DELETE CASCADE\n);\n\nCREATE TABLE IF NOT EXISTS document_directives (\n\tid INTEGER PRIMARY KEY AUTOINCREMENT,\n\tdocument int NOT NULL,\n\tdirective TEXT NOT NULL,\n\trow INTEGER NOT NULL,\n\tcolumn INTEGER NOT NULL,\n\tFOREIGN KEY (document) REFERENCES documents(id) ON DELETE CASCADE,\n\tFOREIGN KEY (directive) REFERENCES directives(name) ON DELETE CASCADE\n);\n\nCREATE TABLE IF NOT EXISTS document_directive_arguments (\n id INTEGER PRIMARY KEY AUTOINCREMENT,\n parent INTEGER NOT NULL,\n name TEXT NOT NULL,\n value INTEGER NOT NULL,\n\n FOREIGN KEY (value) REFERENCES argument_values(id) ON DELETE CASCADE,\n FOREIGN KEY (parent) REFERENCES document_directives(id) ON DELETE CASCADE\n);\n\nCREATE TABLE IF NOT EXISTS selection_refs (\n id INTEGER PRIMARY KEY AUTOINCREMENT,\n parent_id INTEGER,\n child_id INTEGER NOT NULL,\n path_index INTEGER NOT NULL,\n document INTEGER NOT NULL,\n\trow INTEGER NOT NULL,\n\tcolumn INTEGER NOT NULL,\n\tinternal BOOLEAN NOT NULL DEFAULT false,\n FOREIGN KEY (parent_id) REFERENCES selections(id) ON DELETE CASCADE,\n FOREIGN KEY (child_id) REFERENCES selections(id) ON DELETE CASCADE,\n FOREIGN KEY (document) REFERENCES documents(id) ON DELETE CASCADE\n);\n\nCREATE TABLE IF NOT EXISTS selection_arguments (\n id INTEGER PRIMARY KEY AUTOINCREMENT,\n selection_id INTEGER NOT NULL,\n document INTEGER NOT NULL,\n name TEXT NOT NULL,\n value INTEGER NOT NULL,\n row INTEGER NOT NULL,\n column INTEGER NOT NULL,\n field_argument TEXT NOT NULL,\n\n FOREIGN KEY (value) REFERENCES argument_values(id) ON DELETE CASCADE,\n FOREIGN KEY (selection_id) REFERENCES selections(id) ON DELETE CASCADE,\n FOREIGN KEY (document) REFERENCES documents(id) ON DELETE CASCADE\n);\n\n\nCREATE TABLE IF NOT EXISTS argument_values (\n id INTEGER PRIMARY KEY AUTOINCREMENT,\n kind TEXT NOT NULL CHECK (kind IN ('Variable', 'Int', 'Float', 'String', 'Block', 'Boolean', 'Null', 'Enum', 'List', 'Object')),\n raw TEXT NOT NULL,\n row INTEGER NOT NULL,\n column INTEGER NOT NULL,\n expected_type TEXT NOT NULL,\n expected_type_modifiers TEXT,\n document INTEGER NOT NULL,\n\n FOREIGN KEY (document) REFERENCES documents(id) ON DELETE CASCADE\n);\n\nCREATE TABLE IF NOT EXISTS argument_value_children (\n id INTEGER PRIMARY KEY AUTOINCREMENT,\n name TEXT,\n parent INTEGER NOT NULL,\n value INTEGER NOT NULL,\n row INTEGER NOT NULL,\n column INTEGER NOT NULL,\n document INTEGER NOT NULL,\n\n FOREIGN KEY (document) REFERENCES documents(id) ON DELETE CASCADE,\n FOREIGN KEY (parent) REFERENCES argument_values(id) ON DELETE CASCADE,\n FOREIGN KEY (value) REFERENCES argument_values(id) ON DELETE CASCADE\n);\n\nCREATE TABLE IF NOT EXISTS discovered_lists (\n id INTEGER PRIMARY KEY AUTOINCREMENT,\n name TEXT,\n node_type TEXT NOT NULL,\n edge_type TEXT,\n connection_type TEXT NOT NULL,\n node INTEGER NOT NULL,\n page_size INTEGER NOT NULL,\n document INTEGER NOT NULL,\n mode TEXT NOT NULL,\n embedded BOOLEAN NOT NULL,\n target_type TEXT NOT NULL,\n connection BOOLEAN default false,\n list_field INTEGER NOT NULL,\n paginate TEXT,\n supports_forward BOOLEAN default false,\n supports_backward BOOLEAN default false,\n cursor_type TEXT,\n\n FOREIGN KEY (list_field) REFERENCES selections(id) ON DELETE CASCADE,\n\t FOREIGN KEY (node) REFERENCES selections(id) ON DELETE CASCADE,\n FOREIGN KEY (node_type) REFERENCES types(name) ON DELETE CASCADE,\n FOREIGN KEY (document) REFERENCES documents(id) ON DELETE CASCADE\n);\n\n-- refetch_meta carries the \"refetch\" artifact-block metadata for documents that are\n-- refetchable but are NOT lists (e.g. @refetchable fragments). Lists keep their refetch\n-- metadata on discovered_lists since it is intrinsic to pagination; this table is for the\n-- list-less case so we don't have to fake a discovered_lists row.\nCREATE TABLE IF NOT EXISTS refetch_meta (\n id INTEGER PRIMARY KEY AUTOINCREMENT,\n document INTEGER NOT NULL,\n selection INTEGER NOT NULL,\n target_type TEXT NOT NULL,\n method TEXT NOT NULL DEFAULT 'offset',\n mode TEXT NOT NULL DEFAULT 'Infinite',\n page_size INTEGER NOT NULL DEFAULT 0,\n embedded BOOLEAN NOT NULL DEFAULT false,\n\n FOREIGN KEY (document) REFERENCES documents(id) ON DELETE CASCADE,\n FOREIGN KEY (selection) REFERENCES selections(id) ON DELETE CASCADE\n);\n\nCREATE TABLE IF NOT EXISTS document_dependencies (\n document INTEGER NOT NULL,\n depends_on TEXT NOT NULL,\n\n FOREIGN KEY (document) REFERENCES documents(id) ON DELETE CASCADE,\n UNIQUE (document, depends_on)\n);\n\n-----------------------------------------------------------\n-- Indices\n-----------------------------------------------------------\n\n-- component_fields\nCREATE INDEX IF NOT EXISTS idx_component_fields_type_fields ON component_fields(type_field);\n\n-- discovered_lists\nCREATE INDEX IF NOT EXISTS idx_discovered_lists_document ON discovered_lists(document);\nCREATE INDEX IF NOT EXISTS idx_discovered_lists_node ON discovered_lists(node);\nCREATE INDEX IF NOT EXISTS idx_discovered_lists_list_field ON discovered_lists(list_field);\n-- note: no index on discovered_lists(connection) \u2014 boolean column, ~2 distinct values\n\n-- refetch_meta\nCREATE INDEX IF NOT EXISTS idx_refetch_meta_selection ON refetch_meta(selection);\nCREATE INDEX IF NOT EXISTS idx_refetch_meta_document ON refetch_meta(document);\n\n-- types\nCREATE INDEX IF NOT EXISTS idx_types_kind_operation ON types(kind, operation);\n-- note: no index on types(name) \u2014 covered by PRIMARY KEY UNIQUE\n\n-- documents\nCREATE INDEX IF NOT EXISTS idx_documents_kind ON documents(kind);\nCREATE INDEX IF NOT EXISTS idx_documents_type_condition ON documents(type_condition);\nCREATE INDEX IF NOT EXISTS idx_documents_raw_document ON documents(raw_document);\nCREATE INDEX IF NOT EXISTS idx_documents_name_kind ON documents(name, kind);\n\n-- raw_documents\nCREATE INDEX IF NOT EXISTS idx_raw_documents_current_task ON raw_documents(current_task);\nCREATE INDEX IF NOT EXISTS idx_raw_documents_filepath ON raw_documents(filepath);\n\n-- selections\nCREATE INDEX IF NOT EXISTS idx_selections_type ON selections(type);\nCREATE INDEX IF NOT EXISTS idx_selections_alias ON selections(alias);\nCREATE INDEX IF NOT EXISTS idx_selections_field_name_kind ON selections(field_name, kind);\n\n-- selection_refs: composite covers document-only lookups, so no separate single-column index needed\nCREATE INDEX IF NOT EXISTS idx_selection_refs_parent_id ON selection_refs(parent_id);\n\nCREATE INDEX IF NOT EXISTS idx_selection_refs_child_id ON selection_refs(child_id);\nCREATE INDEX IF NOT EXISTS idx_selection_refs_document_parent_id ON selection_refs(document, parent_id);\n\n-- selection_directives / selection_directive_arguments / selection_arguments\nCREATE INDEX IF NOT EXISTS idx_selection_directives_selection ON selection_directives(selection_id);\nCREATE INDEX IF NOT EXISTS idx_selection_directives_directive ON selection_directives(directive);\nCREATE INDEX IF NOT EXISTS idx_selection_directive_arguments_parent_name ON selection_directive_arguments(parent, name);\n-- note: no index on selection_directive_arguments(parent) alone \u2014 covered by (parent,name) composite\nCREATE INDEX IF NOT EXISTS idx_selection_directive_arguments_value ON selection_directive_arguments(value);\n-- document FK on selection_directive_arguments and selection_arguments: used in WHERE/JOIN in CollectDocuments\nCREATE INDEX IF NOT EXISTS idx_selection_directive_arguments_document ON selection_directive_arguments(document);\nCREATE INDEX IF NOT EXISTS idx_selection_arguments_document ON selection_arguments(document);\nCREATE INDEX IF NOT EXISTS idx_selection_arguments_selection ON selection_arguments(selection_id);\nCREATE INDEX IF NOT EXISTS idx_selection_arguments_value ON selection_arguments(value);\n\n-- type_fields / type_field_arguments\n-- note: no index on type_fields(id) or type_field_arguments(id) \u2014 covered by their TEXT PRIMARY KEYs\nCREATE INDEX IF NOT EXISTS idx_type_fields_parent ON type_fields(parent);\nCREATE INDEX IF NOT EXISTS idx_type_fields_name ON type_fields(name);\nCREATE INDEX IF NOT EXISTS idx_type_configs_name ON type_configs(name);\n\n-- possible_types\n-- note: no index on possible_types(type) \u2014 covered by PRIMARY KEY(type,member) leading column\nCREATE INDEX IF NOT EXISTS idx_possible_types_member ON possible_types(member);\n\n-- type_fields: type and document FK columns have no implicit index\nCREATE INDEX IF NOT EXISTS idx_type_fields_type ON type_fields(type);\nCREATE INDEX IF NOT EXISTS idx_type_fields_document ON type_fields(document);\n\n-- enum_values\n-- note: no index on enum_values(parent) or (parent,value) \u2014 both covered by UNIQUE(parent,value)\n\n-- document_directives / document_directive_arguments\nCREATE INDEX IF NOT EXISTS idx_document_directives_document ON document_directives(document);\nCREATE INDEX IF NOT EXISTS idx_document_directives_directive ON document_directives(directive);\nCREATE INDEX IF NOT EXISTS idx_document_directive_arguments_parent_name ON document_directive_arguments(parent, name);\n-- note: no index on document_directive_arguments(parent) alone \u2014 covered by (parent,name) composite\nCREATE INDEX IF NOT EXISTS idx_document_directive_arguments_value on document_directive_arguments(value);\n\n-- document_variables\n-- note: no index on document_variables(document,name) \u2014 covered by UNIQUE(document,name)\n-- default_value FK is used as a JOIN column in validate and fragmentArguments transforms\nCREATE INDEX IF NOT EXISTS idx_document_variables_default_value ON document_variables(default_value);\nCREATE INDEX IF NOT EXISTS idx_document_variables_document_id ON document_variables(document, id);\nCREATE INDEX IF NOT EXISTS idx_document_variables_document_type_modifiers_default ON document_variables(document, type_modifiers, default_value);\n\n-- document_variable_directives / document_variable_directive_arguments\nCREATE INDEX IF NOT EXISTS idx_document_variable_directives_parent ON document_variable_directives(parent);\nCREATE INDEX IF NOT EXISTS idx_document_variable_directives_directive ON document_variable_directives(directive);\nCREATE INDEX IF NOT EXISTS idx_document_variable_directive_arguments_parent ON document_variable_directive_arguments(parent);\n\n-- document_dependencies\n-- note: no index on document_dependencies(document) \u2014 covered by UNIQUE(document,depends_on) leading column\nCREATE INDEX IF NOT EXISTS idx_document_dependency_depends_on on document_dependencies(depends_on);\n\n-- argument_values: composite (document,id) covers document-only lookups\n-- note: no separate index on argument_values(document) alone\nCREATE INDEX IF NOT EXISTS idx_argument_values_kind_raw ON argument_values(kind, raw);\nCREATE INDEX IF NOT EXISTS idx_argument_values_document_id ON argument_values(document, id);\nCREATE INDEX IF NOT EXISTS idx_argument_values_expected_type_document ON argument_values(expected_type, document);\n\n-- argument_value_children: composite (parent,value) covers parent-only lookups\n-- note: no separate index on argument_value_children(parent) alone\nCREATE INDEX IF NOT EXISTS idx_argument_value_children_parent_value ON argument_value_children(parent, value);\nCREATE INDEX IF NOT EXISTS idx_argument_value_children_value ON argument_value_children(value);\n-- document FK: large table; index needed for efficient CASCADE DELETE from documents\nCREATE INDEX IF NOT EXISTS idx_argument_value_children_document ON argument_value_children(document);\n";
6
+ export declare const schema_version: number;
6
7
  export declare function write_config(db: Db, config: Config, invoke_hook: (plugin: string, hook: string, args: Record<string, any>) => Promise<Record<string, any>>, plugins: Array<PluginSpec>, mode: string, logger?: Logger): Promise<void>;
@@ -1,3 +1,4 @@
1
+ import { createHash } from "node:crypto";
1
2
  import path from "node:path";
2
3
  import { Logger } from "./logger.js";
3
4
  import { default_config } from "./project.js";
@@ -374,6 +375,24 @@ CREATE TABLE IF NOT EXISTS discovered_lists (
374
375
  FOREIGN KEY (document) REFERENCES documents(id) ON DELETE CASCADE
375
376
  );
376
377
 
378
+ -- refetch_meta carries the "refetch" artifact-block metadata for documents that are
379
+ -- refetchable but are NOT lists (e.g. @refetchable fragments). Lists keep their refetch
380
+ -- metadata on discovered_lists since it is intrinsic to pagination; this table is for the
381
+ -- list-less case so we don't have to fake a discovered_lists row.
382
+ CREATE TABLE IF NOT EXISTS refetch_meta (
383
+ id INTEGER PRIMARY KEY AUTOINCREMENT,
384
+ document INTEGER NOT NULL,
385
+ selection INTEGER NOT NULL,
386
+ target_type TEXT NOT NULL,
387
+ method TEXT NOT NULL DEFAULT 'offset',
388
+ mode TEXT NOT NULL DEFAULT 'Infinite',
389
+ page_size INTEGER NOT NULL DEFAULT 0,
390
+ embedded BOOLEAN NOT NULL DEFAULT false,
391
+
392
+ FOREIGN KEY (document) REFERENCES documents(id) ON DELETE CASCADE,
393
+ FOREIGN KEY (selection) REFERENCES selections(id) ON DELETE CASCADE
394
+ );
395
+
377
396
  CREATE TABLE IF NOT EXISTS document_dependencies (
378
397
  document INTEGER NOT NULL,
379
398
  depends_on TEXT NOT NULL,
@@ -395,6 +414,10 @@ CREATE INDEX IF NOT EXISTS idx_discovered_lists_node ON discovered_lists(node);
395
414
  CREATE INDEX IF NOT EXISTS idx_discovered_lists_list_field ON discovered_lists(list_field);
396
415
  -- note: no index on discovered_lists(connection) \u2014 boolean column, ~2 distinct values
397
416
 
417
+ -- refetch_meta
418
+ CREATE INDEX IF NOT EXISTS idx_refetch_meta_selection ON refetch_meta(selection);
419
+ CREATE INDEX IF NOT EXISTS idx_refetch_meta_document ON refetch_meta(document);
420
+
398
421
  -- types
399
422
  CREATE INDEX IF NOT EXISTS idx_types_kind_operation ON types(kind, operation);
400
423
  -- note: no index on types(name) \u2014 covered by PRIMARY KEY UNIQUE
@@ -485,6 +508,7 @@ CREATE INDEX IF NOT EXISTS idx_argument_value_children_value ON argument_value_c
485
508
  -- document FK: large table; index needed for efficient CASCADE DELETE from documents
486
509
  CREATE INDEX IF NOT EXISTS idx_argument_value_children_document ON argument_value_children(document);
487
510
  `;
511
+ const schema_version = parseInt(createHash("sha1").update(create_schema).digest("hex").slice(0, 8), 16) & 2147483647;
488
512
  async function write_config(db, config, invoke_hook, plugins, mode, logger = new Logger(LogLevel.Summary)) {
489
513
  const env = {};
490
514
  logger.time("Environment");
@@ -595,5 +619,6 @@ async function write_config(db, config, invoke_hook, plugins, mode, logger = new
595
619
  }
596
620
  export {
597
621
  create_schema,
622
+ schema_version,
598
623
  write_config
599
624
  };
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "houdini",
3
- "version": "2.0.0-next.40",
3
+ "version": "2.0.0-next.45",
4
4
  "description": "The disappearing GraphQL clients",
5
5
  "keywords": [
6
6
  "typescript",
@@ -18,6 +18,7 @@
18
18
  "scripts": {
19
19
  "build": "scripts build-node",
20
20
  "compile": "scripts build-node",
21
+ "sync-schema": "node scripts/sync-schema.mjs",
21
22
  "typedefs": "scripts typedefs"
22
23
  },
23
24
  "devDependencies": {
@@ -194,4 +195,4 @@
194
195
  },
195
196
  "bin": "./build/cmd/index.js",
196
197
  "types": "./lib/index.d.ts"
197
- }
198
+ }
@@ -1,18 +1,16 @@
1
- import type { ConfigFile } from '../lib/index.js';
2
1
  import type { RouterManifest, RouterPageManifest } from './types.js';
3
- type GraphQLVariables = Record<string, string | number | boolean | null> | null;
2
+ type GraphQLScalar = string | number | boolean | null;
3
+ type GraphQLVariables = Record<string, GraphQLScalar | GraphQLScalar[]> | null;
4
4
  export type RouteParam = {
5
5
  name: string;
6
- matcher: string;
7
6
  optional: boolean;
8
7
  rest: boolean;
9
8
  chained: boolean;
10
9
  type?: string;
11
10
  };
12
- export type ParamMatcher = (param: string) => boolean;
13
11
  export declare function find_prefix_match<_ComponentType>(manifest: RouterManifest<_ComponentType>, url: string): RouterPageManifest<_ComponentType> | null;
14
- export declare function find_match<_ComponentType>(config: ConfigFile, manifest: RouterManifest<_ComponentType>, current: string, allowNull: true): [RouterPageManifest<_ComponentType> | null, GraphQLVariables];
15
- export declare function find_match<_ComponentType>(config: ConfigFile, manifest: RouterManifest<_ComponentType>, current: string, allowNull?: false): [RouterPageManifest<_ComponentType>, GraphQLVariables];
12
+ export declare function find_match<_ComponentType>(manifest: RouterManifest<_ComponentType>, current: string, allowNull: true): [RouterPageManifest<_ComponentType> | null, GraphQLVariables, Record<string, any>];
13
+ export declare function find_match<_ComponentType>(manifest: RouterManifest<_ComponentType>, current: string, allowNull?: false): [RouterPageManifest<_ComponentType>, GraphQLVariables, Record<string, any>];
16
14
  /**
17
15
  * Creates the regex pattern, extracts parameter names, and generates types for a route
18
16
  */
@@ -28,7 +26,7 @@ export declare function parse_page_pattern(id: string): {
28
26
  */
29
27
  export declare function get_route_segments(route: string): string[];
30
28
  export declare function exec(match: RegExpMatchArray, params: readonly RouteParam[]): Record<string, string> | undefined;
31
- export declare function parseScalar(config: ConfigFile, type: string, value?: string): string | number | boolean | undefined;
29
+ export declare function parseScalar(type: string, value?: string): string | number | boolean | undefined;
32
30
  export {};
33
31
  /**
34
32
  Copyright (c) 2020 [these people](https://github.com/sveltejs/kit/graphs/contributors)
@@ -1,6 +1,7 @@
1
- const param_pattern = /^(\[)?(\.\.\.)?(\w+)(?:=(\w+))?(\])?$/;
1
+ const param_pattern = /^(\[)?(\.\.\.)?(\w+)(\])?$/;
2
2
  function find_prefix_match(manifest, url) {
3
- const urlSegments = url.split("/").filter(Boolean);
3
+ const path = url.split("?")[0];
4
+ const urlSegments = path.split("/").filter(Boolean);
4
5
  let best = null;
5
6
  let bestCount = -1;
6
7
  for (const page of Object.values(manifest.pages)) {
@@ -25,11 +26,14 @@ function find_prefix_match(manifest, url) {
25
26
  }
26
27
  return best;
27
28
  }
28
- function find_match(config, manifest, current, allowNull = true) {
29
+ function find_match(manifest, current, allowNull = true) {
30
+ const queryIndex = current.indexOf("?");
31
+ const path = queryIndex === -1 ? current : current.slice(0, queryIndex);
32
+ const search = queryIndex === -1 ? "" : current.slice(queryIndex + 1);
29
33
  let match = null;
30
34
  let matchVariables = null;
31
35
  for (const page of Object.values(manifest.pages)) {
32
- const urlMatch = current.match(page.pattern);
36
+ const urlMatch = path.match(page.pattern);
33
37
  if (!urlMatch) {
34
38
  continue;
35
39
  }
@@ -47,35 +51,60 @@ function find_match(config, manifest, current, allowNull = true) {
47
51
  for (const [variable, { type }] of Object.entries(document.variables)) {
48
52
  if (matchVariables?.[variable]) {
49
53
  variables[variable] = parseScalar(
50
- config,
51
54
  type,
52
55
  matchVariables[variable]
53
56
  );
54
57
  }
55
58
  }
56
59
  }
57
- return [match, variables];
60
+ const searchObject = {};
61
+ if (search) {
62
+ const searchParams = new URLSearchParams(search);
63
+ for (const key of new Set(searchParams.keys())) {
64
+ const values = searchParams.getAll(key);
65
+ searchObject[key] = values.length > 1 ? values : values[0];
66
+ }
67
+ for (const { name, type, wrappers } of match?.searchParams ?? []) {
68
+ if (variables[name] != null) {
69
+ continue;
70
+ }
71
+ if (wrappers.includes("List")) {
72
+ const raw = searchParams.getAll(name);
73
+ if (raw.length === 0) {
74
+ continue;
75
+ }
76
+ variables[name] = raw.map((value) => parseScalar(type, value)).filter((value) => value !== void 0);
77
+ } else if (searchParams.has(name)) {
78
+ const parsed = parseScalar(type, searchParams.get(name) ?? void 0);
79
+ if (parsed !== void 0) {
80
+ variables[name] = parsed;
81
+ }
82
+ }
83
+ if (name in searchObject && variables[name] != null) {
84
+ searchObject[name] = variables[name];
85
+ }
86
+ }
87
+ }
88
+ return [match, variables, searchObject];
58
89
  }
59
90
  function parse_page_pattern(id) {
60
91
  const params = [];
61
92
  const pattern = id === "/" ? /^\/$/ : new RegExp(
62
93
  `^${get_route_segments(id).map((segment) => {
63
- const rest_match = /^\[\.\.\.(\w+)(?:=(\w+))?\]$/.exec(segment);
94
+ const rest_match = /^\[\.\.\.(\w+)\]$/.exec(segment);
64
95
  if (rest_match) {
65
96
  params.push({
66
97
  name: rest_match[1],
67
- matcher: rest_match[2],
68
98
  optional: false,
69
99
  rest: true,
70
100
  chained: true
71
101
  });
72
102
  return "(?:/(.*))?";
73
103
  }
74
- const optional_match = /^\[\[(\w+)(?:=(\w+))?\]\]$/.exec(segment);
104
+ const optional_match = /^\[\[(\w+)\]\]$/.exec(segment);
75
105
  if (optional_match) {
76
106
  params.push({
77
107
  name: optional_match[1],
78
- matcher: optional_match[2],
79
108
  optional: true,
80
109
  rest: false,
81
110
  chained: true
@@ -103,13 +132,12 @@ function parse_page_pattern(id) {
103
132
  const match = param_pattern.exec(content);
104
133
  if (!match) {
105
134
  throw new Error(
106
- `Invalid param: ${content}. Params and matcher names can only have underscores and alphanumeric characters.`
135
+ `Invalid param: ${content}. Params can only have underscores and alphanumeric characters.`
107
136
  );
108
137
  }
109
- const [, is_optional, is_rest, name, matcher] = match;
138
+ const [, is_optional, is_rest, name] = match;
110
139
  params.push({
111
140
  name,
112
- matcher,
113
141
  optional: !!is_optional,
114
142
  rest: !!is_rest,
115
143
  chained: is_rest ? i === 1 && parts[0] === "" : false
@@ -152,7 +180,7 @@ function exec(match, params) {
152
180
  function escapeRegex(str) {
153
181
  return str.normalize().replace(/[[\]]/g, "\\$&").replace(/%/g, "%25").replace(/\//g, "%2[Ff]").replace(/\?/g, "%3[Ff]").replace(/#/g, "%23").replace(/[.*+?^${}()|\\]/g, "\\$&");
154
182
  }
155
- function parseScalar(config, type, value) {
183
+ function parseScalar(type, value) {
156
184
  if (typeof value === "undefined") {
157
185
  return void 0;
158
186
  }
@@ -179,9 +207,6 @@ function parseScalar(config, type, value) {
179
207
  }
180
208
  return result;
181
209
  }
182
- if (config.scalars?.[type]?.marshal) {
183
- return config.scalars[type].marshal(value);
184
- }
185
210
  return value;
186
211
  }
187
212
  export {
@@ -21,10 +21,14 @@ export declare function _serverHandler<ComponentType = unknown>({ schema, server
21
21
  manifest: RouterManifest<unknown>;
22
22
  session: App.Session;
23
23
  componentCache: Record<string, any>;
24
+ headers: Record<string, string>;
24
25
  }) => Response | Promise<Response | undefined> | undefined;
25
26
  config_file: ConfigFile;
26
27
  } & Omit<YogaServerOptions, 'schema'>): (request: Request, ...extraContext: Array<any>) => Promise<Response>;
27
28
  export declare const serverAdapterFactory: (args: Parameters<typeof _serverHandler>[0]) => ReturnType<typeof createServerAdapter>;
29
+ export declare function collect_response_headers(match: {
30
+ headers?: Array<() => Promise<(() => unknown) | undefined>>;
31
+ } | null): Promise<Record<string, string>>;
28
32
  export type ServerAdapterFactory = typeof serverAdapterFactory;
29
33
  type YogaParams = Required<ConstructorParameters<typeof YogaServer>>[0];
30
34
  type YogaSchemaDefinition<TContext> = NonNullable<YogaConfig<any, TContext>['schema']>;
@@ -58,8 +58,9 @@ function _serverHandler({
58
58
  { status: 500 }
59
59
  );
60
60
  }
61
- const url = new URL(request.url).pathname;
62
- if (requestHandler && url === graphqlEndpoint) {
61
+ const parsedURL = new URL(request.url);
62
+ const url = parsedURL.pathname + parsedURL.search;
63
+ if (requestHandler && parsedURL.pathname === graphqlEndpoint) {
63
64
  return requestHandler(request, ...extraContext);
64
65
  }
65
66
  const authResponse = await handle_request({
@@ -70,16 +71,18 @@ function _serverHandler({
70
71
  if (authResponse) {
71
72
  return authResponse;
72
73
  }
73
- const [exactMatch] = find_match(config_file, manifest, url);
74
+ const [exactMatch] = find_match(manifest, url);
74
75
  const is404 = !exactMatch;
75
76
  const match = exactMatch ?? find_prefix_match(manifest, url);
77
+ const headers = await collect_response_headers(match);
76
78
  const rendered = await on_render({
77
79
  url,
78
80
  match,
79
81
  is404,
80
82
  session: await get_session(request.headers, session_keys),
81
83
  manifest,
82
- componentCache
84
+ componentCache,
85
+ headers
83
86
  });
84
87
  if (rendered) {
85
88
  return rendered;
@@ -90,6 +93,22 @@ function _serverHandler({
90
93
  const serverAdapterFactory = (args) => {
91
94
  return createServerAdapter(_serverHandler(args));
92
95
  };
96
+ async function collect_response_headers(match) {
97
+ const merged = {};
98
+ for (const load of match?.headers ?? []) {
99
+ const fn = await load();
100
+ if (typeof fn !== "function") {
101
+ continue;
102
+ }
103
+ const result = await fn();
104
+ if (result && typeof result === "object") {
105
+ for (const [key, value] of Object.entries(result)) {
106
+ merged[key] = String(value);
107
+ }
108
+ }
109
+ }
110
+ return merged;
111
+ }
93
112
  function localApiSessionKeys(configFile) {
94
113
  return configFile.router?.auth?.sessionKeys ?? [];
95
114
  }
@@ -129,5 +148,6 @@ class Server {
129
148
  export {
130
149
  Server,
131
150
  _serverHandler,
151
+ collect_response_headers,
132
152
  serverAdapterFactory
133
153
  };
@@ -5,6 +5,7 @@ export type YogaServer = ReturnType<typeof createYoga>;
5
5
  export type YogaServerOptions = Parameters<typeof createYoga>[0];
6
6
  export type RouterManifest<_ComponentType> = {
7
7
  pages: Record<string, RouterPageManifest<_ComponentType>>;
8
+ pagesByUrl: Record<string, string>;
8
9
  };
9
10
  export type { ServerAdapterFactory } from './server.js';
10
11
  export type RouterPageManifest<_ComponentType> = {
@@ -12,6 +13,7 @@ export type RouterPageManifest<_ComponentType> = {
12
13
  url: string;
13
14
  pattern: RegExp;
14
15
  params: readonly RouteParam[];
16
+ searchParams: readonly SearchParam[];
15
17
  documents: Record<string, {
16
18
  artifact: () => Promise<{
17
19
  default: QueryArtifact;
@@ -24,4 +26,12 @@ export type RouterPageManifest<_ComponentType> = {
24
26
  component: () => Promise<{
25
27
  default: _ComponentType;
26
28
  }>;
29
+ headers?: Array<() => Promise<RouteHeaderFunction | undefined>>;
27
30
  };
31
+ export type SearchParam = {
32
+ name: string;
33
+ type: string;
34
+ wrappers: readonly string[];
35
+ };
36
+ export type RouteHeaderFunction = () => RouteHeaders | Promise<RouteHeaders>;
37
+ export type RouteHeaders = Record<string, string>;
@@ -44,7 +44,7 @@ export declare class Cache {
44
44
  field?: string;
45
45
  when?: {};
46
46
  }): void;
47
- refresh(id: string): void;
47
+ refresh(id: string | string[]): void;
48
48
  markRecordStale(id: string, options: {
49
49
  field?: string;
50
50
  when?: {};
@@ -4,7 +4,7 @@ import { flatten } from "../flatten.js";
4
4
  import { computeKey } from "../key.js";
5
5
  import { getFieldsForType } from "../selection.js";
6
6
  import { PendingValue } from "../types.js";
7
- import { fragmentKey } from "../types.js";
7
+ import { ArtifactKind, fragmentKey } from "../types.js";
8
8
  import { GarbageCollector } from "./gc.js";
9
9
  import { ListManager, opaqueListID } from "./lists.js";
10
10
  import { StaleManager } from "./staleManager.js";
@@ -126,21 +126,29 @@ class Cache {
126
126
  );
127
127
  }
128
128
  }
129
- // ask every document whose data contains the record to refetch itself.
130
- // this includes documents that only contain the record behind a masked
131
- // boundary (a fragment spread) thanks to their masked parent subscriptions
129
+ // ask every document whose data contains the record(s) to refetch itself.
130
+ // this includes documents that only contain a record behind a masked
131
+ // boundary (a fragment spread) thanks to their masked parent subscriptions.
132
+ // passing several ids notifies each document at most once, even if it
133
+ // depends on more than one of them (eg a list returned by a mutation).
132
134
  refresh(id) {
133
- const recordIDs = [this._internal_unstable.storage.idMaps[id], id].filter(
134
- Boolean
135
- );
135
+ const ids = Array.isArray(id) ? id : [id];
136
136
  const notified = /* @__PURE__ */ new Set();
137
- for (const recordID of recordIDs) {
138
- for (const [spec] of this._internal_unstable.subscriptions.getAll(recordID, {
139
- includeMaskedParents: true
140
- })) {
141
- if (!notified.has(spec.onMessage)) {
142
- notified.add(spec.onMessage);
143
- spec.onMessage({ kind: "refetch" });
137
+ for (const baseID of ids) {
138
+ const recordIDs = [this._internal_unstable.storage.idMaps[baseID], baseID].filter(
139
+ Boolean
140
+ );
141
+ for (const recordID of recordIDs) {
142
+ for (const [spec] of this._internal_unstable.subscriptions.getAll(recordID, {
143
+ includeMaskedParents: true
144
+ })) {
145
+ if (spec.kind === ArtifactKind.Subscription) {
146
+ continue;
147
+ }
148
+ if (!notified.has(spec.onMessage)) {
149
+ notified.add(spec.onMessage);
150
+ spec.onMessage({ kind: "refetch" });
151
+ }
144
152
  }
145
153
  }
146
154
  }
@@ -587,9 +595,10 @@ class CacheInternal {
587
595
  let parentID;
588
596
  if (operation.parentID) {
589
597
  if (operation.parentID.kind !== "Variable") {
590
- parentID = operation.parentID.value;
598
+ parentID = "value" in operation.parentID ? String(operation.parentID.value) : void 0;
591
599
  } else {
592
- const id = variables[operation.parentID.value];
600
+ const varName = operation.parentID.name.value;
601
+ const id = variables[varName];
593
602
  if (typeof id !== "string") {
594
603
  throw new Error("parentID value must be a string");
595
604
  }
@@ -599,9 +608,10 @@ class CacheInternal {
599
608
  let opaqueListID2;
600
609
  if (operation.listID) {
601
610
  if (operation.listID.kind !== "Variable") {
602
- opaqueListID2 = operation.listID.value;
611
+ opaqueListID2 = "value" in operation.listID ? String(operation.listID.value) : void 0;
603
612
  } else {
604
- const id = variables[operation.listID.value];
613
+ const varName = operation.listID.name.value;
614
+ const id = variables[varName];
605
615
  if (typeof id !== "string") {
606
616
  throw new Error("listID value must be a string");
607
617
  }
@@ -52,6 +52,7 @@ export declare class InMemorySubscriptions {
52
52
  remove(id: string, selection: SubscriptionSelection, targets: SubscriptionSpec[], variables: {}, visited?: string[], masked?: boolean): void;
53
53
  reset(): Readonly<{
54
54
  rootType: string;
55
+ kind?: import("../types.js").ArtifactKinds;
55
56
  selection: SubscriptionSelection;
56
57
  onMessage: (message: import("../types.js").CacheMessage) => void;
57
58
  parentID?: string;
@@ -3,5 +3,6 @@ export declare function getMockConfig(): ConfigFile | null;
3
3
  export declare function setMockConfig(config: ConfigFile | null): void;
4
4
  export declare function defaultConfigValues(file: ConfigFile): ConfigFile;
5
5
  export declare function keyFieldsForType(configFile: ConfigFile, type: string): string[];
6
+ export declare function entityRefetchVariables(configFile: ConfigFile, targetType: string | undefined | null, state: Record<string, any> | null | undefined): Record<string, any>;
6
7
  export declare function computeID(configFile: ConfigFile, type: string, data: any): string;
7
8
  export declare function getCurrentConfig(): ConfigFile;
@@ -25,6 +25,18 @@ function keyFieldsForType(configFile, type) {
25
25
  const withDefault = defaultConfigValues(configFile);
26
26
  return withDefault.types?.[type]?.keys || withDefault.defaultKeys;
27
27
  }
28
+ function entityRefetchVariables(configFile, targetType, state) {
29
+ if (!targetType || targetType === "Query" || !state) {
30
+ return {};
31
+ }
32
+ const config = defaultConfigValues(configFile);
33
+ const typeConfig = config.types?.[targetType];
34
+ if (typeConfig?.resolve?.arguments) {
35
+ return typeConfig.resolve.arguments(state) ?? {};
36
+ }
37
+ const keys = keyFieldsForType(config, targetType);
38
+ return Object.fromEntries(keys.map((key) => [key, state[key]]));
39
+ }
28
40
  function computeID(configFile, type, data) {
29
41
  const fields = keyFieldsForType(configFile, type);
30
42
  let id = "";
@@ -49,6 +61,7 @@ function getCurrentConfig() {
49
61
  export {
50
62
  computeID,
51
63
  defaultConfigValues,
64
+ entityRefetchVariables,
52
65
  getCurrentConfig,
53
66
  getMockConfig,
54
67
  keyFieldsForType,
@@ -2,7 +2,7 @@ export * from './client.js';
2
2
  export { deepEquals } from './deepEquals.js';
3
3
  export * from './scalars.js';
4
4
  export * from './types.js';
5
- export { computeID, keyFieldsForType, setMockConfig, getMockConfig, getCurrentConfig, } from './config.js';
5
+ export { computeID, keyFieldsForType, entityRefetchVariables, setMockConfig, getMockConfig, getCurrentConfig, } from './config.js';
6
6
  export { getFieldsForType } from './selection.js';
7
7
  export { flatten } from './flatten.js';
8
8
  export * from './pageInfo.js';
@@ -5,6 +5,7 @@ export * from "./types.js";
5
5
  import {
6
6
  computeID,
7
7
  keyFieldsForType,
8
+ entityRefetchVariables,
8
9
  setMockConfig,
9
10
  getMockConfig,
10
11
  getCurrentConfig
@@ -21,6 +22,7 @@ export {
21
22
  computeID,
22
23
  createLRUCache,
23
24
  deepEquals,
25
+ entityRefetchVariables,
24
26
  flatten,
25
27
  getCurrentConfig,
26
28
  getFieldsForType,
@@ -72,6 +72,7 @@ export type MutationArtifact = BaseCompiledDocument<'HoudiniMutation'> & {
72
72
  };
73
73
  export type FragmentArtifact = BaseCompiledDocument<'HoudiniFragment'> & {
74
74
  enableLoadingState?: 'global' | 'local';
75
+ plural?: boolean;
75
76
  };
76
77
  export type SubscriptionArtifact = BaseCompiledDocument<'HoudiniSubscription'>;
77
78
  export declare const RefetchUpdateMode: {
@@ -107,8 +108,14 @@ export type BaseCompiledDocument<_Kind extends ArtifactKinds> = Readonly<{
107
108
  direction: 'forward' | 'backward' | 'both';
108
109
  mode: PaginateModes;
109
110
  };
111
+ operations?: readonly RootOperation[];
110
112
  pluginData: Record<string, any>;
111
113
  }>;
114
+ export type RootOperation = {
115
+ action: 'refetch';
116
+ type: string;
117
+ path: readonly string[];
118
+ };
112
119
  export type HoudiniFetchContext = {
113
120
  variables: () => {};
114
121
  };
@@ -146,14 +153,8 @@ export type MutationOperation = {
146
153
  action: 'insert' | 'remove' | 'delete' | 'toggle' | 'upsert';
147
154
  list?: string;
148
155
  type?: string;
149
- parentID?: {
150
- kind: string;
151
- value: string;
152
- };
153
- listID?: {
154
- kind: string;
155
- value: string;
156
- };
156
+ parentID?: ValueNode;
157
+ listID?: ValueNode;
157
158
  position?: 'first' | 'last';
158
159
  target?: 'all';
159
160
  when?: {
@@ -256,6 +257,7 @@ export type CacheMessage<_Data = any> = {
256
257
  };
257
258
  export type SubscriptionSpec = Readonly<{
258
259
  rootType: string;
260
+ kind?: ArtifactKinds;
259
261
  selection: SubscriptionSelection;
260
262
  onMessage: (message: CacheMessage) => void;
261
263
  parentID?: string;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "houdini",
3
- "version": "2.0.0-next.40",
3
+ "version": "2.0.0-next.45",
4
4
  "description": "The disappearing GraphQL clients",
5
5
  "keywords": [
6
6
  "typescript",
@@ -50,7 +50,7 @@
50
50
  "recast": "^0.23.11",
51
51
  "sql.js": "^1.14.1",
52
52
  "ws": "^8.21.0",
53
- "houdini-core": "^2.0.0-next.27"
53
+ "houdini-core": "^2.0.0-next.31"
54
54
  },
55
55
  "peerDependencies": {
56
56
  "graphql": ">=16",
@@ -183,6 +183,7 @@
183
183
  "scripts": {
184
184
  "build": "scripts build-node",
185
185
  "compile": "scripts build-node",
186
+ "sync-schema": "node scripts/sync-schema.mjs",
186
187
  "typedefs": "scripts typedefs"
187
188
  },
188
189
  "bin": {