diff --git a/.eslintrc.json b/.eslintrc.json deleted file mode 100644 index 825c5fe69a..0000000000 --- a/.eslintrc.json +++ /dev/null @@ -1,67 +0,0 @@ -{ - "env": { - "browser": true, - "es2021": true, - "node": true, - "jest": true - }, - "extends": [ - "eslint:recommended", - "plugin:@typescript-eslint/recommended", - "prettier" - ], - "overrides": [], - "parser": "@typescript-eslint/parser", - "parserOptions": { - "ecmaVersion": "latest", - "sourceType": "module" - }, - "plugins": [ - "@typescript-eslint", - "simple-import-sort", - "unused-imports" - ], - "rules": { - "indent": [ - "error", - 2 - ], - "quotes": [ - "error", - "single", - { - "avoidEscape": true, - "allowTemplateLiterals": true - } - ], - "quote-props": [ - "error", - "as-needed" - ], - "semi": [ - "error", - "always" - ], - "comma-dangle": [ - "error", - "never" - ], - "simple-import-sort/imports": 1, - "simple-import-sort/exports": 1, - "unused-imports/no-unused-imports": 1, - "@typescript-eslint/no-unused-vars": [ - 1, - { - "argsIgnorePattern": "React|res|next|^_" - } - ], - "@typescript-eslint/no-explicit-any": 0, - "@typescript-eslint/no-var-requires": 0, - "no-console": 0, - "@typescript-eslint/ban-ts-comment": 0, - "prefer-const": 0, - "no-case-declarations": 0, - "no-implicit-globals": 0, - "@typescript-eslint/no-unsafe-declaration-merging": 0 - } -} diff --git a/agentic/agent/__tests__/agent.live.test.ts b/agentic/agent/__tests__/agent.live.test.ts index f0c5e84cce..1935d72fc7 100644 --- a/agentic/agent/__tests__/agent.live.test.ts +++ b/agentic/agent/__tests__/agent.live.test.ts @@ -1,5 +1,5 @@ +import { type AssistantMessage,createUserMessage } from '@agentic-kit/chat'; import { OpenAIAdapter } from '@agentic-kit/openai'; -import { createUserMessage, type AssistantMessage } from '@agentic-kit/chat'; import { Agent } from '../src'; diff --git a/agentic/agent/__tests__/agent.test.ts b/agentic/agent/__tests__/agent.test.ts index c47ec6a651..454458145b 100644 --- a/agentic/agent/__tests__/agent.test.ts +++ b/agentic/agent/__tests__/agent.test.ts @@ -1,9 +1,3 @@ -import { - createScriptedProvider, - makeFakeAssistantMessage, - makeFakeModel, - ZERO_USAGE, -} from './helpers'; import { type AssistantMessage, type Context, @@ -20,6 +14,12 @@ import { type AgentTool, DecisionValidationError, } from '../src'; +import { + createScriptedProvider, + makeFakeAssistantMessage, + makeFakeModel, + ZERO_USAGE, +} from './helpers'; describe('@agentic-kit/agent', () => { it('runs a minimal sequential tool loop', async () => { diff --git a/agentic/agent/__tests__/run-handle.test.ts b/agentic/agent/__tests__/run-handle.test.ts index 0d9a339210..d629d4cda3 100644 --- a/agentic/agent/__tests__/run-handle.test.ts +++ b/agentic/agent/__tests__/run-handle.test.ts @@ -1,8 +1,3 @@ -import { - createScriptedProvider, - makeFakeAssistantMessage, - makeFakeModel, -} from './helpers'; import { type AssistantMessageEvent, type Context, @@ -12,6 +7,11 @@ import { } from '@agentic-kit/chat'; import { Agent, type AgentEvent, type AgentTool, parseSSEStream } from '../src'; +import { + createScriptedProvider, + makeFakeAssistantMessage, + makeFakeModel, +} from './helpers'; describe('AgentRunHandle', () => { describe('events()', () => { diff --git a/agentic/agentic-kit/src/index.ts b/agentic/agentic-kit/src/index.ts index 5fe63af1f5..cc1930cec5 100644 --- a/agentic/agentic-kit/src/index.ts +++ b/agentic/agentic-kit/src/index.ts @@ -1,4 +1,3 @@ -export * from '@agentic-kit/chat'; - export * as agent from '@agentic-kit/agent'; +export * from '@agentic-kit/chat'; export * as harness from '@agentic-kit/harness'; diff --git a/agentic/chat/__tests__/adapter.test.ts b/agentic/chat/__tests__/adapter.test.ts index af1483da06..11657f79b0 100644 --- a/agentic/chat/__tests__/adapter.test.ts +++ b/agentic/chat/__tests__/adapter.test.ts @@ -1,9 +1,3 @@ -import { - createScriptedProvider, - makeFakeAssistantMessage, - makeFakeModel, -} from './helpers'; - import { AgentKit, type AssistantMessage, @@ -11,6 +5,11 @@ import { type ModelDescriptor, transformMessages, } from '../src'; +import { + createScriptedProvider, + makeFakeAssistantMessage, + makeFakeModel, +} from './helpers'; function createFakeModel(): ModelDescriptor { return makeFakeModel({ name: 'Demo' }); diff --git a/agentic/chat/__tests__/inject-deferral-results.test.ts b/agentic/chat/__tests__/inject-deferral-results.test.ts index 9202c490b4..318b7fb786 100644 --- a/agentic/chat/__tests__/inject-deferral-results.test.ts +++ b/agentic/chat/__tests__/inject-deferral-results.test.ts @@ -1,7 +1,6 @@ -import { makeFakeAssistantMessage } from './helpers'; - import type { AssistantMessage, Message, ToolResultMessage } from '../src'; import { injectDeferralResults } from '../src'; +import { makeFakeAssistantMessage } from './helpers'; function assistantWithToolCall( id: string, diff --git a/agentic/cli/src/config.ts b/agentic/cli/src/config.ts index 74794eea56..626078a24b 100644 --- a/agentic/cli/src/config.ts +++ b/agentic/cli/src/config.ts @@ -1,8 +1,7 @@ +import { HarnessDirs, harnessDirs, SkillsManifest } from '@agentic-kit/harness'; import * as fs from 'fs'; import * as path from 'path'; -import { harnessDirs, HarnessDirs, SkillsManifest } from '@agentic-kit/harness'; - export const DEFAULT_SKILLS_REPO = 'constructive-io/constructive-skills'; export const DEFAULT_SKILLS_PIN = 'main'; diff --git a/agentic/cli/src/index.ts b/agentic/cli/src/index.ts index 8747f4b44b..95415ceb0a 100644 --- a/agentic/cli/src/index.ts +++ b/agentic/cli/src/index.ts @@ -1,12 +1,12 @@ #!/usr/bin/env node -import { loadConfig } from './config'; import { init, skillsList, skillsUpdate, usage } from './commands'; +import { loadConfig } from './config'; import { materializeDbTools } from './db-tools'; import { assembleSkills } from './skills'; -export { assembleSkills } from './skills'; export { AgentCliConfig, loadConfig } from './config'; export { HOST_ENV_VARS, materializeDbTools } from './db-tools'; +export { assembleSkills } from './skills'; async function run(args: string[]): Promise { const config = loadConfig(process.env.AGENT_HOME); diff --git a/agentic/cli/src/skills.ts b/agentic/cli/src/skills.ts index 17aab835b3..c3233d2be7 100644 --- a/agentic/cli/src/skills.ts +++ b/agentic/cli/src/skills.ts @@ -1,5 +1,3 @@ -import * as path from 'path'; - import { DirectorySkillSource, fetchSkillsFromGit, @@ -9,6 +7,7 @@ import { resolveSkills, SkillSource } from '@agentic-kit/harness'; +import * as path from 'path'; import { AgentCliConfig, BASE_LAYER, OVERLAY_LAYER } from './config'; diff --git a/agentic/harness/__tests__/blueprint.test.ts b/agentic/harness/__tests__/blueprint.test.ts index 22c0ecbe2a..3ecec5a515 100644 --- a/agentic/harness/__tests__/blueprint.test.ts +++ b/agentic/harness/__tests__/blueprint.test.ts @@ -1,6 +1,6 @@ import { expandBlueprintDefaults } from '../src/blueprint/blueprint-defaults'; -import { fieldTypeToTypeName, toFieldDefault, toFieldType } from '../src/blueprint/field-type'; import type { BlueprintDefinition } from '../src/blueprint/blueprint-schema'; +import { fieldTypeToTypeName, toFieldDefault, toFieldType } from '../src/blueprint/field-type'; describe('field-type conversions', () => { it('round-trips array types', () => { diff --git a/agentic/harness/__tests__/fetch.test.ts b/agentic/harness/__tests__/fetch.test.ts index b901abad9c..3c1bba1387 100644 --- a/agentic/harness/__tests__/fetch.test.ts +++ b/agentic/harness/__tests__/fetch.test.ts @@ -2,7 +2,6 @@ import * as crypto from 'crypto'; import * as fs from 'fs'; import * as os from 'os'; import * as path from 'path'; - import * as tar from 'tar'; import { fetchSkillsRelease, latestLocalRelease, resolvePin } from '../src/skills/fetch'; diff --git a/agentic/harness/__tests__/gating.test.ts b/agentic/harness/__tests__/gating.test.ts index 54c19ad8c1..d6d5aebee7 100644 --- a/agentic/harness/__tests__/gating.test.ts +++ b/agentic/harness/__tests__/gating.test.ts @@ -1,4 +1,4 @@ -import { createConfirmGate, ConfirmGate, ConfirmGateDeps, GateHost } from '../src/gating/confirm-gate'; +import { ConfirmGate, ConfirmGateDeps, createConfirmGate, GateHost } from '../src/gating/confirm-gate'; import { createDeclineGuard } from '../src/gating/decline-guard'; import { buildConfirmPrompt } from '../src/gating/prompts'; diff --git a/agentic/harness/__tests__/git-fetch.test.ts b/agentic/harness/__tests__/git-fetch.test.ts index d88bbb4dd3..d54f0180f5 100644 --- a/agentic/harness/__tests__/git-fetch.test.ts +++ b/agentic/harness/__tests__/git-fetch.test.ts @@ -1,7 +1,6 @@ import * as fs from 'fs'; import * as os from 'os'; import * as path from 'path'; - import * as tar from 'tar'; import { fetchSkillsFromGit, listGitTagVersions } from '../src/skills/git-fetch'; diff --git a/agentic/harness/src/blueprint/blueprint-defaults.ts b/agentic/harness/src/blueprint/blueprint-defaults.ts index 52cc796702..8d5c74e3c0 100644 --- a/agentic/harness/src/blueprint/blueprint-defaults.ts +++ b/agentic/harness/src/blueprint/blueprint-defaults.ts @@ -1,3 +1,4 @@ +import type { BlueprintDefinition } from './blueprint-schema'; import { type FieldDefault, type FieldType, toFieldDefault, toFieldType } from './field-type'; import { buildNodeData, @@ -5,7 +6,6 @@ import { getPolicyFieldDefaults, getPolicyProvisioningConfig, } from './policy-provisioning'; -import type { BlueprintDefinition } from './blueprint-schema'; const DEFAULT_GRANTS = [ { diff --git a/agentic/harness/src/gating/prompts.ts b/agentic/harness/src/gating/prompts.ts index 33a507b63f..0e951db9de 100644 --- a/agentic/harness/src/gating/prompts.ts +++ b/agentic/harness/src/gating/prompts.ts @@ -15,9 +15,8 @@ export const MUTATING_DB_TOOLS = new Set([ 'run_codegen', ]); -import type { ConfirmPreview, ConfirmPreviewField, ConfirmPreviewTable } from './preview'; - import { filterInternalPolicies } from '../blueprint/internal-policies'; +import type { ConfirmPreview, ConfirmPreviewField, ConfirmPreviewTable } from './preview'; export type ConfirmPrompt = { title: string; message: string; preview?: ConfirmPreview }; @@ -81,113 +80,113 @@ export function buildConfirmPrompt( input: Record | undefined, ): ConfirmPrompt { switch (toolName) { - case 'provision_database': { - const name = str(input, 'database_name') ?? 'new database'; - return { - title: 'Provision database?', - message: `Sign up an owner and provision a new Constructive database "${name}" (standard module set), then write credentials to the project .env.`, - }; - } - case 'provision_blueprint': { - const name = str(input, 'name') ?? 'new schema'; - const tables = blueprintTables(input); - const count = tables.length; - return { - title: 'Create tables?', - message: `Provision blueprint "${name}"${count ? ` (${count} table${count === 1 ? '' : 's'})` : ''} in the project database.`, - preview: count > 0 ? { kind: 'blueprint', tables } : undefined, - }; - } - case 'add_relation': { - const source = str(input, 'source_table') ?? '?'; - const target = str(input, 'target_table') ?? '?'; - const isManyToMany = str(input, 'relation_type') === 'many_to_many'; - const message = isManyToMany - ? `Create a junction table "${str(input, 'junction_table_name') ?? '?'}" linking existing tables "${source}" ↔ "${target}".` - : `Add a foreign-key column "${str(input, 'field_name') ?? '?'}" on existing table "${source}" referencing "${target}".`; - return { title: 'Add relation?', message }; - } - case 'delete_table': - return { - title: 'Delete table?', - message: `Permanently delete the table "${str(input, 'table_name') ?? '?'}" and its data.`, - }; - case 'create_field': { - const tableName = str(input, 'table_name') ?? '?'; - const fieldName = str(input, 'field_name') ?? '?'; - return { - title: 'Add field?', - message: `Add field "${fieldName}" to table "${tableName}".`, - preview: { - kind: 'field', - tableName, - field: { - name: fieldName, - type: str(input, 'type') ?? '?', - isRequired: input?.is_required === true, - defaultValue: str(input, 'default_value') ?? null, - }, + case 'provision_database': { + const name = str(input, 'database_name') ?? 'new database'; + return { + title: 'Provision database?', + message: `Sign up an owner and provision a new Constructive database "${name}" (standard module set), then write credentials to the project .env.`, + }; + } + case 'provision_blueprint': { + const name = str(input, 'name') ?? 'new schema'; + const tables = blueprintTables(input); + const count = tables.length; + return { + title: 'Create tables?', + message: `Provision blueprint "${name}"${count ? ` (${count} table${count === 1 ? '' : 's'})` : ''} in the project database.`, + preview: count > 0 ? { kind: 'blueprint', tables } : undefined, + }; + } + case 'add_relation': { + const source = str(input, 'source_table') ?? '?'; + const target = str(input, 'target_table') ?? '?'; + const isManyToMany = str(input, 'relation_type') === 'many_to_many'; + const message = isManyToMany + ? `Create a junction table "${str(input, 'junction_table_name') ?? '?'}" linking existing tables "${source}" ↔ "${target}".` + : `Add a foreign-key column "${str(input, 'field_name') ?? '?'}" on existing table "${source}" referencing "${target}".`; + return { title: 'Add relation?', message }; + } + case 'delete_table': + return { + title: 'Delete table?', + message: `Permanently delete the table "${str(input, 'table_name') ?? '?'}" and its data.`, + }; + case 'create_field': { + const tableName = str(input, 'table_name') ?? '?'; + const fieldName = str(input, 'field_name') ?? '?'; + return { + title: 'Add field?', + message: `Add field "${fieldName}" to table "${tableName}".`, + preview: { + kind: 'field', + tableName, + field: { + name: fieldName, + type: str(input, 'type') ?? '?', + isRequired: input?.is_required === true, + defaultValue: str(input, 'default_value') ?? null, }, - }; - } - case 'update_field': - return { - title: 'Update field?', - message: `Modify field "${str(input, 'field_name') ?? '?'}" on table "${str(input, 'table_name') ?? '?'}".`, - }; - case 'delete_field': - return { - title: 'Delete field?', - message: `Permanently delete field "${str(input, 'field_name') ?? '?'}" from table "${str(input, 'table_name') ?? '?'}".`, - }; - case 'add_policies': { - const tableName = str(input, 'table_name') ?? '?'; - const policies = policyTypes(input); - const count = policies.length; - return { - title: 'Add policies?', - message: `Add ${count || ''} RLS ${count === 1 ? 'policy' : 'policies'} to table "${tableName}".`, - preview: count > 0 ? { kind: 'policies', tableName, policies } : undefined, - }; - } - case 'apply_template': - return { - title: 'Apply template?', - message: `Apply blueprint template "${str(input, 'templateName') ?? '?'}" to the project database.`, - }; - case 'create_template': { - const source = str(input, 'blueprintName'); - return { - title: 'Create template?', - message: `Create reusable template "${str(input, 'displayName') ?? '?'}" in the catalog from ${source ? `blueprint "${source}"` : 'the latest blueprint'}.`, - }; - } - case 'update_template': - return { - title: 'Update template?', - message: `Update blueprint template "${str(input, 'templateName') ?? '?'}".`, - }; - case 'delete_template': - return { - title: 'Delete template?', - message: `Permanently delete blueprint template "${str(input, 'templateName') ?? '?'}".`, - }; - case 'add_records': { - const rows = recordRows(input); - const count = rows.length; - const tableName = str(input, 'table_name') ?? '?'; - return { - title: 'Add records?', - message: `Insert ${count || ''} row${count === 1 ? '' : 's'} into table "${tableName}".`, - preview: count > 0 ? { kind: 'records', tableName, rows } : undefined, - }; - } - case 'run_codegen': - return { - title: 'Run codegen?', - message: 'Generate the typed GraphQL SDK in packages/app (upgrade codegen, run it, normalize barrels).', - }; - default: - return { title: 'Run tool?', message: `Allow "${toolName}" to run?` }; + }, + }; + } + case 'update_field': + return { + title: 'Update field?', + message: `Modify field "${str(input, 'field_name') ?? '?'}" on table "${str(input, 'table_name') ?? '?'}".`, + }; + case 'delete_field': + return { + title: 'Delete field?', + message: `Permanently delete field "${str(input, 'field_name') ?? '?'}" from table "${str(input, 'table_name') ?? '?'}".`, + }; + case 'add_policies': { + const tableName = str(input, 'table_name') ?? '?'; + const policies = policyTypes(input); + const count = policies.length; + return { + title: 'Add policies?', + message: `Add ${count || ''} RLS ${count === 1 ? 'policy' : 'policies'} to table "${tableName}".`, + preview: count > 0 ? { kind: 'policies', tableName, policies } : undefined, + }; + } + case 'apply_template': + return { + title: 'Apply template?', + message: `Apply blueprint template "${str(input, 'templateName') ?? '?'}" to the project database.`, + }; + case 'create_template': { + const source = str(input, 'blueprintName'); + return { + title: 'Create template?', + message: `Create reusable template "${str(input, 'displayName') ?? '?'}" in the catalog from ${source ? `blueprint "${source}"` : 'the latest blueprint'}.`, + }; + } + case 'update_template': + return { + title: 'Update template?', + message: `Update blueprint template "${str(input, 'templateName') ?? '?'}".`, + }; + case 'delete_template': + return { + title: 'Delete template?', + message: `Permanently delete blueprint template "${str(input, 'templateName') ?? '?'}".`, + }; + case 'add_records': { + const rows = recordRows(input); + const count = rows.length; + const tableName = str(input, 'table_name') ?? '?'; + return { + title: 'Add records?', + message: `Insert ${count || ''} row${count === 1 ? '' : 's'} into table "${tableName}".`, + preview: count > 0 ? { kind: 'records', tableName, rows } : undefined, + }; + } + case 'run_codegen': + return { + title: 'Run codegen?', + message: 'Generate the typed GraphQL SDK in packages/app (upgrade codegen, run it, normalize barrels).', + }; + default: + return { title: 'Run tool?', message: `Allow "${toolName}" to run?` }; } } diff --git a/agentic/harness/src/index.ts b/agentic/harness/src/index.ts index 6fe5c08aa8..31edacaef9 100644 --- a/agentic/harness/src/index.ts +++ b/agentic/harness/src/index.ts @@ -1,21 +1,21 @@ -export * from './types'; -export * from './stash'; +export * from './blueprint/blueprint-defaults'; +export * from './blueprint/blueprint-schema'; +export * from './blueprint/field-type'; +export * from './blueprint/internal-policies'; +export * from './blueprint/policy-provisioning'; +export * from './gating/confirm-gate'; +export * from './gating/decline-guard'; +export * from './gating/preview'; +export * from './gating/prompts'; +export * from './skills/fetch'; export * from './skills/frontmatter'; +export * from './skills/git-fetch'; +export * from './skills/integrity'; export * from './skills/manifest'; -export * from './skills/source'; -export * from './skills/overlay'; export * from './skills/materialize'; +export * from './skills/overlay'; export * from './skills/registry'; -export * from './skills/integrity'; -export * from './skills/fetch'; -export * from './skills/git-fetch'; +export * from './skills/source'; export * from './skills/update-check'; -export * from './gating/preview'; -export * from './gating/decline-guard'; -export * from './gating/prompts'; -export * from './gating/confirm-gate'; -export * from './blueprint/field-type'; -export * from './blueprint/internal-policies'; -export * from './blueprint/policy-provisioning'; -export * from './blueprint/blueprint-schema'; -export * from './blueprint/blueprint-defaults'; +export * from './stash'; +export * from './types'; diff --git a/agentic/harness/src/skills/fetch.ts b/agentic/harness/src/skills/fetch.ts index 5439a5b161..8790ff069e 100644 --- a/agentic/harness/src/skills/fetch.ts +++ b/agentic/harness/src/skills/fetch.ts @@ -1,7 +1,6 @@ import * as fs from 'fs'; import * as os from 'os'; import * as path from 'path'; - import * as semver from 'semver'; import * as tar from 'tar'; diff --git a/agentic/harness/src/skills/git-fetch.ts b/agentic/harness/src/skills/git-fetch.ts index 4e08e5baa1..ace4af9c5c 100644 --- a/agentic/harness/src/skills/git-fetch.ts +++ b/agentic/harness/src/skills/git-fetch.ts @@ -1,7 +1,6 @@ import * as fs from 'fs'; import * as os from 'os'; import * as path from 'path'; - import * as semver from 'semver'; import * as tar from 'tar'; diff --git a/agentic/harness/src/skills/update-check.ts b/agentic/harness/src/skills/update-check.ts index 627855c8b4..1692d440e1 100644 --- a/agentic/harness/src/skills/update-check.ts +++ b/agentic/harness/src/skills/update-check.ts @@ -1,6 +1,5 @@ import * as fs from 'fs'; import * as path from 'path'; - import * as semver from 'semver'; import { GitFetchOptions, listGitTagVersions } from './git-fetch'; diff --git a/agentic/harness/src/stash.ts b/agentic/harness/src/stash.ts index 8e60cdd0b7..ee95f739e5 100644 --- a/agentic/harness/src/stash.ts +++ b/agentic/harness/src/stash.ts @@ -1,6 +1,5 @@ -import * as path from 'path'; - import { appstash, AppStashResult } from 'appstash'; +import * as path from 'path'; export interface HarnessDirs { /** appstash root layout for the tool (config/cache/data/logs/tmp). */ diff --git a/agentic/pi/src/confirm-gate.ts b/agentic/pi/src/confirm-gate.ts index 7897fa3a1c..94f270bd41 100644 --- a/agentic/pi/src/confirm-gate.ts +++ b/agentic/pi/src/confirm-gate.ts @@ -1,3 +1,4 @@ +import type { ConfirmPreview } from '@agentic-kit/harness'; import { type ConfirmGate as HarnessConfirmGate, createConfirmGate as createHarnessConfirmGate, @@ -8,7 +9,6 @@ import type { ToolCallEvent, ToolCallEventResult, } from '@earendil-works/pi-coding-agent'; -import type { ConfirmPreview } from '@agentic-kit/harness'; import type { resolveDataToken, resolveProjectContext } from './context'; import type { createTemplatePreviewTables } from './tools/templates'; diff --git a/agentic/pi/src/tools/provision-database.ts b/agentic/pi/src/tools/provision-database.ts index ff8d4940c8..e917dc7639 100644 --- a/agentic/pi/src/tools/provision-database.ts +++ b/agentic/pi/src/tools/provision-database.ts @@ -5,11 +5,9 @@ import path from 'node:path'; import type { ToolDefinition } from '@earendil-works/pi-coding-agent'; import { z } from 'zod'; -import { getHost } from '../host'; -import { toolSchema } from '../tool-schema'; - import { prewarmAppWorkspace } from '../app-workspace'; import { probeDatabase } from '../db-probe'; +import { getHost } from '../host'; import { createDatabaseProvision } from '../provision-database/create-database-provision'; import { selectProvisionCredential } from '../provision-database/credential'; import { @@ -21,6 +19,7 @@ import { import { loadProvisionManifest } from '../provision-database/manifest'; import { applySqlFixups } from '../provision-database/pg-fixups'; import { type ProvisionOverlay, resolveProvisionModules } from '../provision-database/resolve'; +import { toolSchema } from '../tool-schema'; const DEFAULT_API_ENDPOINT = 'http://api.localhost:3000/graphql'; const DEFAULT_MODULES_ENDPOINT = 'http://modules.localhost:3000/graphql'; diff --git a/agentic/pi/src/tools/run-codegen.ts b/agentic/pi/src/tools/run-codegen.ts index c0ee7689ea..8a09cb7a39 100644 --- a/agentic/pi/src/tools/run-codegen.ts +++ b/agentic/pi/src/tools/run-codegen.ts @@ -5,9 +5,6 @@ import path from 'node:path'; import type { ToolDefinition } from '@earendil-works/pi-coding-agent'; import { z } from 'zod'; -import { getHost } from '../host'; -import { toolSchema } from '../tool-schema'; - import { ensureAppScaffold, ensureWorkspaceConfig, @@ -16,8 +13,10 @@ import { prewarmAppWorkspace, run, } from '../app-workspace'; +import { getHost } from '../host'; import { normalizeSdkBarrels } from '../run-codegen/barrels'; import { codegenEndpointEnv, derivePlaneEndpoints, envLocalContent } from '../run-codegen/endpoints'; +import { toolSchema } from '../tool-schema'; const DEFAULT_API_ENDPOINT = 'http://api.localhost:3000/graphql'; diff --git a/agentic/react/__tests__/use-chat.test.ts b/agentic/react/__tests__/use-chat.test.ts index 8e014c3370..66d51622f4 100644 --- a/agentic/react/__tests__/use-chat.test.ts +++ b/agentic/react/__tests__/use-chat.test.ts @@ -1,9 +1,9 @@ import type { AgentEvent } from '@agentic-kit/agent'; -import { createScriptedSSEResponse, makeFakeAssistantMessage, ZERO_USAGE } from './helpers'; -import { act, renderHook, waitFor } from '@testing-library/react'; import type { AssistantMessage, Message, UserMessage } from '@agentic-kit/chat'; +import { act, renderHook, waitFor } from '@testing-library/react'; import { useChat } from '../src'; +import { createScriptedSSEResponse, makeFakeAssistantMessage, ZERO_USAGE } from './helpers'; function streamFromEvents(events: AgentEvent[]): Response { return createScriptedSSEResponse(events); diff --git a/eslint.config.mjs b/eslint.config.mjs new file mode 100644 index 0000000000..10770023e9 --- /dev/null +++ b/eslint.config.mjs @@ -0,0 +1,54 @@ +import base from '@constructive-io/eslint-config'; + +export default [ + ...base, + { + // several rules this repo turns off still have inline disable comments; + // leave them in place rather than have --fix strip them + linterOptions: { + reportUnusedDisableDirectives: 'off' + } + }, + { + ignores: [ + // codegen output, regenerated by `pnpm generate` + 'sdk/constructive-cli/src/**', + 'sdk/constructive-react/src/**', + 'sdk/constructive-sdk/src/**', + 'sdk/migrate-client/src/migrate/**', + '**/__generated__/**', + '**/*.generated.ts', + 'postgres/pg-ast/src/asts.ts', + 'postgres/pg-ast/src/wrapped.ts', + // read verbatim at codegen time and written into generated clients + 'graphql/codegen/src/core/codegen/templates/**', + // codegen output snapshots and standalone sqitch/pgpm fixture projects + '__fixtures__/**', + '**/__fixtures__/**' + ] + }, + { + rules: { + // `declare global { namespace Grafast { ... } }` augmentations + '@typescript-eslint/no-namespace': 'off', + // `Function` in plugin/callback signatures + '@typescript-eslint/no-unsafe-function-type': 'off', + // `{}` as a type-level marker (StrictSelect) and placeholder option bags + '@typescript-eslint/no-empty-object-type': 'off' + } + }, + { + // ANSI escapes are matched on purpose + files: ['pgpm/logger/**'], + rules: { + 'no-control-regex': 'off' + } + }, + { + // type-level assertions are expressions by construction + files: ['**/*.type-test.ts'], + rules: { + '@typescript-eslint/no-unused-expressions': 'off' + } + } +]; diff --git a/examples/codegen-integration/codegen.config.ts b/examples/codegen-integration/codegen.config.ts index 48301d8b45..e05b6f4f0c 100644 --- a/examples/codegen-integration/codegen.config.ts +++ b/examples/codegen-integration/codegen.config.ts @@ -1,8 +1,8 @@ -import { defineConfig } from "@constructive-io/graphql-codegen"; +import { defineConfig } from '@constructive-io/graphql-codegen'; export default defineConfig({ - endpoint: "http://example.local/graphql", // not used for fixture run - output: "src/generated", + endpoint: 'http://example.local/graphql', // not used for fixture run + output: 'src/generated', reactQuery: true, orm: true, codegen: { @@ -10,5 +10,5 @@ export default defineConfig({ skipQueryField: true }, // Use the example schema fixtures baked into the repo - schemaFile: "../../graphql/codegen/examples/example.schema.graphql" + schemaFile: '../../graphql/codegen/examples/example.schema.graphql' }); diff --git a/examples/codegen-integration/scripts/codegen-runner.ts b/examples/codegen-integration/scripts/codegen-runner.ts index 1c4f620662..539fcd8dc5 100644 --- a/examples/codegen-integration/scripts/codegen-runner.ts +++ b/examples/codegen-integration/scripts/codegen-runner.ts @@ -1,4 +1,5 @@ import path from 'path'; + import { generate } from '../../../graphql/codegen/src/core/generate'; const root = path.resolve(__dirname, '..'); diff --git a/graphile/graphile-bucket-provisioner-plugin/__tests__/plugin.test.ts b/graphile/graphile-bucket-provisioner-plugin/__tests__/plugin.test.ts index 0ee54bc9d5..9d8dd575d1 100644 --- a/graphile/graphile-bucket-provisioner-plugin/__tests__/plugin.test.ts +++ b/graphile/graphile-bucket-provisioner-plugin/__tests__/plugin.test.ts @@ -111,7 +111,7 @@ function createMockPgClient(overrides: Record = {}) { allowed_origins: null, }], }, - 'app_public': { + app_public: { rows: [{ id: 'bucket-uuid-789', key: 'public', @@ -218,7 +218,7 @@ describe('createBucketProvisionerPlugin', () => { it('provisions a private bucket', async () => { const privateBucketOverrides = { - 'app_public': { + app_public: { rows: [{ id: 'bucket-uuid-private', key: 'private', @@ -388,7 +388,7 @@ describe('createBucketProvisionerPlugin', () => { createBucketProvisionerPlugin(createDefaultOptions()); const pgClient = createMockPgClient({ - 'app_public': { rows: [] }, + app_public: { rows: [] }, }); const mockWithPgClient = jest.fn((_settings: any, callback: any) => callback(pgClient), @@ -911,7 +911,7 @@ describe('createBucketProvisionerPlugin', () => { const wrapped = hook(field, build, context); const pgClient = createMockPgClient({ - 'app_public': { + app_public: { rows: [{ id: 'bucket-uuid-789', key: 'public', @@ -964,7 +964,7 @@ describe('createBucketProvisionerPlugin', () => { const wrapped = hook(field, build, context); const pgClient = createMockPgClient({ - 'app_public': { + app_public: { rows: [{ id: 'bucket-uuid-789', key: 'public', @@ -1017,7 +1017,7 @@ describe('CORS resolution hierarchy', () => { createBucketProvisionerPlugin(createDefaultOptions()); const pgClient = createMockPgClient({ - 'app_public': { + app_public: { rows: [{ id: 'bucket-uuid-cdn', key: 'cdn-assets', @@ -1074,7 +1074,7 @@ describe('CORS resolution hierarchy', () => { createBucketProvisionerPlugin(createDefaultOptions()); const pgClient = createMockPgClient({ - 'app_public': { + app_public: { rows: [{ id: 'bucket-uuid-uploads', key: 'uploads', @@ -1133,7 +1133,7 @@ describe('CORS resolution hierarchy', () => { })); const pgClient = createMockPgClient({ - 'app_public': { + app_public: { rows: [{ id: 'bucket-uuid-docs', key: 'docs', @@ -1190,7 +1190,7 @@ describe('CORS resolution hierarchy', () => { createBucketProvisionerPlugin(createDefaultOptions()); const pgClient = createMockPgClient({ - 'app_public': { + app_public: { rows: [{ id: 'bucket-uuid-cdn', key: 'cdn-public', @@ -1253,7 +1253,7 @@ describe('bucket name resolution', () => { }); const pgClient = createMockPgClient({ - 'app_public': { + app_public: { rows: [{ id: 'bucket-uuid', key: 'private', diff --git a/graphile/graphile-bucket-provisioner-plugin/__tests__/types.test.ts b/graphile/graphile-bucket-provisioner-plugin/__tests__/types.test.ts index 59b72cb026..96a4ba1c88 100644 --- a/graphile/graphile-bucket-provisioner-plugin/__tests__/types.test.ts +++ b/graphile/graphile-bucket-provisioner-plugin/__tests__/types.test.ts @@ -5,15 +5,15 @@ */ import type { + BucketAccessType, + BucketNameResolver, BucketProvisionerPluginOptions, ConnectionConfigOrGetter, - BucketNameResolver, ProvisionBucketInput, ProvisionBucketPayload, + ProvisionResult, StorageConnectionConfig, StorageProvider, - BucketAccessType, - ProvisionResult, } from '../src/types'; describe('BucketProvisionerPluginOptions', () => { diff --git a/graphile/graphile-bucket-provisioner-plugin/src/index.ts b/graphile/graphile-bucket-provisioner-plugin/src/index.ts index c9e988f3da..77919ee720 100644 --- a/graphile/graphile-bucket-provisioner-plugin/src/index.ts +++ b/graphile/graphile-bucket-provisioner-plugin/src/index.ts @@ -41,13 +41,13 @@ export { BucketProvisionerPlugin, createBucketProvisionerPlugin } from './plugin'; export { BucketProvisionerPreset } from './preset'; export type { + BucketAccessType, + BucketNameResolver, BucketProvisionerPluginOptions, ConnectionConfigOrGetter, - BucketNameResolver, ProvisionBucketInput, ProvisionBucketPayload, + ProvisionResult, StorageConnectionConfig, StorageProvider, - BucketAccessType, - ProvisionResult, } from './types'; diff --git a/graphile/graphile-bucket-provisioner-plugin/src/plugin.ts b/graphile/graphile-bucket-provisioner-plugin/src/plugin.ts index 74eeedff40..63ba72fe02 100644 --- a/graphile/graphile-bucket-provisioner-plugin/src/plugin.ts +++ b/graphile/graphile-bucket-provisioner-plugin/src/plugin.ts @@ -31,19 +31,18 @@ * COMMENT ON TABLE buckets IS E'@storageBuckets\nStorage buckets table'; */ -import { context as grafastContext, lambda, object } from 'grafast'; -import type { GraphileConfig } from 'graphile-config'; -import { extendSchema, gql } from 'graphile-utils'; -import { Logger } from '@pgpmjs/logger'; -import { QuoteUtils } from '@pgsql/quotes'; +import type { ProvisionResult,StorageConnectionConfig } from '@constructive-io/bucket-provisioner'; import { BucketProvisioner, } from '@constructive-io/bucket-provisioner'; -import type { StorageConnectionConfig, ProvisionResult } from '@constructive-io/bucket-provisioner'; +import { Logger } from '@pgpmjs/logger'; +import { QuoteUtils } from '@pgsql/quotes'; +import { context as grafastContext, lambda, object } from 'grafast'; +import type { GraphileConfig } from 'graphile-config'; +import { extendSchema, gql } from 'graphile-utils'; import type { BucketProvisionerPluginOptions, - BucketNameResolver, } from './types'; const log = new Logger('graphile-bucket-provisioner:plugin'); diff --git a/graphile/graphile-bucket-provisioner-plugin/src/preset.ts b/graphile/graphile-bucket-provisioner-plugin/src/preset.ts index 500cfe76cc..c5e9384082 100644 --- a/graphile/graphile-bucket-provisioner-plugin/src/preset.ts +++ b/graphile/graphile-bucket-provisioner-plugin/src/preset.ts @@ -6,8 +6,9 @@ */ import type { GraphileConfig } from 'graphile-config'; -import type { BucketProvisionerPluginOptions } from './types'; + import { createBucketProvisionerPlugin } from './plugin'; +import type { BucketProvisionerPluginOptions } from './types'; /** * Creates a preset that includes the bucket provisioner plugin with the given options. diff --git a/graphile/graphile-bucket-provisioner-plugin/src/types.ts b/graphile/graphile-bucket-provisioner-plugin/src/types.ts index aa2f6a61a1..45a5c172ba 100644 --- a/graphile/graphile-bucket-provisioner-plugin/src/types.ts +++ b/graphile/graphile-bucket-provisioner-plugin/src/types.ts @@ -7,14 +7,14 @@ */ import type { - StorageConnectionConfig, - StorageProvider, BucketAccessType, ProvisionResult, + StorageConnectionConfig, + StorageProvider, } from '@constructive-io/bucket-provisioner'; // Re-export types that consumers will need -export type { StorageConnectionConfig, StorageProvider, BucketAccessType, ProvisionResult }; +export type { BucketAccessType, ProvisionResult,StorageConnectionConfig, StorageProvider }; /** * S3 connection configuration or a lazy getter that returns it on first use. diff --git a/graphile/graphile-bulk-mutations/src/plugins/BulkDeletePlugin.ts b/graphile/graphile-bulk-mutations/src/plugins/BulkDeletePlugin.ts index 3bdd04eea3..4731702283 100644 --- a/graphile/graphile-bulk-mutations/src/plugins/BulkDeletePlugin.ts +++ b/graphile/graphile-bulk-mutations/src/plugins/BulkDeletePlugin.ts @@ -2,7 +2,7 @@ import '../augmentations'; import { sideEffectWithPgClient } from '@dataplan/pg'; import type { GraphileConfig } from 'graphile-config'; -import type { GraphQLOutputType, GraphQLInputType } from 'graphql'; +import type { GraphQLInputType,GraphQLOutputType } from 'graphql'; const version = '0.1.0'; diff --git a/graphile/graphile-cache/src/create-instance.ts b/graphile/graphile-cache/src/create-instance.ts index fc4c625ae2..575b767589 100644 --- a/graphile/graphile-cache/src/create-instance.ts +++ b/graphile/graphile-cache/src/create-instance.ts @@ -1,8 +1,10 @@ import { createServer } from 'node:http'; + import { Logger } from '@pgpmjs/logger'; import express from 'express'; -import { postgraphile } from 'postgraphile'; import { grafserv } from 'grafserv/express/v4'; +import { postgraphile } from 'postgraphile'; + import type { GraphileCacheEntry } from './graphile-cache'; const log = new Logger('graphile-cache:create'); diff --git a/graphile/graphile-cache/src/graphile-cache.ts b/graphile/graphile-cache/src/graphile-cache.ts index ae016550fb..83782c6a21 100644 --- a/graphile/graphile-cache/src/graphile-cache.ts +++ b/graphile/graphile-cache/src/graphile-cache.ts @@ -1,12 +1,12 @@ -import { EventEmitter } from 'events'; -import { parseEnvNumber } from '12factor-env'; import { Logger } from '@pgpmjs/logger'; -import { LRUCache } from 'lru-cache'; -import { pgCache } from 'pg-cache'; +import { parseEnvNumber } from '12factor-env'; +import { EventEmitter } from 'events'; import type { Express } from 'express'; +import type { GrafservBase } from 'grafserv'; import type { Server as HttpServer } from 'http'; +import { LRUCache } from 'lru-cache'; +import { pgCache } from 'pg-cache'; import type { PostGraphileInstance } from 'postgraphile'; -import type { GrafservBase } from 'grafserv'; const log = new Logger('graphile-cache'); diff --git a/graphile/graphile-cache/src/index.ts b/graphile/graphile-cache/src/index.ts index e64be532b9..9a845fafe3 100644 --- a/graphile/graphile-cache/src/index.ts +++ b/graphile/graphile-cache/src/index.ts @@ -1,33 +1,26 @@ // Main exports from graphile-cache package export { - // Cache instance and entry type - graphileCache, - GraphileCacheEntry, - closeAllCaches, - - // Time constants - ONE_HOUR_MS, - FIVE_MINUTES_MS, - - // Eviction tracking - EvictionReason, - + // Cache configuration + CacheConfig, // Event emitter for cache events CacheEventEmitter, - CacheEvictionEvent, cacheEvents, - - // Cache configuration - CacheConfig, - getCacheConfig, - + CacheEvictionEvent, // Cache stats CacheStats, - getCacheStats, - // Clear matching entries - clearMatchingEntries -} from './graphile-cache'; + clearMatchingEntries, + closeAllCaches, + // Eviction tracking + EvictionReason, + FIVE_MINUTES_MS, + getCacheConfig, + getCacheStats, + // Cache instance and entry type + graphileCache, + GraphileCacheEntry, + // Time constants + ONE_HOUR_MS} from './graphile-cache'; // Factory for creating PostGraphile v5 instances export { createGraphileInstance } from './create-instance'; diff --git a/graphile/graphile-cache/src/module-config-cache.ts b/graphile/graphile-cache/src/module-config-cache.ts index fa7a8111e7..63af02a93e 100644 --- a/graphile/graphile-cache/src/module-config-cache.ts +++ b/graphile/graphile-cache/src/module-config-cache.ts @@ -11,8 +11,8 @@ * - clear() hook for future LISTEN/NOTIFY invalidation */ -import { LRUCache } from 'lru-cache'; import { Logger } from '@pgpmjs/logger'; +import { LRUCache } from 'lru-cache'; export interface ModuleConfigCacheOptions { /** Cache name (used in log prefix) */ diff --git a/graphile/graphile-connection-filter/__tests__/connection-filter.test.ts b/graphile/graphile-connection-filter/__tests__/connection-filter.test.ts index 9fc92d560e..d1ae91ff14 100644 --- a/graphile/graphile-connection-filter/__tests__/connection-filter.test.ts +++ b/graphile/graphile-connection-filter/__tests__/connection-filter.test.ts @@ -1,9 +1,10 @@ -import { join } from 'path'; -import { getConnectionsObject, seed } from 'graphile-test'; -import type { GraphQLQueryFnObj } from 'graphile-test'; import type { GraphileConfig } from 'graphile-config'; -import { ConnectionFilterPreset } from '../src'; +import type { GraphQLQueryFnObj } from 'graphile-test'; +import { getConnectionsObject, seed } from 'graphile-test'; +import { join } from 'path'; + import type { ConnectionFilterOperatorFactory } from '../src'; +import { ConnectionFilterPreset } from '../src'; const SCHEMA = 'filter_test'; const sqlFile = (f: string) => join(__dirname, '../sql', f); diff --git a/graphile/graphile-connection-filter/src/augmentations.ts b/graphile/graphile-connection-filter/src/augmentations.ts index 8984911f4f..cee914fc2e 100644 --- a/graphile/graphile-connection-filter/src/augmentations.ts +++ b/graphile/graphile-connection-filter/src/augmentations.ts @@ -8,7 +8,8 @@ import 'graphile-build'; import 'graphile-build-pg'; -import type { ConnectionFilterOperatorFactory, ConnectionFilterOperatorSpec, ConnectionFilterOperatorsDigest, PgConnectionFilterOperatorsScope } from './types'; + +import type { ConnectionFilterOperatorFactory, ConnectionFilterOperatorsDigest, PgConnectionFilterOperatorsScope } from './types'; declare global { namespace GraphileBuild { diff --git a/graphile/graphile-connection-filter/src/index.ts b/graphile/graphile-connection-filter/src/index.ts index 44faf101fa..f79596da9e 100644 --- a/graphile/graphile-connection-filter/src/index.ts +++ b/graphile/graphile-connection-filter/src/index.ts @@ -60,35 +60,35 @@ export { ConnectionFilterPreset } from './preset'; // Re-export all plugins for granular use export { - ConnectionFilterInflectionPlugin, - ConnectionFilterTypesPlugin, ConnectionFilterArgPlugin, ConnectionFilterAttributesPlugin, - ConnectionFilterOperatorsPlugin, - ConnectionFilterCustomOperatorsPlugin, - ConnectionFilterLogicalOperatorsPlugin, + ConnectionFilterBackwardRelationsPlugin, ConnectionFilterComputedAttributesPlugin, + ConnectionFilterCustomOperatorsPlugin, ConnectionFilterForwardRelationsPlugin, - ConnectionFilterBackwardRelationsPlugin, + ConnectionFilterInflectionPlugin, + ConnectionFilterLogicalOperatorsPlugin, + ConnectionFilterOperatorsPlugin, + ConnectionFilterTypesPlugin, makeApplyFromOperatorSpec, } from './plugins'; // Re-export types export type { - ConnectionFilterOperatorSpec, - ConnectionFilterOperatorRegistration, ConnectionFilterOperatorFactory, - ConnectionFilterOptions, + ConnectionFilterOperatorRegistration, ConnectionFilterOperatorsDigest, + ConnectionFilterOperatorSpec, + ConnectionFilterOptions, PgConnectionFilterOperatorsScope, } from './types'; export { $$filters } from './types'; // Re-export utilities export { - isEmpty, - makeAssertAllowed, + getComputedAttributeResources, getQueryBuilder, isComputedScalarAttributeResource, - getComputedAttributeResources, + isEmpty, + makeAssertAllowed, } from './utils'; diff --git a/graphile/graphile-connection-filter/src/plugins/ConnectionFilterArgPlugin.ts b/graphile/graphile-connection-filter/src/plugins/ConnectionFilterArgPlugin.ts index d4639a8107..6096d70fb2 100644 --- a/graphile/graphile-connection-filter/src/plugins/ConnectionFilterArgPlugin.ts +++ b/graphile/graphile-connection-filter/src/plugins/ConnectionFilterArgPlugin.ts @@ -1,6 +1,8 @@ import '../augmentations'; + import type { GraphileConfig } from 'graphile-config'; import type { GraphQLInputType, GraphQLNamedType } from 'graphql'; + import { isEmpty } from '../utils'; const version = '1.0.0'; @@ -91,58 +93,58 @@ export const ConnectionFilterArgPlugin: GraphileConfig.Plugin = { type: FilterType, ...(isPgFieldConnection ? { - applyPlan: EXPORTABLE( - ( - PgCondition: any, - isEmpty: any, - attributeCodec: any - ) => - function (_: any, $connection: any, fieldArg: any) { - const $pgSelect = $connection.getSubplan(); - fieldArg.apply( - $pgSelect, - (queryBuilder: any, value: any) => { - // If where is null/undefined or empty {}, treat as "no filter" — skip - if (value == null || isEmpty(value)) return; - const condition = new PgCondition(queryBuilder); - if (attributeCodec) { - condition.extensions.pgFilterAttribute = { - codec: attributeCodec, - }; - } - return condition; + applyPlan: EXPORTABLE( + ( + PgCondition: any, + isEmpty: any, + attributeCodec: any + ) => + function (_: any, $connection: any, fieldArg: any) { + const $pgSelect = $connection.getSubplan(); + fieldArg.apply( + $pgSelect, + (queryBuilder: any, value: any) => { + // If where is null/undefined or empty {}, treat as "no filter" — skip + if (value == null || isEmpty(value)) return; + const condition = new PgCondition(queryBuilder); + if (attributeCodec) { + condition.extensions.pgFilterAttribute = { + codec: attributeCodec, + }; } - ); - }, - [PgCondition, isEmpty, attributeCodec] - ), - } + return condition; + } + ); + }, + [PgCondition, isEmpty, attributeCodec] + ), + } : { - applyPlan: EXPORTABLE( - ( - PgCondition: any, - isEmpty: any, - attributeCodec: any - ) => - function (_: any, $pgSelect: any, fieldArg: any) { - fieldArg.apply( - $pgSelect, - (queryBuilder: any, value: any) => { - // If where is null/undefined or empty {}, treat as "no filter" — skip - if (value == null || isEmpty(value)) return; - const condition = new PgCondition(queryBuilder); - if (attributeCodec) { - condition.extensions.pgFilterAttribute = { - codec: attributeCodec, - }; - } - return condition; + applyPlan: EXPORTABLE( + ( + PgCondition: any, + isEmpty: any, + attributeCodec: any + ) => + function (_: any, $pgSelect: any, fieldArg: any) { + fieldArg.apply( + $pgSelect, + (queryBuilder: any, value: any) => { + // If where is null/undefined or empty {}, treat as "no filter" — skip + if (value == null || isEmpty(value)) return; + const condition = new PgCondition(queryBuilder); + if (attributeCodec) { + condition.extensions.pgFilterAttribute = { + codec: attributeCodec, + }; } - ); - }, - [PgCondition, isEmpty, attributeCodec] - ), - }), + return condition; + } + ); + }, + [PgCondition, isEmpty, attributeCodec] + ), + }), }, }, `Adding connection where arg '${argName}' to field '${fieldName}' of '${Self.name}'` diff --git a/graphile/graphile-connection-filter/src/plugins/ConnectionFilterAttributesPlugin.ts b/graphile/graphile-connection-filter/src/plugins/ConnectionFilterAttributesPlugin.ts index 08c3a59d61..ad263ec595 100644 --- a/graphile/graphile-connection-filter/src/plugins/ConnectionFilterAttributesPlugin.ts +++ b/graphile/graphile-connection-filter/src/plugins/ConnectionFilterAttributesPlugin.ts @@ -1,6 +1,8 @@ import '../augmentations'; + import type { GraphileConfig } from 'graphile-config'; import type { GraphQLInputType } from 'graphql'; + import { isEmpty } from '../utils'; const version = '1.0.0'; diff --git a/graphile/graphile-connection-filter/src/plugins/ConnectionFilterBackwardRelationsPlugin.ts b/graphile/graphile-connection-filter/src/plugins/ConnectionFilterBackwardRelationsPlugin.ts index 6b9d6084c2..50f8bd2f9a 100644 --- a/graphile/graphile-connection-filter/src/plugins/ConnectionFilterBackwardRelationsPlugin.ts +++ b/graphile/graphile-connection-filter/src/plugins/ConnectionFilterBackwardRelationsPlugin.ts @@ -1,8 +1,10 @@ import '../augmentations'; -import type { GraphileConfig } from 'graphile-config'; + import type { PgCodecRelation, PgCodecWithAttributes, PgResource } from '@dataplan/pg'; -import type { SQL } from 'pg-sql2'; +import type { GraphileConfig } from 'graphile-config'; import type { GraphQLInputObjectType } from 'graphql'; +import type { SQL } from 'pg-sql2'; + import { makeAssertAllowed } from '../utils'; const version = '1.0.0'; diff --git a/graphile/graphile-connection-filter/src/plugins/ConnectionFilterComputedAttributesPlugin.ts b/graphile/graphile-connection-filter/src/plugins/ConnectionFilterComputedAttributesPlugin.ts index 0a2dfa2520..df4d7f8f24 100644 --- a/graphile/graphile-connection-filter/src/plugins/ConnectionFilterComputedAttributesPlugin.ts +++ b/graphile/graphile-connection-filter/src/plugins/ConnectionFilterComputedAttributesPlugin.ts @@ -1,9 +1,11 @@ import '../augmentations'; + import type { GraphileConfig } from 'graphile-config'; import type { GraphQLInputType } from 'graphql'; + import { - isComputedScalarAttributeResource, getComputedAttributeResources, + isComputedScalarAttributeResource, } from '../utils'; const version = '1.0.0'; diff --git a/graphile/graphile-connection-filter/src/plugins/ConnectionFilterCustomOperatorsPlugin.ts b/graphile/graphile-connection-filter/src/plugins/ConnectionFilterCustomOperatorsPlugin.ts index cf345907c8..dc377c3485 100644 --- a/graphile/graphile-connection-filter/src/plugins/ConnectionFilterCustomOperatorsPlugin.ts +++ b/graphile/graphile-connection-filter/src/plugins/ConnectionFilterCustomOperatorsPlugin.ts @@ -1,6 +1,8 @@ import '../augmentations'; + import type { GraphileConfig } from 'graphile-config'; import type { GraphQLInputType } from 'graphql'; + import type { ConnectionFilterOperatorSpec } from '../types'; import { $$filters } from '../types'; import { makeApplyFromOperatorSpec } from './operatorApply'; diff --git a/graphile/graphile-connection-filter/src/plugins/ConnectionFilterForwardRelationsPlugin.ts b/graphile/graphile-connection-filter/src/plugins/ConnectionFilterForwardRelationsPlugin.ts index 34f711bfbf..6dda6d85e4 100644 --- a/graphile/graphile-connection-filter/src/plugins/ConnectionFilterForwardRelationsPlugin.ts +++ b/graphile/graphile-connection-filter/src/plugins/ConnectionFilterForwardRelationsPlugin.ts @@ -1,8 +1,10 @@ import '../augmentations'; + +import type { PgCodecRelation, PgCodecWithAttributes, PgResource } from '@dataplan/pg'; import type { GraphileConfig } from 'graphile-config'; -import type { PgCondition, PgCodecRelation, PgCodecWithAttributes, PgResource } from '@dataplan/pg'; -import type { SQL } from 'pg-sql2'; import type { GraphQLInputObjectType } from 'graphql'; +import type { SQL } from 'pg-sql2'; + import { makeAssertAllowed } from '../utils'; const version = '1.0.0'; diff --git a/graphile/graphile-connection-filter/src/plugins/ConnectionFilterInflectionPlugin.ts b/graphile/graphile-connection-filter/src/plugins/ConnectionFilterInflectionPlugin.ts index 2b7a016def..d49569a103 100644 --- a/graphile/graphile-connection-filter/src/plugins/ConnectionFilterInflectionPlugin.ts +++ b/graphile/graphile-connection-filter/src/plugins/ConnectionFilterInflectionPlugin.ts @@ -1,4 +1,5 @@ import '../augmentations'; + import type { GraphileConfig } from 'graphile-config'; /** diff --git a/graphile/graphile-connection-filter/src/plugins/ConnectionFilterLogicalOperatorsPlugin.ts b/graphile/graphile-connection-filter/src/plugins/ConnectionFilterLogicalOperatorsPlugin.ts index 3fca39596b..3517689ed8 100644 --- a/graphile/graphile-connection-filter/src/plugins/ConnectionFilterLogicalOperatorsPlugin.ts +++ b/graphile/graphile-connection-filter/src/plugins/ConnectionFilterLogicalOperatorsPlugin.ts @@ -1,5 +1,7 @@ import '../augmentations'; + import type { GraphileConfig } from 'graphile-config'; + import { makeAssertAllowed } from '../utils'; const version = '1.0.0'; diff --git a/graphile/graphile-connection-filter/src/plugins/ConnectionFilterOperatorsPlugin.ts b/graphile/graphile-connection-filter/src/plugins/ConnectionFilterOperatorsPlugin.ts index 9bf62642bc..55bb18ce91 100644 --- a/graphile/graphile-connection-filter/src/plugins/ConnectionFilterOperatorsPlugin.ts +++ b/graphile/graphile-connection-filter/src/plugins/ConnectionFilterOperatorsPlugin.ts @@ -1,5 +1,7 @@ import '../augmentations'; + import type { GraphileConfig } from 'graphile-config'; + import { makeApplyFromOperatorSpec } from './operatorApply'; const version = '1.0.0'; @@ -870,75 +872,75 @@ export const ConnectionFilterOperatorsPlugin: GraphileConfig.Plugin = { if (!isEnumCodec(underlyingType)) enumLike = false; switch (underlyingType) { - case TYPES.numeric: - case TYPES.money: - case TYPES.float: - case TYPES.float4: - case TYPES.bigint: - case TYPES.int: - case TYPES.int2: - case TYPES.boolean: - case TYPES.varbit: - case TYPES.bit: - case TYPES.date: - case TYPES.timestamp: - case TYPES.timestamptz: - case TYPES.time: - case TYPES.timetz: - case TYPES.interval: - case TYPES.json: - case TYPES.jsonb: - case TYPES.cidr: - case TYPES.inet: - case TYPES.macaddr: - case TYPES.macaddr8: - case TYPES.text: - case TYPES.name: - case TYPES.citext: - case TYPES.varchar: - case TYPES.char: - case TYPES.bpchar: - case TYPES.uuid: - break; - default: - sortable = false; + case TYPES.numeric: + case TYPES.money: + case TYPES.float: + case TYPES.float4: + case TYPES.bigint: + case TYPES.int: + case TYPES.int2: + case TYPES.boolean: + case TYPES.varbit: + case TYPES.bit: + case TYPES.date: + case TYPES.timestamp: + case TYPES.timestamptz: + case TYPES.time: + case TYPES.timetz: + case TYPES.interval: + case TYPES.json: + case TYPES.jsonb: + case TYPES.cidr: + case TYPES.inet: + case TYPES.macaddr: + case TYPES.macaddr8: + case TYPES.text: + case TYPES.name: + case TYPES.citext: + case TYPES.varchar: + case TYPES.char: + case TYPES.bpchar: + case TYPES.uuid: + break; + default: + sortable = false; } switch (underlyingType) { - case TYPES.cidr: - case TYPES.inet: - case TYPES.macaddr: - case TYPES.macaddr8: - break; - default: - inetLike = false; + case TYPES.cidr: + case TYPES.inet: + case TYPES.macaddr: + case TYPES.macaddr8: + break; + default: + inetLike = false; } switch (underlyingType) { - case TYPES.text: - case TYPES.name: - case TYPES.citext: - case TYPES.varchar: - case TYPES.char: - case TYPES.bpchar: - break; - default: - textLike = false; + case TYPES.text: + case TYPES.name: + case TYPES.citext: + case TYPES.varchar: + case TYPES.char: + case TYPES.bpchar: + break; + default: + textLike = false; } switch (underlyingType) { - case TYPES.json: - case TYPES.jsonb: - break; - default: - jsonLike = false; + case TYPES.json: + case TYPES.jsonb: + break; + default: + jsonLike = false; } switch (underlyingType) { - case TYPES.hstore: - break; - default: - hstoreLike = false; + case TYPES.hstore: + break; + default: + hstoreLike = false; } } @@ -950,14 +952,14 @@ export const ConnectionFilterOperatorsPlugin: GraphileConfig.Plugin = { : enumLike ? connectionFilterEnumOperators : { - ...standardOperators, - ...(sortable ? sortOperators : null), - ...(inetLike ? inetOperators : null), - ...(jsonLike ? jsonbOperators : null), - ...(hstoreLike ? hstoreOperators : null), - ...(textLike ? patternMatchingOperators : null), - ...(textLike ? insensitiveOperators : null), - }; + ...standardOperators, + ...(sortable ? sortOperators : null), + ...(inetLike ? inetOperators : null), + ...(jsonLike ? jsonbOperators : null), + ...(hstoreLike ? hstoreOperators : null), + ...(textLike ? patternMatchingOperators : null), + ...(textLike ? insensitiveOperators : null), + }; // Build the operator fields const operatorFields = Object.entries(operatorSpecs).reduce( diff --git a/graphile/graphile-connection-filter/src/plugins/ConnectionFilterTypesPlugin.ts b/graphile/graphile-connection-filter/src/plugins/ConnectionFilterTypesPlugin.ts index 1ab2d1a0bf..ff3cf4016d 100644 --- a/graphile/graphile-connection-filter/src/plugins/ConnectionFilterTypesPlugin.ts +++ b/graphile/graphile-connection-filter/src/plugins/ConnectionFilterTypesPlugin.ts @@ -1,4 +1,5 @@ import '../augmentations'; + import type { GraphileConfig } from 'graphile-config'; const version = '1.0.0'; @@ -171,9 +172,9 @@ export const ConnectionFilterTypesPlugin: GraphileConfig.Plugin = { const domainBaseTypeName = codec.domainOfCodec && !codec.domainOfCodec.arrayOfCodec ? build.getGraphQLTypeNameByPgCodec( - codec.domainOfCodec, - 'output' - ) + codec.domainOfCodec, + 'output' + ) : null; return { diff --git a/graphile/graphile-connection-filter/src/plugins/index.ts b/graphile/graphile-connection-filter/src/plugins/index.ts index 0e8db1cb4f..e30b48a355 100644 --- a/graphile/graphile-connection-filter/src/plugins/index.ts +++ b/graphile/graphile-connection-filter/src/plugins/index.ts @@ -1,11 +1,11 @@ -export { ConnectionFilterInflectionPlugin } from './ConnectionFilterInflectionPlugin'; -export { ConnectionFilterTypesPlugin } from './ConnectionFilterTypesPlugin'; export { ConnectionFilterArgPlugin } from './ConnectionFilterArgPlugin'; export { ConnectionFilterAttributesPlugin } from './ConnectionFilterAttributesPlugin'; -export { ConnectionFilterOperatorsPlugin } from './ConnectionFilterOperatorsPlugin'; -export { ConnectionFilterCustomOperatorsPlugin } from './ConnectionFilterCustomOperatorsPlugin'; -export { ConnectionFilterLogicalOperatorsPlugin } from './ConnectionFilterLogicalOperatorsPlugin'; +export { ConnectionFilterBackwardRelationsPlugin } from './ConnectionFilterBackwardRelationsPlugin'; export { ConnectionFilterComputedAttributesPlugin } from './ConnectionFilterComputedAttributesPlugin'; +export { ConnectionFilterCustomOperatorsPlugin } from './ConnectionFilterCustomOperatorsPlugin'; export { ConnectionFilterForwardRelationsPlugin } from './ConnectionFilterForwardRelationsPlugin'; -export { ConnectionFilterBackwardRelationsPlugin } from './ConnectionFilterBackwardRelationsPlugin'; +export { ConnectionFilterInflectionPlugin } from './ConnectionFilterInflectionPlugin'; +export { ConnectionFilterLogicalOperatorsPlugin } from './ConnectionFilterLogicalOperatorsPlugin'; +export { ConnectionFilterOperatorsPlugin } from './ConnectionFilterOperatorsPlugin'; +export { ConnectionFilterTypesPlugin } from './ConnectionFilterTypesPlugin'; export { makeApplyFromOperatorSpec } from './operatorApply'; diff --git a/graphile/graphile-connection-filter/src/preset.ts b/graphile/graphile-connection-filter/src/preset.ts index 33704f45a7..8a60af8bd0 100644 --- a/graphile/graphile-connection-filter/src/preset.ts +++ b/graphile/graphile-connection-filter/src/preset.ts @@ -22,20 +22,22 @@ */ import './augmentations'; + import type { GraphileConfig } from 'graphile-config'; -import type { ConnectionFilterOptions } from './types'; + import { - ConnectionFilterInflectionPlugin, - ConnectionFilterTypesPlugin, ConnectionFilterArgPlugin, ConnectionFilterAttributesPlugin, - ConnectionFilterOperatorsPlugin, - ConnectionFilterCustomOperatorsPlugin, - ConnectionFilterLogicalOperatorsPlugin, + ConnectionFilterBackwardRelationsPlugin, ConnectionFilterComputedAttributesPlugin, + ConnectionFilterCustomOperatorsPlugin, ConnectionFilterForwardRelationsPlugin, - ConnectionFilterBackwardRelationsPlugin, + ConnectionFilterInflectionPlugin, + ConnectionFilterLogicalOperatorsPlugin, + ConnectionFilterOperatorsPlugin, + ConnectionFilterTypesPlugin, } from './plugins'; +import type { ConnectionFilterOptions } from './types'; /** * Default schema options for the connection filter. diff --git a/graphile/graphile-connection-filter/src/types.ts b/graphile/graphile-connection-filter/src/types.ts index c4634d9143..8b97e8f847 100644 --- a/graphile/graphile-connection-filter/src/types.ts +++ b/graphile/graphile-connection-filter/src/types.ts @@ -1,5 +1,5 @@ -import type { SQL } from 'pg-sql2'; import type { GraphQLInputType } from 'graphql'; +import type { SQL } from 'pg-sql2'; /** * Symbol used to store the filter operator registry on the build object. diff --git a/graphile/graphile-function-bindings/src/plugin.ts b/graphile/graphile-function-bindings/src/plugin.ts index 65653698eb..0881770327 100644 --- a/graphile/graphile-function-bindings/src/plugin.ts +++ b/graphile/graphile-function-bindings/src/plugin.ts @@ -30,9 +30,9 @@ import 'graphile-build'; import 'graphile-build-pg'; +import { QueryBuilder, type SqlValue } from '@constructive-io/query-builder'; import { withPgClientFromPgService } from '@dataplan/pg'; import { Logger } from '@pgpmjs/logger'; -import { QueryBuilder, type SqlValue } from '@constructive-io/query-builder'; import { access, context as grafastContext, lambda, object } from 'grafast'; import type { GraphileConfig } from 'graphile-config'; import { isValidNameError } from 'graphql'; diff --git a/graphile/graphile-i18n/src/__tests__/i18n.test.ts b/graphile/graphile-i18n/src/__tests__/i18n.test.ts index 0e17dc6a71..4435813e32 100644 --- a/graphile/graphile-i18n/src/__tests__/i18n.test.ts +++ b/graphile/graphile-i18n/src/__tests__/i18n.test.ts @@ -8,9 +8,10 @@ * - Fallback to base table values when no translation exists */ -import { join } from 'path'; -import { getConnections, seed } from 'graphile-test'; import type { GraphQLResponse } from 'graphile-test'; +import { getConnections, seed } from 'graphile-test'; +import { join } from 'path'; + import { createI18nPlugin } from '../plugin'; type QueryFn = ( diff --git a/graphile/graphile-i18n/src/index.ts b/graphile/graphile-i18n/src/index.ts index ec72a81d9b..c12d2f9170 100644 --- a/graphile/graphile-i18n/src/index.ts +++ b/graphile/graphile-i18n/src/index.ts @@ -38,8 +38,8 @@ export { createI18nPlugin, I18nPlugin } from './plugin'; export { I18nPreset } from './preset'; // Middleware -export { makeI18nContext, additionalGraphQLContextFromRequest } from './middleware'; +export { additionalGraphQLContextFromRequest,makeI18nContext } from './middleware'; // Types -export type { I18nPluginOptions, I18nTableInfo, TranslatableField } from './types'; export type { I18nMiddlewareOptions } from './middleware'; +export type { I18nPluginOptions, I18nTableInfo, TranslatableField } from './types'; diff --git a/graphile/graphile-i18n/src/plugin.ts b/graphile/graphile-i18n/src/plugin.ts index ebe3ab14a4..0fb1af80d6 100644 --- a/graphile/graphile-i18n/src/plugin.ts +++ b/graphile/graphile-i18n/src/plugin.ts @@ -19,8 +19,9 @@ import 'graphile-build'; import 'graphile-build-pg'; -import { TYPES } from '@dataplan/pg'; + import type { PgCodecWithAttributes } from '@dataplan/pg'; +import { TYPES } from '@dataplan/pg'; import { context as grafastContext, lambda, object } from 'grafast'; import type { GraphileConfig } from 'graphile-config'; diff --git a/graphile/graphile-i18n/src/preset.ts b/graphile/graphile-i18n/src/preset.ts index 834f0d731e..d4488e9609 100644 --- a/graphile/graphile-i18n/src/preset.ts +++ b/graphile/graphile-i18n/src/preset.ts @@ -30,6 +30,7 @@ */ import type { GraphileConfig } from 'graphile-config'; + import { createI18nPlugin } from './plugin'; import type { I18nPluginOptions } from './types'; diff --git a/graphile/graphile-llm/src/__tests__/graphile-llm.test.ts b/graphile/graphile-llm/src/__tests__/graphile-llm.test.ts index 1774bbc6b5..30f2b58439 100644 --- a/graphile/graphile-llm/src/__tests__/graphile-llm.test.ts +++ b/graphile/graphile-llm/src/__tests__/graphile-llm.test.ts @@ -1067,7 +1067,11 @@ describe('Real Ollama + unifiedSearch + pgvector RRF integration', () => { afterAll(async () => { if (db) { - try { await db.client.query('ROLLBACK'); } catch {} + try { + await db.client.query('ROLLBACK'); + } catch { + // ignore + } } if (teardown) await teardown(); }); diff --git a/graphile/graphile-llm/src/env.ts b/graphile/graphile-llm/src/env.ts index b9a8c767ce..bac764f19c 100644 --- a/graphile/graphile-llm/src/env.ts +++ b/graphile/graphile-llm/src/env.ts @@ -5,15 +5,14 @@ * modules import from './env'. The actual implementation lives in the * shared @constructive-io/llm-env package. */ -export { - getEnvVars, - getEnvOptions, - getLlmEnvOptions, - llmDefaults, -} from '@constructive-io/llm-env'; - export type { LlmEnvOptions, LlmProviderConfig, ResolvedLlmEnvOptions, } from '@constructive-io/llm-env'; +export { + getEnvOptions, + getEnvVars, + getLlmEnvOptions, + llmDefaults, +} from '@constructive-io/llm-env'; diff --git a/graphile/graphile-llm/src/index.ts b/graphile/graphile-llm/src/index.ts index 01664f0c32..47e5d36bad 100644 --- a/graphile/graphile-llm/src/index.ts +++ b/graphile/graphile-llm/src/index.ts @@ -32,7 +32,7 @@ // Environment configuration (re-exported from @constructive-io/llm-env) export type { LlmEnvOptions, LlmProviderConfig, ResolvedLlmEnvOptions } from './env'; -export { getEnvVars, getEnvOptions, getLlmEnvOptions, llmDefaults } from './env'; +export { getEnvOptions, getEnvVars, getLlmEnvOptions, llmDefaults } from './env'; // Preset (recommended entry point) export { GraphileLlmPreset } from './preset'; diff --git a/graphile/graphile-llm/src/plugins/text-search-plugin.ts b/graphile/graphile-llm/src/plugins/text-search-plugin.ts index 781e7694f0..cb6d8e34e9 100644 --- a/graphile/graphile-llm/src/plugins/text-search-plugin.ts +++ b/graphile/graphile-llm/src/plugins/text-search-plugin.ts @@ -32,8 +32,8 @@ import type { GraphileConfig } from 'graphile-config'; -import { llmConfigStore } from '../embedder'; import type { LlmConfigOverrides } from '../embedder'; +import { llmConfigStore } from '../embedder'; // ─── TypeScript Augmentation ──────────────────────────────────────────────── diff --git a/graphile/graphile-ltree/src/__tests__/ltree.test.ts b/graphile/graphile-ltree/src/__tests__/ltree.test.ts index 5f118e7f3e..1723046198 100644 --- a/graphile/graphile-ltree/src/__tests__/ltree.test.ts +++ b/graphile/graphile-ltree/src/__tests__/ltree.test.ts @@ -4,8 +4,8 @@ import { getConnections, seed } from 'graphile-test'; import { join } from 'path'; import type { PgTestClient } from 'pgsql-test'; -import { createFolderOperatorFactory } from '../plugins/folder-filter-operators'; import { LtreeExtensionDetectionPlugin } from '../plugins/detect-ltree'; +import { createFolderOperatorFactory } from '../plugins/folder-filter-operators'; import { LtreeCodecPlugin } from '../plugins/ltree-codec'; interface FileNode { diff --git a/graphile/graphile-ltree/src/index.ts b/graphile/graphile-ltree/src/index.ts index f3dd6195cf..72de55a598 100644 --- a/graphile/graphile-ltree/src/index.ts +++ b/graphile/graphile-ltree/src/index.ts @@ -17,7 +17,7 @@ export { GraphileFolderPreset, GraphileLtreePreset } from './preset'; // Individual plugins export type { LtreeExtensionInfo } from './plugins/detect-ltree'; export { LtreeExtensionDetectionPlugin } from './plugins/detect-ltree'; -export { ltreeToSlash, LTREE_SCALAR_NAME, LtreeCodecPlugin, slashToLtree } from './plugins/ltree-codec'; +export { LTREE_SCALAR_NAME, LtreeCodecPlugin, ltreeToSlash, slashToLtree } from './plugins/ltree-codec'; // Connection filter operator factories export { createFolderOperatorFactory } from './plugins/folder-filter-operators'; diff --git a/graphile/graphile-meta/src/constraint-meta-builders.ts b/graphile/graphile-meta/src/constraint-meta-builders.ts index 1d6001dfa9..5cc7dfcfea 100644 --- a/graphile/graphile-meta/src/constraint-meta-builders.ts +++ b/graphile/graphile-meta/src/constraint-meta-builders.ts @@ -1,5 +1,5 @@ +import { type BuildContext,buildFieldList } from './table-meta-context'; import { buildFieldMeta } from './type-mappings'; -import { buildFieldList, type BuildContext } from './table-meta-context'; import type { ForeignKeyConstraintMeta, PgAttribute, diff --git a/graphile/graphile-meta/src/encoding-meta-builders.ts b/graphile/graphile-meta/src/encoding-meta-builders.ts index d4044b9fa4..179f255a55 100644 --- a/graphile/graphile-meta/src/encoding-meta-builders.ts +++ b/graphile/graphile-meta/src/encoding-meta-builders.ts @@ -79,23 +79,23 @@ export function buildScalarEncoding( } switch (kind) { - case 'geojson': - return { - kind, - geometrySubtype: + case 'geojson': + return { + kind, + geometrySubtype: typeof ext?.geometrySubtype === 'string' ? ext.geometrySubtype : null, - srid: typeof ext?.geometrySrid === 'number' ? ext.geometrySrid : null - }; - case 'vector': - return { - kind, - elementType: 'float', - dimensions: + srid: typeof ext?.geometrySrid === 'number' ? ext.geometrySrid : null + }; + case 'vector': + return { + kind, + elementType: 'float', + dimensions: typeof ext?.vectorDimensions === 'number' ? ext.vectorDimensions : null - }; - case 'ltree': - return { kind, dotPath: true }; - default: - return { kind }; + }; + case 'ltree': + return { kind, dotPath: true }; + default: + return { kind }; } } diff --git a/graphile/graphile-meta/src/graphql-meta-field.ts b/graphile/graphile-meta/src/graphql-meta-field.ts index 03c16bc9c9..9f4a149c80 100644 --- a/graphile/graphile-meta/src/graphql-meta-field.ts +++ b/graphile/graphile-meta/src/graphql-meta-field.ts @@ -35,7 +35,7 @@ function createMetaSchemaType(): GraphQLObjectType { kind: { type: nn(GraphQLString), description: - "Machine kind: bigint, datetime, date, time, interval, uuid, geojson, point, inet, ltree, vector, bytea, or composite." + 'Machine kind: bigint, datetime, date, time, interval, uuid, geojson, point, inet, ltree, vector, bytea, or composite.' }, elementType: { type: GraphQLString, description: "For 'vector': element scalar (e.g. 'float')." }, dimensions: { type: GraphQLInt, description: "For 'vector': declared length, else null." }, diff --git a/graphile/graphile-meta/src/name-meta-builders.ts b/graphile/graphile-meta/src/name-meta-builders.ts index fdfbefad75..26a055f783 100644 --- a/graphile/graphile-meta/src/name-meta-builders.ts +++ b/graphile/graphile-meta/src/name-meta-builders.ts @@ -97,9 +97,9 @@ export function buildQueryMeta( const codec = resource.codec; const connectionType = codec ? safeInflection( - () => inflection.tableConnectionType?.(codec), - `${tableType}Connection`, - ) + () => inflection.tableConnectionType?.(codec), + `${tableType}Connection`, + ) : null; const orderedUniques = [...uniques].sort( (left, right) => Number(!!right.isPrimary) - Number(!!left.isPrimary), @@ -183,9 +183,9 @@ export function buildQueryMeta( ), one: hasPrimaryKey ? safeInflection( - () => inflection.tableFieldName?.(resource), - tableType.toLowerCase(), - ) + () => inflection.tableFieldName?.(resource), + tableType.toLowerCase(), + ) : null, create: safeInflection( () => inflection.createField?.(resource), @@ -193,15 +193,15 @@ export function buildQueryMeta( ), update: hasPrimaryKey ? safeInflection( - () => inflection.updateByKeys?.(resource), - `update${tableType}`, - ) + () => inflection.updateByKeys?.(resource), + `update${tableType}`, + ) : null, delete: hasPrimaryKey ? safeInflection( - () => inflection.deleteByKeys?.(resource), - `delete${tableType}`, - ) + () => inflection.deleteByKeys?.(resource), + `delete${tableType}`, + ) : null, }; } diff --git a/graphile/graphile-meta/src/relation-meta-builders.ts b/graphile/graphile-meta/src/relation-meta-builders.ts index 9ae2c5c485..8b41228197 100644 --- a/graphile/graphile-meta/src/relation-meta-builders.ts +++ b/graphile/graphile-meta/src/relation-meta-builders.ts @@ -1,4 +1,3 @@ -import { safeInflection } from './inflection-utils'; import { buildForeignKeyConstraint, } from './constraint-meta-builders'; @@ -6,8 +5,9 @@ import { findExecutableField, getFieldContainerType, } from './graphql-schema-utils'; +import { safeInflection } from './inflection-utils'; import { resolveTableType } from './name-meta-builders'; -import { buildFieldList, type BuildContext } from './table-meta-context'; +import { type BuildContext,buildFieldList } from './table-meta-context'; import { getRelation, getResourceCodec, @@ -114,13 +114,13 @@ export function buildBelongsToRelations( if (context.schema && !remoteCodec) continue; const executable = remoteCodec ? resolveDirectRelationField( - relationName, - relation, - isUnique, - codec, - remoteCodec, - context, - ) + relationName, + relation, + isUnique, + codec, + remoteCodec, + context, + ) : null; if (context.schema && !executable) continue; const remoteTypeName = remoteCodec @@ -162,13 +162,13 @@ export function buildReverseRelations( if (context.schema && !remoteCodec) continue; const executable = remoteCodec ? resolveDirectRelationField( - relationName, - relation, - isUnique, - codec, - remoteCodec, - context, - ) + relationName, + relation, + isUnique, + codec, + remoteCodec, + context, + ) : null; if (context.schema && !executable) continue; const remoteTypeName = remoteCodec @@ -211,32 +211,32 @@ function buildManyToManyRelation( const rightTypeName = resolveTableType(context.build, rightCodec); const executable = context.schema ? findExecutableField(getFieldContainerType(context.schema, leftTypeName), [ - { - name: safeInflection( - () => - context.build.inflection.manyToManyRelationConnectionField?.( - details - ), - null, - ), - typeName: safeInflection( - () => - context.build.inflection.manyToManyRelationConnectionType?.({ - ...details, - leftTableTypeName: leftTypeName, - }), - null, - ), - }, - { - name: safeInflection( - () => - context.build.inflection.manyToManyRelationListField?.(details), - null, - ), - typeName: rightTypeName, - }, - ]) + { + name: safeInflection( + () => + context.build.inflection.manyToManyRelationConnectionField?.( + details + ), + null, + ), + typeName: safeInflection( + () => + context.build.inflection.manyToManyRelationConnectionType?.({ + ...details, + leftTableTypeName: leftTypeName, + }), + null, + ), + }, + { + name: safeInflection( + () => + context.build.inflection.manyToManyRelationListField?.(details), + null, + ), + typeName: rightTypeName, + }, + ]) : null; if (context.schema && !executable) return null; diff --git a/graphile/graphile-meta/src/table-meta-builder.ts b/graphile/graphile-meta/src/table-meta-builder.ts index 1978f94a4a..615f4bdc92 100644 --- a/graphile/graphile-meta/src/table-meta-builder.ts +++ b/graphile/graphile-meta/src/table-meta-builder.ts @@ -92,9 +92,9 @@ function buildTableMeta( codecForLookup && context.build.hasGraphQLTypeForPgCodec?.(codecForLookup, 'output') ? context.build.getGraphQLTypeNameByPgCodec?.( - codecForLookup, - 'output' - ) + codecForLookup, + 'output' + ) : null; if (registeredTypeName && registeredTypeName !== finalTypeName) { return []; diff --git a/graphile/graphile-meta/src/table-resource-utils.ts b/graphile/graphile-meta/src/table-resource-utils.ts index 1d095f37be..b5e2e65eef 100644 --- a/graphile/graphile-meta/src/table-resource-utils.ts +++ b/graphile/graphile-meta/src/table-resource-utils.ts @@ -1,3 +1,4 @@ +import type { TableResourceWithCodec } from './table-meta-context'; import type { MetaBuild, PgAttribute, @@ -6,7 +7,6 @@ import type { PgTableResource, PgUnique, } from './types'; -import type { TableResourceWithCodec } from './table-meta-context'; function isRecord(value: unknown): value is Record { return typeof value === 'object' && value !== null; diff --git a/graphile/graphile-pg-aggregates/__tests__/pg-aggregates.test.ts b/graphile/graphile-pg-aggregates/__tests__/pg-aggregates.test.ts index 3498f5069e..b0770e079b 100644 --- a/graphile/graphile-pg-aggregates/__tests__/pg-aggregates.test.ts +++ b/graphile/graphile-pg-aggregates/__tests__/pg-aggregates.test.ts @@ -1,8 +1,9 @@ -import { join } from 'path'; -import { getConnectionsObject, seed } from 'graphile-test'; -import type { GraphQLQueryFnObj } from 'graphile-test'; import type { GraphileConfig } from 'graphile-config'; import { ConnectionFilterPreset } from 'graphile-connection-filter'; +import type { GraphQLQueryFnObj } from 'graphile-test'; +import { getConnectionsObject, seed } from 'graphile-test'; +import { join } from 'path'; + import { PgAggregatesPreset } from '../src'; const SCHEMA = 'agg_test'; diff --git a/graphile/graphile-postgis/__tests__/aggregate-functions.test.ts b/graphile/graphile-postgis/__tests__/aggregate-functions.test.ts index cc0b27a1ad..459b4f116e 100644 --- a/graphile/graphile-postgis/__tests__/aggregate-functions.test.ts +++ b/graphile/graphile-postgis/__tests__/aggregate-functions.test.ts @@ -15,10 +15,10 @@ function createMockBuild(schemaName = 'public', hasPostgis = true): MockBuild { return { pgGISExtensionInfo: hasPostgis ? { - schemaName, - geometryCodec: { name: 'geometry' }, - geographyCodec: null - } + schemaName, + geometryCodec: { name: 'geometry' }, + geographyCodec: null + } : undefined, extend(base: Record, extra: Record, _reason: string) { return { ...base, ...extra }; diff --git a/graphile/graphile-postgis/__tests__/codec.test.ts b/graphile/graphile-postgis/__tests__/codec.test.ts index a802975b24..4f1e19e145 100644 --- a/graphile/graphile-postgis/__tests__/codec.test.ts +++ b/graphile/graphile-postgis/__tests__/codec.test.ts @@ -1,7 +1,8 @@ import type { PgCodec } from '@dataplan/pg'; + +import { GisSubtype } from '../src/constants'; import { PostgisCodecPlugin } from '../src/plugins/codec'; import type { GisFieldValue } from '../src/types'; -import { GisSubtype } from '../src/constants'; import { getGISTypeModifier } from '../src/utils'; // Test event shape matching the GatherHooks.pgCodecs_findPgCodec event diff --git a/graphile/graphile-postgis/__tests__/connection-filter-integration.test.ts b/graphile/graphile-postgis/__tests__/connection-filter-integration.test.ts index 8479d56989..be84d06e31 100644 --- a/graphile/graphile-postgis/__tests__/connection-filter-integration.test.ts +++ b/graphile/graphile-postgis/__tests__/connection-filter-integration.test.ts @@ -1,5 +1,6 @@ -import { CONCRETE_SUBTYPES, GisSubtype } from '../src/constants'; import type { ConnectionFilterOperatorSpec as OperatorSpec } from 'graphile-connection-filter'; + +import { CONCRETE_SUBTYPES } from '../src/constants'; import { createPostgisOperatorFactory } from '../src/plugins/connection-filter-operators'; /** diff --git a/graphile/graphile-postgis/__tests__/connection-filter-operators.test.ts b/graphile/graphile-postgis/__tests__/connection-filter-operators.test.ts index 7e8e9c068c..0fe7ed1388 100644 --- a/graphile/graphile-postgis/__tests__/connection-filter-operators.test.ts +++ b/graphile/graphile-postgis/__tests__/connection-filter-operators.test.ts @@ -1,4 +1,5 @@ import sql from 'pg-sql2'; + import { CONCRETE_SUBTYPES } from '../src/constants'; import { createPostgisOperatorFactory } from '../src/plugins/connection-filter-operators'; import { GraphilePostgisPreset } from '../src/preset'; @@ -57,10 +58,10 @@ function runFactory(options: { const postgisInfo = hasPostgis ? { - schemaName, - geometryCodec: { name: 'geometry' }, - geographyCodec: { name: 'geography' } - } + schemaName, + geometryCodec: { name: 'geometry' }, + geographyCodec: { name: 'geography' } + } : undefined; const build = { diff --git a/graphile/graphile-postgis/__tests__/constants.test.ts b/graphile/graphile-postgis/__tests__/constants.test.ts index 8ff318e0a0..51c5d269d2 100644 --- a/graphile/graphile-postgis/__tests__/constants.test.ts +++ b/graphile/graphile-postgis/__tests__/constants.test.ts @@ -1,9 +1,8 @@ import { - GisSubtype, - SUBTYPE_STRING_BY_SUBTYPE, + CONCRETE_SUBTYPES, GIS_SUBTYPE_NAME, - CONCRETE_SUBTYPES -} from '../src/constants'; + GisSubtype, + SUBTYPE_STRING_BY_SUBTYPE} from '../src/constants'; describe('GisSubtype enum', () => { it('should have correct numeric values', () => { diff --git a/graphile/graphile-postgis/__tests__/geometry-fields.test.ts b/graphile/graphile-postgis/__tests__/geometry-fields.test.ts index 8ba98d0e91..0b1438b934 100644 --- a/graphile/graphile-postgis/__tests__/geometry-fields.test.ts +++ b/graphile/graphile-postgis/__tests__/geometry-fields.test.ts @@ -1,6 +1,6 @@ import { GisSubtype } from '../src/constants'; -import { getGISTypeName } from '../src/utils'; import { PostgisGeometryFieldsPlugin } from '../src/plugins/geometry-fields'; +import { getGISTypeName } from '../src/utils'; describe('PostgisGeometryFieldsPlugin', () => { describe('plugin metadata', () => { diff --git a/graphile/graphile-postgis/__tests__/preset.test.ts b/graphile/graphile-postgis/__tests__/preset.test.ts index 4e8de6801a..4240751a44 100644 --- a/graphile/graphile-postgis/__tests__/preset.test.ts +++ b/graphile/graphile-postgis/__tests__/preset.test.ts @@ -1,13 +1,13 @@ -import { GraphilePostgisPreset } from '../src/preset'; +import { PostgisAggregatePlugin } from '../src/plugins/aggregate-functions'; import { PostgisCodecPlugin } from '../src/plugins/codec'; -import { PostgisInflectionPlugin } from '../src/plugins/inflection'; import { PostgisExtensionDetectionPlugin } from '../src/plugins/detect-extension'; -import { PostgisRegisterTypesPlugin } from '../src/plugins/register-types'; import { PostgisGeometryFieldsPlugin } from '../src/plugins/geometry-fields'; +import { PostgisInflectionPlugin } from '../src/plugins/inflection'; import { PostgisMeasurementFieldsPlugin } from '../src/plugins/measurement-fields'; -import { PostgisTransformationFieldsPlugin } from '../src/plugins/transformation-functions'; -import { PostgisAggregatePlugin } from '../src/plugins/aggregate-functions'; +import { PostgisRegisterTypesPlugin } from '../src/plugins/register-types'; import { PostgisSpatialRelationsPlugin } from '../src/plugins/spatial-relations'; +import { PostgisTransformationFieldsPlugin } from '../src/plugins/transformation-functions'; +import { GraphilePostgisPreset } from '../src/preset'; describe('GraphilePostgisPreset', () => { it('should include all 9 plugins', () => { diff --git a/graphile/graphile-postgis/__tests__/register-types.test.ts b/graphile/graphile-postgis/__tests__/register-types.test.ts index 5e333293cc..65ed29eb4f 100644 --- a/graphile/graphile-postgis/__tests__/register-types.test.ts +++ b/graphile/graphile-postgis/__tests__/register-types.test.ts @@ -1,6 +1,6 @@ -import { GisSubtype, CONCRETE_SUBTYPES } from '../src/constants'; -import { getGISTypeModifier, getGISTypeName } from '../src/utils'; +import { CONCRETE_SUBTYPES,GisSubtype } from '../src/constants'; import { PostgisRegisterTypesPlugin } from '../src/plugins/register-types'; +import { getGISTypeModifier, getGISTypeName } from '../src/utils'; describe('PostgisRegisterTypesPlugin', () => { describe('plugin metadata', () => { diff --git a/graphile/graphile-postgis/__tests__/spatial-relations.test.ts b/graphile/graphile-postgis/__tests__/spatial-relations.test.ts index d9fe6b1e84..8e29ba7d7b 100644 --- a/graphile/graphile-postgis/__tests__/spatial-relations.test.ts +++ b/graphile/graphile-postgis/__tests__/spatial-relations.test.ts @@ -1,10 +1,10 @@ import sql from 'pg-sql2'; + import { + collectSpatialRelations, OPERATOR_REGISTRY, parseSpatialRelationTag, - collectSpatialRelations, PostgisSpatialRelationsPlugin, - type SpatialRelationInfo, } from '../src/plugins/spatial-relations'; import { GraphilePostgisPreset } from '../src/preset'; diff --git a/graphile/graphile-postgis/__tests__/within-distance-operator.test.ts b/graphile/graphile-postgis/__tests__/within-distance-operator.test.ts index 90b7a64ddf..eb2511507f 100644 --- a/graphile/graphile-postgis/__tests__/within-distance-operator.test.ts +++ b/graphile/graphile-postgis/__tests__/within-distance-operator.test.ts @@ -1,4 +1,5 @@ import sql from 'pg-sql2'; + import { CONCRETE_SUBTYPES } from '../src/constants'; import { createWithinDistanceOperatorFactory } from '../src/plugins/within-distance-operator'; import { GraphilePostgisPreset } from '../src/preset'; @@ -74,10 +75,10 @@ function runFactory(options: { const postgisInfo = hasPostgis ? { - schemaName, - geometryCodec: { name: 'geometry' }, - geographyCodec: { name: 'geography' } - } + schemaName, + geometryCodec: { name: 'geometry' }, + geographyCodec: { name: 'geography' } + } : undefined; const build = { diff --git a/graphile/graphile-postgis/src/index.ts b/graphile/graphile-postgis/src/index.ts index 60b5aa3212..2a341e6568 100644 --- a/graphile/graphile-postgis/src/index.ts +++ b/graphile/graphile-postgis/src/index.ts @@ -17,33 +17,33 @@ export { GraphilePostgisPreset } from './preset'; // Individual plugins +export { PostgisAggregatePlugin } from './plugins/aggregate-functions'; export { PostgisCodecPlugin } from './plugins/codec'; -export { PostgisInflectionPlugin } from './plugins/inflection'; export { PostgisExtensionDetectionPlugin } from './plugins/detect-extension'; -export { PostgisRegisterTypesPlugin } from './plugins/register-types'; export { PostgisGeometryFieldsPlugin } from './plugins/geometry-fields'; +export { PostgisInflectionPlugin } from './plugins/inflection'; export { PostgisMeasurementFieldsPlugin } from './plugins/measurement-fields'; -export { PostgisTransformationFieldsPlugin } from './plugins/transformation-functions'; -export { PostgisAggregatePlugin } from './plugins/aggregate-functions'; -export { - PostgisSpatialRelationsPlugin, - OPERATOR_REGISTRY, - parseSpatialRelationTag, - collectSpatialRelations, -} from './plugins/spatial-relations'; +export { PostgisRegisterTypesPlugin } from './plugins/register-types'; export type { SpatialOperatorRegistration, SpatialRelationInfo, } from './plugins/spatial-relations'; +export { + collectSpatialRelations, + OPERATOR_REGISTRY, + parseSpatialRelationTag, + PostgisSpatialRelationsPlugin, +} from './plugins/spatial-relations'; +export { PostgisTransformationFieldsPlugin } from './plugins/transformation-functions'; // Connection filter operator factories (spatial operators for graphile-connection-filter) export { createPostgisOperatorFactory } from './plugins/connection-filter-operators'; export { createWithinDistanceOperatorFactory } from './plugins/within-distance-operator'; // Constants and utilities -export { GisSubtype, SUBTYPE_STRING_BY_SUBTYPE, GIS_SUBTYPE_NAME, CONCRETE_SUBTYPES } from './constants'; +export { CONCRETE_SUBTYPES,GIS_SUBTYPE_NAME, GisSubtype, SUBTYPE_STRING_BY_SUBTYPE } from './constants'; export { getGISTypeDetails, getGISTypeModifier, getGISTypeName } from './utils'; // Types -export type { GisTypeDetails, GisFieldValue } from './types'; export type { PostgisExtensionInfo } from './plugins/detect-extension'; +export type { GisFieldValue,GisTypeDetails } from './types'; diff --git a/graphile/graphile-postgis/src/plugins/aggregate-functions.ts b/graphile/graphile-postgis/src/plugins/aggregate-functions.ts index d24916f69a..2aa41edbb7 100644 --- a/graphile/graphile-postgis/src/plugins/aggregate-functions.ts +++ b/graphile/graphile-postgis/src/plugins/aggregate-functions.ts @@ -1,10 +1,10 @@ import 'graphile-build'; import 'graphile-build-pg'; -import type { GraphileConfig } from 'graphile-config'; - // Import types.ts for Build augmentation side effects import '../types'; +import type { GraphileConfig } from 'graphile-config'; + /** * PostgisAggregatePlugin * diff --git a/graphile/graphile-postgis/src/plugins/codec.ts b/graphile/graphile-postgis/src/plugins/codec.ts index 4049f28949..59dfde1679 100644 --- a/graphile/graphile-postgis/src/plugins/codec.ts +++ b/graphile/graphile-postgis/src/plugins/codec.ts @@ -1,8 +1,10 @@ import 'graphile-build-pg'; + import type { PgCodec } from '@dataplan/pg'; import type { GraphileConfig } from 'graphile-config'; import type { SQL } from 'pg-sql2'; import sql from 'pg-sql2'; + import { GIS_SUBTYPE_NAME } from '../constants'; import type { GisFieldValue } from '../types'; import { getGISTypeDetails } from '../utils'; diff --git a/graphile/graphile-postgis/src/plugins/connection-filter-operators.ts b/graphile/graphile-postgis/src/plugins/connection-filter-operators.ts index 777649a22c..5431c81fc3 100644 --- a/graphile/graphile-postgis/src/plugins/connection-filter-operators.ts +++ b/graphile/graphile-postgis/src/plugins/connection-filter-operators.ts @@ -1,14 +1,16 @@ import 'graphile-build'; import 'graphile-build-pg'; import 'graphile-connection-filter'; + import type { PgCodec } from '@dataplan/pg'; import type { ConnectionFilterOperatorFactory, ConnectionFilterOperatorRegistration, ConnectionFilterOperatorSpec, } from 'graphile-connection-filter'; -import sql from 'pg-sql2'; import type { SQL } from 'pg-sql2'; +import sql from 'pg-sql2'; + import { CONCRETE_SUBTYPES } from '../constants'; import type { PostgisExtensionInfo } from './detect-extension'; @@ -18,21 +20,21 @@ import type { PostgisExtensionInfo } from './detect-extension'; */ function buildOperatorExpr(op: string, i: SQL, v: SQL): SQL { switch (op) { - case '=': return sql.fragment`${i} = ${v}`; - case '&&': return sql.fragment`${i} && ${v}`; - case '&&&': return sql.fragment`${i} &&& ${v}`; - case '&<': return sql.fragment`${i} &< ${v}`; - case '&<|': return sql.fragment`${i} &<| ${v}`; - case '&>': return sql.fragment`${i} &> ${v}`; - case '|&>': return sql.fragment`${i} |&> ${v}`; - case '<<': return sql.fragment`${i} << ${v}`; - case '<<|': return sql.fragment`${i} <<| ${v}`; - case '>>': return sql.fragment`${i} >> ${v}`; - case '|>>': return sql.fragment`${i} |>> ${v}`; - case '~': return sql.fragment`${i} ~ ${v}`; - case '~=': return sql.fragment`${i} ~= ${v}`; - default: - throw new Error(`Unexpected PostGIS SQL operator: ${op}`); + case '=': return sql.fragment`${i} = ${v}`; + case '&&': return sql.fragment`${i} && ${v}`; + case '&&&': return sql.fragment`${i} &&& ${v}`; + case '&<': return sql.fragment`${i} &< ${v}`; + case '&<|': return sql.fragment`${i} &<| ${v}`; + case '&>': return sql.fragment`${i} &> ${v}`; + case '|&>': return sql.fragment`${i} |&> ${v}`; + case '<<': return sql.fragment`${i} << ${v}`; + case '<<|': return sql.fragment`${i} <<| ${v}`; + case '>>': return sql.fragment`${i} >> ${v}`; + case '|>>': return sql.fragment`${i} |>> ${v}`; + case '~': return sql.fragment`${i} ~ ${v}`; + case '~=': return sql.fragment`${i} ~= ${v}`; + default: + throw new Error(`Unexpected PostGIS SQL operator: ${op}`); } } diff --git a/graphile/graphile-postgis/src/plugins/detect-extension.ts b/graphile/graphile-postgis/src/plugins/detect-extension.ts index 5b8f6c1e11..b91f0ea182 100644 --- a/graphile/graphile-postgis/src/plugins/detect-extension.ts +++ b/graphile/graphile-postgis/src/plugins/detect-extension.ts @@ -1,7 +1,9 @@ import 'graphile-build'; import 'graphile-build-pg'; + import type { PgCodec } from '@dataplan/pg'; import type { GraphileConfig } from 'graphile-config'; + import type { PostgisExtensionInfo } from '../types'; export type { PostgisExtensionInfo } from '../types'; diff --git a/graphile/graphile-postgis/src/plugins/geometry-fields.ts b/graphile/graphile-postgis/src/plugins/geometry-fields.ts index 0242f53c1d..4cf8c56459 100644 --- a/graphile/graphile-postgis/src/plugins/geometry-fields.ts +++ b/graphile/graphile-postgis/src/plugins/geometry-fields.ts @@ -1,18 +1,19 @@ import 'graphile-build'; import 'graphile-build-pg'; +// Import types.ts for Build/Inflection/Scope augmentation side effects +import '../types'; + import type { GraphileConfig } from 'graphile-config'; import type { GraphQLFieldConfig, GraphQLList as GraphQLListType, GraphQLOutputType } from 'graphql'; + import { GisSubtype } from '../constants'; -import type { GisFieldValue, GisTypeDetails } from '../types'; +import type { GisFieldValue } from '../types'; import { getGISTypeName } from '../utils'; -// Import types.ts for Build/Inflection/Scope augmentation side effects -import '../types'; - /** * PostgisGeometryFieldsPlugin * @@ -54,50 +55,50 @@ export const PostgisGeometryFieldsPlugin: GraphileConfig.Plugin = { const getType = build.getPostgisTypeByGeometryType; switch (subtype) { - case GisSubtype.Point: - return addPointFields( - fields, build, pgGISCodecName, hasZ, - GraphQLNonNull, GraphQLFloat, inflection - ); - - case GisSubtype.LineString: - return addLineStringFields( - fields, build, pgGISCodecName, hasZ, hasM, srid, - GraphQLList, getType - ); - - case GisSubtype.Polygon: - return addPolygonFields( - fields, build, pgGISCodecName, hasZ, hasM, srid, - GraphQLList, getType - ); - - case GisSubtype.MultiPoint: - return addMultiPointFields( - fields, build, pgGISCodecName, hasZ, hasM, srid, - GraphQLList, getType - ); - - case GisSubtype.MultiLineString: - return addMultiLineStringFields( - fields, build, pgGISCodecName, hasZ, hasM, srid, - GraphQLList, getType - ); - - case GisSubtype.MultiPolygon: - return addMultiPolygonFields( - fields, build, pgGISCodecName, hasZ, hasM, srid, - GraphQLList, getType - ); - - case GisSubtype.GeometryCollection: - return addGeometryCollectionFields( - fields, build, pgGISCodecName, hasZ, hasM, - GraphQLList - ); - - default: - return fields; + case GisSubtype.Point: + return addPointFields( + fields, build, pgGISCodecName, hasZ, + GraphQLNonNull, GraphQLFloat, inflection + ); + + case GisSubtype.LineString: + return addLineStringFields( + fields, build, pgGISCodecName, hasZ, hasM, srid, + GraphQLList, getType + ); + + case GisSubtype.Polygon: + return addPolygonFields( + fields, build, pgGISCodecName, hasZ, hasM, srid, + GraphQLList, getType + ); + + case GisSubtype.MultiPoint: + return addMultiPointFields( + fields, build, pgGISCodecName, hasZ, hasM, srid, + GraphQLList, getType + ); + + case GisSubtype.MultiLineString: + return addMultiLineStringFields( + fields, build, pgGISCodecName, hasZ, hasM, srid, + GraphQLList, getType + ); + + case GisSubtype.MultiPolygon: + return addMultiPolygonFields( + fields, build, pgGISCodecName, hasZ, hasM, srid, + GraphQLList, getType + ); + + case GisSubtype.GeometryCollection: + return addGeometryCollectionFields( + fields, build, pgGISCodecName, hasZ, hasM, + GraphQLList + ); + + default: + return fields; } } } diff --git a/graphile/graphile-postgis/src/plugins/inflection.ts b/graphile/graphile-postgis/src/plugins/inflection.ts index f6cc537ad8..3cd5aae4d1 100644 --- a/graphile/graphile-postgis/src/plugins/inflection.ts +++ b/graphile/graphile-postgis/src/plugins/inflection.ts @@ -1,9 +1,10 @@ -import type { GraphileConfig } from 'graphile-config'; -import { GisSubtype, SUBTYPE_STRING_BY_SUBTYPE } from '../constants'; - // Import types.ts for the Inflection augmentation side effects import '../types'; +import type { GraphileConfig } from 'graphile-config'; + +import { GisSubtype, SUBTYPE_STRING_BY_SUBTYPE } from '../constants'; + /** * PostgisInflectionPlugin * diff --git a/graphile/graphile-postgis/src/plugins/measurement-fields.ts b/graphile/graphile-postgis/src/plugins/measurement-fields.ts index 57d542afdc..f206b394fe 100644 --- a/graphile/graphile-postgis/src/plugins/measurement-fields.ts +++ b/graphile/graphile-postgis/src/plugins/measurement-fields.ts @@ -1,13 +1,14 @@ import 'graphile-build'; import 'graphile-build-pg'; +// Import types.ts for Build/Inflection/Scope augmentation side effects +import '../types'; + import type { GraphileConfig } from 'graphile-config'; import type { GraphQLFieldConfig } from 'graphql'; + import { GisSubtype } from '../constants'; import type { GisFieldValue } from '../types'; -// Import types.ts for Build/Inflection/Scope augmentation side effects -import '../types'; - // ─── Client-side geodesic calculations ─────────────────────────────────── // // These compute approximate measurements from GeoJSON coordinates using diff --git a/graphile/graphile-postgis/src/plugins/register-types.ts b/graphile/graphile-postgis/src/plugins/register-types.ts index 54ed4da29f..f1eb9c7f0f 100644 --- a/graphile/graphile-postgis/src/plugins/register-types.ts +++ b/graphile/graphile-postgis/src/plugins/register-types.ts @@ -1,17 +1,18 @@ import 'graphile-build'; import 'graphile-build-pg'; +// Import types.ts for the Build/Inflection/Scope augmentation side effects +import '../types'; + import type { PgCodec } from '@dataplan/pg'; import type { GraphileConfig } from 'graphile-config'; import type { GraphQLInterfaceType, GraphQLObjectType, GraphQLOutputType, ValueNode } from 'graphql'; -import sql from 'pg-sql2'; import type { SQL } from 'pg-sql2'; -import { GisSubtype, CONCRETE_SUBTYPES } from '../constants'; +import sql from 'pg-sql2'; + +import { CONCRETE_SUBTYPES,GisSubtype } from '../constants'; import type { GisFieldValue, PostgisExtensionInfo } from '../types'; import { getGISTypeDetails, getGISTypeModifier, getGISTypeName } from '../utils'; -// Import types.ts for the Build/Inflection/Scope augmentation side effects -import '../types'; - /** * PostgisRegisterTypesPlugin * @@ -214,18 +215,18 @@ export const PostgisRegisterTypesPlugin: GraphileConfig.Plugin = { [inflection.geojsonFieldName()]: { type: geoJsonType, description: 'Converts the object to GeoJSON', - resolve(data: GisFieldValue) { - return data.__geojson; + resolve(data: GisFieldValue) { + return data.__geojson; + } + }, + srid: { + type: new GraphQLNonNull(GraphQLInt), + description: 'Spatial reference identifier (SRID)', + resolve(data: GisFieldValue) { + return data.__srid; + } } - }, - srid: { - type: new GraphQLNonNull(GraphQLInt), - description: 'Spatial reference identifier (SRID)', - resolve(data: GisFieldValue) { - return data.__srid; - } - } - }; + }; } }), `PostgisRegisterTypesPlugin registering ${concreteTypeName} type` @@ -363,28 +364,28 @@ function parseLiteralGeoJSON( throw new Error('GeoJSON input exceeds maximum nesting depth'); } switch (ast.kind) { - case Kind.STRING: - case Kind.BOOLEAN: - return ast.value; - case Kind.INT: - case Kind.FLOAT: - return parseFloat(ast.value); - case Kind.OBJECT: { - const value = Object.create(null); - ast.fields.forEach((field) => { - value[field.name.value] = parseLiteralGeoJSON(field.value, variables, Kind, depth + 1); - }); - return value; - } - case Kind.LIST: - return ast.values.map((n) => parseLiteralGeoJSON(n, variables, Kind, depth + 1)); - case Kind.NULL: - return null; - case Kind.VARIABLE: { - const variableName = ast.name.value; - return variables ? variables[variableName] : undefined; - } - default: - return undefined; + case Kind.STRING: + case Kind.BOOLEAN: + return ast.value; + case Kind.INT: + case Kind.FLOAT: + return parseFloat(ast.value); + case Kind.OBJECT: { + const value = Object.create(null); + ast.fields.forEach((field) => { + value[field.name.value] = parseLiteralGeoJSON(field.value, variables, Kind, depth + 1); + }); + return value; + } + case Kind.LIST: + return ast.values.map((n) => parseLiteralGeoJSON(n, variables, Kind, depth + 1)); + case Kind.NULL: + return null; + case Kind.VARIABLE: { + const variableName = ast.name.value; + return variables ? variables[variableName] : undefined; + } + default: + return undefined; } } diff --git a/graphile/graphile-postgis/src/plugins/spatial-relations.ts b/graphile/graphile-postgis/src/plugins/spatial-relations.ts index ba0f5f3aaa..20adc5132c 100644 --- a/graphile/graphile-postgis/src/plugins/spatial-relations.ts +++ b/graphile/graphile-postgis/src/plugins/spatial-relations.ts @@ -1,9 +1,11 @@ import 'graphile-build'; import 'graphile-build-pg'; import 'graphile-connection-filter'; + import type { GraphileConfig } from 'graphile-config'; import type { SQL } from 'pg-sql2'; import sql from 'pg-sql2'; + import type { PostgisExtensionInfo } from './detect-extension'; /** diff --git a/graphile/graphile-postgis/src/plugins/transformation-functions.ts b/graphile/graphile-postgis/src/plugins/transformation-functions.ts index cadbf310ff..8cac7c40d4 100644 --- a/graphile/graphile-postgis/src/plugins/transformation-functions.ts +++ b/graphile/graphile-postgis/src/plugins/transformation-functions.ts @@ -1,11 +1,12 @@ import 'graphile-build'; import 'graphile-build-pg'; +// Import types.ts for Build augmentation side effects +import '../types'; + import type { GraphileConfig } from 'graphile-config'; import type { GraphQLFieldConfig } from 'graphql'; -import type { GisFieldValue } from '../types'; -// Import types.ts for Build augmentation side effects -import '../types'; +import type { GisFieldValue } from '../types'; /** * PostgisTransformationFieldsPlugin @@ -111,30 +112,30 @@ function extractAllCoordinates(geojson: unknown): number[][] { const type = geo.type as string; switch (type) { - case 'Point': - return [geo.coordinates as number[]]; + case 'Point': + return [geo.coordinates as number[]]; - case 'MultiPoint': - case 'LineString': - return geo.coordinates as number[][]; + case 'MultiPoint': + case 'LineString': + return geo.coordinates as number[][]; - case 'MultiLineString': - case 'Polygon': - return (geo.coordinates as number[][][]).flat(); + case 'MultiLineString': + case 'Polygon': + return (geo.coordinates as number[][][]).flat(); - case 'MultiPolygon': - return (geo.coordinates as number[][][][]).flat(2); + case 'MultiPolygon': + return (geo.coordinates as number[][][][]).flat(2); - case 'GeometryCollection': { - const geometries = geo.geometries as unknown[]; - const all: number[][] = []; - for (const g of geometries) { - all.push(...extractAllCoordinates(g)); - } - return all; + case 'GeometryCollection': { + const geometries = geo.geometries as unknown[]; + const all: number[][] = []; + for (const g of geometries) { + all.push(...extractAllCoordinates(g)); } + return all; + } - default: - return []; + default: + return []; } } diff --git a/graphile/graphile-postgis/src/plugins/within-distance-operator.ts b/graphile/graphile-postgis/src/plugins/within-distance-operator.ts index 183487582a..630134f516 100644 --- a/graphile/graphile-postgis/src/plugins/within-distance-operator.ts +++ b/graphile/graphile-postgis/src/plugins/within-distance-operator.ts @@ -1,6 +1,9 @@ import 'graphile-build'; import 'graphile-build-pg'; import 'graphile-connection-filter'; +// Import types.ts for Build augmentation side effects +import '../types'; + import type { PgCodec } from '@dataplan/pg'; import type { ConnectionFilterOperatorFactory, @@ -8,14 +11,12 @@ import type { ConnectionFilterOperatorSpec, } from 'graphile-connection-filter'; import type { GraphQLInputObjectType as GraphQLInputObjectTypeType } from 'graphql'; -import sql from 'pg-sql2'; import type { SQL } from 'pg-sql2'; +import sql from 'pg-sql2'; + import { CONCRETE_SUBTYPES } from '../constants'; import type { PostgisExtensionInfo } from './detect-extension'; -// Import types.ts for Build augmentation side effects -import '../types'; - /** * Creates the PostGIS ST_DWithin (withinDistance) operator factory. * diff --git a/graphile/graphile-postgis/src/preset.ts b/graphile/graphile-postgis/src/preset.ts index de789148a7..aad6291763 100644 --- a/graphile/graphile-postgis/src/preset.ts +++ b/graphile/graphile-postgis/src/preset.ts @@ -1,14 +1,15 @@ import type { GraphileConfig } from 'graphile-config'; + +import { PostgisAggregatePlugin } from './plugins/aggregate-functions'; import { PostgisCodecPlugin } from './plugins/codec'; -import { PostgisInflectionPlugin } from './plugins/inflection'; +import { createPostgisOperatorFactory } from './plugins/connection-filter-operators'; import { PostgisExtensionDetectionPlugin } from './plugins/detect-extension'; -import { PostgisRegisterTypesPlugin } from './plugins/register-types'; import { PostgisGeometryFieldsPlugin } from './plugins/geometry-fields'; +import { PostgisInflectionPlugin } from './plugins/inflection'; import { PostgisMeasurementFieldsPlugin } from './plugins/measurement-fields'; -import { PostgisTransformationFieldsPlugin } from './plugins/transformation-functions'; -import { PostgisAggregatePlugin } from './plugins/aggregate-functions'; +import { PostgisRegisterTypesPlugin } from './plugins/register-types'; import { PostgisSpatialRelationsPlugin } from './plugins/spatial-relations'; -import { createPostgisOperatorFactory } from './plugins/connection-filter-operators'; +import { PostgisTransformationFieldsPlugin } from './plugins/transformation-functions'; import { createWithinDistanceOperatorFactory } from './plugins/within-distance-operator'; /** diff --git a/graphile/graphile-postgis/src/types.ts b/graphile/graphile-postgis/src/types.ts index ef470a4304..60defc8ea8 100644 --- a/graphile/graphile-postgis/src/types.ts +++ b/graphile/graphile-postgis/src/types.ts @@ -2,6 +2,7 @@ import type { PgCodec } from '@dataplan/pg'; import type { Geometry } from 'geojson'; import type { GraphQLInterfaceType, GraphQLObjectType } from 'graphql'; import type { SQL } from 'pg-sql2'; + import type { GisSubtype } from './constants'; export interface GisTypeDetails { diff --git a/graphile/graphile-postgis/src/utils.ts b/graphile/graphile-postgis/src/utils.ts index c164fa4e76..89f3062a6f 100644 --- a/graphile/graphile-postgis/src/utils.ts +++ b/graphile/graphile-postgis/src/utils.ts @@ -1,4 +1,4 @@ -import { GisSubtype, GIS_SUBTYPE_NAME } from './constants'; +import { GIS_SUBTYPE_NAME,GisSubtype } from './constants'; import type { GisTypeDetails } from './types'; /** diff --git a/graphile/graphile-presigned-url-plugin/__tests__/s3-signer.integration.test.ts b/graphile/graphile-presigned-url-plugin/__tests__/s3-signer.integration.test.ts index 8890ac4d9f..7fee7273a5 100644 --- a/graphile/graphile-presigned-url-plugin/__tests__/s3-signer.integration.test.ts +++ b/graphile/graphile-presigned-url-plugin/__tests__/s3-signer.integration.test.ts @@ -13,10 +13,10 @@ import { S3Client } from '@aws-sdk/client-s3'; import { createS3Bucket } from '@constructive-io/s3-utils'; import { - generatePresignedPutUrl, + deleteS3Object, generatePresignedGetUrl, + generatePresignedPutUrl, headObject, - deleteS3Object, } from '../src/s3-signer'; import type { S3Config } from '../src/types'; diff --git a/graphile/graphile-presigned-url-plugin/src/download-url-field.ts b/graphile/graphile-presigned-url-plugin/src/download-url-field.ts index e4aa6b76e6..0fad704a0c 100644 --- a/graphile/graphile-presigned-url-plugin/src/download-url-field.ts +++ b/graphile/graphile-presigned-url-plugin/src/download-url-field.ts @@ -19,14 +19,15 @@ * the plan() function is required for Grafast to execute the S3 signing. */ -import type { GraphileConfig } from 'graphile-config'; import 'graphile-build'; -import { context as grafastContext, lambda, object } from 'grafast'; + import { Logger } from '@pgpmjs/logger'; +import { context as grafastContext, lambda, object } from 'grafast'; +import type { GraphileConfig } from 'graphile-config'; -import type { PresignedUrlPluginOptions, S3Config, StorageModuleConfig } from './types'; import { generatePresignedGetUrl } from './s3-signer'; import { loadAllStorageModules, resolveStorageConfigFromCodec } from './storage-module-cache'; +import type { PresignedUrlPluginOptions, S3Config, StorageModuleConfig } from './types'; const log = new Logger('graphile-presigned-url:download-url'); @@ -159,26 +160,26 @@ export function createDownloadUrlPlugin( // resolve it without the request role's pgSettings. const config = databaseId ? resolveStorageConfigFromCodec( - capturedCodec, - await withPgClient(null, (pgClient: any) => loadAllStorageModules(pgClient, databaseId)), - ) + capturedCodec, + await withPgClient(null, (pgClient: any) => loadAllStorageModules(pgClient, databaseId)), + ) : null; const resolved = config ? await withPgClient(pgSettings, async (pgClient: any) => { - // Look up the bucket key for scoped S3 resolution - let bucketKey = 'public'; - if (bucketId) { - const bucketResult = await pgClient.query({ - text: `SELECT key FROM ${config.bucketsQualifiedName} WHERE id = $1 LIMIT 1`, - values: [bucketId], - }); - if (bucketResult.rows[0]?.key) { - bucketKey = bucketResult.rows[0].key; - } + // Look up the bucket key for scoped S3 resolution + let bucketKey = 'public'; + if (bucketId) { + const bucketResult = await pgClient.query({ + text: `SELECT key FROM ${config.bucketsQualifiedName} WHERE id = $1 LIMIT 1`, + values: [bucketId], + }); + if (bucketResult.rows[0]?.key) { + bucketKey = bucketResult.rows[0].key; } + } - return { config, databaseId, bucketKey }; - }) + return { config, databaseId, bucketKey }; + }) : null; if (resolved) { downloadUrlExpirySeconds = resolved.config.downloadUrlExpirySeconds; diff --git a/graphile/graphile-presigned-url-plugin/src/index.ts b/graphile/graphile-presigned-url-plugin/src/index.ts index 94e3babc03..3d8ee4fe44 100644 --- a/graphile/graphile-presigned-url-plugin/src/index.ts +++ b/graphile/graphile-presigned-url-plugin/src/index.ts @@ -27,19 +27,19 @@ * ``` */ -export { PresignedUrlPlugin, createPresignedUrlPlugin } from './plugin'; export { createDownloadUrlPlugin } from './download-url-field'; +export { createPresignedUrlPlugin,PresignedUrlPlugin } from './plugin'; export { PresignedUrlPreset } from './preset'; -export { getStorageModuleConfig, getStorageModuleConfigForOwner, getBucketConfig, resolveStorageModuleByFileId, loadAllStorageModules, resolveStorageConfigFromCodec, clearStorageModuleCache, clearBucketCache, isS3BucketProvisioned, markS3BucketProvisioned } from './storage-module-cache'; -export { generatePresignedPutUrl, generatePresignedGetUrl, deleteS3Object, headObject } from './s3-signer'; +export { deleteS3Object, generatePresignedGetUrl, generatePresignedPutUrl, headObject } from './s3-signer'; +export { clearBucketCache, clearStorageModuleCache, getBucketConfig, getStorageModuleConfig, getStorageModuleConfigForOwner, isS3BucketProvisioned, loadAllStorageModules, markS3BucketProvisioned,resolveStorageConfigFromCodec, resolveStorageModuleByFileId } from './storage-module-cache'; export type { BucketConfig, - StorageModuleConfig, + BucketNameResolver, + EnsureBucketProvisioned, + PresignedUrlPluginOptions, RequestUploadUrlInput, RequestUploadUrlPayload, S3Config, S3ConfigOrGetter, - PresignedUrlPluginOptions, - BucketNameResolver, - EnsureBucketProvisioned, + StorageModuleConfig, } from './types'; diff --git a/graphile/graphile-presigned-url-plugin/src/plugin.ts b/graphile/graphile-presigned-url-plugin/src/plugin.ts index 1fb64bd55e..6f1c34f38e 100644 --- a/graphile/graphile-presigned-url-plugin/src/plugin.ts +++ b/graphile/graphile-presigned-url-plugin/src/plugin.ts @@ -17,14 +17,15 @@ * cached storage module configs. */ -import { access, context as grafastContext, lambda, object } from 'grafast'; -import type { GraphileConfig } from 'graphile-config'; import 'graphile-build'; + import { Logger } from '@pgpmjs/logger'; +import { access, context as grafastContext, lambda, object } from 'grafast'; +import type { GraphileConfig } from 'graphile-config'; -import type { PresignedUrlPluginOptions, S3Config, StorageModuleConfig, BucketConfig } from './types'; -import { loadAllStorageModules, resolveStorageConfigFromCodec, getBucketConfig, isS3BucketProvisioned, markS3BucketProvisioned } from './storage-module-cache'; -import { generatePresignedPutUrl, deleteS3Object } from './s3-signer'; +import { deleteS3Object,generatePresignedPutUrl } from './s3-signer'; +import { getBucketConfig, isS3BucketProvisioned, loadAllStorageModules, markS3BucketProvisioned,resolveStorageConfigFromCodec } from './storage-module-cache'; +import type { BucketConfig,PresignedUrlPluginOptions, S3Config, StorageModuleConfig } from './types'; const log = new Logger('graphile-presigned-url:plugin'); @@ -34,7 +35,7 @@ const MAX_CONTENT_HASH_LENGTH = 128; const MAX_CONTENT_TYPE_LENGTH = 255; const MAX_CUSTOM_KEY_LENGTH = 1024; const SHA256_HEX_REGEX = /^[a-f0-9]{64}$/; -const CUSTOM_KEY_REGEX = /^[a-zA-Z0-9][a-zA-Z0-9_.\-\/]*$/; +const CUSTOM_KEY_REGEX = /^[a-zA-Z0-9][a-zA-Z0-9_.\-/]*$/; // --- Helpers --- @@ -153,90 +154,90 @@ export function createPresignedUrlPlugin( if (!isRootMutation) return fields; const { - graphql: { - GraphQLString, - GraphQLNonNull, - GraphQLInt, - GraphQLBoolean, - GraphQLObjectType, - GraphQLInputObjectType, - GraphQLList, - }, - } = build; + graphql: { + GraphQLString, + GraphQLNonNull, + GraphQLInt, + GraphQLBoolean, + GraphQLObjectType, + GraphQLInputObjectType, + GraphQLList, + }, + } = build; - const bucketCodecs = Object.values((build.input as any).pgRegistry.pgCodecs).filter( - (codec: any) => codec.attributes && (codec.extensions as any)?.tags?.storageBuckets, - ); + const bucketCodecs = Object.values((build.input as any).pgRegistry.pgCodecs).filter( + (codec: any) => codec.attributes && (codec.extensions as any)?.tags?.storageBuckets, + ); - if (bucketCodecs.length === 0) return fields; + if (bucketCodecs.length === 0) return fields; - const newFields: Record = {}; + const newFields: Record = {}; - // --- File upload mutations (uploadAppFile, uploadDataRoomFile, etc.) --- - const fileCodecs = Object.values((build.input as any).pgRegistry.pgCodecs).filter( - (codec: any) => codec.attributes && (codec.extensions as any)?.tags?.storageFiles, - ); + // --- File upload mutations (uploadAppFile, uploadDataRoomFile, etc.) --- + const fileCodecs = Object.values((build.input as any).pgRegistry.pgCodecs).filter( + (codec: any) => codec.attributes && (codec.extensions as any)?.tags?.storageFiles, + ); - for (const filesCodec of fileCodecs as any[]) { - const filesTypeName = (build.inflection as any).tableType(filesCodec); - - // Find the matching bucket codec by table name prefix. - // Schema-name matching is ambiguous when multiple storage modules share - // the same PG schema (e.g. app_files + data_room_files both in storage_public). - // Instead, derive the prefix from the raw SQL table name: - // "data_room_files" → prefix "data_room" → matches "data_room_buckets" - // "app_files" → prefix "app" → matches "app_buckets" - const filesRawName = filesCodec.extensions?.pg?.name as string | undefined; - const filesPrefix = filesRawName?.replace(/_files$/, ''); - const matchingBucketCodec = (bucketCodecs as any[]).find((bc: any) => { - const bucketRawName = bc.extensions?.pg?.name as string | undefined; - const bucketPrefix = bucketRawName?.replace(/_buckets$/, ''); - return bucketPrefix === filesPrefix; - }); - if (!matchingBucketCodec) { - log.debug(`Skipping upload mutation for ${filesCodec.name}: no matching bucket codec with prefix "${filesPrefix}"`); - continue; - } + for (const filesCodec of fileCodecs as any[]) { + const filesTypeName = (build.inflection as any).tableType(filesCodec); + + // Find the matching bucket codec by table name prefix. + // Schema-name matching is ambiguous when multiple storage modules share + // the same PG schema (e.g. app_files + data_room_files both in storage_public). + // Instead, derive the prefix from the raw SQL table name: + // "data_room_files" → prefix "data_room" → matches "data_room_buckets" + // "app_files" → prefix "app" → matches "app_buckets" + const filesRawName = filesCodec.extensions?.pg?.name as string | undefined; + const filesPrefix = filesRawName?.replace(/_files$/, ''); + const matchingBucketCodec = (bucketCodecs as any[]).find((bc: any) => { + const bucketRawName = bc.extensions?.pg?.name as string | undefined; + const bucketPrefix = bucketRawName?.replace(/_buckets$/, ''); + return bucketPrefix === filesPrefix; + }); + if (!matchingBucketCodec) { + log.debug(`Skipping upload mutation for ${filesCodec.name}: no matching bucket codec with prefix "${filesPrefix}"`); + continue; + } - const hasOwnerId = !!matchingBucketCodec.attributes.owner_id; - const mutationName = `upload${filesTypeName}`; - - const ownerIdGqlType = hasOwnerId - ? (build as any).getGraphQLTypeByPgCodec(matchingBucketCodec.attributes.owner_id.codec, 'input') - : null; - - const InputType = new GraphQLInputObjectType({ - name: `Upload${filesTypeName}Input`, - fields: { - bucketKey: { type: new GraphQLNonNull(GraphQLString), description: 'Bucket key (e.g., "public", "private")' }, - ...(hasOwnerId - ? { ownerId: { type: new GraphQLNonNull(ownerIdGqlType || GraphQLString), description: 'Owner entity ID (required for entity-scoped buckets)' } } - : {}), - contentHash: { type: new GraphQLNonNull(GraphQLString), description: 'SHA-256 content hash (hex-encoded, 64 chars)' }, - contentType: { type: new GraphQLNonNull(GraphQLString), description: 'MIME type of the file' }, - size: { type: new GraphQLNonNull(GraphQLInt), description: 'File size in bytes' }, - filename: { type: GraphQLString, description: 'Original filename (optional)' }, - key: { type: GraphQLString, description: 'Custom S3 key (only when bucket has allow_custom_keys=true)' }, - }, - }); - - const PayloadType = new GraphQLObjectType({ - name: `Upload${filesTypeName}Payload`, - fields: { - uploadUrl: { type: GraphQLString, description: 'Presigned PUT URL (null if deduplicated)' }, - fileId: { type: new GraphQLNonNull(GraphQLString), description: 'The file ID (UUID)' }, - key: { type: new GraphQLNonNull(GraphQLString), description: 'The S3 object key' }, - deduplicated: { type: new GraphQLNonNull(GraphQLBoolean), description: 'Whether this file was deduplicated (content already exists)' }, - expiresAt: { type: GraphQLString, description: 'Presigned URL expiry time (null if deduplicated)' }, - previousVersionId: { type: GraphQLString, description: 'ID of the previous version (when using custom keys)' }, - }, - }); + const hasOwnerId = !!matchingBucketCodec.attributes.owner_id; + const mutationName = `upload${filesTypeName}`; + + const ownerIdGqlType = hasOwnerId + ? (build as any).getGraphQLTypeByPgCodec(matchingBucketCodec.attributes.owner_id.codec, 'input') + : null; + + const InputType = new GraphQLInputObjectType({ + name: `Upload${filesTypeName}Input`, + fields: { + bucketKey: { type: new GraphQLNonNull(GraphQLString), description: 'Bucket key (e.g., "public", "private")' }, + ...(hasOwnerId + ? { ownerId: { type: new GraphQLNonNull(ownerIdGqlType || GraphQLString), description: 'Owner entity ID (required for entity-scoped buckets)' } } + : {}), + contentHash: { type: new GraphQLNonNull(GraphQLString), description: 'SHA-256 content hash (hex-encoded, 64 chars)' }, + contentType: { type: new GraphQLNonNull(GraphQLString), description: 'MIME type of the file' }, + size: { type: new GraphQLNonNull(GraphQLInt), description: 'File size in bytes' }, + filename: { type: GraphQLString, description: 'Original filename (optional)' }, + key: { type: GraphQLString, description: 'Custom S3 key (only when bucket has allow_custom_keys=true)' }, + }, + }); + + const PayloadType = new GraphQLObjectType({ + name: `Upload${filesTypeName}Payload`, + fields: { + uploadUrl: { type: GraphQLString, description: 'Presigned PUT URL (null if deduplicated)' }, + fileId: { type: new GraphQLNonNull(GraphQLString), description: 'The file ID (UUID)' }, + key: { type: new GraphQLNonNull(GraphQLString), description: 'The S3 object key' }, + deduplicated: { type: new GraphQLNonNull(GraphQLBoolean), description: 'Whether this file was deduplicated (content already exists)' }, + expiresAt: { type: GraphQLString, description: 'Presigned URL expiry time (null if deduplicated)' }, + previousVersionId: { type: GraphQLString, description: 'ID of the previous version (when using custom keys)' }, + }, + }); - const capturedFilesCodec = filesCodec; + const capturedFilesCodec = filesCodec; - log.debug(`Adding file upload mutation "${mutationName}" for ${filesTypeName} (entity-scoped=${hasOwnerId})`); + log.debug(`Adding file upload mutation "${mutationName}" for ${filesTypeName} (entity-scoped=${hasOwnerId})`); - newFields[mutationName] = context.fieldWithHooks( + newFields[mutationName] = context.fieldWithHooks( { fieldName: mutationName } as any, { description: `Upload a file: resolves the bucket by key, creates the file row, and returns a presigned PUT URL.`, @@ -304,54 +305,54 @@ export function createPresignedUrlPlugin( }); }, }, - ); + ); - // --- Bulk file upload mutation --- - const BulkFileInputType = new GraphQLInputObjectType({ - name: `Upload${filesTypeName}BulkFileInput`, - fields: { - contentHash: { type: new GraphQLNonNull(GraphQLString), description: 'SHA-256 content hash (hex-encoded, 64 chars)' }, - contentType: { type: new GraphQLNonNull(GraphQLString), description: 'MIME type of the file' }, - size: { type: new GraphQLNonNull(GraphQLInt), description: 'File size in bytes' }, - filename: { type: GraphQLString, description: 'Original filename (optional)' }, - key: { type: GraphQLString, description: 'Custom S3 key (only when bucket has allow_custom_keys=true)' }, - }, - }); - - const BulkFilePayloadType = new GraphQLObjectType({ - name: `Upload${filesTypeName}BulkFilePayload`, - fields: { - uploadUrl: { type: GraphQLString }, - fileId: { type: new GraphQLNonNull(GraphQLString) }, - key: { type: new GraphQLNonNull(GraphQLString) }, - deduplicated: { type: new GraphQLNonNull(GraphQLBoolean) }, - expiresAt: { type: GraphQLString }, - previousVersionId: { type: GraphQLString }, - }, - }); - - const BulkInputType = new GraphQLInputObjectType({ - name: `Upload${filesTypeName}BulkInput`, - fields: { - bucketKey: { type: new GraphQLNonNull(GraphQLString), description: 'Bucket key (e.g., "public", "private")' }, - ...(hasOwnerId - ? { ownerId: { type: new GraphQLNonNull(ownerIdGqlType || GraphQLString), description: 'Owner entity ID (required for entity-scoped buckets)' } } - : {}), - files: { type: new GraphQLNonNull(new GraphQLList(new GraphQLNonNull(BulkFileInputType))), description: 'Array of files to upload' }, - }, - }); + // --- Bulk file upload mutation --- + const BulkFileInputType = new GraphQLInputObjectType({ + name: `Upload${filesTypeName}BulkFileInput`, + fields: { + contentHash: { type: new GraphQLNonNull(GraphQLString), description: 'SHA-256 content hash (hex-encoded, 64 chars)' }, + contentType: { type: new GraphQLNonNull(GraphQLString), description: 'MIME type of the file' }, + size: { type: new GraphQLNonNull(GraphQLInt), description: 'File size in bytes' }, + filename: { type: GraphQLString, description: 'Original filename (optional)' }, + key: { type: GraphQLString, description: 'Custom S3 key (only when bucket has allow_custom_keys=true)' }, + }, + }); + + const BulkFilePayloadType = new GraphQLObjectType({ + name: `Upload${filesTypeName}BulkFilePayload`, + fields: { + uploadUrl: { type: GraphQLString }, + fileId: { type: new GraphQLNonNull(GraphQLString) }, + key: { type: new GraphQLNonNull(GraphQLString) }, + deduplicated: { type: new GraphQLNonNull(GraphQLBoolean) }, + expiresAt: { type: GraphQLString }, + previousVersionId: { type: GraphQLString }, + }, + }); + + const BulkInputType = new GraphQLInputObjectType({ + name: `Upload${filesTypeName}BulkInput`, + fields: { + bucketKey: { type: new GraphQLNonNull(GraphQLString), description: 'Bucket key (e.g., "public", "private")' }, + ...(hasOwnerId + ? { ownerId: { type: new GraphQLNonNull(ownerIdGqlType || GraphQLString), description: 'Owner entity ID (required for entity-scoped buckets)' } } + : {}), + files: { type: new GraphQLNonNull(new GraphQLList(new GraphQLNonNull(BulkFileInputType))), description: 'Array of files to upload' }, + }, + }); - const BulkPayloadType = new GraphQLObjectType({ - name: `Upload${filesTypeName}BulkPayload`, - fields: { - files: { type: new GraphQLNonNull(new GraphQLList(new GraphQLNonNull(BulkFilePayloadType))) }, - }, - }); + const BulkPayloadType = new GraphQLObjectType({ + name: `Upload${filesTypeName}BulkPayload`, + fields: { + files: { type: new GraphQLNonNull(new GraphQLList(new GraphQLNonNull(BulkFilePayloadType))) }, + }, + }); - const bulkMutationName = `upload${filesTypeName}s`; - log.debug(`Adding bulk file upload mutation "${bulkMutationName}" for ${filesTypeName}`); + const bulkMutationName = `upload${filesTypeName}s`; + log.debug(`Adding bulk file upload mutation "${bulkMutationName}" for ${filesTypeName}`); - newFields[bulkMutationName] = context.fieldWithHooks( + newFields[bulkMutationName] = context.fieldWithHooks( { fieldName: bulkMutationName } as any, { description: `Upload multiple files: resolves the bucket by key, creates file rows, and returns presigned PUT URLs for each.`, @@ -431,8 +432,8 @@ export function createPresignedUrlPlugin( }); }, }, - ); - } + ); + } return build.extend( fields, diff --git a/graphile/graphile-presigned-url-plugin/src/preset.ts b/graphile/graphile-presigned-url-plugin/src/preset.ts index 1fb2146185..3ab986721e 100644 --- a/graphile/graphile-presigned-url-plugin/src/preset.ts +++ b/graphile/graphile-presigned-url-plugin/src/preset.ts @@ -7,9 +7,10 @@ */ import type { GraphileConfig } from 'graphile-config'; -import type { PresignedUrlPluginOptions } from './types'; -import { createPresignedUrlPlugin } from './plugin'; + import { createDownloadUrlPlugin } from './download-url-field'; +import { createPresignedUrlPlugin } from './plugin'; +import type { PresignedUrlPluginOptions } from './types'; /** * Creates a preset that includes the presigned URL plugins with the given options. diff --git a/graphile/graphile-presigned-url-plugin/src/s3-signer.ts b/graphile/graphile-presigned-url-plugin/src/s3-signer.ts index c4fbba5d66..c2e21d8608 100644 --- a/graphile/graphile-presigned-url-plugin/src/s3-signer.ts +++ b/graphile/graphile-presigned-url-plugin/src/s3-signer.ts @@ -1,12 +1,12 @@ import { - S3Client, - PutObjectCommand, + DeleteObjectCommand, GetObjectCommand, HeadObjectCommand, - DeleteObjectCommand, + PutObjectCommand, } from '@aws-sdk/client-s3'; import { getSignedUrl } from '@aws-sdk/s3-request-presigner'; import { Logger } from '@pgpmjs/logger'; + import type { S3Config } from './types'; const log = new Logger('graphile-presigned-url:s3'); diff --git a/graphile/graphile-presigned-url-plugin/src/storage-module-cache.ts b/graphile/graphile-presigned-url-plugin/src/storage-module-cache.ts index 6ea403fbb5..1b08d73382 100644 --- a/graphile/graphile-presigned-url-plugin/src/storage-module-cache.ts +++ b/graphile/graphile-presigned-url-plugin/src/storage-module-cache.ts @@ -1,7 +1,8 @@ import { Logger } from '@pgpmjs/logger'; -import { LRUCache } from 'lru-cache'; import { QuoteUtils } from '@pgsql/quotes'; -import type { StorageModuleConfig, BucketConfig } from './types'; +import { LRUCache } from 'lru-cache'; + +import type { BucketConfig,StorageModuleConfig } from './types'; const log = new Logger('graphile-presigned-url:cache'); diff --git a/graphile/graphile-query/__tests__/graphile-query.test.ts b/graphile/graphile-query/__tests__/graphile-query.test.ts index 256b9f55ec..f51a56a8e3 100644 --- a/graphile/graphile-query/__tests__/graphile-query.test.ts +++ b/graphile/graphile-query/__tests__/graphile-query.test.ts @@ -2,13 +2,14 @@ * Tests for graphile-query PostGraphile v5 integration */ import { Pool } from 'pg'; -import { getConnections, GetConnectionResult } from 'pgsql-test'; +import { GetConnectionResult,getConnections } from 'pgsql-test'; + import { + createGraphileQuery, + createGraphileQuerySimple, getSchema, GraphileQuery, GraphileQuerySimple, - createGraphileQuery, - createGraphileQuerySimple, } from '../src'; const TEST_SCHEMA = ` diff --git a/graphile/graphile-query/src/index.ts b/graphile/graphile-query/src/index.ts index 1ec0cd30fd..a9e0cdaff5 100644 --- a/graphile/graphile-query/src/index.ts +++ b/graphile/graphile-query/src/index.ts @@ -1,11 +1,11 @@ -import type { ExecutionResult, GraphQLSchema, DocumentNode } from 'graphql'; -import { parse } from 'graphql'; -import type { GraphileConfig } from 'graphile-config'; +import { execute } from 'grafast'; import { makeSchema } from 'graphile-build'; import { defaultPreset as graphileBuildDefaultPreset } from 'graphile-build'; import { defaultPreset as graphileBuildPgDefaultPreset, withPgClientFromPgService } from 'graphile-build-pg'; +import type { GraphileConfig } from 'graphile-config'; import { makePgService } from 'graphile-settings'; -import { execute } from 'grafast'; +import type { DocumentNode,ExecutionResult, GraphQLSchema } from 'graphql'; +import { parse } from 'graphql'; import type { Pool } from 'pg'; /** diff --git a/graphile/graphile-realtime-subscriptions/__tests__/cursor-tracker.test.ts b/graphile/graphile-realtime-subscriptions/__tests__/cursor-tracker.test.ts index b16bd2d95d..05a3c9b50a 100644 --- a/graphile/graphile-realtime-subscriptions/__tests__/cursor-tracker.test.ts +++ b/graphile/graphile-realtime-subscriptions/__tests__/cursor-tracker.test.ts @@ -21,12 +21,12 @@ jest.mock('@pgpmjs/logger', () => ({ import { CursorTracker, - DEFAULT_POLL_INTERVAL_MS, - DEFAULT_HEARTBEAT_INTERVAL_MS, DEFAULT_BATCH_LIMIT, + DEFAULT_HEARTBEAT_INTERVAL_MS, + DEFAULT_POLL_INTERVAL_MS, DEFAULT_SCHEMA, } from '../src/cursor-tracker'; -import type { Queryable, ChangeLogEntry } from '../src/types'; +import type { ChangeLogEntry,Queryable } from '../src/types'; // --- Test helpers --- diff --git a/graphile/graphile-realtime-subscriptions/__tests__/plugin.test.ts b/graphile/graphile-realtime-subscriptions/__tests__/plugin.test.ts index 0bb2035211..b08a0a9309 100644 --- a/graphile/graphile-realtime-subscriptions/__tests__/plugin.test.ts +++ b/graphile/graphile-realtime-subscriptions/__tests__/plugin.test.ts @@ -55,10 +55,10 @@ jest.mock('graphile-utils', () => ({ import { createRealtimeSubscriptionsPlugin, - RealtimeSubscriptionsPlugin, - parseNotifyPayload, - EventThrottle, DEFAULT_OVERFLOW_THRESHOLD, + EventThrottle, + parseNotifyPayload, + RealtimeSubscriptionsPlugin, } from '../src/plugin'; // --- Test helpers --- diff --git a/graphile/graphile-realtime-subscriptions/__tests__/realtime-manager.test.ts b/graphile/graphile-realtime-subscriptions/__tests__/realtime-manager.test.ts index d5fa6c2418..c0d10650e0 100644 --- a/graphile/graphile-realtime-subscriptions/__tests__/realtime-manager.test.ts +++ b/graphile/graphile-realtime-subscriptions/__tests__/realtime-manager.test.ts @@ -1,7 +1,8 @@ +import { EventEmitter } from 'events'; + import { RealtimeManager } from '../src/realtime-manager'; -import { extractRowId, entryToNotifyPayload, entryToChannel } from '../src/realtime-manager'; +import { entryToChannel,entryToNotifyPayload, extractRowId } from '../src/realtime-manager'; import type { ChangeLogEntry, Queryable } from '../src/types'; -import { EventEmitter } from 'events'; // --------------------------------------------------------------------------- // Helpers diff --git a/graphile/graphile-realtime-subscriptions/src/cursor-tracker.ts b/graphile/graphile-realtime-subscriptions/src/cursor-tracker.ts index 45a9ad761f..ab1f1204b9 100644 --- a/graphile/graphile-realtime-subscriptions/src/cursor-tracker.ts +++ b/graphile/graphile-realtime-subscriptions/src/cursor-tracker.ts @@ -13,13 +13,13 @@ * and this class calls pool.query() directly for each operation. */ -import { randomUUID } from 'crypto'; import { Logger } from '@pgpmjs/logger'; import { QuoteUtils } from '@pgsql/quotes'; +import { randomUUID } from 'crypto'; import type { - CursorTrackerOptions, ChangeLogEntry, + CursorTrackerOptions, Queryable, } from './types'; @@ -153,8 +153,8 @@ export class CursorTracker { } export { - DEFAULT_POLL_INTERVAL_MS, - DEFAULT_HEARTBEAT_INTERVAL_MS, DEFAULT_BATCH_LIMIT, + DEFAULT_HEARTBEAT_INTERVAL_MS, + DEFAULT_POLL_INTERVAL_MS, DEFAULT_SCHEMA, }; diff --git a/graphile/graphile-realtime-subscriptions/src/index.ts b/graphile/graphile-realtime-subscriptions/src/index.ts index 0b8aa410a6..d0fdf741ca 100644 --- a/graphile/graphile-realtime-subscriptions/src/index.ts +++ b/graphile/graphile-realtime-subscriptions/src/index.ts @@ -17,14 +17,14 @@ * ``` */ +export { CursorTracker } from './cursor-tracker'; export { createRealtimeSubscriptionsPlugin, RealtimeSubscriptionsPlugin } from './plugin'; export { RealtimeSubscriptionsPreset } from './preset'; -export { CursorTracker } from './cursor-tracker'; export { RealtimeManager } from './realtime-manager'; export type { RealtimeSubscriptionsPluginOptions } from './types'; export type { - CursorTrackerOptions, ChangeLogEntry, + CursorTrackerOptions, Queryable, RealtimeManagerOptions, } from './types'; diff --git a/graphile/graphile-realtime-subscriptions/src/plugin.ts b/graphile/graphile-realtime-subscriptions/src/plugin.ts index 77695a9a4c..85a38958d7 100644 --- a/graphile/graphile-realtime-subscriptions/src/plugin.ts +++ b/graphile/graphile-realtime-subscriptions/src/plugin.ts @@ -46,10 +46,10 @@ * preventing cross-tenant event leaks. */ -import { context as grafastContext, listen, object, constant, lambda } from 'grafast'; +import { Logger } from '@pgpmjs/logger'; +import { constant, context as grafastContext, lambda,listen, object } from 'grafast'; import type { GraphileConfig } from 'graphile-config'; import { extendSchema } from 'graphile-utils'; -import { Logger } from '@pgpmjs/logger'; import type { RealtimeSubscriptionsPluginOptions } from './types'; @@ -341,7 +341,7 @@ export { createRealtimeSubscriptionsPlugin as RealtimeSubscriptionsPlugin }; // Re-export CursorTracker and RealtimeManager for convenience export { CursorTracker } from './cursor-tracker'; export { RealtimeManager } from './realtime-manager'; -export type { CursorTrackerOptions, ChangeLogEntry, Queryable, RealtimeManagerOptions } from './types'; +export type { ChangeLogEntry, CursorTrackerOptions, Queryable, RealtimeManagerOptions } from './types'; // Exported for testing -export { parseNotifyPayload, EventThrottle, DEFAULT_OVERFLOW_THRESHOLD }; +export { DEFAULT_OVERFLOW_THRESHOLD,EventThrottle, parseNotifyPayload }; diff --git a/graphile/graphile-realtime-subscriptions/src/preset.ts b/graphile/graphile-realtime-subscriptions/src/preset.ts index d3f37908c2..138d260a2d 100644 --- a/graphile/graphile-realtime-subscriptions/src/preset.ts +++ b/graphile/graphile-realtime-subscriptions/src/preset.ts @@ -6,8 +6,9 @@ */ import type { GraphileConfig } from 'graphile-config'; -import type { RealtimeSubscriptionsPluginOptions } from './types'; + import { createRealtimeSubscriptionsPlugin } from './plugin'; +import type { RealtimeSubscriptionsPluginOptions } from './types'; export function RealtimeSubscriptionsPreset( options: RealtimeSubscriptionsPluginOptions = {}, diff --git a/graphile/graphile-realtime-subscriptions/src/realtime-manager.ts b/graphile/graphile-realtime-subscriptions/src/realtime-manager.ts index d2da0405a3..58bcf11926 100644 --- a/graphile/graphile-realtime-subscriptions/src/realtime-manager.ts +++ b/graphile/graphile-realtime-subscriptions/src/realtime-manager.ts @@ -153,4 +153,4 @@ export class RealtimeManager { } } -export { extractRowId, entryToNotifyPayload, entryToChannel }; +export { entryToChannel,entryToNotifyPayload, extractRowId }; diff --git a/graphile/graphile-realtime-test/__tests__/realtime-websocket.integration.test.ts b/graphile/graphile-realtime-test/__tests__/realtime-websocket.integration.test.ts index c609d82f9e..56e75b0b3e 100644 --- a/graphile/graphile-realtime-test/__tests__/realtime-websocket.integration.test.ts +++ b/graphile/graphile-realtime-test/__tests__/realtime-websocket.integration.test.ts @@ -12,15 +12,15 @@ * 4. Returns ws handle for creating clients, firing events, and teardown */ -import { join } from 'node:path'; import { randomUUID } from 'node:crypto'; +import { join } from 'node:path'; import { subscribe as grafastSubscribe } from 'grafast'; import { parse } from 'graphql'; import { seed } from 'pgsql-test'; -import { getConnections } from '../src/get-connections'; import type { GetConnectionsResult } from '../src/get-connections'; +import { getConnections } from '../src/get-connections'; import { delay } from '../src/ws-helpers'; // ─── Test Suite ───────────────────────────────────────────────────────────── diff --git a/graphile/graphile-realtime-test/__tests__/realtime.integration.test.ts b/graphile/graphile-realtime-test/__tests__/realtime.integration.test.ts index 10539f9244..c721b9aff9 100644 --- a/graphile/graphile-realtime-test/__tests__/realtime.integration.test.ts +++ b/graphile/graphile-realtime-test/__tests__/realtime.integration.test.ts @@ -10,17 +10,18 @@ * - Sparse set filtering (ids argument) works */ +import { randomUUID } from 'crypto'; +import type { ExecutionResult } from 'graphql'; import { join } from 'path'; import { seed } from 'pgsql-test'; + +import type { RealtimeTestContext } from '../src'; import { + buildInvalidatePayload, + buildPayload, createRealtimeTestContext, waitForEvent, - buildPayload, - buildInvalidatePayload, } from '../src'; -import type { RealtimeTestContext } from '../src'; -import type { ExecutionResult } from 'graphql'; -import { randomUUID } from 'crypto'; // ─── Schema Discovery Tests ────────────────────────────────────────────────── diff --git a/graphile/graphile-realtime-test/src/context.ts b/graphile/graphile-realtime-test/src/context.ts index 7046708270..b7a8fe2919 100644 --- a/graphile/graphile-realtime-test/src/context.ts +++ b/graphile/graphile-realtime-test/src/context.ts @@ -1,21 +1,19 @@ -import type { GraphQLSchema, ExecutionResult } from 'graphql'; +import { makeSchema } from 'graphile-build'; +import { defaultPreset as graphileBuildDefaultPreset } from 'graphile-build'; +import { defaultPreset as graphileBuildPgDefaultPreset } from 'graphile-build-pg'; import type { GraphileConfig } from 'graphile-config'; -import type { PgTestClient } from 'pgsql-test/test-client'; +import { createRealtimeSubscriptionsPlugin } from 'graphile-realtime-subscriptions'; +import type { GetConnectionsInput } from 'graphile-test'; +import type { ExecutionResult,GraphQLSchema } from 'graphql'; import type { GetConnectionOpts, GetConnectionResult } from 'pgsql-test'; import { getConnections as getPgConnections } from 'pgsql-test'; import type { SeedAdapter } from 'pgsql-test/seed/types'; - -import { makeSchema } from 'graphile-build'; -import { defaultPreset as graphileBuildDefaultPreset } from 'graphile-build'; -import { defaultPreset as graphileBuildPgDefaultPreset } from 'graphile-build-pg'; +import type { PgTestClient } from 'pgsql-test/test-client'; import { makePgService } from 'postgraphile/adaptors/pg'; -import type { GetConnectionsInput } from 'graphile-test'; -import { createRealtimeSubscriptionsPlugin } from 'graphile-realtime-subscriptions'; - -import { subscribe as subscribeHelper } from './subscribe.js'; import { notify, notifyChange, notifyInvalidate } from './notify.js'; import { makeRealtimeSmartTagsPlugin } from './smart-tags.js'; +import { subscribe as subscribeHelper } from './subscribe.js'; /** * Minimal preset matching graphile-test's MinimalPreset. diff --git a/graphile/graphile-realtime-test/src/get-connections.ts b/graphile/graphile-realtime-test/src/get-connections.ts index 4e27cd173b..10897e06a6 100644 --- a/graphile/graphile-realtime-test/src/get-connections.ts +++ b/graphile/graphile-realtime-test/src/get-connections.ts @@ -1,23 +1,22 @@ -import type { GraphQLSchema } from 'graphql'; +import { makeSchema } from 'graphile-build'; +import { defaultPreset as graphileBuildDefaultPreset } from 'graphile-build'; +import { defaultPreset as graphileBuildPgDefaultPreset } from 'graphile-build-pg'; import type { GraphileConfig } from 'graphile-config'; +import { createRealtimeSubscriptionsPlugin } from 'graphile-realtime-subscriptions'; +import type { GraphQLSchema } from 'graphql'; +import type { Client as GqlWsClient } from 'graphql-ws'; +import type { Pool } from 'pg'; import type { GetConnectionOpts, GetConnectionResult } from 'pgsql-test'; import { getConnections as getPgConnections } from 'pgsql-test'; import type { SeedAdapter } from 'pgsql-test/seed/types'; import type { PgTestClient } from 'pgsql-test/test-client'; -import type { Pool } from 'pg'; -import type { Client as GqlWsClient } from 'graphql-ws'; - -import { makeSchema } from 'graphile-build'; -import { defaultPreset as graphileBuildDefaultPreset } from 'graphile-build'; -import { defaultPreset as graphileBuildPgDefaultPreset } from 'graphile-build-pg'; import { makePgService } from 'postgraphile/adaptors/pg'; -import { createRealtimeSubscriptionsPlugin } from 'graphile-realtime-subscriptions'; +import { notify, notifyChange, notifyInvalidate } from './notify.js'; import { makeRealtimeSmartTagsPlugin } from './smart-tags.js'; -import { createWsTestServer } from './ws-server.js'; +import { collectWsEvents, delay,nextEvent } from './ws-helpers.js'; import type { WsTestServer } from './ws-server.js'; -import { nextEvent, collectWsEvents, delay } from './ws-helpers.js'; -import { notify, notifyChange, notifyInvalidate } from './notify.js'; +import { createWsTestServer } from './ws-server.js'; // --- Types --- diff --git a/graphile/graphile-realtime-test/src/index.ts b/graphile/graphile-realtime-test/src/index.ts index 659aea1674..cc4cb1702f 100644 --- a/graphile/graphile-realtime-test/src/index.ts +++ b/graphile/graphile-realtime-test/src/index.ts @@ -1,31 +1,25 @@ -export { createRealtimeTestContext } from './context.js'; export type { RealtimeTestContext, RealtimeTestInput } from './context.js'; - -export { makeRealtimeSmartTagsPlugin } from './smart-tags.js'; - -export { - subscribe, - waitForEvent, - collectEvents, -} from './subscribe.js'; -export type { SubscriptionEvent, SubscribeOptions } from './subscribe.js'; - +export { createRealtimeTestContext } from './context.js'; +export type { + GetConnectionsInput, + GetConnectionsResult, + WsHandle, +} from './get-connections.js'; +export { getConnections } from './get-connections.js'; export { + buildInvalidatePayload, + buildPayload, notify, notifyChange, notifyInvalidate, - buildPayload, - buildInvalidatePayload, } from './notify.js'; - -export { nextEvent, collectWsEvents, delay } from './ws-helpers.js'; - +export { makeRealtimeSmartTagsPlugin } from './smart-tags.js'; +export type { SubscribeOptions,SubscriptionEvent } from './subscribe.js'; +export { + collectEvents, + subscribe, + waitForEvent, +} from './subscribe.js'; +export { collectWsEvents, delay,nextEvent } from './ws-helpers.js'; +export type { WsTestServer,WsTestServerInput } from './ws-server.js'; export { createWsTestServer } from './ws-server.js'; -export type { WsTestServerInput, WsTestServer } from './ws-server.js'; - -export { getConnections } from './get-connections.js'; -export type { - GetConnectionsInput, - GetConnectionsResult, - WsHandle, -} from './get-connections.js'; diff --git a/graphile/graphile-realtime-test/src/subscribe.ts b/graphile/graphile-realtime-test/src/subscribe.ts index 28142c244b..89de892993 100644 --- a/graphile/graphile-realtime-test/src/subscribe.ts +++ b/graphile/graphile-realtime-test/src/subscribe.ts @@ -1,7 +1,7 @@ import { subscribe as grafastSubscribe } from 'grafast'; -import { parse } from 'graphql'; -import type { GraphQLSchema, DocumentNode, ExecutionResult } from 'graphql'; import type { GraphileConfig } from 'graphile-config'; +import type { DocumentNode, ExecutionResult,GraphQLSchema } from 'graphql'; +import { parse } from 'graphql'; /** * A single event yielded by a subscription iterator. diff --git a/graphile/graphile-realtime-test/src/ws-server.ts b/graphile/graphile-realtime-test/src/ws-server.ts index 6dc8c6ff03..238d59d1ff 100644 --- a/graphile/graphile-realtime-test/src/ws-server.ts +++ b/graphile/graphile-realtime-test/src/ws-server.ts @@ -2,11 +2,11 @@ import { createServer, type Server as HttpServer } from 'node:http'; import type { AddressInfo } from 'node:net'; import { subscribe as grafastSubscribe } from 'grafast'; -import type { ExecutionResult, GraphQLSchema } from 'graphql'; import type { GraphileConfig } from 'graphile-config'; -import { createClient, type Client as GqlWsClient } from 'graphql-ws'; +import type { ExecutionResult, GraphQLSchema } from 'graphql'; +import { type Client as GqlWsClient,createClient } from 'graphql-ws'; import { useServer } from 'graphql-ws/use/ws'; -import { WebSocketServer, WebSocket } from 'ws'; +import { WebSocket,WebSocketServer } from 'ws'; export interface WsTestServerInput { schema: GraphQLSchema; diff --git a/graphile/graphile-schema/__tests__/fetch-endpoint-schema.test.ts b/graphile/graphile-schema/__tests__/fetch-endpoint-schema.test.ts index c94afba817..b54c78bb5d 100644 --- a/graphile/graphile-schema/__tests__/fetch-endpoint-schema.test.ts +++ b/graphile/graphile-schema/__tests__/fetch-endpoint-schema.test.ts @@ -1,5 +1,6 @@ import * as http from 'node:http'; -import { getIntrospectionQuery, buildSchema, introspectionFromSchema } from 'graphql'; + +import { buildSchema, introspectionFromSchema } from 'graphql'; import { fetchEndpointSchemaSDL } from '../src/fetch-endpoint-schema'; diff --git a/graphile/graphile-schema/src/build-introspection.ts b/graphile/graphile-schema/src/build-introspection.ts index 1f535a06cd..93ccddf068 100644 --- a/graphile/graphile-schema/src/build-introspection.ts +++ b/graphile/graphile-schema/src/build-introspection.ts @@ -1,8 +1,9 @@ -import type { TableMeta } from 'graphile-settings' -import { buildSchemaArtifacts } from './build-schema' -import type { BuildSchemaOptions } from './build-schema' +import type { TableMeta } from 'graphile-settings'; -export type { BuildSchemaOptions as BuildIntrospectionOptions } +import type { BuildSchemaOptions } from './build-schema'; +import { buildSchemaArtifacts } from './build-schema'; + +export type { BuildSchemaOptions as BuildIntrospectionOptions }; /** * Build introspection metadata for all tables visible in the given schemas. @@ -31,5 +32,5 @@ export type { BuildSchemaOptions as BuildIntrospectionOptions } export async function buildIntrospectionJSON( opts: BuildSchemaOptions ): Promise { - return (await buildSchemaArtifacts(opts)).tablesMeta + return (await buildSchemaArtifacts(opts)).tablesMeta; } diff --git a/graphile/graphile-schema/src/build-schema.ts b/graphile/graphile-schema/src/build-schema.ts index 744fe09d00..35f3bcc907 100644 --- a/graphile/graphile-schema/src/build-schema.ts +++ b/graphile/graphile-schema/src/build-schema.ts @@ -1,11 +1,11 @@ -import deepmerge from 'deepmerge' -import { graphql, lexicographicSortSchema, printSchema } from 'graphql' -import { ConstructivePreset, getTablesMetaForSchema, makePgService } from 'graphile-settings' -import { makeSchema } from 'graphile-build' -import { getPgPool } from 'pg-cache' -import { getPgEnvOptions } from 'pg-env' -import type { GraphileConfig } from 'graphile-config' -import type { TableMeta } from 'graphile-settings' +import deepmerge from 'deepmerge'; +import { makeSchema } from 'graphile-build'; +import type { GraphileConfig } from 'graphile-config'; +import type { TableMeta } from 'graphile-settings'; +import { ConstructivePreset, getTablesMetaForSchema, makePgService } from 'graphile-settings'; +import { graphql, lexicographicSortSchema, printSchema } from 'graphql'; +import { getPgPool } from 'pg-cache'; +import { getPgEnvOptions } from 'pg-env'; export type BuildSchemaOptions = { database?: string; @@ -36,16 +36,16 @@ export type BuildSchemaArtifacts = { * concurrent builds in one process can never cross-contaminate results. */ export async function buildSchemaArtifacts(opts: BuildSchemaOptions): Promise { - const database = opts.database ?? 'constructive' - const schemas = Array.isArray(opts.schemas) ? opts.schemas : [] + const database = opts.database ?? 'constructive'; + const schemas = Array.isArray(opts.schemas) ? opts.schemas : []; - const config = getPgEnvOptions({ database }) + const config = getPgEnvOptions({ database }); // Create the pool through pg-cache so it is tracked and can be cleaned up // by callers via pgCache.delete(database) before dropping ephemeral databases. // Without this, makePgService creates its own internal pool that isn't released, // causing "database has active sessions" errors during ephemeral DB teardown. - const pool = getPgPool(config) + const pool = getPgPool(config); // Hybrid preset composition: use deepmerge for safe scalar/object keys // (plugins, disablePlugins, schema, gather, etc.) but pluck out `extends` @@ -53,9 +53,9 @@ export async function buildSchemaArtifacts(opts: BuildSchemaOptions): Promise { - return (await buildSchemaArtifacts(opts)).sdl + return (await buildSchemaArtifacts(opts)).sdl; } diff --git a/graphile/graphile-schema/src/fetch-endpoint-schema.ts b/graphile/graphile-schema/src/fetch-endpoint-schema.ts index 11a8d33b9f..3acc0171b3 100644 --- a/graphile/graphile-schema/src/fetch-endpoint-schema.ts +++ b/graphile/graphile-schema/src/fetch-endpoint-schema.ts @@ -1,6 +1,7 @@ -import { getIntrospectionQuery, buildClientSchema, printSchema } from 'graphql' -import * as http from 'node:http' -import * as https from 'node:https' +import * as http from 'node:http'; +import * as https from 'node:https'; + +import { buildClientSchema, getIntrospectionQuery, printSchema } from 'graphql'; export type FetchEndpointSchemaOptions = { headerHost?: string; @@ -9,34 +10,34 @@ export type FetchEndpointSchemaOptions = { }; export async function fetchEndpointSchemaSDL(endpoint: string, opts?: FetchEndpointSchemaOptions): Promise { - const url = new URL(endpoint) - const requestUrl = url + const url = new URL(endpoint); + const requestUrl = url; - const introspectionQuery = getIntrospectionQuery({ descriptions: true }) + const introspectionQuery = getIntrospectionQuery({ descriptions: true }); const postData = JSON.stringify({ query: introspectionQuery, variables: null, operationName: 'IntrospectionQuery', - }) + }); const headers: Record = { 'Content-Type': 'application/json', 'Content-Length': String(Buffer.byteLength(postData)), - } + }; if (opts?.headerHost) { - headers['Host'] = opts.headerHost + headers['Host'] = opts.headerHost; } if (opts?.auth) { - headers['Authorization'] = opts.auth + headers['Authorization'] = opts.auth; } if (opts?.headers) { for (const [key, value] of Object.entries(opts.headers)) { - headers[key] = value + headers[key] = value; } } - const isHttps = requestUrl.protocol === 'https:' - const lib = isHttps ? https : http + const isHttps = requestUrl.protocol === 'https:'; + const lib = isHttps ? https : http; const responseData: string = await new Promise((resolve, reject) => { const req = lib.request({ @@ -46,35 +47,35 @@ export async function fetchEndpointSchemaSDL(endpoint: string, opts?: FetchEndpo method: 'POST', headers, }, (res) => { - let data = '' - res.on('data', (chunk) => { data += chunk }) + let data = ''; + res.on('data', (chunk) => { data += chunk; }); res.on('end', () => { if (res.statusCode && res.statusCode >= 400) { - reject(new Error(`HTTP ${res.statusCode} – ${data}`)) - return + reject(new Error(`HTTP ${res.statusCode} – ${data}`)); + return; } - resolve(data) - }) - }) - req.on('error', (err) => reject(err)) - req.write(postData) - req.end() - }) + resolve(data); + }); + }); + req.on('error', (err) => reject(err)); + req.write(postData); + req.end(); + }); - let json: any + let json: any; try { - json = JSON.parse(responseData) + json = JSON.parse(responseData); } catch (e) { - throw new Error(`Failed to parse response: ${responseData}`) + throw new Error(`Failed to parse response: ${responseData}`); } if (json.errors) { - throw new Error('Introspection returned errors') + throw new Error('Introspection returned errors'); } if (!json.data) { - throw new Error('No data in introspection response') + throw new Error('No data in introspection response'); } - const schema = buildClientSchema(json.data as any) - return printSchema(schema) + const schema = buildClientSchema(json.data as any); + return printSchema(schema); } diff --git a/graphile/graphile-schema/src/index.ts b/graphile/graphile-schema/src/index.ts index 77c3f4aac2..ba6238a6ba 100644 --- a/graphile/graphile-schema/src/index.ts +++ b/graphile/graphile-schema/src/index.ts @@ -1,21 +1,21 @@ -export { buildSchemaArtifacts, buildSchemaSDL } from './build-schema'; -export type { BuildSchemaArtifacts, BuildSchemaOptions } from './build-schema'; export { buildIntrospectionJSON } from './build-introspection'; +export type { BuildSchemaArtifacts, BuildSchemaOptions } from './build-schema'; +export { buildSchemaArtifacts, buildSchemaSDL } from './build-schema'; +export type { FetchEndpointSchemaOptions } from './fetch-endpoint-schema'; +export { fetchEndpointSchemaSDL } from './fetch-endpoint-schema'; export type { - TableMeta, - FieldMeta, - TypeMeta, - IndexMeta, + BelongsToRelation, ConstraintsMeta, - PrimaryKeyConstraintMeta, - UniqueConstraintMeta, + FieldMeta, ForeignKeyConstraintMeta, - RelationsMeta, - BelongsToRelation, HasRelation, - ManyToManyRelation, + IndexMeta, InflectionMeta, + ManyToManyRelation, + PrimaryKeyConstraintMeta, QueryMeta, + RelationsMeta, + TableMeta, + TypeMeta, + UniqueConstraintMeta, } from 'graphile-settings'; -export { fetchEndpointSchemaSDL } from './fetch-endpoint-schema'; -export type { FetchEndpointSchemaOptions } from './fetch-endpoint-schema'; diff --git a/graphile/graphile-search/src/__tests__/rrf-scoring.test.ts b/graphile/graphile-search/src/__tests__/rrf-scoring.test.ts index 6d96471818..d83d8220c1 100644 --- a/graphile/graphile-search/src/__tests__/rrf-scoring.test.ts +++ b/graphile/graphile-search/src/__tests__/rrf-scoring.test.ts @@ -10,20 +10,21 @@ * - Invariants: searchScore always [0,1], SEARCH_SCORE_DESC correct ordering */ -import { join } from 'path'; -import { getConnections, seed } from 'graphile-test'; +import type { GraphileConfig } from 'graphile-config'; +import { ConnectionFilterPreset } from 'graphile-connection-filter'; import type { GraphQLResponse } from 'graphile-test'; +import { getConnections, seed } from 'graphile-test'; +import { join } from 'path'; import type { PgTestClient } from 'pgsql-test'; -import { ConnectionFilterPreset } from 'graphile-connection-filter'; + +import { createBm25Adapter } from '../adapters/bm25'; +import { createPgvectorAdapter } from '../adapters/pgvector'; +import { createTrgmAdapter } from '../adapters/trgm'; +import { createTsvectorAdapter } from '../adapters/tsvector'; import { Bm25CodecPlugin } from '../codecs/bm25-codec'; -import { VectorCodecPlugin } from '../codecs/vector-codec'; import { TsvectorCodecPlugin } from '../codecs/tsvector-codec'; +import { VectorCodecPlugin } from '../codecs/vector-codec'; import { createUnifiedSearchPlugin } from '../plugin'; -import { createTsvectorAdapter } from '../adapters/tsvector'; -import { createBm25Adapter } from '../adapters/bm25'; -import { createTrgmAdapter } from '../adapters/trgm'; -import { createPgvectorAdapter } from '../adapters/pgvector'; -import type { GraphileConfig } from 'graphile-config'; // ─── Smart Tags Plugin ─────────────────────────────────────────────────────── @@ -168,7 +169,11 @@ describe('RRF scoring — single adapter scenarios', () => { afterAll(async () => { if (db) { - try { await db.client.query('ROLLBACK'); } catch {} + try { + await db.client.query('ROLLBACK'); + } catch { + // ignore + } } if (teardown) await teardown(); }); @@ -361,7 +366,11 @@ describe('RRF scoring — multi-adapter combinations', () => { afterAll(async () => { if (db) { - try { await db.client.query('ROLLBACK'); } catch {} + try { + await db.client.query('ROLLBACK'); + } catch { + // ignore + } } if (teardown) await teardown(); }); @@ -604,7 +613,11 @@ describe('RRF scoring — unifiedSearch + pgvector fusion (simulating LLM path)' afterAll(async () => { if (db) { - try { await db.client.query('ROLLBACK'); } catch {} + try { + await db.client.query('ROLLBACK'); + } catch { + // ignore + } } if (teardown) await teardown(); }); @@ -792,7 +805,11 @@ describe('RRF scoring — chunk-aware tables', () => { afterAll(async () => { if (db) { - try { await db.client.query('ROLLBACK'); } catch {} + try { + await db.client.query('ROLLBACK'); + } catch { + // ignore + } } if (teardown) await teardown(); }); @@ -964,7 +981,11 @@ describe('RRF scoring — custom @searchConfig weights', () => { afterAll(async () => { if (db) { - try { await db.client.query('ROLLBACK'); } catch {} + try { + await db.client.query('ROLLBACK'); + } catch { + // ignore + } } if (teardown) await teardown(); }); @@ -1089,7 +1110,11 @@ describe('RRF scoring — recency boost', () => { afterAll(async () => { if (db) { - try { await db.client.query('ROLLBACK'); } catch {} + try { + await db.client.query('ROLLBACK'); + } catch { + // ignore + } } if (teardown) await teardown(); }); @@ -1208,7 +1233,11 @@ describe('RRF scoring — custom rrfK parameter', () => { afterAll(async () => { if (db) { - try { await db.client.query('ROLLBACK'); } catch {} + try { + await db.client.query('ROLLBACK'); + } catch { + // ignore + } } if (teardown) await teardown(); }); diff --git a/graphile/graphile-search/src/__tests__/search-config-integration.test.ts b/graphile/graphile-search/src/__tests__/search-config-integration.test.ts index d63a5dc8ab..593579ac3e 100644 --- a/graphile/graphile-search/src/__tests__/search-config-integration.test.ts +++ b/graphile/graphile-search/src/__tests__/search-config-integration.test.ts @@ -7,20 +7,21 @@ * @searchConfig and @hasChunks are JSON objects, not simple strings). */ -import { join } from 'path'; -import { getConnections, seed } from 'graphile-test'; +import type { GraphileConfig } from 'graphile-config'; +import { ConnectionFilterPreset } from 'graphile-connection-filter'; import type { GraphQLResponse } from 'graphile-test'; +import { getConnections, seed } from 'graphile-test'; +import { join } from 'path'; import type { PgTestClient } from 'pgsql-test'; -import { ConnectionFilterPreset } from 'graphile-connection-filter'; + +import { createBm25Adapter } from '../adapters/bm25'; +import { createPgvectorAdapter } from '../adapters/pgvector'; +import { createTrgmAdapter } from '../adapters/trgm'; +import { createTsvectorAdapter } from '../adapters/tsvector'; import { Bm25CodecPlugin } from '../codecs/bm25-codec'; -import { VectorCodecPlugin } from '../codecs/vector-codec'; import { TsvectorCodecPlugin } from '../codecs/tsvector-codec'; +import { VectorCodecPlugin } from '../codecs/vector-codec'; import { createUnifiedSearchPlugin } from '../plugin'; -import { createTsvectorAdapter } from '../adapters/tsvector'; -import { createBm25Adapter } from '../adapters/bm25'; -import { createTrgmAdapter } from '../adapters/trgm'; -import { createPgvectorAdapter } from '../adapters/pgvector'; -import type { GraphileConfig } from 'graphile-config'; // ─── Smart Tags Plugin ─────────────────────────────────────────────────────── // Injects @searchConfig and @hasChunks smart tags on test tables during the diff --git a/graphile/graphile-search/src/__tests__/search-config.test.ts b/graphile/graphile-search/src/__tests__/search-config.test.ts index 1ead0f6b6b..fd7a559161 100644 --- a/graphile/graphile-search/src/__tests__/search-config.test.ts +++ b/graphile/graphile-search/src/__tests__/search-config.test.ts @@ -8,10 +8,10 @@ // We need to test the internal helpers. Since they're not exported, // we test them indirectly through the adapter/plugin behavior using mocked codecs. +import { createBm25Adapter } from '../adapters/bm25'; import { createPgvectorAdapter } from '../adapters/pgvector'; -import { createUnifiedSearchPlugin } from '../plugin'; import { createTsvectorAdapter } from '../adapters/tsvector'; -import { createBm25Adapter } from '../adapters/bm25'; +import { createUnifiedSearchPlugin } from '../plugin'; // ─── pgvector adapter: chunk detection ──────────────────────────────────────── diff --git a/graphile/graphile-search/src/__tests__/unified-search.test.ts b/graphile/graphile-search/src/__tests__/unified-search.test.ts index 86973af455..176cd7b993 100644 --- a/graphile/graphile-search/src/__tests__/unified-search.test.ts +++ b/graphile/graphile-search/src/__tests__/unified-search.test.ts @@ -1,16 +1,17 @@ -import { join } from 'path'; -import { getConnections, seed } from 'graphile-test'; +import { ConnectionFilterPreset } from 'graphile-connection-filter'; import type { GraphQLResponse } from 'graphile-test'; +import { getConnections, seed } from 'graphile-test'; +import { join } from 'path'; import type { PgTestClient } from 'pgsql-test'; -import { ConnectionFilterPreset } from 'graphile-connection-filter'; + +import { createBm25Adapter } from '../adapters/bm25'; +import { createPgvectorAdapter } from '../adapters/pgvector'; +import { createTrgmAdapter } from '../adapters/trgm'; +import { createTsvectorAdapter } from '../adapters/tsvector'; import { Bm25CodecPlugin } from '../codecs/bm25-codec'; -import { VectorCodecPlugin } from '../codecs/vector-codec'; import { TsvectorCodecPlugin } from '../codecs/tsvector-codec'; +import { VectorCodecPlugin } from '../codecs/vector-codec'; import { createUnifiedSearchPlugin } from '../plugin'; -import { createTsvectorAdapter } from '../adapters/tsvector'; -import { createBm25Adapter } from '../adapters/bm25'; -import { createTrgmAdapter } from '../adapters/trgm'; -import { createPgvectorAdapter } from '../adapters/pgvector'; // ─── Result types ──────────────────────────────────────────────────────────── diff --git a/graphile/graphile-search/src/adapters/bm25.ts b/graphile/graphile-search/src/adapters/bm25.ts index 26ea207f38..d5ebd22254 100644 --- a/graphile/graphile-search/src/adapters/bm25.ts +++ b/graphile/graphile-search/src/adapters/bm25.ts @@ -13,10 +13,11 @@ * LEAST(parent_score, chunk_score) (lower = better for BM25). */ -import type { SearchAdapter, SearchableColumn, FilterApplyResult } from '../types'; import type { SQL } from 'pg-sql2'; + import { bm25IndexStore as moduleBm25IndexStore } from '../codecs/bm25-codec'; -import { getChunksInfo, type ChunksInfo } from './chunks'; +import type { FilterApplyResult,SearchableColumn, SearchAdapter } from '../types'; +import { type ChunksInfo,getChunksInfo } from './chunks'; /** * BM25 index info discovered during gather phase. diff --git a/graphile/graphile-search/src/adapters/index.ts b/graphile/graphile-search/src/adapters/index.ts index 69d36ea61c..7211ed99f8 100644 --- a/graphile/graphile-search/src/adapters/index.ts +++ b/graphile/graphile-search/src/adapters/index.ts @@ -5,17 +5,13 @@ * search algorithm. They are plain objects — not Graphile plugins. */ -export { createTsvectorAdapter } from './tsvector'; -export type { TsvectorAdapterOptions } from './tsvector'; - -export { createBm25Adapter } from './bm25'; export type { Bm25AdapterOptions, Bm25IndexInfo } from './bm25'; - -export { createTrgmAdapter } from './trgm'; -export type { TrgmAdapterOptions } from './trgm'; - -export { createPgvectorAdapter } from './pgvector'; -export type { PgvectorAdapterOptions } from './pgvector'; - -export { getChunksInfo } from './chunks'; +export { createBm25Adapter } from './bm25'; export type { ChunksInfo } from './chunks'; +export { getChunksInfo } from './chunks'; +export type { PgvectorAdapterOptions } from './pgvector'; +export { createPgvectorAdapter } from './pgvector'; +export type { TrgmAdapterOptions } from './trgm'; +export { createTrgmAdapter } from './trgm'; +export type { TsvectorAdapterOptions } from './tsvector'; +export { createTsvectorAdapter } from './tsvector'; diff --git a/graphile/graphile-search/src/adapters/pgvector.ts b/graphile/graphile-search/src/adapters/pgvector.ts index b36ac10fc4..038509bfab 100644 --- a/graphile/graphile-search/src/adapters/pgvector.ts +++ b/graphile/graphile-search/src/adapters/pgvector.ts @@ -6,9 +6,10 @@ * Wraps the same SQL logic as graphile-pgvector but as a SearchAdapter. */ -import type { SearchAdapter, SearchableColumn, FilterApplyResult } from '../types'; import type { SQL } from 'pg-sql2'; -import { getChunksInfo, type ChunksInfo } from './chunks'; + +import type { FilterApplyResult,SearchableColumn, SearchAdapter } from '../types'; +import { type ChunksInfo,getChunksInfo } from './chunks'; /** * Build a distance expression for the given metric. @@ -21,13 +22,13 @@ function buildDistanceExpr( metric: string, ): SQL { switch (metric) { - case 'L2': - return sql`(${columnExpr} <-> ${vectorExpr})`; - case 'IP': - return sql`(${columnExpr} <#> ${vectorExpr})`; - case 'COSINE': - default: - return sql`(${columnExpr} <=> ${vectorExpr})`; + case 'L2': + return sql`(${columnExpr} <-> ${vectorExpr})`; + case 'IP': + return sql`(${columnExpr} <#> ${vectorExpr})`; + case 'COSINE': + default: + return sql`(${columnExpr} <=> ${vectorExpr})`; } } diff --git a/graphile/graphile-search/src/adapters/trgm.ts b/graphile/graphile-search/src/adapters/trgm.ts index 67cef51501..103e6c7bd4 100644 --- a/graphile/graphile-search/src/adapters/trgm.ts +++ b/graphile/graphile-search/src/adapters/trgm.ts @@ -10,9 +10,10 @@ * GREATEST(parent_similarity, chunk_similarity). */ -import type { SearchAdapter, SearchableColumn, FilterApplyResult } from '../types'; import type { SQL } from 'pg-sql2'; -import { getChunksInfo, type ChunksInfo } from './chunks'; + +import type { FilterApplyResult,SearchableColumn, SearchAdapter } from '../types'; +import { type ChunksInfo,getChunksInfo } from './chunks'; function isTextCodec(codec: any): boolean { const name = codec?.name; diff --git a/graphile/graphile-search/src/adapters/tsvector.ts b/graphile/graphile-search/src/adapters/tsvector.ts index d9a2ab8c17..308086bb68 100644 --- a/graphile/graphile-search/src/adapters/tsvector.ts +++ b/graphile/graphile-search/src/adapters/tsvector.ts @@ -10,9 +10,10 @@ * GREATEST(parent_rank, chunk_rank). */ -import type { SearchAdapter, SearchableColumn, FilterApplyResult } from '../types'; import type { SQL } from 'pg-sql2'; -import { getChunksInfo, type ChunksInfo } from './chunks'; + +import type { FilterApplyResult,SearchableColumn, SearchAdapter } from '../types'; +import { type ChunksInfo,getChunksInfo } from './chunks'; function isTsvectorCodec(codec: any): boolean { // In graphile-build-pg >= 5.0.0-rc.8, the built-in TYPES.tsvector codec diff --git a/graphile/graphile-search/src/codecs/bm25-codec.ts b/graphile/graphile-search/src/codecs/bm25-codec.ts index 117ca88340..b48beceeda 100644 --- a/graphile/graphile-search/src/codecs/bm25-codec.ts +++ b/graphile/graphile-search/src/codecs/bm25-codec.ts @@ -13,6 +13,7 @@ */ import 'graphile-build-pg'; + import type { GraphileConfig } from 'graphile-config'; import sql from 'pg-sql2'; diff --git a/graphile/graphile-search/src/codecs/index.ts b/graphile/graphile-search/src/codecs/index.ts index 344dfc0590..41a283597d 100644 --- a/graphile/graphile-search/src/codecs/index.ts +++ b/graphile/graphile-search/src/codecs/index.ts @@ -6,21 +6,19 @@ * types and indexes before the schema build phase. */ -export { - TsvectorCodecPlugin, - TsvectorCodecPreset, - createTsvectorCodecPlugin, -} from './tsvector-codec'; -export type { TsvectorCodecPluginOptions } from './tsvector-codec'; - +export type { Bm25IndexInfo } from './bm25-codec'; export { Bm25CodecPlugin, Bm25CodecPreset, - bm25IndexStore, bm25ExtensionDetected, + bm25IndexStore, } from './bm25-codec'; -export type { Bm25IndexInfo } from './bm25-codec'; - +export type { TsvectorCodecPluginOptions } from './tsvector-codec'; +export { + createTsvectorCodecPlugin, + TsvectorCodecPlugin, + TsvectorCodecPreset, +} from './tsvector-codec'; export { VectorCodecPlugin, VectorCodecPreset, diff --git a/graphile/graphile-search/src/codecs/vector-codec.ts b/graphile/graphile-search/src/codecs/vector-codec.ts index 3d58eff963..e764ba1238 100644 --- a/graphile/graphile-search/src/codecs/vector-codec.ts +++ b/graphile/graphile-search/src/codecs/vector-codec.ts @@ -14,6 +14,7 @@ import 'graphile-build-pg'; import 'graphile-build'; + import type { GraphileConfig } from 'graphile-config'; import sql from 'pg-sql2'; diff --git a/graphile/graphile-search/src/index.ts b/graphile/graphile-search/src/index.ts index bab7a05850..b28afee219 100644 --- a/graphile/graphile-search/src/index.ts +++ b/graphile/graphile-search/src/index.ts @@ -34,47 +34,47 @@ export { createUnifiedSearchPlugin } from './plugin'; // Preset -export { UnifiedSearchPreset } from './preset'; export type { UnifiedSearchPresetOptions } from './preset'; +export { UnifiedSearchPreset } from './preset'; // Types export type { - SearchAdapter, - SearchableColumn, - ScoreSemantics, FilterApplyResult, + ScoreSemantics, + SearchableColumn, + SearchAdapter, UnifiedSearchOptions, } from './types'; // Adapters -export { - createTsvectorAdapter, - createBm25Adapter, - createTrgmAdapter, - createPgvectorAdapter, -} from './adapters'; export type { - TsvectorAdapterOptions, Bm25AdapterOptions, - TrgmAdapterOptions, PgvectorAdapterOptions, + TrgmAdapterOptions, + TsvectorAdapterOptions, +} from './adapters'; +export { + createBm25Adapter, + createPgvectorAdapter, + createTrgmAdapter, + createTsvectorAdapter, } from './adapters'; // Codec plugins (tree-shakable — import only the codecs you need) +export type { + Bm25IndexInfo, + TsvectorCodecPluginOptions, +} from './codecs'; export { - TsvectorCodecPlugin, - TsvectorCodecPreset, - createTsvectorCodecPlugin, Bm25CodecPlugin, Bm25CodecPreset, bm25IndexStore, + createTsvectorCodecPlugin, + TsvectorCodecPlugin, + TsvectorCodecPreset, VectorCodecPlugin, VectorCodecPreset, } from './codecs'; -export type { - TsvectorCodecPluginOptions, - Bm25IndexInfo, -} from './codecs'; // Operator factories for connection filter integration export { diff --git a/graphile/graphile-search/src/plugin.ts b/graphile/graphile-search/src/plugin.ts index 08e2e751a0..c67f796be3 100644 --- a/graphile/graphile-search/src/plugin.ts +++ b/graphile/graphile-search/src/plugin.ts @@ -20,11 +20,13 @@ import 'graphile-build'; import 'graphile-build-pg'; import 'graphile-connection-filter'; -import { TYPES } from '@dataplan/pg'; + import type { PgCodecWithAttributes } from '@dataplan/pg'; +import { TYPES } from '@dataplan/pg'; import type { GraphileConfig } from 'graphile-config'; import { getQueryBuilder } from 'graphile-plugin-utils'; -import type { SearchAdapter, SearchableColumn, UnifiedSearchOptions } from './types'; + +import type { SearchableColumn, SearchAdapter, UnifiedSearchOptions } from './types'; // ─── TypeScript Namespace Augmentations ────────────────────────────────────── diff --git a/graphile/graphile-search/src/preset.ts b/graphile/graphile-search/src/preset.ts index 5ad42bec48..4253aa525b 100644 --- a/graphile/graphile-search/src/preset.ts +++ b/graphile/graphile-search/src/preset.ts @@ -18,20 +18,21 @@ */ import type { GraphileConfig } from 'graphile-config'; -import { createUnifiedSearchPlugin } from './plugin'; -import { createTsvectorAdapter } from './adapters/tsvector'; + +import type { Bm25AdapterOptions } from './adapters/bm25'; import { createBm25Adapter } from './adapters/bm25'; -import { createTrgmAdapter } from './adapters/trgm'; +import type { PgvectorAdapterOptions } from './adapters/pgvector'; import { createPgvectorAdapter } from './adapters/pgvector'; -import { TsvectorCodecPlugin } from './codecs/tsvector-codec'; +import type { TrgmAdapterOptions } from './adapters/trgm'; +import { createTrgmAdapter } from './adapters/trgm'; +import type { TsvectorAdapterOptions } from './adapters/tsvector'; +import { createTsvectorAdapter } from './adapters/tsvector'; import { Bm25CodecPlugin } from './codecs/bm25-codec'; -import { VectorCodecPlugin } from './codecs/vector-codec'; import { createMatchesOperatorFactory, createTrgmOperatorFactories } from './codecs/operator-factories'; +import { TsvectorCodecPlugin } from './codecs/tsvector-codec'; +import { VectorCodecPlugin } from './codecs/vector-codec'; +import { createUnifiedSearchPlugin } from './plugin'; import type { UnifiedSearchOptions } from './types'; -import type { TsvectorAdapterOptions } from './adapters/tsvector'; -import type { Bm25AdapterOptions } from './adapters/bm25'; -import type { TrgmAdapterOptions } from './adapters/trgm'; -import type { PgvectorAdapterOptions } from './adapters/pgvector'; /** * Options for configuring which adapters are enabled and their settings. diff --git a/graphile/graphile-settings/__tests__/PublicKeySignature.test.ts b/graphile/graphile-settings/__tests__/PublicKeySignature.test.ts index 431afccad2..cc833a3333 100644 --- a/graphile/graphile-settings/__tests__/PublicKeySignature.test.ts +++ b/graphile/graphile-settings/__tests__/PublicKeySignature.test.ts @@ -1,5 +1,5 @@ -import { PublicKeySignature } from '../src/plugins/PublicKeySignature'; import type { PublicKeyChallengeConfig } from '../src/plugins/PublicKeySignature'; +import { PublicKeySignature } from '../src/plugins/PublicKeySignature'; const defaultConfig: PublicKeyChallengeConfig = { schema: 'app_private', diff --git a/graphile/graphile-settings/__tests__/meta-schema-contract.integration.test.ts b/graphile/graphile-settings/__tests__/meta-schema-contract.integration.test.ts index 20ebc0257f..9693d85a33 100644 --- a/graphile/graphile-settings/__tests__/meta-schema-contract.integration.test.ts +++ b/graphile/graphile-settings/__tests__/meta-schema-contract.integration.test.ts @@ -1,14 +1,13 @@ +import type { GraphQLQueryUnwrappedFnObj } from 'graphile-test'; +import { getConnectionsObjectUnwrapped, seed } from 'graphile-test'; import { buildClientSchema, getIntrospectionQuery, getNamedType, - isInterfaceType, - isObjectType, type GraphQLSchema, - type IntrospectionQuery -} from 'graphql'; -import type { GraphQLQueryUnwrappedFnObj } from 'graphile-test'; -import { getConnectionsObjectUnwrapped, seed } from 'graphile-test'; + type IntrospectionQuery, + isInterfaceType, + isObjectType} from 'graphql'; import { join } from 'path'; import { ConstructivePreset } from '../src/presets/constructive-preset'; diff --git a/graphile/graphile-settings/__tests__/preset-integration.test.ts b/graphile/graphile-settings/__tests__/preset-integration.test.ts index 99b0be867e..bd2aec987a 100644 --- a/graphile/graphile-settings/__tests__/preset-integration.test.ts +++ b/graphile/graphile-settings/__tests__/preset-integration.test.ts @@ -11,9 +11,10 @@ * * Requires postgres-plus:18 image with postgis, vector, pg_textsearch, pg_trgm extensions. */ -import { join } from 'path'; -import { getConnectionsObject, seed } from 'graphile-test'; import type { GraphQLQueryFnObj } from 'graphile-test'; +import { getConnectionsObject, seed } from 'graphile-test'; +import { join } from 'path'; + import { ConstructivePreset } from '../src/presets/constructive-preset'; const SCHEMA = 'integration_test'; diff --git a/graphile/graphile-settings/__tests__/required-input-plugin.test.ts b/graphile/graphile-settings/__tests__/required-input-plugin.test.ts index e0efee781a..a4653b0be0 100644 --- a/graphile/graphile-settings/__tests__/required-input-plugin.test.ts +++ b/graphile/graphile-settings/__tests__/required-input-plugin.test.ts @@ -1,4 +1,5 @@ -import { GraphQLNonNull, GraphQLString, GraphQLInt } from 'graphql'; +import { GraphQLInt,GraphQLNonNull, GraphQLString } from 'graphql'; + import { RequiredInputPlugin, RequiredInputPreset } from '../src/plugins/required-input-plugin'; // --------------------------------------------------------------------------- diff --git a/graphile/graphile-settings/src/index.ts b/graphile/graphile-settings/src/index.ts index 0c5740aa4d..afa9154a82 100644 --- a/graphile/graphile-settings/src/index.ts +++ b/graphile/graphile-settings/src/index.ts @@ -27,8 +27,6 @@ * ``` */ -import { makePgService } from 'postgraphile/adaptors/pg'; - // Import modules for type augmentation // These add properties to the GraphileConfig.Preset interface: // - grafserv: adds 'grafserv' property @@ -37,13 +35,15 @@ import { makePgService } from 'postgraphile/adaptors/pg'; import 'postgraphile/grafserv'; import 'graphile-build'; +import { makePgService } from 'postgraphile/adaptors/pg'; + // ============================================================================ // Re-export all plugins and presets // ============================================================================ // Main preset + factory -export { ConstructivePreset, createConstructivePreset } from './presets/constructive-preset'; export type { ConstructivePresetOptions } from './presets/constructive-preset'; +export { ConstructivePreset, createConstructivePreset } from './presets/constructive-preset'; // Re-export all plugins for convenience export * from './plugins/index'; diff --git a/graphile/graphile-settings/src/plugins/PublicKeySignature.ts b/graphile/graphile-settings/src/plugins/PublicKeySignature.ts index 95683f8281..2d01aa9712 100644 --- a/graphile/graphile-settings/src/plugins/PublicKeySignature.ts +++ b/graphile/graphile-settings/src/plugins/PublicKeySignature.ts @@ -1,9 +1,9 @@ // import Networks from '@pyramation/crypto-networks'; // import { verifyMessage } from '@pyramation/crypto-keys'; +import { QuoteUtils } from '@pgsql/quotes'; import { context as grafastContext, lambda, object } from 'grafast'; import type { GraphileConfig } from 'graphile-config'; import { extendSchema, gql } from 'graphile-utils'; -import { QuoteUtils } from '@pgsql/quotes'; import pgQueryWithContext from 'pg-query-context'; export interface PublicKeyChallengeConfig { diff --git a/graphile/graphile-settings/src/plugins/custom-inflector.ts b/graphile/graphile-settings/src/plugins/custom-inflector.ts index 8609a89d46..d184d7e5cf 100644 --- a/graphile/graphile-settings/src/plugins/custom-inflector.ts +++ b/graphile/graphile-settings/src/plugins/custom-inflector.ts @@ -1,13 +1,11 @@ import type { GraphileConfig } from 'graphile-config'; import { - singularize, - pluralize, - singularizeLast, - pluralizeLast, distinctPluralize, fixCapitalisedPlural, + pluralizeLast, + singularize, + singularizeLast, toCamelCase, - toPascalCase, } from 'inflekt'; /** diff --git a/graphile/graphile-settings/src/plugins/index.ts b/graphile/graphile-settings/src/plugins/index.ts index a46d08ddb0..829bba18c6 100644 --- a/graphile/graphile-settings/src/plugins/index.ts +++ b/graphile/graphile-settings/src/plugins/index.ts @@ -38,14 +38,14 @@ export { } from './many-to-many-preset'; // Primary key only lookups (disable non-PK unique constraints) +export type { UniqueLookupOptions } from './primary-key-only'; export { createUniqueLookupPlugin, - PrimaryKeyOnlyPlugin, NoUniqueLookupPlugin, - PrimaryKeyOnlyPreset, NoUniqueLookupPreset, + PrimaryKeyOnlyPlugin, + PrimaryKeyOnlyPreset, } from './primary-key-only'; -export type { UniqueLookupOptions } from './primary-key-only'; // Meta schema plugin for introspection (tables, fields, indexes, constraints) export { @@ -54,35 +54,35 @@ export { MetaSchemaPreset, } from './meta-schema'; export type { - TableMeta, - FieldMeta, - TypeMeta, - IndexMeta, + BelongsToRelation, ConstraintsMeta, - PrimaryKeyConstraintMeta, - UniqueConstraintMeta, + FieldMeta, ForeignKeyConstraintMeta, - RelationsMeta, - BelongsToRelation, HasRelation, - ManyToManyRelation, + IndexMeta, InflectionMeta, + ManyToManyRelation, + PrimaryKeyConstraintMeta, QueryMeta, + RelationsMeta, + TableMeta, + TypeMeta, + UniqueConstraintMeta, } from 'graphile-meta'; // PG type mappings for custom PostgreSQL types (email, url, etc.) +export type { TypeMapping } from './pg-type-mappings'; export { PgTypeMappingsPlugin, PgTypeMappingsPreset, } from './pg-type-mappings'; -export type { TypeMapping } from './pg-type-mappings'; // Public key signature plugin for crypto authentication -export { PublicKeySignature } from './PublicKeySignature'; export type { PublicKeyChallengeConfig } from './PublicKeySignature'; +export { PublicKeySignature } from './PublicKeySignature'; // Internal exports for testing -export { _pgTypeToGqlType, _buildFieldMeta } from './meta-schema'; +export { _buildFieldMeta,_pgTypeToGqlType } from './meta-schema'; // Required input plugin - makes @requiredInput tagged fields non-nullable in mutation inputs export { @@ -91,37 +91,37 @@ export { } from './required-input-plugin'; // Unified search — tsvector + BM25 + pg_trgm + pgvector behind a single adapter architecture +export type { + Bm25AdapterOptions, + Bm25IndexInfo, + PgvectorAdapterOptions, + SearchableColumn, + SearchAdapter, + TrgmAdapterOptions, + TsvectorAdapterOptions, + TsvectorCodecPluginOptions, + UnifiedSearchOptions, + UnifiedSearchPresetOptions, +} from 'graphile-search'; export { - // Core plugin + preset - createUnifiedSearchPlugin, - UnifiedSearchPreset, - // Codec plugins (tree-shakable) - TsvectorCodecPlugin, - TsvectorCodecPreset, - createTsvectorCodecPlugin, Bm25CodecPlugin, Bm25CodecPreset, bm25IndexStore, - VectorCodecPlugin, - VectorCodecPreset, - // Adapters - createTsvectorAdapter, createBm25Adapter, - createTrgmAdapter, - createPgvectorAdapter, // Operator factories for connection filter integration createMatchesOperatorFactory, + createPgvectorAdapter, + createTrgmAdapter, createTrgmOperatorFactories, -} from 'graphile-search'; -export type { - SearchAdapter, - SearchableColumn, - UnifiedSearchOptions, - UnifiedSearchPresetOptions, - TsvectorCodecPluginOptions, - Bm25IndexInfo, - TsvectorAdapterOptions, - Bm25AdapterOptions, - TrgmAdapterOptions, - PgvectorAdapterOptions, + // Adapters + createTsvectorAdapter, + createTsvectorCodecPlugin, + // Core plugin + preset + createUnifiedSearchPlugin, + // Codec plugins (tree-shakable) + TsvectorCodecPlugin, + TsvectorCodecPreset, + UnifiedSearchPreset, + VectorCodecPlugin, + VectorCodecPreset, } from 'graphile-search'; diff --git a/graphile/graphile-settings/src/plugins/many-to-many-preset.ts b/graphile/graphile-settings/src/plugins/many-to-many-preset.ts index ba95c08a4f..f801d4bb84 100644 --- a/graphile/graphile-settings/src/plugins/many-to-many-preset.ts +++ b/graphile/graphile-settings/src/plugins/many-to-many-preset.ts @@ -1,5 +1,5 @@ -import type { GraphileConfig } from 'graphile-config'; import { PgManyToManyPreset } from '@graphile-contrib/pg-many-to-many'; +import type { GraphileConfig } from 'graphile-config'; /** * Many-to-Many Preset with OPT-IN behavior (disabled by default). diff --git a/graphile/graphile-settings/src/plugins/minimal-preset.ts b/graphile/graphile-settings/src/plugins/minimal-preset.ts index fd3019ff60..565aea0b95 100644 --- a/graphile/graphile-settings/src/plugins/minimal-preset.ts +++ b/graphile/graphile-settings/src/plugins/minimal-preset.ts @@ -1,6 +1,6 @@ -import type { GraphileConfig } from 'graphile-config'; import { defaultPreset as graphileBuildPreset } from 'graphile-build'; import { defaultPreset as graphileBuildPgPreset } from 'graphile-build-pg'; +import type { GraphileConfig } from 'graphile-config'; /** * Minimal PostGraphile v5 preset without Node/Relay features. diff --git a/graphile/graphile-settings/src/plugins/required-input-plugin.ts b/graphile/graphile-settings/src/plugins/required-input-plugin.ts index 5256e6c1cc..fa76cf21dc 100644 --- a/graphile/graphile-settings/src/plugins/required-input-plugin.ts +++ b/graphile/graphile-settings/src/plugins/required-input-plugin.ts @@ -1,5 +1,6 @@ import 'graphile-build'; import 'graphile-build-pg'; + import type { GraphileConfig } from 'graphile-config'; /** diff --git a/graphile/graphile-settings/src/presets/index.ts b/graphile/graphile-settings/src/presets/index.ts index b9b9261165..7fde74ccca 100644 --- a/graphile/graphile-settings/src/presets/index.ts +++ b/graphile/graphile-settings/src/presets/index.ts @@ -5,5 +5,5 @@ * for common use cases. */ -export { ConstructivePreset, createConstructivePreset } from './constructive-preset'; export type { ConstructivePresetOptions } from './constructive-preset'; +export { ConstructivePreset, createConstructivePreset } from './constructive-preset'; diff --git a/graphile/graphile-settings/src/presigned-url-resolver.ts b/graphile/graphile-settings/src/presigned-url-resolver.ts index 75a44503c3..f9ea6ba75b 100644 --- a/graphile/graphile-settings/src/presigned-url-resolver.ts +++ b/graphile/graphile-settings/src/presigned-url-resolver.ts @@ -11,11 +11,12 @@ * Follows the same lazy-init pattern as upload-resolver.ts. */ -import { createS3Client } from '@constructive-io/s3-utils'; +import { BucketProvisioner } from '@constructive-io/bucket-provisioner'; import { getEnvOptions } from '@constructive-io/graphql-env'; +import { createS3Client } from '@constructive-io/s3-utils'; import { Logger } from '@pgpmjs/logger'; -import type { S3Config, BucketNameResolver, EnsureBucketProvisioned } from 'graphile-presigned-url-plugin'; -import { BucketProvisioner } from '@constructive-io/bucket-provisioner'; +import type { BucketNameResolver, EnsureBucketProvisioned,S3Config } from 'graphile-presigned-url-plugin'; + import { getBucketProvisionerConnection } from './bucket-provisioner-resolver'; const log = new Logger('presigned-url-resolver'); diff --git a/graphile/graphile-settings/src/upload-resolver.ts b/graphile/graphile-settings/src/upload-resolver.ts index 423020b749..09df772021 100644 --- a/graphile/graphile-settings/src/upload-resolver.ts +++ b/graphile/graphile-settings/src/upload-resolver.ts @@ -16,15 +16,15 @@ * CDN_ENDPOINT - S3-compatible endpoint (default: 'http://localhost:9000') */ +import { getEnvOptions } from '@constructive-io/graphql-env'; import Streamer from '@constructive-io/s3-streamer'; import uploadNames from '@constructive-io/upload-names'; -import { getEnvOptions } from '@constructive-io/graphql-env'; import { Logger } from '@pgpmjs/logger'; import { randomBytes } from 'crypto'; import type { - FileUpload, - UploadFieldDefinition, - UploadPluginInfo, + FileUpload, + UploadFieldDefinition, + UploadPluginInfo, } from 'graphile-upload-plugin'; const log = new Logger('upload-resolver'); @@ -34,38 +34,38 @@ let streamer: Streamer | null = null; let bucketName: string; function getStreamer(): Streamer { - if (streamer) return streamer; - - const opts = getEnvOptions(); - const cdn = opts.cdn || {}; - - const provider = cdn.provider || 'minio'; - bucketName = cdn.bucketName || 'test-bucket'; - const awsRegion = cdn.awsRegion || 'us-east-1'; - const awsAccessKey = cdn.awsAccessKey || 'minioadmin'; - const awsSecretKey = cdn.awsSecretKey || 'minioadmin'; - const endpoint = cdn.endpoint || 'http://localhost:9000'; - - if (process.env.NODE_ENV === 'production') { - if (!cdn.awsAccessKey || !cdn.awsSecretKey) { - log.warn('[upload-resolver] WARNING: Using default credentials in production.'); - } - } - - log.info( - `[upload-resolver] Initializing: provider=${provider} bucket=${bucketName}`, - ); - - streamer = new Streamer({ - defaultBucket: bucketName, - awsRegion, - awsSecretKey, - awsAccessKey, - endpoint, - provider, - }); - - return streamer; + if (streamer) return streamer; + + const opts = getEnvOptions(); + const cdn = opts.cdn || {}; + + const provider = cdn.provider || 'minio'; + bucketName = cdn.bucketName || 'test-bucket'; + const awsRegion = cdn.awsRegion || 'us-east-1'; + const awsAccessKey = cdn.awsAccessKey || 'minioadmin'; + const awsSecretKey = cdn.awsSecretKey || 'minioadmin'; + const endpoint = cdn.endpoint || 'http://localhost:9000'; + + if (process.env.NODE_ENV === 'production') { + if (!cdn.awsAccessKey || !cdn.awsSecretKey) { + log.warn('[upload-resolver] WARNING: Using default credentials in production.'); + } + } + + log.info( + `[upload-resolver] Initializing: provider=${provider} bucket=${bucketName}`, + ); + + streamer = new Streamer({ + defaultBucket: bucketName, + awsRegion, + awsSecretKey, + awsAccessKey, + endpoint, + provider, + }); + + return streamer; } /** @@ -73,8 +73,8 @@ function getStreamer(): Streamer { * Format: {random10chars}-{sanitized-filename} */ function generateKey(filename: string): string { - const rand = randomBytes(12).toString('hex'); - return `${rand}-${uploadNames(filename)}`; + const rand = randomBytes(12).toString('hex'); + return `${rand}-${uploadNames(filename)}`; } /** @@ -88,59 +88,59 @@ function generateKey(filename: string): string { * stream bytes, validated against smart-tag/type rules, and only then uploaded. */ async function uploadResolver( - upload: FileUpload, - _args: unknown, - _context: unknown, - info: { uploadPlugin: UploadPluginInfo }, + upload: FileUpload, + _args: unknown, + _context: unknown, + info: { uploadPlugin: UploadPluginInfo }, ): Promise { - const { tags, type } = info.uploadPlugin; - const s3 = getStreamer(); - const { filename } = upload; - const key = generateKey(filename); - - // MIME type validation from smart tags - const typ = type || tags?.type; - const VALID_MIME = /^[a-z]+\/[a-z0-9][a-z0-9!#$&\-.^_+]*$/i; - const mim: string[] = tags?.mime - ? String(tags.mime) - .trim() - .split(',') - .map((a: string) => a.trim()) - .filter((m: string) => VALID_MIME.test(m)) - : typ === 'image' - ? DEFAULT_IMAGE_MIME_TYPES - : []; - - const detected = await s3.detectContentType({ - readStream: upload.createReadStream(), - filename, - }); - const detectedContentType = detected.contentType; - - if (mim.length && !mim.includes(detectedContentType)) { - detected.stream.destroy(); - throw new Error('UPLOAD_MIMETYPE'); - } - - const result = await s3.uploadWithContentType({ - readStream: detected.stream, - contentType: detectedContentType, - magic: detected.magic, - key, - bucket: bucketName, - }); - - const url = result.upload.Location; - const { contentType } = result; - - switch (typ) { - case 'image': - case 'upload': - return { filename, mime: contentType, url }; - case 'attachment': - default: - return url; - } + const { tags, type } = info.uploadPlugin; + const s3 = getStreamer(); + const { filename } = upload; + const key = generateKey(filename); + + // MIME type validation from smart tags + const typ = type || tags?.type; + const VALID_MIME = /^[a-z]+\/[a-z0-9][a-z0-9!#$&\-.^_+]*$/i; + const mim: string[] = tags?.mime + ? String(tags.mime) + .trim() + .split(',') + .map((a: string) => a.trim()) + .filter((m: string) => VALID_MIME.test(m)) + : typ === 'image' + ? DEFAULT_IMAGE_MIME_TYPES + : []; + + const detected = await s3.detectContentType({ + readStream: upload.createReadStream(), + filename, + }); + const detectedContentType = detected.contentType; + + if (mim.length && !mim.includes(detectedContentType)) { + detected.stream.destroy(); + throw new Error('UPLOAD_MIMETYPE'); + } + + const result = await s3.uploadWithContentType({ + readStream: detected.stream, + contentType: detectedContentType, + magic: detected.magic, + key, + bucket: bucketName, + }); + + const url = result.upload.Location; + const { contentType } = result; + + switch (typ) { + case 'image': + case 'upload': + return { filename, mime: contentType, url }; + case 'attachment': + default: + return url; + } } /** @@ -157,22 +157,22 @@ async function uploadResolver( * to every application database. They rarely change, so this config is stable. */ export const constructiveUploadFieldDefinitions: UploadFieldDefinition[] = [ - { - name: 'image', - namespaceName: 'public', - type: 'image', - resolve: uploadResolver, - }, - { - name: 'upload', - namespaceName: 'public', - type: 'upload', - resolve: uploadResolver, - }, - { - name: 'attachment', - namespaceName: 'public', - type: 'attachment', - resolve: uploadResolver, - }, + { + name: 'image', + namespaceName: 'public', + type: 'image', + resolve: uploadResolver, + }, + { + name: 'upload', + namespaceName: 'public', + type: 'upload', + resolve: uploadResolver, + }, + { + name: 'attachment', + namespaceName: 'public', + type: 'attachment', + resolve: uploadResolver, + }, ]; diff --git a/graphile/graphile-sql-expression-validator/__tests__/field-types.test.ts b/graphile/graphile-sql-expression-validator/__tests__/field-types.test.ts index b50741c667..59b9af6fb2 100644 --- a/graphile/graphile-sql-expression-validator/__tests__/field-types.test.ts +++ b/graphile/graphile-sql-expression-validator/__tests__/field-types.test.ts @@ -1,18 +1,14 @@ +import type { + FieldDefault, + FieldDefaultValidationOptions} from '../src/field-types'; import { - validateFieldType, - validateFieldDefault, - fieldTypeToAst, - fieldTypeToSql, fieldDefaultToAst, fieldDefaultToSql, - FORBIDDEN_TYPES -} from '../src/field-types'; -import type { - FieldType, - FieldDefault, - FieldTypeValidationOptions, - FieldDefaultValidationOptions -} from '../src/field-types'; + fieldTypeToAst, + fieldTypeToSql, + FORBIDDEN_TYPES, + validateFieldDefault, + validateFieldType} from '../src/field-types'; import { DEFAULT_ALLOWED_FUNCTIONS } from '../src/validator'; // ═══════════════════════════════════════════════════════════════════ diff --git a/graphile/graphile-sql-expression-validator/__tests__/plugin.test.ts b/graphile/graphile-sql-expression-validator/__tests__/plugin.test.ts index dbe3ce79ff..cc93dac786 100644 --- a/graphile/graphile-sql-expression-validator/__tests__/plugin.test.ts +++ b/graphile/graphile-sql-expression-validator/__tests__/plugin.test.ts @@ -8,11 +8,11 @@ jest.mock('grafast', () => ({ sideEffect: (...args: unknown[]) => mockSideEffect(...args) })); +import type { SqlExpressionValidatorOptions } from '../src'; import { createSqlExpressionValidatorPlugin, SqlExpressionValidatorPreset } from '../src'; -import type { SqlExpressionValidatorOptions } from '../src'; beforeEach(() => { mockSideEffect.mockClear(); diff --git a/graphile/graphile-sql-expression-validator/__tests__/validator.test.ts b/graphile/graphile-sql-expression-validator/__tests__/validator.test.ts index 6d3a26fe45..6214361145 100644 --- a/graphile/graphile-sql-expression-validator/__tests__/validator.test.ts +++ b/graphile/graphile-sql-expression-validator/__tests__/validator.test.ts @@ -1,9 +1,8 @@ +import type { SqlExpressionValidatorOptions } from '../src/validator'; import { + DEFAULT_ALLOWED_FUNCTIONS, parseAndValidateSqlExpression, - validateAst, - DEFAULT_ALLOWED_FUNCTIONS -} from '../src/validator'; -import type { SqlExpressionValidatorOptions } from '../src/validator'; + validateAst} from '../src/validator'; describe('DEFAULT_ALLOWED_FUNCTIONS', () => { it('should contain the expected set of safe PostgreSQL functions', () => { @@ -500,7 +499,7 @@ describe('parseAndValidateSqlExpression', () => { }); it('should allow normal cast to text', async () => { - const result = await parseAndValidateSqlExpression("42::text"); + const result = await parseAndValidateSqlExpression('42::text'); expect(result.valid).toBe(true); }); }); diff --git a/graphile/graphile-sql-expression-validator/src/field-types.ts b/graphile/graphile-sql-expression-validator/src/field-types.ts index 67d6d232b3..323e7056f9 100644 --- a/graphile/graphile-sql-expression-validator/src/field-types.ts +++ b/graphile/graphile-sql-expression-validator/src/field-types.ts @@ -14,8 +14,9 @@ */ import { deparseSync } from 'pgsql-deparser'; + +import type {SqlExpressionValidatorOptions } from './validator'; import { validateAst } from './validator'; -import type { SqlExpressionValidatorOptions, AstValidationResult } from './validator'; // ─── Types ──────────────────────────────────────────────────────── diff --git a/graphile/graphile-sql-expression-validator/src/index.ts b/graphile/graphile-sql-expression-validator/src/index.ts index 7ec577ed93..3310fc5b3c 100644 --- a/graphile/graphile-sql-expression-validator/src/index.ts +++ b/graphile/graphile-sql-expression-validator/src/index.ts @@ -33,17 +33,15 @@ // Standalone validation utilities export { + DEFAULT_ALLOWED_FUNCTIONS, parseAndValidateSqlExpression, - validateAst, - DEFAULT_ALLOWED_FUNCTIONS -} from './validator'; + validateAst} from './validator'; // Types export type { - SqlExpressionValidatorOptions, + AstValidationResult, SqlExpressionValidationResult, - AstValidationResult -} from './validator'; + SqlExpressionValidatorOptions} from './validator'; // PostGraphile v5 plugin and preset export { @@ -53,22 +51,20 @@ export { // FieldType / FieldDefault structured models export { - validateFieldType, - validateFieldDefault, - fieldTypeToAst, - fieldTypeToSql, fieldDefaultToAst, fieldDefaultToSql, - FORBIDDEN_TYPES -} from './field-types'; + fieldTypeToAst, + fieldTypeToSql, + FORBIDDEN_TYPES, + validateFieldDefault, + validateFieldType} from './field-types'; // FieldType / FieldDefault types export type { - FieldType, FieldDefault, FieldDefaultArg, - FieldTypeValidationOptions, FieldDefaultValidationOptions, - FieldTypeValidationResult, - FieldDefaultValidationResult -} from './field-types'; + FieldDefaultValidationResult, + FieldType, + FieldTypeValidationOptions, + FieldTypeValidationResult} from './field-types'; diff --git a/graphile/graphile-sql-expression-validator/src/plugin.ts b/graphile/graphile-sql-expression-validator/src/plugin.ts index 713f6f635a..e7bf31709c 100644 --- a/graphile/graphile-sql-expression-validator/src/plugin.ts +++ b/graphile/graphile-sql-expression-validator/src/plugin.ts @@ -22,16 +22,17 @@ * available; forbidden from defining a GraphQL resolver." */ -import type { GraphileConfig } from 'graphile-config'; import 'graphile-build'; import 'graphile-build-pg'; + import { sideEffect } from 'grafast'; +import type { GraphileConfig } from 'graphile-config'; + +import type { SqlExpressionValidatorOptions } from './validator'; import { + DEFAULT_ALLOWED_FUNCTIONS, parseAndValidateSqlExpression, - validateAst, - DEFAULT_ALLOWED_FUNCTIONS -} from './validator'; -import type { SqlExpressionValidatorOptions } from './validator'; + validateAst} from './validator'; // ─── Helpers ────────────────────────────────────────────────────── diff --git a/graphile/graphile-sql-expression-validator/src/validator.ts b/graphile/graphile-sql-expression-validator/src/validator.ts index ea67546e1b..d1e09e365e 100644 --- a/graphile/graphile-sql-expression-validator/src/validator.ts +++ b/graphile/graphile-sql-expression-validator/src/validator.ts @@ -11,8 +11,8 @@ * types are blocked by default. */ -import { parse } from 'pgsql-parser'; import { deparseSync } from 'pgsql-deparser'; +import { parse } from 'pgsql-parser'; // ─── Types ──────────────────────────────────────────────────────── diff --git a/graphile/graphile-test/__tests__/graphile-test.graphile-tx.test.ts b/graphile/graphile-test/__tests__/graphile-test.graphile-tx.test.ts index 245c5b0d66..50ac774e95 100644 --- a/graphile/graphile-test/__tests__/graphile-test.graphile-tx.test.ts +++ b/graphile/graphile-test/__tests__/graphile-test.graphile-tx.test.ts @@ -5,9 +5,9 @@ import { join } from 'path'; import { seed } from 'pgsql-test'; import type { PgTestClient } from 'pgsql-test/test-client'; -import { snapshot } from '../src/utils'; import { getConnections } from '../src/get-connections'; import type { GraphQLQueryFn } from '../src/types'; +import { snapshot } from '../src/utils'; import { logDbSessionInfo } from '../test-utils/utils'; const schemas = ['app_public']; diff --git a/graphile/graphile-test/__tests__/graphile-test.graphql.test.ts b/graphile/graphile-test/__tests__/graphile-test.graphql.test.ts index d2297f85f0..134f990d9c 100644 --- a/graphile/graphile-test/__tests__/graphile-test.graphql.test.ts +++ b/graphile/graphile-test/__tests__/graphile-test.graphql.test.ts @@ -5,9 +5,9 @@ import { join } from 'path'; import { seed } from 'pgsql-test'; import type { PgTestClient } from 'pgsql-test/test-client'; -import { snapshot } from '../src/utils'; import { getConnections } from '../src/get-connections'; import type { GraphQLQueryFn } from '../src/types'; +import { snapshot } from '../src/utils'; import { logDbSessionInfo } from '../test-utils/utils'; const schemas = ['app_public']; diff --git a/graphile/graphile-test/__tests__/graphile-test.plugins.test.ts b/graphile/graphile-test/__tests__/graphile-test.plugins.test.ts index 1b7e422f18..28de153ab5 100644 --- a/graphile/graphile-test/__tests__/graphile-test.plugins.test.ts +++ b/graphile/graphile-test/__tests__/graphile-test.plugins.test.ts @@ -1,7 +1,7 @@ process.env.LOG_SCOPE = 'graphile-test'; -import gql from 'graphql-tag'; import { GraphQLString } from 'graphql'; +import gql from 'graphql-tag'; import { join } from 'path'; import { seed } from 'pgsql-test'; import type { PgTestClient } from 'pgsql-test/test-client'; diff --git a/graphile/graphile-test/__tests__/graphile-test.roles.test.ts b/graphile/graphile-test/__tests__/graphile-test.roles.test.ts index 2e7144fad6..efd016776c 100644 --- a/graphile/graphile-test/__tests__/graphile-test.roles.test.ts +++ b/graphile/graphile-test/__tests__/graphile-test.roles.test.ts @@ -5,9 +5,9 @@ import { join } from 'path'; import { seed } from 'pgsql-test'; import type { PgTestClient } from 'pgsql-test/test-client'; -import { snapshot } from '../src/utils'; import { getConnections } from '../src/get-connections'; import type { GraphQLQueryFn } from '../src/types'; +import { snapshot } from '../src/utils'; import { logDbSessionInfo } from '../test-utils/utils'; const schemas = ['app_public']; diff --git a/graphile/graphile-test/__tests__/graphile-test.test.ts b/graphile/graphile-test/__tests__/graphile-test.test.ts index 729355721f..14f1ed47d6 100644 --- a/graphile/graphile-test/__tests__/graphile-test.test.ts +++ b/graphile/graphile-test/__tests__/graphile-test.test.ts @@ -4,7 +4,6 @@ import { join } from 'path'; import { seed } from 'pgsql-test'; import type { PgTestClient } from 'pgsql-test/test-client'; -import { snapshot } from '../src/utils'; import { getConnections } from '../src/get-connections'; import type { GraphQLQueryFn } from '../src/types'; import { IntrospectionQuery } from '../test-utils/queries'; diff --git a/graphile/graphile-test/__tests__/graphile-test.types.positional.test.ts b/graphile/graphile-test/__tests__/graphile-test.types.positional.test.ts index 93502d1ea8..015e65393b 100644 --- a/graphile/graphile-test/__tests__/graphile-test.types.positional.test.ts +++ b/graphile/graphile-test/__tests__/graphile-test.types.positional.test.ts @@ -4,9 +4,9 @@ import { join } from 'path'; import { seed } from 'pgsql-test'; import type { PgTestClient } from 'pgsql-test/test-client'; -import { snapshot } from '../src/utils'; import { getConnections } from '../src/get-connections'; import type { GraphQLQueryFn } from '../src/types'; +import { snapshot } from '../src/utils'; const schemas = ['app_public']; const sql = (f: string) => join(__dirname, '/../sql', f); diff --git a/graphile/graphile-test/__tests__/graphile-test.types.positional.unwrapped.test.ts b/graphile/graphile-test/__tests__/graphile-test.types.positional.unwrapped.test.ts index 2f661c871d..0074c91b46 100644 --- a/graphile/graphile-test/__tests__/graphile-test.types.positional.unwrapped.test.ts +++ b/graphile/graphile-test/__tests__/graphile-test.types.positional.unwrapped.test.ts @@ -4,9 +4,9 @@ import { join } from 'path'; import { seed } from 'pgsql-test'; import type { PgTestClient } from 'pgsql-test/test-client'; -import { snapshot } from '../src/utils'; import { getConnectionsUnwrapped } from '../src/get-connections'; import type { GraphQLQueryUnwrappedFn } from '../src/types'; +import { snapshot } from '../src/utils'; const schemas = ['app_public']; const sql = (f: string) => join(__dirname, '/../sql', f); diff --git a/graphile/graphile-test/__tests__/graphile-test.types.test.ts b/graphile/graphile-test/__tests__/graphile-test.types.test.ts index 3f4f7c6821..348b5397db 100644 --- a/graphile/graphile-test/__tests__/graphile-test.types.test.ts +++ b/graphile/graphile-test/__tests__/graphile-test.types.test.ts @@ -4,9 +4,9 @@ import { join } from 'path'; import { seed } from 'pgsql-test'; import type { PgTestClient } from 'pgsql-test/test-client'; -import { snapshot } from '../src/utils'; import { getConnectionsObject } from '../src/get-connections'; import type { GraphQLQueryFnObj } from '../src/types'; +import { snapshot } from '../src/utils'; const schemas = ['app_public']; const sql = (f: string) => join(__dirname, '/../sql', f); diff --git a/graphile/graphile-test/__tests__/graphile-test.types.unwrapped.test.ts b/graphile/graphile-test/__tests__/graphile-test.types.unwrapped.test.ts index c3abfe50b0..f586a695e7 100644 --- a/graphile/graphile-test/__tests__/graphile-test.types.unwrapped.test.ts +++ b/graphile/graphile-test/__tests__/graphile-test.types.unwrapped.test.ts @@ -4,9 +4,9 @@ import { join } from 'path'; import { seed } from 'pgsql-test'; import type { PgTestClient } from 'pgsql-test/test-client'; -import { snapshot } from '../src/utils'; import { getConnectionsObjectUnwrapped } from '../src/get-connections'; import type { GraphQLQueryUnwrappedFnObj } from '../src/types'; +import { snapshot } from '../src/utils'; const schemas = ['app_public']; const sql = (f: string) => join(__dirname, '/../sql', f); diff --git a/graphile/graphile-test/src/context.ts b/graphile/graphile-test/src/context.ts index eb11971465..677eeae4f6 100644 --- a/graphile/graphile-test/src/context.ts +++ b/graphile/graphile-test/src/context.ts @@ -1,19 +1,18 @@ +import { execute } from 'grafast'; +import type { GraphileConfig } from 'graphile-config'; import type { DocumentNode, ExecutionResult, - GraphQLSchema, - GraphQLError, FieldNode, + GraphQLError, + GraphQLSchema, OperationDefinitionNode, SelectionNode, } from 'graphql'; -import { parse, print, Kind } from 'graphql'; -import type { GraphileConfig } from 'graphile-config'; -import { execute } from 'grafast'; -import { withPgClientFromPgService } from 'graphile-build-pg'; -import { makePgService } from 'postgraphile/adaptors/pg'; +import { Kind,parse, print } from 'graphql'; import type { Client, Pool } from 'pg'; import type { GetConnectionOpts, GetConnectionResult } from 'pgsql-test'; +import { makePgService } from 'postgraphile/adaptors/pg'; import type { GetConnectionsInput } from './types'; diff --git a/graphile/graphile-test/src/graphile-test.ts b/graphile/graphile-test/src/graphile-test.ts index 6ad57a09b9..7c9400f41b 100644 --- a/graphile/graphile-test/src/graphile-test.ts +++ b/graphile/graphile-test/src/graphile-test.ts @@ -1,14 +1,13 @@ -import type { GraphQLSchema } from 'graphql'; -import type { GraphileConfig } from 'graphile-config'; -import type { GetConnectionOpts, GetConnectionResult } from 'pgsql-test'; - import { makeSchema } from 'graphile-build'; import { defaultPreset as graphileBuildDefaultPreset } from 'graphile-build'; import { defaultPreset as graphileBuildPgDefaultPreset } from 'graphile-build-pg'; +import type { GraphileConfig } from 'graphile-config'; +import type { GraphQLSchema } from 'graphql'; +import type { GetConnectionOpts, GetConnectionResult } from 'pgsql-test'; import { makePgService } from 'postgraphile/adaptors/pg'; import { runGraphQLInContext } from './context'; -import type { GraphQLQueryOptions, GraphQLTestContext, GetConnectionsInput, Variables } from './types'; +import type { GetConnectionsInput, GraphQLQueryOptions, GraphQLTestContext, Variables } from './types'; /** * Minimal preset that provides core functionality without Node/Relay. diff --git a/graphile/graphile-upload-plugin/__tests__/plugin.test.ts b/graphile/graphile-upload-plugin/__tests__/plugin.test.ts index 0d235ee96d..5b47f2a41c 100644 --- a/graphile/graphile-upload-plugin/__tests__/plugin.test.ts +++ b/graphile/graphile-upload-plugin/__tests__/plugin.test.ts @@ -1,6 +1,7 @@ -import { GraphQLScalarType, GraphQLError } from 'graphql'; import { EventEmitter } from 'events'; +import { GraphQLError,GraphQLScalarType } from 'graphql'; import { Readable } from 'stream'; + import { createUploadPlugin } from '../src/plugin'; import type { UploadFieldDefinition } from '../src/types'; diff --git a/graphile/graphile-upload-plugin/__tests__/scalar.test.ts b/graphile/graphile-upload-plugin/__tests__/scalar.test.ts index c3d3fdc321..1c58bede85 100644 --- a/graphile/graphile-upload-plugin/__tests__/scalar.test.ts +++ b/graphile/graphile-upload-plugin/__tests__/scalar.test.ts @@ -1,4 +1,5 @@ -import { GraphQLScalarType, GraphQLError } from 'graphql'; +import { GraphQLError,GraphQLScalarType } from 'graphql'; + import { createUploadPlugin } from '../src/plugin'; /** diff --git a/graphile/graphile-upload-plugin/__tests__/types.test.ts b/graphile/graphile-upload-plugin/__tests__/types.test.ts index fbcfb2b4b7..96977d3658 100644 --- a/graphile/graphile-upload-plugin/__tests__/types.test.ts +++ b/graphile/graphile-upload-plugin/__tests__/types.test.ts @@ -1,10 +1,9 @@ import type { - UploadFieldDefinition, - UploadResolver, FileUpload, + UploadFieldDefinition, UploadPluginInfo, - UploadPluginOptions -} from '../src/types'; + UploadPluginOptions, + UploadResolver} from '../src/types'; /** * Tests for the UploadFieldDefinition type interface. diff --git a/graphile/graphile-upload-plugin/src/index.ts b/graphile/graphile-upload-plugin/src/index.ts index f00357bf4a..ef83dc060b 100644 --- a/graphile/graphile-upload-plugin/src/index.ts +++ b/graphile/graphile-upload-plugin/src/index.ts @@ -27,7 +27,7 @@ * ``` */ -export { UploadPlugin, createUploadPlugin } from './plugin'; +export { createUploadPlugin,UploadPlugin } from './plugin'; export { UploadPreset } from './preset'; export type { FileUpload, diff --git a/graphile/graphile-upload-plugin/src/plugin.ts b/graphile/graphile-upload-plugin/src/plugin.ts index 2b06fec556..e9b7d7753a 100644 --- a/graphile/graphile-upload-plugin/src/plugin.ts +++ b/graphile/graphile-upload-plugin/src/plugin.ts @@ -23,8 +23,10 @@ import 'graphile-build'; import 'graphile-build-pg'; + import type { GraphileConfig } from 'graphile-config'; import { Readable, Transform } from 'stream'; + import type { UploadFieldDefinition, UploadPluginOptions } from './types'; /** diff --git a/graphile/graphile-upload-plugin/src/preset.ts b/graphile/graphile-upload-plugin/src/preset.ts index aa60c5f7c0..fa6f2bed85 100644 --- a/graphile/graphile-upload-plugin/src/preset.ts +++ b/graphile/graphile-upload-plugin/src/preset.ts @@ -5,8 +5,9 @@ */ import type { GraphileConfig } from 'graphile-config'; -import type { UploadPluginOptions } from './types'; + import { createUploadPlugin } from './plugin'; +import type { UploadPluginOptions } from './types'; /** * Creates a preset that includes the upload plugin with the given options. diff --git a/graphql/codegen/src/__tests__/codegen/cli-generator.test.ts b/graphql/codegen/src/__tests__/codegen/cli-generator.test.ts index 941df8317d..16e6e82622 100644 --- a/graphql/codegen/src/__tests__/codegen/cli-generator.test.ts +++ b/graphql/codegen/src/__tests__/codegen/cli-generator.test.ts @@ -1,23 +1,23 @@ import { generateCli, generateMultiTargetCli, resolveBuiltinNames } from '../../core/codegen/cli'; +import type { MultiTargetDocsInput } from '../../core/codegen/cli/docs-generator'; import { - generateReadme as generateCliReadme, - generateSkills as generateCliSkills, generateMultiTargetReadme, generateMultiTargetSkills, + generateReadme as generateCliReadme, + generateSkills as generateCliSkills, } from '../../core/codegen/cli/docs-generator'; -import type { MultiTargetDocsInput } from '../../core/codegen/cli/docs-generator'; import { resolveDocsConfig } from '../../core/codegen/docs-utils'; -import { - generateOrmReadme, - generateOrmSkills, -} from '../../core/codegen/orm/docs-generator'; import { generateHooksReadme, generateHooksSkills, } from '../../core/codegen/hooks-docs-generator'; import { - generateTargetReadme, + generateOrmReadme, + generateOrmSkills, +} from '../../core/codegen/orm/docs-generator'; +import { generateRootRootReadme, + generateTargetReadme, } from '../../core/codegen/target-docs-generator'; import type { FieldType, diff --git a/graphql/codegen/src/__tests__/codegen/input-types-generator.test.ts b/graphql/codegen/src/__tests__/codegen/input-types-generator.test.ts index f267bef106..607b4207cd 100644 --- a/graphql/codegen/src/__tests__/codegen/input-types-generator.test.ts +++ b/graphql/codegen/src/__tests__/codegen/input-types-generator.test.ts @@ -16,9 +16,9 @@ import type { Argument, FieldType, Relations, + ResolvedType, Table, TypeRef, - ResolvedType, TypeRegistry, } from '../../types/schema'; diff --git a/graphql/codegen/src/__tests__/codegen/query-builder.test.ts b/graphql/codegen/src/__tests__/codegen/query-builder.test.ts index 1a8106d20d..664bbde397 100644 --- a/graphql/codegen/src/__tests__/codegen/query-builder.test.ts +++ b/graphql/codegen/src/__tests__/codegen/query-builder.test.ts @@ -137,7 +137,7 @@ function buildFindManyDocument( select as Record, connectionFieldsMap, operationName, - ) + ) : [t.field({ name: 'id' })]; const variableDefinitions: VariableDefinitionNode[] = []; const queryArgs: ArgumentNode[] = []; @@ -289,7 +289,7 @@ function buildCustomDocument( actualSelect as Record, connectionFieldsMap, entityType, - ) + ) : []; const variableDefs = variableDefinitions.map((definition) => diff --git a/graphql/codegen/src/__tests__/codegen/react-query-hooks.test.ts b/graphql/codegen/src/__tests__/codegen/react-query-hooks.test.ts index b66c2a2078..4a360e35df 100644 --- a/graphql/codegen/src/__tests__/codegen/react-query-hooks.test.ts +++ b/graphql/codegen/src/__tests__/codegen/react-query-hooks.test.ts @@ -33,9 +33,9 @@ import type { FieldType, Operation, Relations, + ResolvedType, Table, TypeRef, - ResolvedType, TypeRegistry, } from '../../types/schema'; diff --git a/graphql/codegen/src/__tests__/codegen/utils.test.ts b/graphql/codegen/src/__tests__/codegen/utils.test.ts index d80358ae05..319afb5206 100644 --- a/graphql/codegen/src/__tests__/codegen/utils.test.ts +++ b/graphql/codegen/src/__tests__/codegen/utils.test.ts @@ -10,8 +10,8 @@ import { gqlTypeToTs, lcFirst, toCamelCase, - toPascalCase, toConstantCase, + toPascalCase, ucFirst, } from '../../core/codegen/utils'; import type { Relations, Table } from '../../types/schema'; diff --git a/graphql/codegen/src/__tests__/introspect/infer-tables.test.ts b/graphql/codegen/src/__tests__/introspect/infer-tables.test.ts index d5678101db..86ee8e8812 100644 --- a/graphql/codegen/src/__tests__/introspect/infer-tables.test.ts +++ b/graphql/codegen/src/__tests__/introspect/infer-tables.test.ts @@ -128,17 +128,17 @@ function createIntrospection( }, ...(mutationFields.length > 0 ? [ - { - name: 'Mutation', - kind: 'OBJECT' as const, - fields: mutationFields.map(makeField), - inputFields: null, - enumValues: null, - interfaces: [], - possibleTypes: null, - description: null, - }, - ] + { + name: 'Mutation', + kind: 'OBJECT' as const, + fields: mutationFields.map(makeField), + inputFields: null, + enumValues: null, + interfaces: [], + possibleTypes: null, + description: null, + }, + ] : []), ...types.map( (t): IntrospectionType => ({ @@ -152,13 +152,13 @@ function createIntrospection( enumValues: t.kind === 'ENUM' ? (t.enumValues ?? []).map( - (v): IntrospectionEnumValue => ({ - name: v, - deprecationReason: null, - description: null, - isDeprecated: false, - }), - ) + (v): IntrospectionEnumValue => ({ + name: v, + deprecationReason: null, + description: null, + isDeprecated: false, + }), + ) : null, interfaces: [], possibleTypes: null, diff --git a/graphql/codegen/src/cli/handler.ts b/graphql/codegen/src/cli/handler.ts index 3a8d3573f4..650b430a1b 100644 --- a/graphql/codegen/src/cli/handler.ts +++ b/graphql/codegen/src/cli/handler.ts @@ -33,10 +33,10 @@ export async function runCodegenHandler( const schemaConfig = args.schemaEnabled ? { - enabled: true, - ...(args.schemaOutput ? { output: String(args.schemaOutput) } : {}), - ...(args.schemaFilename ? { filename: String(args.schemaFilename) } : {}), - } + enabled: true, + ...(args.schemaOutput ? { output: String(args.schemaOutput) } : {}), + ...(args.schemaFilename ? { filename: String(args.schemaFilename) } : {}), + } : undefined; const hasSourceFlags = Boolean( diff --git a/graphql/codegen/src/cli/shared.ts b/graphql/codegen/src/cli/shared.ts index dd41ab4352..e288d19a3d 100644 --- a/graphql/codegen/src/cli/shared.ts +++ b/graphql/codegen/src/cli/shared.ts @@ -9,7 +9,7 @@ import { inflektTree } from 'inflekt/transform-keys'; import type { Question } from 'inquirerer'; import type { GenerateResult } from '../core/generate'; -import { mergeConfig, type GraphQLSDKConfigTarget } from '../types/config'; +import { type GraphQLSDKConfigTarget,mergeConfig } from '../types/config'; export const splitCommas = ( input: string | undefined, diff --git a/graphql/codegen/src/client/error.ts b/graphql/codegen/src/client/error.ts index 390501f11d..f670adbc0f 100644 --- a/graphql/codegen/src/client/error.ts +++ b/graphql/codegen/src/client/error.ts @@ -2,19 +2,19 @@ * Re-export error handling utilities from @constructive-io/graphql-query. */ export { - ConstructiveError, classify, + ConstructiveError, createError, + type ErrorClass, + type ErrorContext, format, + type GraphQLError, isConstructiveError, isPublicCode, isPublicError, isRetryable, parse, + type ParsedError, parseGraphQLError, toError, - type ErrorClass, - type ErrorContext, - type GraphQLError, - type ParsedError, } from '@constructive-io/graphql-query'; diff --git a/graphql/codegen/src/client/execute.ts b/graphql/codegen/src/client/execute.ts index b83bd66bc9..2948c00749 100644 --- a/graphql/codegen/src/client/execute.ts +++ b/graphql/codegen/src/client/execute.ts @@ -2,10 +2,10 @@ * Re-export GraphQL execution utilities from @constructive-io/graphql-query. */ export { - execute, createGraphQLClient, + execute, type ExecuteOptions, - type GraphQLResponse, - type GraphQLClientOptions, type GraphQLClient, + type GraphQLClientOptions, + type GraphQLResponse, } from '@constructive-io/graphql-query'; diff --git a/graphql/codegen/src/client/typed-document.ts b/graphql/codegen/src/client/typed-document.ts index 47e3197bc5..f7caf1e798 100644 --- a/graphql/codegen/src/client/typed-document.ts +++ b/graphql/codegen/src/client/typed-document.ts @@ -2,6 +2,6 @@ * Re-export TypedDocumentString from @constructive-io/graphql-query. */ export { - TypedDocumentString, type DocumentTypeDecoration, + TypedDocumentString, } from '@constructive-io/graphql-query'; diff --git a/graphql/codegen/src/core/ast.ts b/graphql/codegen/src/core/ast.ts index 0a00bcde2b..6424391a08 100644 --- a/graphql/codegen/src/core/ast.ts +++ b/graphql/codegen/src/core/ast.ts @@ -6,12 +6,12 @@ * now live in graphql-query. */ export { + createOne, + deleteOne, getAll, getCount, getMany, getOne, - createOne, - patchOne, - deleteOne, getSelections, + patchOne, } from '@constructive-io/graphql-query'; diff --git a/graphql/codegen/src/core/codegen/cli/command-map-generator.ts b/graphql/codegen/src/core/codegen/cli/command-map-generator.ts index 5077f5c963..cd27095e41 100644 --- a/graphql/codegen/src/core/codegen/cli/command-map-generator.ts +++ b/graphql/codegen/src/core/codegen/cli/command-map-generator.ts @@ -1,9 +1,9 @@ import * as t from '@babel/types'; import { toKebabCase } from 'inflekt'; +import type { Operation,Table } from '../../../types/schema'; import { generateCode } from '../babel-ast'; import { getGeneratedFileHeader, getTableNames } from '../utils'; -import type { Table, Operation } from '../../../types/schema'; import type { GeneratedFile } from './executor-generator'; function createImportDeclaration( diff --git a/graphql/codegen/src/core/codegen/cli/custom-command-generator.ts b/graphql/codegen/src/core/codegen/cli/custom-command-generator.ts index 3081b08919..6d72d79899 100644 --- a/graphql/codegen/src/core/codegen/cli/custom-command-generator.ts +++ b/graphql/codegen/src/core/codegen/cli/custom-command-generator.ts @@ -1,11 +1,11 @@ import * as t from '@babel/types'; import { toKebabCase } from 'inflekt'; +import type { Operation, TypeRef } from '../../../types/schema'; import { generateCode } from '../babel-ast'; import { getGeneratedFileHeader, ucFirst } from '../utils'; -import type { Operation, TypeRef } from '../../../types/schema'; -import type { GeneratedFile } from './executor-generator'; import { buildQuestionsArray } from './arg-mapper'; +import type { GeneratedFile } from './executor-generator'; function createImportDeclaration( moduleSpecifier: string, @@ -365,14 +365,14 @@ export function generateCustomCommand(op: Operation, options?: CustomCommandOpti const argsExpr = op.args.length > 0 ? t.tsAsExpression( - t.tsAsExpression( - hasInputObjectArg - ? t.identifier('parsedAnswers') - : t.identifier('answers'), - t.tsUnknownKeyword(), - ), - t.tsTypeReference(t.identifier(variablesTypeName)), - ) + t.tsAsExpression( + hasInputObjectArg + ? t.identifier('parsedAnswers') + : t.identifier('answers'), + t.tsUnknownKeyword(), + ), + t.tsTypeReference(t.identifier(variablesTypeName)), + ) : t.objectExpression([]); // For OBJECT return types, generate runtime select from --select flag diff --git a/graphql/codegen/src/core/codegen/cli/docs-generator.ts b/graphql/codegen/src/core/codegen/cli/docs-generator.ts index 18b3ce4ef7..fdbf6c0c6c 100644 --- a/graphql/codegen/src/core/codegen/cli/docs-generator.ts +++ b/graphql/codegen/src/core/codegen/cli/docs-generator.ts @@ -1,33 +1,30 @@ import { toKebabCase } from 'inflekt'; -import type { Table, Operation, TypeRegistry } from '../../../types/schema'; +import type { Operation, Table, TypeRegistry } from '../../../types/schema'; +import type { GeneratedDocFile } from '../docs-utils'; import { - flattenArgs, - flattenedArgsToFlags, - cleanTypeName, - fieldPlaceholder, - getEditableFields, - getSearchFields, - categorizeSpecialFields, - buildSpecialFieldsMarkdown, buildSearchExamples, buildSearchExamplesMarkdown, - getReadmeHeader, - getReadmeFooter, - gqlTypeToJsonSchemaType, buildSkillFile, buildSkillReference, + buildSpecialFieldsMarkdown, + categorizeSpecialFields, + cleanTypeName, + flattenArgs, + flattenedArgsToFlags, + getEditableFields, + getReadmeFooter, + getReadmeHeader, } from '../docs-utils'; -import type { GeneratedDocFile } from '../docs-utils'; import { + getPrimaryKeyInfo, getScalarFields, getTableNames, - getPrimaryKeyInfo, } from '../utils'; import { getFieldsWithDefaults } from './table-command-generator'; -export { resolveDocsConfig } from '../docs-utils'; export type { GeneratedDocFile } from '../docs-utils'; +export { resolveDocsConfig } from '../docs-utils'; export function generateReadme( tables: Table[], diff --git a/graphql/codegen/src/core/codegen/cli/index.ts b/graphql/codegen/src/core/codegen/cli/index.ts index fdd48989e2..9bf444c25d 100644 --- a/graphql/codegen/src/core/codegen/cli/index.ts +++ b/graphql/codegen/src/core/codegen/cli/index.ts @@ -3,10 +3,10 @@ import type { Operation, Table, TypeRegistry } from '../../../types/schema'; import { generateCommandMap, generateMultiTargetCommandMap } from './command-map-generator'; import { generateConfigCommand } from './config-command-generator'; import { generateCustomCommand } from './custom-command-generator'; -import { generateExecutorFile, generateMultiTargetExecutorFile } from './executor-generator'; import type { GeneratedFile, MultiTargetExecutorInput } from './executor-generator'; -import { generateHelpersFile } from './helpers-generator'; +import { generateExecutorFile, generateMultiTargetExecutorFile } from './executor-generator'; import type { HelpersGeneratorInput } from './helpers-generator'; +import { generateHelpersFile } from './helpers-generator'; import { generateAuthCommand, generateAuthCommandWithName, @@ -14,7 +14,7 @@ import { generateMultiTargetContextCommand, } from './infra-generator'; import { generateTableCommand } from './table-command-generator'; -import { generateUtilsFile, generateEntryPointFile, generateEmbedderFile } from './utils-generator'; +import { generateEmbedderFile,generateEntryPointFile, generateUtilsFile } from './utils-generator'; export interface GenerateCliOptions { tables: Table[]; @@ -274,29 +274,29 @@ export function generateMultiTargetCli( }; } -export { generateExecutorFile, generateMultiTargetExecutorFile } from './executor-generator'; -export { generateTableCommand } from './table-command-generator'; -export { generateCustomCommand } from './custom-command-generator'; +export type { GeneratedDocFile } from '../docs-utils'; +export { resolveDocsConfig } from '../docs-utils'; export { generateCommandMap, generateMultiTargetCommandMap } from './command-map-generator'; export { generateConfigCommand } from './config-command-generator'; -export { generateHelpersFile } from './helpers-generator'; -export type { HelpersGeneratorInput } from './helpers-generator'; -export { - generateContextCommand, - generateAuthCommand, - generateMultiTargetContextCommand, - generateAuthCommandWithName, -} from './infra-generator'; +export { generateCustomCommand } from './custom-command-generator'; +export type { MultiTargetDocsInput } from './docs-generator'; export { - generateReadme, generateAgentsDocs, - generateSkills, - generateMultiTargetReadme, generateMultiTargetAgentsDocs, + generateMultiTargetReadme, generateMultiTargetSkills, + generateReadme, + generateSkills, } from './docs-generator'; -export type { MultiTargetDocsInput } from './docs-generator'; -export { resolveDocsConfig } from '../docs-utils'; -export type { GeneratedDocFile } from '../docs-utils'; -export { generateUtilsFile, generateEntryPointFile, generateEmbedderFile } from './utils-generator'; export type { GeneratedFile, MultiTargetExecutorInput } from './executor-generator'; +export { generateExecutorFile, generateMultiTargetExecutorFile } from './executor-generator'; +export type { HelpersGeneratorInput } from './helpers-generator'; +export { generateHelpersFile } from './helpers-generator'; +export { + generateAuthCommand, + generateAuthCommandWithName, + generateContextCommand, + generateMultiTargetContextCommand, +} from './infra-generator'; +export { generateTableCommand } from './table-command-generator'; +export { generateEmbedderFile,generateEntryPointFile, generateUtilsFile } from './utils-generator'; diff --git a/graphql/codegen/src/core/codegen/cli/table-command-generator.ts b/graphql/codegen/src/core/codegen/cli/table-command-generator.ts index 7471776f0a..b82aafb08a 100644 --- a/graphql/codegen/src/core/codegen/cli/table-command-generator.ts +++ b/graphql/codegen/src/core/codegen/cli/table-command-generator.ts @@ -1,30 +1,30 @@ import * as t from '@babel/types'; import { toKebabCase } from 'inflekt'; +import type { Table, TypeRegistry } from '../../../types/schema'; import { generateCode } from '../babel-ast'; +import type { SpecialFieldGroup } from '../docs-utils'; +import { categorizeSpecialFields } from '../docs-utils'; import { + getCreateInputTypeName, + getDeleteInputTypeName, + getExtraInputKeys, + getFilterTypeName, getGeneratedFileHeader, + getOrderByTypeName, + getPatchTypeName, getPrimaryKeyInfo, getScalarFields, getSelectableScalarFields, getTableNames, + getUpdateInputTypeName, getWritableFieldNames, - resolveInnerInputType, - ucFirst, lcFirst, + resolveInnerInputType, toPascalCase, - getCreateInputTypeName, - getPatchTypeName, - getFilterTypeName, - getOrderByTypeName, - getExtraInputKeys, - getUpdateInputTypeName, - getDeleteInputTypeName, + ucFirst, } from '../utils'; -import type { Table, TypeRegistry } from '../../../types/schema'; import type { GeneratedFile } from './executor-generator'; -import { categorizeSpecialFields } from '../docs-utils'; -import type { SpecialFieldGroup } from '../docs-utils'; function createImportDeclaration( moduleSpecifier: string, @@ -84,28 +84,28 @@ function getTsTypeForField(field: { type: { gqlType: string; isArray: boolean } // (e.g., _uuid[] in PG -> string in the ORM input), so we do NOT wrap // in tsArrayType here. switch (gqlType) { - case 'Boolean': - return t.tsBooleanKeyword(); - case 'Int': - case 'BigInt': - case 'Float': - case 'BigFloat': - return t.tsNumberKeyword(); - case 'JSON': - case 'GeoJSON': - return t.tsTypeReference( - t.identifier('Record'), - t.tsTypeParameterInstantiation([ - t.tsStringKeyword(), - t.tsUnknownKeyword(), - ]), - ); - case 'Interval': - // IntervalInput is a complex type, skip assertion - return null; - case 'UUID': - default: - return t.tsStringKeyword(); + case 'Boolean': + return t.tsBooleanKeyword(); + case 'Int': + case 'BigInt': + case 'Float': + case 'BigFloat': + return t.tsNumberKeyword(); + case 'JSON': + case 'GeoJSON': + return t.tsTypeReference( + t.identifier('Record'), + t.tsTypeParameterInstantiation([ + t.tsStringKeyword(), + t.tsUnknownKeyword(), + ]), + ); + case 'Interval': + // IntervalInput is a complex type, skip assertion + return null; + case 'UUID': + default: + return t.tsStringKeyword(); } } @@ -116,13 +116,13 @@ function getTsTypeForField(field: { type: { gqlType: string; isArray: boolean } function getQuestionTypeForField(field: { type: { gqlType: string } }): string { const gqlType = field.type.gqlType.replace(/!/g, ''); switch (gqlType) { - case 'Boolean': - return 'boolean'; - case 'JSON': - case 'GeoJSON': - return 'json'; - default: - return 'text'; + case 'Boolean': + return 'boolean'; + case 'JSON': + case 'GeoJSON': + return 'json'; + default: + return 'text'; } } @@ -133,25 +133,25 @@ function buildFieldSchemaObject(table: Table): t.ObjectExpression { const gqlType = f.type.gqlType.replace(/!/g, ''); let schemaType: string; switch (gqlType) { - case 'Boolean': - schemaType = 'boolean'; - break; - case 'Int': - case 'BigInt': - schemaType = 'int'; - break; - case 'Float': - schemaType = 'float'; - break; - case 'JSON': - case 'GeoJSON': - schemaType = 'json'; - break; - case 'UUID': - schemaType = 'uuid'; - break; - default: - schemaType = 'string'; + case 'Boolean': + schemaType = 'boolean'; + break; + case 'Int': + case 'BigInt': + schemaType = 'int'; + break; + case 'Float': + schemaType = 'float'; + break; + case 'JSON': + case 'GeoJSON': + schemaType = 'json'; + break; + case 'UUID': + schemaType = 'uuid'; + break; + default: + schemaType = 'string'; } return t.objectProperty( t.identifier(f.name), @@ -1180,10 +1180,10 @@ function buildMutationHandler( const selectObj = operation === 'delete' ? t.objectExpression( - pkFields.map((pkField) => - t.objectProperty(t.identifier(pkField.name), t.booleanLiteral(true)), - ), - ) + pkFields.map((pkField) => + t.objectProperty(t.identifier(pkField.name), t.booleanLiteral(true)), + ), + ) : buildSelectObject(table, typeRegistry); let ormArgs: t.ObjectExpression; @@ -1377,10 +1377,10 @@ function buildBulkMutationHandler( // Map CLI op name to ORM method name const ormMethod = (() => { switch (operation) { - case 'bulk-create': return 'bulkCreate'; - case 'bulk-upsert': return 'bulkUpsert'; - case 'bulk-update': return 'bulkUpdate'; - case 'bulk-delete': return 'bulkDelete'; + case 'bulk-create': return 'bulkCreate'; + case 'bulk-upsert': return 'bulkUpsert'; + case 'bulk-update': return 'bulkUpdate'; + case 'bulk-delete': return 'bulkDelete'; } })(); diff --git a/graphql/codegen/src/core/codegen/custom-mutations.ts b/graphql/codegen/src/core/codegen/custom-mutations.ts index af5dd5c8de..defea80546 100644 --- a/graphql/codegen/src/core/codegen/custom-mutations.ts +++ b/graphql/codegen/src/core/codegen/custom-mutations.ts @@ -164,12 +164,12 @@ function generateCustomMutationHookInternal( if (hasSelect) { statements.push( - createImportDeclaration( - '../../orm/select-types', - ['InferSelectResult', 'HookStrictSelect', 'StrictSelect'], - true, - ), - ); + createImportDeclaration( + '../../orm/select-types', + ['InferSelectResult', 'HookStrictSelect', 'StrictSelect'], + true, + ), + ); } // Re-exports @@ -230,12 +230,12 @@ function generateCustomMutationHookInternal( const mutationKeyExpr = useCentralizedKeys ? callExpr( - t.memberExpression( - t.identifier('customMutationKeys'), - t.identifier(operation.name), - ), - [], - ) + t.memberExpression( + t.identifier('customMutationKeys'), + t.identifier(operation.name), + ), + [], + ) : undefined; // Cast to ORM's StrictSelect (not HookStrictSelect) since the ORM @@ -340,12 +340,12 @@ function generateCustomMutationHookInternal( const mutationKeyExpr = useCentralizedKeys ? callExpr( - t.memberExpression( - t.identifier('customMutationKeys'), - t.identifier(operation.name), - ), - [], - ) + t.memberExpression( + t.identifier('customMutationKeys'), + t.identifier(operation.name), + ), + [], + ) : undefined; let mutationFnExpr: t.Expression; diff --git a/graphql/codegen/src/core/codegen/custom-queries.ts b/graphql/codegen/src/core/codegen/custom-queries.ts index 3b7203c9be..b3330dd450 100644 --- a/graphql/codegen/src/core/codegen/custom-queries.ts +++ b/graphql/codegen/src/core/codegen/custom-queries.ts @@ -45,9 +45,7 @@ import { typeRef, typeRefToTsTypeAST, useQueryOptionsImplType, - useQueryOptionsType, voidStatement, - wrapInferSelectResultType, } from './hooks-ast'; import { getSelectTypeName } from './select-helpers'; import { @@ -167,12 +165,12 @@ export function generateCustomQueryHook( if (hasSelect) { statements.push( - createImportDeclaration( - '../../orm/select-types', - ['InferSelectResult', 'HookStrictSelect'], - true, - ), - ); + createImportDeclaration( + '../../orm/select-types', + ['InferSelectResult', 'HookStrictSelect'], + true, + ), + ); } // Re-exports @@ -367,14 +365,14 @@ export function generateCustomQueryHook( 'variables', hasRequiredArgs ? t.memberExpression( - t.identifier('params'), - t.identifier('variables'), - ) + t.identifier('params'), + t.identifier('variables'), + ) : t.logicalExpression( - '??', - t.memberExpression(t.identifier('params'), t.identifier('variables')), - t.objectExpression([]), - ), + '??', + t.memberExpression(t.identifier('params'), t.identifier('variables')), + t.objectExpression([]), + ), ), ); } @@ -423,11 +421,11 @@ export function generateCustomQueryHook( ]); const queryFnArgs = hasArgs ? [ - hasRequiredArgs - ? t.tsNonNullExpression(t.identifier('variables')) - : t.identifier('variables'), - selectArgExpr, - ] + hasRequiredArgs + ? t.tsNonNullExpression(t.identifier('variables')) + : t.identifier('variables'), + selectArgExpr, + ] : [selectArgExpr]; const queryFnExpr = t.arrowFunctionExpression( [], @@ -441,22 +439,22 @@ export function generateCustomQueryHook( const extraProps: (t.ObjectProperty | t.SpreadElement)[] = []; const enabledExpr = hasRequiredArgs ? t.logicalExpression( - '&&', - t.unaryExpression( - '!', - t.unaryExpression('!', t.identifier('variables')), - ), - t.binaryExpression( - '!==', - t.optionalMemberExpression( - t.identifier('params'), - t.identifier('enabled'), - false, - true, - ), - t.booleanLiteral(false), + '&&', + t.unaryExpression( + '!', + t.unaryExpression('!', t.identifier('variables')), + ), + t.binaryExpression( + '!==', + t.optionalMemberExpression( + t.identifier('params'), + t.identifier('enabled'), + false, + true, ), - ) + t.booleanLiteral(false), + ), + ) : undefined; extraProps.push(spreadObj(t.identifier('queryOptions'))); @@ -530,21 +528,21 @@ export function generateCustomQueryHook( 'variables', hasRequiredArgs ? t.optionalMemberExpression( + t.identifier('params'), + t.identifier('variables'), + false, + true, + ) + : t.logicalExpression( + '??', + t.optionalMemberExpression( t.identifier('params'), t.identifier('variables'), false, true, - ) - : t.logicalExpression( - '??', - t.optionalMemberExpression( - t.identifier('params'), - t.identifier('variables'), - false, - true, - ), - t.objectExpression([]), ), + t.objectExpression([]), + ), ), ); const destructPattern = t.objectPattern([ @@ -584,10 +582,10 @@ export function generateCustomQueryHook( const queryFnArgs = hasArgs ? [ - hasRequiredArgs - ? t.tsNonNullExpression(t.identifier('variables')) - : t.identifier('variables'), - ] + hasRequiredArgs + ? t.tsNonNullExpression(t.identifier('variables')) + : t.identifier('variables'), + ] : []; const queryFnExpr = t.arrowFunctionExpression( [], @@ -600,22 +598,22 @@ export function generateCustomQueryHook( const enabledExpr = hasRequiredArgs ? t.logicalExpression( - '&&', - t.unaryExpression( - '!', - t.unaryExpression('!', t.identifier('variables')), - ), - t.binaryExpression( - '!==', - t.optionalMemberExpression( - t.identifier('params'), - t.identifier('enabled'), - false, - true, - ), - t.booleanLiteral(false), + '&&', + t.unaryExpression( + '!', + t.unaryExpression('!', t.identifier('variables')), + ), + t.binaryExpression( + '!==', + t.optionalMemberExpression( + t.identifier('params'), + t.identifier('enabled'), + false, + true, ), - ) + t.booleanLiteral(false), + ), + ) : undefined; body.push( @@ -711,10 +709,10 @@ export function generateCustomQueryHook( hasRequiredArgs ? t.memberExpression(t.identifier('params'), t.identifier('variables')) : t.logicalExpression( - '??', - t.memberExpression(t.identifier('params'), t.identifier('variables')), - t.objectExpression([]), - ), + '??', + t.memberExpression(t.identifier('params'), t.identifier('variables')), + t.objectExpression([]), + ), ), ); } @@ -727,11 +725,11 @@ export function generateCustomQueryHook( ]); const fCallArgs = hasArgs ? [ - hasRequiredArgs - ? t.tsNonNullExpression(t.identifier('variables')) - : t.identifier('variables'), - selectArgExpr, - ] + hasRequiredArgs + ? t.tsNonNullExpression(t.identifier('variables')) + : t.identifier('variables'), + selectArgExpr, + ] : [selectArgExpr]; fBody.push( t.returnStatement( @@ -771,21 +769,21 @@ export function generateCustomQueryHook( 'variables', hasRequiredArgs ? t.optionalMemberExpression( + t.identifier('params'), + t.identifier('variables'), + false, + true, + ) + : t.logicalExpression( + '??', + t.optionalMemberExpression( t.identifier('params'), t.identifier('variables'), false, true, - ) - : t.logicalExpression( - '??', - t.optionalMemberExpression( - t.identifier('params'), - t.identifier('variables'), - false, - true, - ), - t.objectExpression([]), ), + t.objectExpression([]), + ), ), ); const fCallArgs = hasRequiredArgs @@ -913,14 +911,14 @@ export function generateCustomQueryHook( 'variables', hasRequiredArgs ? t.memberExpression( - t.identifier('params'), - t.identifier('variables'), - ) + t.identifier('params'), + t.identifier('variables'), + ) : t.logicalExpression( - '??', - t.memberExpression(t.identifier('params'), t.identifier('variables')), - t.objectExpression([]), - ), + '??', + t.memberExpression(t.identifier('params'), t.identifier('variables')), + t.objectExpression([]), + ), ), ); } @@ -933,11 +931,11 @@ export function generateCustomQueryHook( ]); const pCallArgs = hasArgs ? [ - hasRequiredArgs - ? t.tsNonNullExpression(t.identifier('variables')) - : t.identifier('variables'), - selectArgExpr, - ] + hasRequiredArgs + ? t.tsNonNullExpression(t.identifier('variables')) + : t.identifier('variables'), + selectArgExpr, + ] : [selectArgExpr]; const prefetchQueryCall = callExpr( t.memberExpression( @@ -1005,21 +1003,21 @@ export function generateCustomQueryHook( 'variables', hasRequiredArgs ? t.optionalMemberExpression( + t.identifier('params'), + t.identifier('variables'), + false, + true, + ) + : t.logicalExpression( + '??', + t.optionalMemberExpression( t.identifier('params'), t.identifier('variables'), false, true, - ) - : t.logicalExpression( - '??', - t.optionalMemberExpression( - t.identifier('params'), - t.identifier('variables'), - false, - true, - ), - t.objectExpression([]), ), + t.objectExpression([]), + ), ), ); const pCallArgs = hasRequiredArgs diff --git a/graphql/codegen/src/core/codegen/docs-utils.ts b/graphql/codegen/src/core/codegen/docs-utils.ts index 12181ecf5b..e9106969c1 100644 --- a/graphql/codegen/src/core/codegen/docs-utils.ts +++ b/graphql/codegen/src/core/codegen/docs-utils.ts @@ -1,6 +1,6 @@ import type { DocsConfig } from '../../types/config'; import type { Argument, Field, Operation, Table, TypeRef, TypeRegistry } from '../../types/schema'; -import { getScalarFields, getPrimaryKeyInfo, getWritableFieldNames } from './utils'; +import { getPrimaryKeyInfo, getScalarFields, getWritableFieldNames } from './utils'; export interface GeneratedDocFile { fileName: string; @@ -634,14 +634,14 @@ export function argPlaceholder(arg: Argument, registry?: TypeRegistry): string { export function gqlTypeToJsonSchemaType(gqlType: string): string { switch (gqlType) { - case 'Int': - return 'integer'; - case 'Float': - return 'number'; - case 'Boolean': - return 'boolean'; - default: - return 'string'; + case 'Int': + return 'integer'; + case 'Float': + return 'number'; + case 'Boolean': + return 'boolean'; + default: + return 'string'; } } diff --git a/graphql/codegen/src/core/codegen/hooks-docs-generator.ts b/graphql/codegen/src/core/codegen/hooks-docs-generator.ts index b99fff6d97..ac2015852c 100644 --- a/graphql/codegen/src/core/codegen/hooks-docs-generator.ts +++ b/graphql/codegen/src/core/codegen/hooks-docs-generator.ts @@ -1,35 +1,32 @@ import { toKebabCase } from 'inflekt'; import type { Operation, Table, TypeRegistry } from '../../types/schema'; +import type { GeneratedDocFile } from './docs-utils'; import { + argPlaceholder, buildSkillFile, buildSkillReference, - formatArgType, fieldPlaceholder, - pkPlaceholder, - argPlaceholder, - getReadmeHeader, + formatArgType, getReadmeFooter, - gqlTypeToJsonSchemaType, + getReadmeHeader, + pkPlaceholder, } from './docs-utils'; -import type { GeneratedDocFile } from './docs-utils'; import { - getTableNames, - getScalarFields, - getPrimaryKeyInfo, + getBulkCreateMutationHookName, + getBulkDeleteMutationHookName, + getBulkUpdateMutationHookName, + getBulkUpsertMutationHookName, + getCreateMutationHookName, + getDeleteMutationHookName, getListQueryHookName, + getPrimaryKeyInfo, + getScalarFields, getSingleQueryHookName, - getCreateMutationHookName, + getTableNames, getUpdateMutationHookName, - getDeleteMutationHookName, - getBulkCreateMutationHookName, - getBulkUpsertMutationHookName, - getBulkUpdateMutationHookName, - getBulkDeleteMutationHookName, hasValidPrimaryKey, ucFirst, - lcFirst, - fieldTypeToTs, } from './utils'; function getCustomHookName(op: Operation): string { @@ -311,15 +308,15 @@ export function generateHooksSkills( `${getListQueryHookName(table)}({ selection: { fields: { ${selectFields} } } })`, ...(hasValidPrimaryKey(table) ? [ - `${getSingleQueryHookName(table)}({ ${pk.name}: ${pkPlaceholder(pk)}, selection: { fields: { ${selectFields} } } })`, - ] + `${getSingleQueryHookName(table)}({ ${pk.name}: ${pkPlaceholder(pk)}, selection: { fields: { ${selectFields} } } })`, + ] : []), `${getCreateMutationHookName(table)}({ selection: { fields: { ${pk.name}: true } } })`, ...(hasValidPrimaryKey(table) ? [ - `${getUpdateMutationHookName(table)}({ selection: { fields: { ${pk.name}: true } } })`, - `${getDeleteMutationHookName(table)}({})`, - ] + `${getUpdateMutationHookName(table)}({ selection: { fields: { ${pk.name}: true } } })`, + `${getDeleteMutationHookName(table)}({})`, + ] : []), ...(table.query?.bulkInsert ? [`${getBulkCreateMutationHookName(table)}() — bulk create with data array`] : []), ...(table.query?.bulkUpsert ? [`${getBulkUpsertMutationHookName(table)}() — bulk upsert with onConflict`] : []), @@ -379,14 +376,14 @@ export function generateHooksSkills( code: op.kind === 'mutation' ? [ - `const { mutate, isLoading } = ${hookName}();`, - ...(callArgs - ? [`mutate(${callArgs});`] - : ['mutate();']), - ] + `const { mutate, isLoading } = ${hookName}();`, + ...(callArgs + ? [`mutate(${callArgs});`] + : ['mutate();']), + ] : [ - `const { data, isLoading } = ${hookName}(${callArgs});`, - ], + `const { data, isLoading } = ${hookName}(${callArgs});`, + ], }, ], }), diff --git a/graphql/codegen/src/core/codegen/index.ts b/graphql/codegen/src/core/codegen/index.ts index eafc83dd1e..8e8cf67550 100644 --- a/graphql/codegen/src/core/codegen/index.ts +++ b/graphql/codegen/src/core/codegen/index.ts @@ -48,11 +48,11 @@ import { generateMutationKeysFile } from './mutation-keys'; import { generateAllMutationHooks } from './mutations'; import { generateAllQueryHooks } from './queries'; import { generateQueryKeysFile } from './query-keys'; +import { generateSelectionFile } from './selection'; import { generateAllSubscriptionHooks, generateConnectionStateHook, } from './subscriptions'; -import { generateSelectionFile } from './selection'; import { getTableNames } from './utils'; // ============================================================================ @@ -239,9 +239,9 @@ export function generate(options: GenerateOptions): GenerateResult { content: customQueryHooks.length > 0 ? generateCustomQueriesBarrel( - tables, - customQueryHooks.map((h) => h.operationName), - ) + tables, + customQueryHooks.map((h) => h.operationName), + ) : generateQueriesBarrel(tables), }); @@ -292,9 +292,9 @@ export function generate(options: GenerateOptions): GenerateResult { content: customMutationHooks.length > 0 ? generateCustomMutationsBarrel( - tables, - customMutationHooks.map((h) => h.operationName), - ) + tables, + customMutationHooks.map((h) => h.operationName), + ) : generateMutationsBarrel(tables), }); } diff --git a/graphql/codegen/src/core/codegen/mutations.ts b/graphql/codegen/src/core/codegen/mutations.ts index ff9e06d973..9bd18aa631 100644 --- a/graphql/codegen/src/core/codegen/mutations.ts +++ b/graphql/codegen/src/core/codegen/mutations.ts @@ -32,8 +32,8 @@ import { shorthandProp, spreadObj, sRef, - typeRef, typeLiteralWithProps, + typeRef, useMutationOptionsType, useMutationResultType, voidStatement, @@ -252,12 +252,12 @@ export function generateCreateMutationHook( const mutationKeyExpr = useCentralizedKeys ? callExpr( - t.memberExpression( - t.identifier(mutationKeysName), - t.identifier('create'), - ), - [], - ) + t.memberExpression( + t.identifier(mutationKeysName), + t.identifier('create'), + ), + [], + ) : undefined; // mutationFn: (data: CreateInput['singular']) => getClient().singular.create({ data, select: ... }).unwrap() @@ -280,13 +280,13 @@ export function generateCreateMutationHook( // onSuccess: invalidate lists const listKeyExpr = useCentralizedKeys ? callExpr( - t.memberExpression(t.identifier(keysName), t.identifier('lists')), - [], - ) + t.memberExpression(t.identifier(keysName), t.identifier('lists')), + [], + ) : t.arrayExpression([ - t.stringLiteral(typeName.toLowerCase()), - t.stringLiteral('list'), - ]); + t.stringLiteral(typeName.toLowerCase()), + t.stringLiteral('list'), + ]); const onSuccessFn = t.arrowFunctionExpression( [], @@ -432,8 +432,8 @@ export function generateUpdateMutationHook( t.identifier(ek.name), t.tsTypeAnnotation( ek.tsType === 'number' ? t.tsNumberKeyword() : - ek.tsType === 'boolean' ? t.tsBooleanKeyword() : - t.tsStringKeyword() + ek.tsType === 'boolean' ? t.tsBooleanKeyword() : + t.tsStringKeyword() ), ), ), @@ -533,31 +533,31 @@ export function generateUpdateMutationHook( // onSuccess: invalidate detail and lists const detailKeyExpr = useCentralizedKeys ? callExpr( - t.memberExpression(t.identifier(keysName), t.identifier('detail')), - [ - t.memberExpression( - t.identifier('variables'), - t.identifier(pkField.name), - ), - ], - ) - : t.arrayExpression([ - t.stringLiteral(typeName.toLowerCase()), - t.stringLiteral('detail'), + t.memberExpression(t.identifier(keysName), t.identifier('detail')), + [ t.memberExpression( t.identifier('variables'), t.identifier(pkField.name), ), - ]); + ], + ) + : t.arrayExpression([ + t.stringLiteral(typeName.toLowerCase()), + t.stringLiteral('detail'), + t.memberExpression( + t.identifier('variables'), + t.identifier(pkField.name), + ), + ]); const listKeyExpr = useCentralizedKeys ? callExpr( - t.memberExpression(t.identifier(keysName), t.identifier('lists')), - [], - ) + t.memberExpression(t.identifier(keysName), t.identifier('lists')), + [], + ) : t.arrayExpression([ - t.stringLiteral(typeName.toLowerCase()), - t.stringLiteral('list'), - ]); + t.stringLiteral(typeName.toLowerCase()), + t.stringLiteral('list'), + ]); const onSuccessParam = t.identifier('_'); const variablesParam = t.identifier('variables'); @@ -711,8 +711,8 @@ export function generateDeleteMutationHook( t.identifier(ek.name), t.tsTypeAnnotation( ek.tsType === 'number' ? t.tsNumberKeyword() : - ek.tsType === 'boolean' ? t.tsBooleanKeyword() : - t.tsStringKeyword() + ek.tsType === 'boolean' ? t.tsBooleanKeyword() : + t.tsStringKeyword() ), ), ), @@ -806,31 +806,31 @@ export function generateDeleteMutationHook( // onSuccess: remove detail, invalidate lists const detailKeyExpr = useCentralizedKeys ? callExpr( - t.memberExpression(t.identifier(keysName), t.identifier('detail')), - [ - t.memberExpression( - t.identifier('variables'), - t.identifier(pkField.name), - ), - ], - ) - : t.arrayExpression([ - t.stringLiteral(typeName.toLowerCase()), - t.stringLiteral('detail'), + t.memberExpression(t.identifier(keysName), t.identifier('detail')), + [ t.memberExpression( t.identifier('variables'), t.identifier(pkField.name), ), - ]); + ], + ) + : t.arrayExpression([ + t.stringLiteral(typeName.toLowerCase()), + t.stringLiteral('detail'), + t.memberExpression( + t.identifier('variables'), + t.identifier(pkField.name), + ), + ]); const listKeyExpr = useCentralizedKeys ? callExpr( - t.memberExpression(t.identifier(keysName), t.identifier('lists')), - [], - ) + t.memberExpression(t.identifier(keysName), t.identifier('lists')), + [], + ) : t.arrayExpression([ - t.stringLiteral(typeName.toLowerCase()), - t.stringLiteral('list'), - ]); + t.stringLiteral(typeName.toLowerCase()), + t.stringLiteral('list'), + ]); const onSuccessFn = t.arrowFunctionExpression( [t.identifier('_'), t.identifier('variables')], @@ -901,10 +901,10 @@ function generateBulkMutationHook( const mutationFieldName = (() => { switch (op) { - case 'bulkCreate': return table.query?.bulkInsert; - case 'bulkUpsert': return table.query?.bulkUpsert; - case 'bulkUpdate': return table.query?.bulkUpdate; - case 'bulkDelete': return table.query?.bulkDelete; + case 'bulkCreate': return table.query?.bulkInsert; + case 'bulkUpsert': return table.query?.bulkUpsert; + case 'bulkUpdate': return table.query?.bulkUpdate; + case 'bulkDelete': return table.query?.bulkDelete; } })(); if (!mutationFieldName) return null; @@ -912,18 +912,18 @@ function generateBulkMutationHook( const { typeName, singularName } = getTableNames(table); const hookName = (() => { switch (op) { - case 'bulkCreate': return getBulkCreateMutationHookName(table); - case 'bulkUpsert': return getBulkUpsertMutationHookName(table); - case 'bulkUpdate': return getBulkUpdateMutationHookName(table); - case 'bulkDelete': return getBulkDeleteMutationHookName(table); + case 'bulkCreate': return getBulkCreateMutationHookName(table); + case 'bulkUpsert': return getBulkUpsertMutationHookName(table); + case 'bulkUpdate': return getBulkUpdateMutationHookName(table); + case 'bulkDelete': return getBulkDeleteMutationHookName(table); } })(); const fileName = (() => { switch (op) { - case 'bulkCreate': return getBulkCreateMutationFileName(table); - case 'bulkUpsert': return getBulkUpsertMutationFileName(table); - case 'bulkUpdate': return getBulkUpdateMutationFileName(table); - case 'bulkDelete': return getBulkDeleteMutationFileName(table); + case 'bulkCreate': return getBulkCreateMutationFileName(table); + case 'bulkUpsert': return getBulkUpsertMutationFileName(table); + case 'bulkUpdate': return getBulkUpdateMutationFileName(table); + case 'bulkDelete': return getBulkDeleteMutationFileName(table); } })(); const keysName = `${lcFirst(typeName)}Keys`; @@ -994,64 +994,64 @@ function generateBulkMutationHook( // Build the variable type for the mutationFn parameter const varType = (() => { switch (op) { - case 'bulkCreate': - return t.tsTypeLiteral([ - t.tsPropertySignature( - t.identifier('data'), - t.tsTypeAnnotation( - t.tsArrayType( - t.tsIndexedAccessType( - typeRef(createInputTypeName), - t.tsLiteralType(t.stringLiteral(singularName)), - ), - ), - ), - ), - (() => { - const p = t.tsPropertySignature( - t.identifier('onConflict'), - t.tsTypeAnnotation(t.tsUnknownKeyword()), - ); - p.optional = true; - return p; - })(), - ]); - case 'bulkUpsert': - return t.tsTypeLiteral([ - t.tsPropertySignature( - t.identifier('data'), - t.tsTypeAnnotation( - t.tsArrayType( - t.tsIndexedAccessType( - typeRef(createInputTypeName), - t.tsLiteralType(t.stringLiteral(singularName)), - ), + case 'bulkCreate': + return t.tsTypeLiteral([ + t.tsPropertySignature( + t.identifier('data'), + t.tsTypeAnnotation( + t.tsArrayType( + t.tsIndexedAccessType( + typeRef(createInputTypeName), + t.tsLiteralType(t.stringLiteral(singularName)), ), ), ), - t.tsPropertySignature( + ), + (() => { + const p = t.tsPropertySignature( t.identifier('onConflict'), t.tsTypeAnnotation(t.tsUnknownKeyword()), + ); + p.optional = true; + return p; + })(), + ]); + case 'bulkUpsert': + return t.tsTypeLiteral([ + t.tsPropertySignature( + t.identifier('data'), + t.tsTypeAnnotation( + t.tsArrayType( + t.tsIndexedAccessType( + typeRef(createInputTypeName), + t.tsLiteralType(t.stringLiteral(singularName)), + ), + ), ), - ]); - case 'bulkUpdate': - return t.tsTypeLiteral([ - t.tsPropertySignature( - t.identifier('where'), - t.tsTypeAnnotation(typeRef(filterTypeName)), - ), - t.tsPropertySignature( - t.identifier('data'), - t.tsTypeAnnotation(typeRef(patchTypeName)), - ), - ]); - case 'bulkDelete': - return t.tsTypeLiteral([ - t.tsPropertySignature( - t.identifier('where'), - t.tsTypeAnnotation(typeRef(filterTypeName)), - ), - ]); + ), + t.tsPropertySignature( + t.identifier('onConflict'), + t.tsTypeAnnotation(t.tsUnknownKeyword()), + ), + ]); + case 'bulkUpdate': + return t.tsTypeLiteral([ + t.tsPropertySignature( + t.identifier('where'), + t.tsTypeAnnotation(typeRef(filterTypeName)), + ), + t.tsPropertySignature( + t.identifier('data'), + t.tsTypeAnnotation(typeRef(patchTypeName)), + ), + ]); + case 'bulkDelete': + return t.tsTypeLiteral([ + t.tsPropertySignature( + t.identifier('where'), + t.tsTypeAnnotation(typeRef(filterTypeName)), + ), + ]); } })(); @@ -1105,41 +1105,41 @@ function generateBulkMutationHook( const mutationKeyExpr = useCentralizedKeys ? callExpr( - t.memberExpression( - t.identifier(mutationKeysName), - t.identifier(op), - ), - [], - ) + t.memberExpression( + t.identifier(mutationKeysName), + t.identifier(op), + ), + [], + ) : undefined; // Build the ORM method call depending on the operation const ormMethodName = op; const mutationFnArgs = (() => { switch (op) { - case 'bulkCreate': - return t.objectExpression([ - shorthandProp('data'), - objectProp('onConflict', t.memberExpression(t.identifier('vars'), t.identifier('onConflict'))), - objectProp('select', t.memberExpression(t.identifier('args'), t.identifier('select'))), - ]); - case 'bulkUpsert': - return t.objectExpression([ - shorthandProp('data'), - objectProp('onConflict', t.memberExpression(t.identifier('vars'), t.identifier('onConflict'))), - objectProp('select', t.memberExpression(t.identifier('args'), t.identifier('select'))), - ]); - case 'bulkUpdate': - return t.objectExpression([ - objectProp('where', t.memberExpression(t.identifier('vars'), t.identifier('where'))), - shorthandProp('data'), - objectProp('select', t.memberExpression(t.identifier('args'), t.identifier('select'))), - ]); - case 'bulkDelete': - return t.objectExpression([ - objectProp('where', t.memberExpression(t.identifier('vars'), t.identifier('where'))), - objectProp('select', t.memberExpression(t.identifier('args'), t.identifier('select'))), - ]); + case 'bulkCreate': + return t.objectExpression([ + shorthandProp('data'), + objectProp('onConflict', t.memberExpression(t.identifier('vars'), t.identifier('onConflict'))), + objectProp('select', t.memberExpression(t.identifier('args'), t.identifier('select'))), + ]); + case 'bulkUpsert': + return t.objectExpression([ + shorthandProp('data'), + objectProp('onConflict', t.memberExpression(t.identifier('vars'), t.identifier('onConflict'))), + objectProp('select', t.memberExpression(t.identifier('args'), t.identifier('select'))), + ]); + case 'bulkUpdate': + return t.objectExpression([ + objectProp('where', t.memberExpression(t.identifier('vars'), t.identifier('where'))), + shorthandProp('data'), + objectProp('select', t.memberExpression(t.identifier('args'), t.identifier('select'))), + ]); + case 'bulkDelete': + return t.objectExpression([ + objectProp('where', t.memberExpression(t.identifier('vars'), t.identifier('where'))), + objectProp('select', t.memberExpression(t.identifier('args'), t.identifier('select'))), + ]); } })(); @@ -1152,13 +1152,13 @@ function generateBulkMutationHook( // onSuccess: invalidate lists const listKeyExpr = useCentralizedKeys ? callExpr( - t.memberExpression(t.identifier(keysName), t.identifier('lists')), - [], - ) + t.memberExpression(t.identifier(keysName), t.identifier('lists')), + [], + ) : t.arrayExpression([ - t.stringLiteral(typeName.toLowerCase()), - t.stringLiteral('list'), - ]); + t.stringLiteral(typeName.toLowerCase()), + t.stringLiteral('list'), + ]); const onSuccessFn = t.arrowFunctionExpression( [], diff --git a/graphql/codegen/src/core/codegen/orm/custom-ops-generator.ts b/graphql/codegen/src/core/codegen/orm/custom-ops-generator.ts index 29225ea72d..bbd46228e7 100644 --- a/graphql/codegen/src/core/codegen/orm/custom-ops-generator.ts +++ b/graphql/codegen/src/core/codegen/orm/custom-ops-generator.ts @@ -8,7 +8,7 @@ import * as t from '@babel/types'; import type { Argument, Operation } from '../../../types/schema'; import { addJSDocComment, generateCode } from '../babel-ast'; -import { NON_SELECT_TYPES, getSelectTypeName } from '../select-helpers'; +import { getSelectTypeName,NON_SELECT_TYPES } from '../select-helpers'; import { getTypeBaseName, isTypeRequired, @@ -317,11 +317,11 @@ function buildOperationMethod( const selectExpr = selectTypeName ? t.memberExpression(t.identifier('options'), t.identifier('select')) : t.optionalMemberExpression( - t.identifier('options'), - t.identifier('select'), - false, - true, - ); + t.identifier('options'), + t.identifier('select'), + false, + true, + ); const entityTypeExpr = selectTypeName && payloadTypeName ? t.stringLiteral(payloadTypeName) diff --git a/graphql/codegen/src/core/codegen/orm/docs-generator.ts b/graphql/codegen/src/core/codegen/orm/docs-generator.ts index 3ca6e9e399..7356be2125 100644 --- a/graphql/codegen/src/core/codegen/orm/docs-generator.ts +++ b/graphql/codegen/src/core/codegen/orm/docs-generator.ts @@ -1,27 +1,25 @@ import { toKebabCase } from 'inflekt'; import type { Operation, Table, TypeRegistry } from '../../../types/schema'; +import type { GeneratedDocFile } from '../docs-utils'; import { + argPlaceholder, buildSkillFile, buildSkillReference, - formatArgType, + buildSpecialFieldsMarkdown, + categorizeSpecialFields, fieldPlaceholder, - pkPlaceholder, - argPlaceholder, + formatArgType, getEditableFields, - categorizeSpecialFields, - buildSpecialFieldsMarkdown, - getReadmeHeader, getReadmeFooter, - gqlTypeToJsonSchemaType, + getReadmeHeader, + pkPlaceholder, } from '../docs-utils'; -import type { GeneratedDocFile } from '../docs-utils'; import { + getPrimaryKeyInfo, getScalarFields, getTableNames, - getPrimaryKeyInfo, lcFirst, - fieldTypeToTs, } from '../utils'; export function generateOrmReadme( diff --git a/graphql/codegen/src/core/codegen/orm/input-types-generator.ts b/graphql/codegen/src/core/codegen/orm/input-types-generator.ts index ea12921102..4e8734b662 100644 --- a/graphql/codegen/src/core/codegen/orm/input-types-generator.ts +++ b/graphql/codegen/src/core/codegen/orm/input-types-generator.ts @@ -139,18 +139,18 @@ function parseTypeString(typeStr: string): t.TSType { // Handle primitive types switch (typeStr) { - case 'string': - return t.tsStringKeyword(); - case 'number': - return t.tsNumberKeyword(); - case 'boolean': - return t.tsBooleanKeyword(); - case 'null': - return t.tsNullKeyword(); - case 'unknown': - return t.tsUnknownKeyword(); - default: - return t.tsTypeReference(t.identifier(typeStr)); + case 'string': + return t.tsStringKeyword(); + case 'number': + return t.tsNumberKeyword(); + case 'boolean': + return t.tsBooleanKeyword(); + case 'null': + return t.tsNullKeyword(); + case 'unknown': + return t.tsUnknownKeyword(); + default: + return t.tsTypeReference(t.identifier(typeStr)); } } diff --git a/graphql/codegen/src/core/codegen/orm/model-generator.ts b/graphql/codegen/src/core/codegen/orm/model-generator.ts index 944d7a58f8..7fe20b2608 100644 --- a/graphql/codegen/src/core/codegen/orm/model-generator.ts +++ b/graphql/codegen/src/core/codegen/orm/model-generator.ts @@ -5,11 +5,10 @@ * Each method uses function overloads for IDE autocompletion of select objects. */ import * as t from '@babel/types'; - import { singularize } from 'inflekt'; import type { Table, TypeRegistry } from '../../../types/schema'; -import { asConst, generateCode } from '../babel-ast'; +import { generateCode } from '../babel-ast'; import { getCreateInputTypeName, getCreateMutationName, @@ -26,7 +25,6 @@ import { lcFirst, ucFirst, } from '../utils'; -import type { ExtraInputKey } from '../utils'; export interface GeneratedModelFile { fileName: string; @@ -370,64 +368,64 @@ export function generateModelFile( ), t.objectProperty( t.identifier('orderBy'), - t.tsAsExpression( - t.optionalMemberExpression( - t.identifier('args'), - t.identifier('orderBy'), - false, - true, - ), - t.tsUnionType([ - t.tsArrayType(t.tsStringKeyword()), - t.tsUndefinedKeyword(), - ]), - ), - ), - t.objectProperty( - t.identifier('first'), + t.tsAsExpression( t.optionalMemberExpression( t.identifier('args'), - t.identifier('first'), + t.identifier('orderBy'), false, true, ), + t.tsUnionType([ + t.tsArrayType(t.tsStringKeyword()), + t.tsUndefinedKeyword(), + ]), ), - t.objectProperty( + ), + t.objectProperty( + t.identifier('first'), + t.optionalMemberExpression( + t.identifier('args'), + t.identifier('first'), + false, + true, + ), + ), + t.objectProperty( + t.identifier('last'), + t.optionalMemberExpression( + t.identifier('args'), t.identifier('last'), - t.optionalMemberExpression( - t.identifier('args'), - t.identifier('last'), - false, - true, - ), + false, + true, ), - t.objectProperty( + ), + t.objectProperty( + t.identifier('after'), + t.optionalMemberExpression( + t.identifier('args'), t.identifier('after'), - t.optionalMemberExpression( - t.identifier('args'), - t.identifier('after'), - false, - true, - ), + false, + true, ), - t.objectProperty( + ), + t.objectProperty( + t.identifier('before'), + t.optionalMemberExpression( + t.identifier('args'), t.identifier('before'), - t.optionalMemberExpression( - t.identifier('args'), - t.identifier('before'), - false, - true, - ), + false, + true, ), - t.objectProperty( + ), + t.objectProperty( + t.identifier('offset'), + t.optionalMemberExpression( + t.identifier('args'), t.identifier('offset'), - t.optionalMemberExpression( - t.identifier('args'), - t.identifier('offset'), - false, - true, - ), + false, + true, ), + ), ]; const bodyArgs = [ t.stringLiteral(typeName), @@ -932,16 +930,16 @@ export function generateModelFile( // Build extraKeys object for partitioned table fields const extraKeysArg = updateExtraKeys.length > 0 ? t.objectExpression( - updateExtraKeys.map((ek) => - t.objectProperty( + updateExtraKeys.map((ek) => + t.objectProperty( + t.identifier(ek.name), + t.memberExpression( + t.memberExpression(t.identifier('args'), t.identifier('where')), t.identifier(ek.name), - t.memberExpression( - t.memberExpression(t.identifier('args'), t.identifier('where')), - t.identifier(ek.name), - ), ), ), - ) + ), + ) : t.identifier('undefined'); const bodyArgs = [ t.stringLiteral(typeName), diff --git a/graphql/codegen/src/core/codegen/queries.ts b/graphql/codegen/src/core/codegen/queries.ts index b4d8460c67..21d562e940 100644 --- a/graphql/codegen/src/core/codegen/queries.ts +++ b/graphql/codegen/src/core/codegen/queries.ts @@ -17,8 +17,6 @@ import { buildListSelectionArgsCall, buildSelectionArgsCall, callExpr, - connectionResultType, - constDecl, createFunctionParam, createImportDeclaration, createSAndTDataTypeParams, @@ -31,7 +29,6 @@ import { exportDeclareFunction, exportFunction, generateHookFileCode, - inferSelectResultType, listQueryResultType, listSelectionConfigType, objectProp, @@ -43,8 +40,6 @@ import { spreadObj, sRef, typeRef, - typeLiteralWithProps, - useQueryOptionsType, useQueryOptionsImplType, voidStatement, withFieldsListSelectionType, @@ -452,9 +447,9 @@ export function generateListQueryHook( const p1ParamType = hasRelationships && useCentralizedKeys ? t.tsIntersectionType([ - p1BaseParamType, - scopeTypeLiteral(scopeTypeName), - ]) + p1BaseParamType, + scopeTypeLiteral(scopeTypeName), + ]) : p1BaseParamType; const p1Decl = exportAsyncDeclareFunction( prefetchFnName, @@ -479,21 +474,7 @@ export function generateListQueryHook( const pImplParamType = hasRelationships && useCentralizedKeys ? t.tsIntersectionType([ - t.tsTypeLiteral([ - t.tsPropertySignature( - t.identifier('selection'), - t.tsTypeAnnotation( - listSelectionConfigType( - typeRef(selectTypeName), - filterTypeName, - orderByTypeName, - ), - ), - ), - ]), - scopeTypeLiteral(scopeTypeName), - ]) - : t.tsTypeLiteral([ + t.tsTypeLiteral([ t.tsPropertySignature( t.identifier('selection'), t.tsTypeAnnotation( @@ -504,7 +485,21 @@ export function generateListQueryHook( ), ), ), - ]); + ]), + scopeTypeLiteral(scopeTypeName), + ]) + : t.tsTypeLiteral([ + t.tsPropertySignature( + t.identifier('selection'), + t.tsTypeAnnotation( + listSelectionConfigType( + typeRef(selectTypeName), + filterTypeName, + orderByTypeName, + ), + ), + ), + ]); const pBody: t.Statement[] = []; pBody.push( buildListSelectionArgsCall( @@ -517,14 +512,14 @@ export function generateListQueryHook( const queryKeyExpr = hasRelationships && useCentralizedKeys ? buildListQueryKey( - t.identifier('args'), - t.optionalMemberExpression( - t.identifier('params'), - t.identifier('scope'), - false, - true, - ), - ) + t.identifier('args'), + t.optionalMemberExpression( + t.identifier('params'), + t.identifier('scope'), + false, + true, + ), + ) : buildListQueryKey(t.identifier('args')); const prefetchCall = callExpr( @@ -915,9 +910,9 @@ export function generateSingleQueryHook( const p1ParamType = hasRelationships && useCentralizedKeys ? t.tsIntersectionType([ - p1BaseParamType, - scopeTypeLiteral(scopeTypeName), - ]) + p1BaseParamType, + scopeTypeLiteral(scopeTypeName), + ]) : p1BaseParamType; const p1Decl = exportAsyncDeclareFunction( prefetchFnName, @@ -942,19 +937,7 @@ export function generateSingleQueryHook( const pImplParamType = hasRelationships && useCentralizedKeys ? t.tsIntersectionType([ - t.tsTypeLiteral([ - t.tsPropertySignature( - t.identifier(pkFieldName), - t.tsTypeAnnotation(pkTsType), - ), - t.tsPropertySignature( - t.identifier('selection'), - t.tsTypeAnnotation(selectionConfigType(typeRef(selectTypeName))), - ), - ]), - scopeTypeLiteral(scopeTypeName), - ]) - : t.tsTypeLiteral([ + t.tsTypeLiteral([ t.tsPropertySignature( t.identifier(pkFieldName), t.tsTypeAnnotation(pkTsType), @@ -963,30 +946,42 @@ export function generateSingleQueryHook( t.identifier('selection'), t.tsTypeAnnotation(selectionConfigType(typeRef(selectTypeName))), ), - ]); + ]), + scopeTypeLiteral(scopeTypeName), + ]) + : t.tsTypeLiteral([ + t.tsPropertySignature( + t.identifier(pkFieldName), + t.tsTypeAnnotation(pkTsType), + ), + t.tsPropertySignature( + t.identifier('selection'), + t.tsTypeAnnotation(selectionConfigType(typeRef(selectTypeName))), + ), + ]); const pBody: t.Statement[] = []; pBody.push(buildSelectionArgsCall(selectTypeName)); const queryKeyExpr = hasRelationships && useCentralizedKeys ? buildDetailQueryKey( - t.memberExpression( - t.identifier('params'), - t.identifier(pkFieldName), - ), - t.optionalMemberExpression( - t.identifier('params'), - t.identifier('scope'), - false, - true, - ), - ) + t.memberExpression( + t.identifier('params'), + t.identifier(pkFieldName), + ), + t.optionalMemberExpression( + t.identifier('params'), + t.identifier('scope'), + false, + true, + ), + ) : buildDetailQueryKey( - t.memberExpression( - t.identifier('params'), - t.identifier(pkFieldName), - ), - ); + t.memberExpression( + t.identifier('params'), + t.identifier(pkFieldName), + ), + ); const prefetchCall = callExpr( t.memberExpression( diff --git a/graphql/codegen/src/core/codegen/subscriptions.ts b/graphql/codegen/src/core/codegen/subscriptions.ts index cf00ae7246..6c2c593a6d 100644 --- a/graphql/codegen/src/core/codegen/subscriptions.ts +++ b/graphql/codegen/src/core/codegen/subscriptions.ts @@ -16,7 +16,6 @@ import { createFunctionParam, createImportDeclaration, createTypeReExport, - exportDeclareFunction, exportFunction, generateHookFileCode, objectProp, diff --git a/graphql/codegen/src/core/codegen/target-docs-generator.ts b/graphql/codegen/src/core/codegen/target-docs-generator.ts index ceacf5ef38..2048f76396 100644 --- a/graphql/codegen/src/core/codegen/target-docs-generator.ts +++ b/graphql/codegen/src/core/codegen/target-docs-generator.ts @@ -1,6 +1,6 @@ import type { GraphQLSDKConfigTarget } from '../../types/config'; -import { getReadmeHeader, getReadmeFooter } from './docs-utils'; import type { GeneratedDocFile } from './docs-utils'; +import { getReadmeFooter,getReadmeHeader } from './docs-utils'; export interface TargetReadmeOptions { hasOrm: boolean; diff --git a/graphql/codegen/src/core/codegen/type-resolver.ts b/graphql/codegen/src/core/codegen/type-resolver.ts index 489fb1d59f..ba5fb3e734 100644 --- a/graphql/codegen/src/core/codegen/type-resolver.ts +++ b/graphql/codegen/src/core/codegen/type-resolver.ts @@ -115,42 +115,42 @@ export function typeRefToTsType( tracker?: TypeTracker, ): string { switch (typeRef.kind) { - case 'NON_NULL': - // Non-null wrapper - unwrap and return the inner type - if (typeRef.ofType) { - return typeRefToTsType(typeRef.ofType, tracker); - } - return 'unknown'; + case 'NON_NULL': + // Non-null wrapper - unwrap and return the inner type + if (typeRef.ofType) { + return typeRefToTsType(typeRef.ofType, tracker); + } + return 'unknown'; - case 'LIST': - // List wrapper - wrap inner type in array - if (typeRef.ofType) { - const innerType = typeRefToTsType(typeRef.ofType, tracker); - return `${innerType}[]`; - } - return 'unknown[]'; + case 'LIST': + // List wrapper - wrap inner type in array + if (typeRef.ofType) { + const innerType = typeRefToTsType(typeRef.ofType, tracker); + return `${innerType}[]`; + } + return 'unknown[]'; - case 'SCALAR': - // Scalar type - map to TS type - return scalarToTsType(typeRef.name ?? 'unknown'); + case 'SCALAR': + // Scalar type - map to TS type + return scalarToTsType(typeRef.name ?? 'unknown'); - case 'ENUM': { - // Enum type - use the GraphQL enum name and track it - const typeName = typeRef.name ?? 'string'; - tracker?.track(typeName); - return typeName; - } + case 'ENUM': { + // Enum type - use the GraphQL enum name and track it + const typeName = typeRef.name ?? 'string'; + tracker?.track(typeName); + return typeName; + } - case 'OBJECT': - case 'INPUT_OBJECT': { - // Object types - use the GraphQL type name and track it - const typeName = typeRef.name ?? 'unknown'; - tracker?.track(typeName); - return typeName; - } + case 'OBJECT': + case 'INPUT_OBJECT': { + // Object types - use the GraphQL type name and track it + const typeName = typeRef.name ?? 'unknown'; + tracker?.track(typeName); + return typeName; + } - default: - return 'unknown'; + default: + return 'unknown'; } } diff --git a/graphql/codegen/src/core/codegen/types.ts b/graphql/codegen/src/core/codegen/types.ts index dbf39e5108..b148e63ada 100644 --- a/graphql/codegen/src/core/codegen/types.ts +++ b/graphql/codegen/src/core/codegen/types.ts @@ -4,8 +4,8 @@ import * as t from '@babel/types'; import type { Table } from '../../types/schema'; -import { SCALAR_NAMES } from './scalars'; import { generateCode } from './babel-ast'; +import { SCALAR_NAMES } from './scalars'; import { fieldTypeToTs, getGeneratedFileHeader, diff --git a/graphql/codegen/src/core/codegen/utils.ts b/graphql/codegen/src/core/codegen/utils.ts index 48259f1ec8..aae8f48c36 100644 --- a/graphql/codegen/src/core/codegen/utils.ts +++ b/graphql/codegen/src/core/codegen/utils.ts @@ -19,7 +19,7 @@ import type { import { scalarToFilterType, scalarToTsType } from './scalars'; // Re-export string manipulation helpers from inflekt (single source of truth) -export { lcFirst, toCamelCase, toPascalCase, toConstantCase, ucFirst }; +export { lcFirst, toCamelCase, toConstantCase, toPascalCase, ucFirst }; // ============================================================================ // Naming conventions for generated code diff --git a/graphql/codegen/src/core/custom-ast.ts b/graphql/codegen/src/core/custom-ast.ts index f43eacf8a5..6d37f384ed 100644 --- a/graphql/codegen/src/core/custom-ast.ts +++ b/graphql/codegen/src/core/custom-ast.ts @@ -5,12 +5,12 @@ * (geometry, interval, etc.). The canonical implementations now live in graphql-query. */ export { + geometryAst, + geometryCollectionAst, + geometryPointAst, getCustomAst, getCustomAstForCleanField, - requiresSubfieldSelection, - geometryPointAst, - geometryCollectionAst, - geometryAst, intervalAst, isIntervalType, + requiresSubfieldSelection, } from '@constructive-io/graphql-query'; diff --git a/graphql/codegen/src/core/generate.ts b/graphql/codegen/src/core/generate.ts index 7e2ace908e..2a589dcd87 100644 --- a/graphql/codegen/src/core/generate.ts +++ b/graphql/codegen/src/core/generate.ts @@ -7,9 +7,8 @@ import * as fs from 'node:fs'; import path from 'node:path'; -import { buildClientSchema, printSchema } from 'graphql'; - import { PgpmPackage } from '@pgpmjs/core'; +import { buildClientSchema, printSchema } from 'graphql'; import { pgCache } from 'pg-cache'; import { createEphemeralDb, type EphemeralDbResult } from 'pgsql-client'; import { deployPgpm } from 'pgsql-seed'; @@ -18,36 +17,36 @@ import type { CliConfig, DbConfig, GraphQLSDKConfigTarget, PgpmConfig, SchemaCon import { getConfigOptions } from '../types/config'; import type { Operation, Table, TypeRegistry } from '../types/schema'; import { generate as generateReactQueryFiles } from './codegen'; -import { generateRootBarrel, generateMultiTargetBarrel } from './codegen/barrel'; -import { generateCli as generateCliFiles, generateMultiTargetCli } from './codegen/cli'; +import { generateMultiTargetBarrel,generateRootBarrel } from './codegen/barrel'; import type { MultiTargetCliTarget } from './codegen/cli'; +import { generateCli as generateCliFiles, generateMultiTargetCli } from './codegen/cli'; +import type { MultiTargetDocsInput } from './codegen/cli/docs-generator'; import { - generateReadme as generateCliReadme, generateAgentsDocs as generateCliAgentsDocs, - generateSkills as generateCliSkills, - generateMultiTargetReadme, generateMultiTargetAgentsDocs, + generateMultiTargetReadme, generateMultiTargetSkills, + generateReadme as generateCliReadme, + generateSkills as generateCliSkills, } from './codegen/cli/docs-generator'; -import type { MultiTargetDocsInput } from './codegen/cli/docs-generator'; import { resolveDocsConfig } from './codegen/docs-utils'; import { - generateHooksReadme, generateHooksAgentsDocs, + generateHooksReadme, generateHooksSkills, } from './codegen/hooks-docs-generator'; import { generateOrm as generateOrmFiles } from './codegen/orm'; import { - generateOrmReadme, generateOrmAgentsDocs, + generateOrmReadme, generateOrmSkills, } from './codegen/orm/docs-generator'; import { generateSharedTypes } from './codegen/shared'; +import type { RootRootReadmeTarget } from './codegen/target-docs-generator'; import { - generateTargetReadme, generateRootRootReadme, + generateTargetReadme, } from './codegen/target-docs-generator'; -import type { RootRootReadmeTarget } from './codegen/target-docs-generator'; import { createSchemaSource, validateSourceOptions } from './introspect'; import { writeGeneratedFiles } from './output'; import { runCodegenPipeline, validateTablesFound } from './pipeline'; @@ -694,170 +693,170 @@ export async function generateMulti( const sharedSources = await prepareSharedPgpmSources(configs, cliOverrides); try { - for (const name of names) { - const baseConfig: GraphQLSDKConfigTarget = { - ...configs[name], - ...(cliOverrides ?? {}), - }; - const targetConfig = applySharedPgpmDb(baseConfig, sharedSources); - const result = await generate( - { - ...targetConfig, - verbose, - dryRun, - schema: schemaEnabled - ? { ...schema, filename: schema?.filename ?? `${name}.graphql` } - : targetConfig.schema, - }, - useUnifiedCli ? { skipCli: true, targetName: name } : { targetName: name }, - ); - results.push({ name, result }); - if (!result.success) { - hasError = true; - } else { - const resolvedConfig = getConfigOptions(targetConfig); - const gens: string[] = []; - if (resolvedConfig.reactQuery) gens.push('React Query'); - if (resolvedConfig.orm || resolvedConfig.reactQuery || !!resolvedConfig.cli) gens.push('ORM'); - if (resolvedConfig.cli) gens.push('CLI'); - targetInfos.push({ - name, - output: resolvedConfig.output, - endpoint: resolvedConfig.endpoint || undefined, - generators: gens, - }); - - if (useUnifiedCli && result.pipelineData) { - const isAuthTarget = name === 'auth'; - cliTargets.push({ + for (const name of names) { + const baseConfig: GraphQLSDKConfigTarget = { + ...configs[name], + ...(cliOverrides ?? {}), + }; + const targetConfig = applySharedPgpmDb(baseConfig, sharedSources); + const result = await generate( + { + ...targetConfig, + verbose, + dryRun, + schema: schemaEnabled + ? { ...schema, filename: schema?.filename ?? `${name}.graphql` } + : targetConfig.schema, + }, + useUnifiedCli ? { skipCli: true, targetName: name } : { targetName: name }, + ); + results.push({ name, result }); + if (!result.success) { + hasError = true; + } else { + const resolvedConfig = getConfigOptions(targetConfig); + const gens: string[] = []; + if (resolvedConfig.reactQuery) gens.push('React Query'); + if (resolvedConfig.orm || resolvedConfig.reactQuery || !!resolvedConfig.cli) gens.push('ORM'); + if (resolvedConfig.cli) gens.push('CLI'); + targetInfos.push({ name, - endpoint: resolvedConfig.endpoint || '', - ormImportPath: `../${resolvedConfig.output.replace(/^\.\//, '')}/orm`, - tables: result.pipelineData.tables, - customOperations: result.pipelineData.customOperations, - isAuthTarget, - typeRegistry: result.pipelineData.customOperations.typeRegistry, + output: resolvedConfig.output, + endpoint: resolvedConfig.endpoint || undefined, + generators: gens, }); - } - } - } - if (useUnifiedCli && cliTargets.length > 0 && !dryRun) { - const cliConfig = typeof unifiedCli === 'object' ? unifiedCli : {}; - const toolName = cliConfig.toolName ?? 'app'; - const firstTargetConfig = configs[names[0]]; - const { files } = generateMultiTargetCli({ - toolName, - builtinNames: cliConfig.builtinNames, - targets: cliTargets, - entryPoint: cliConfig.entryPoint, - }); - - const cliFilesToWrite = files.map((file) => ({ - path: path.posix.join('cli', file.fileName), - content: file.content, - })); - - const firstTargetDocsConfig = names.length > 0 && configs[names[0]]?.docs; - const docsConfig = resolveDocsConfig(firstTargetDocsConfig); - const { resolveBuiltinNames } = await import('./codegen/cli'); - const builtinNames = resolveBuiltinNames( - cliTargets.map((t) => t.name), - cliConfig.builtinNames, - ); - - // Merge all target type registries into a combined registry for docs generation - const combinedRegistry = new Map(); - for (const t of cliTargets) { - if (t.typeRegistry) { - for (const [key, value] of t.typeRegistry) { - combinedRegistry.set(key, value); + if (useUnifiedCli && result.pipelineData) { + const isAuthTarget = name === 'auth'; + cliTargets.push({ + name, + endpoint: resolvedConfig.endpoint || '', + ormImportPath: `../${resolvedConfig.output.replace(/^\.\//, '')}/orm`, + tables: result.pipelineData.tables, + customOperations: result.pipelineData.customOperations, + isAuthTarget, + typeRegistry: result.pipelineData.customOperations.typeRegistry, + }); } } } - const docsInput: MultiTargetDocsInput = { - toolName, - builtinNames, - registry: combinedRegistry.size > 0 ? combinedRegistry : undefined, - targets: cliTargets.map((t) => ({ - name: t.name, - endpoint: t.endpoint, - tables: t.tables, - customOperations: [ - ...(t.customOperations?.queries ?? []), - ...(t.customOperations?.mutations ?? []), - ], - isAuthTarget: t.isAuthTarget, - })), - }; - - if (docsConfig.readme) { - const readme = generateMultiTargetReadme(docsInput); - cliFilesToWrite.push({ path: path.posix.join('cli', readme.fileName), content: readme.content }); - } - if (docsConfig.agents) { - const agents = generateMultiTargetAgentsDocs(docsInput); - cliFilesToWrite.push({ path: path.posix.join('cli', agents.fileName), content: agents.content }); - } - const { writeGeneratedFiles: writeFiles } = await import('./output'); - await writeFiles(cliFilesToWrite, '.', [], { pruneStaleFiles: false }); + if (useUnifiedCli && cliTargets.length > 0 && !dryRun) { + const cliConfig = typeof unifiedCli === 'object' ? unifiedCli : {}; + const toolName = cliConfig.toolName ?? 'app'; + const firstTargetConfig = configs[names[0]]; + const { files } = generateMultiTargetCli({ + toolName, + builtinNames: cliConfig.builtinNames, + targets: cliTargets, + entryPoint: cliConfig.entryPoint, + }); - if (docsConfig.skills) { - const cliSkillsToWrite = generateMultiTargetSkills(docsInput).map((skill) => ({ - path: skill.fileName, - content: skill.content, + const cliFilesToWrite = files.map((file) => ({ + path: path.posix.join('cli', file.fileName), + content: file.content, })); - const firstTargetResolved = getConfigOptions({ - ...(firstTargetConfig ?? {}), - ...(cliOverrides ?? {}), - }); - const skillsOutputDir = resolveSkillsOutputDir( - firstTargetResolved, - firstTargetResolved.output, + const firstTargetDocsConfig = names.length > 0 && configs[names[0]]?.docs; + const docsConfig = resolveDocsConfig(firstTargetDocsConfig); + const { resolveBuiltinNames } = await import('./codegen/cli'); + const builtinNames = resolveBuiltinNames( + cliTargets.map((t) => t.name), + cliConfig.builtinNames, ); - await writeFiles(cliSkillsToWrite, skillsOutputDir, [], { pruneStaleFiles: false }); - } - } + // Merge all target type registries into a combined registry for docs generation + const combinedRegistry = new Map(); + for (const t of cliTargets) { + if (t.typeRegistry) { + for (const [key, value] of t.typeRegistry) { + combinedRegistry.set(key, value); + } + } + } - // Generate root-root README and barrel if multi-target - if (names.length > 1 && targetInfos.length > 0 && !dryRun) { - const { writeGeneratedFiles: writeFiles } = await import('./output'); + const docsInput: MultiTargetDocsInput = { + toolName, + builtinNames, + registry: combinedRegistry.size > 0 ? combinedRegistry : undefined, + targets: cliTargets.map((t) => ({ + name: t.name, + endpoint: t.endpoint, + tables: t.tables, + customOperations: [ + ...(t.customOperations?.queries ?? []), + ...(t.customOperations?.mutations ?? []), + ], + isAuthTarget: t.isAuthTarget, + })), + }; - const rootReadme = generateRootRootReadme(targetInfos); - await writeFiles( - [{ path: rootReadme.fileName, content: rootReadme.content }], - '.', - [], - { pruneStaleFiles: false }, - ); + if (docsConfig.readme) { + const readme = generateMultiTargetReadme(docsInput); + cliFilesToWrite.push({ path: path.posix.join('cli', readme.fileName), content: readme.content }); + } + if (docsConfig.agents) { + const agents = generateMultiTargetAgentsDocs(docsInput); + cliFilesToWrite.push({ path: path.posix.join('cli', agents.fileName), content: agents.content }); + } + const { writeGeneratedFiles: writeFiles } = await import('./output'); + await writeFiles(cliFilesToWrite, '.', [], { pruneStaleFiles: false }); + + if (docsConfig.skills) { + const cliSkillsToWrite = generateMultiTargetSkills(docsInput).map((skill) => ({ + path: skill.fileName, + content: skill.content, + })); + + const firstTargetResolved = getConfigOptions({ + ...(firstTargetConfig ?? {}), + ...(cliOverrides ?? {}), + }); + const skillsOutputDir = resolveSkillsOutputDir( + firstTargetResolved, + firstTargetResolved.output, + ); + await writeFiles(cliSkillsToWrite, skillsOutputDir, [], { pruneStaleFiles: false }); + + } + } - // Write a root barrel (index.ts) that re-exports each target as a - // namespace so the package has a single entry-point. Derive the - // common output root from the first target's output path. - const successfulNames = results - .filter((r) => r.result.success) - .map((r) => r.name); - if (successfulNames.length > 0) { - const firstOutput = getConfigOptions(configs[successfulNames[0]]).output; - const outputRoot = path.dirname(firstOutput); - const barrelContent = generateMultiTargetBarrel(successfulNames); + // Generate root-root README and barrel if multi-target + if (names.length > 1 && targetInfos.length > 0 && !dryRun) { + const { writeGeneratedFiles: writeFiles } = await import('./output'); + + const rootReadme = generateRootRootReadme(targetInfos); await writeFiles( - [{ path: 'index.ts', content: barrelContent }], - outputRoot, + [{ path: rootReadme.fileName, content: rootReadme.content }], + '.', [], { pruneStaleFiles: false }, ); - // Write manifest so removeStaleTargetDirs knows which dirs are generated - fs.writeFileSync( - path.join(outputRoot, TARGETS_MANIFEST), - JSON.stringify(successfulNames.sort()) + '\n', - ); + // Write a root barrel (index.ts) that re-exports each target as a + // namespace so the package has a single entry-point. Derive the + // common output root from the first target's output path. + const successfulNames = results + .filter((r) => r.result.success) + .map((r) => r.name); + if (successfulNames.length > 0) { + const firstOutput = getConfigOptions(configs[successfulNames[0]]).output; + const outputRoot = path.dirname(firstOutput); + const barrelContent = generateMultiTargetBarrel(successfulNames); + await writeFiles( + [{ path: 'index.ts', content: barrelContent }], + outputRoot, + [], + { pruneStaleFiles: false }, + ); + + // Write manifest so removeStaleTargetDirs knows which dirs are generated + fs.writeFileSync( + path.join(outputRoot, TARGETS_MANIFEST), + JSON.stringify(successfulNames.sort()) + '\n', + ); + } } - } } finally { for (const shared of sharedSources.values()) { diff --git a/graphql/codegen/src/core/introspect/schema-query.ts b/graphql/codegen/src/core/introspect/schema-query.ts index a769983dd3..0a0e94bbd0 100644 --- a/graphql/codegen/src/core/introspect/schema-query.ts +++ b/graphql/codegen/src/core/introspect/schema-query.ts @@ -1,5 +1,5 @@ /** * Re-export schema query from @constructive-io/graphql-query. */ -export { SCHEMA_INTROSPECTION_QUERY } from '@constructive-io/graphql-query'; export type { IntrospectionQueryResponse } from '@constructive-io/graphql-query'; +export { SCHEMA_INTROSPECTION_QUERY } from '@constructive-io/graphql-query'; diff --git a/graphql/codegen/src/core/introspect/source/database.ts b/graphql/codegen/src/core/introspect/source/database.ts index 2435948b66..493f71f31e 100644 --- a/graphql/codegen/src/core/introspect/source/database.ts +++ b/graphql/codegen/src/core/introspect/source/database.ts @@ -6,10 +6,9 @@ * Also returns _meta table metadata correlated to the same schema build * (via buildSchemaArtifacts). */ -import { buildSchema, introspectionFromSchema } from 'graphql'; - -import { buildSchemaArtifacts } from 'graphile-schema'; import type { TableMeta } from 'graphile-schema'; +import { buildSchemaArtifacts } from 'graphile-schema'; +import { buildSchema, introspectionFromSchema } from 'graphql'; import type { IntrospectionQueryResponse } from '../../../types/introspection'; import { diff --git a/graphql/codegen/src/core/introspect/source/index.ts b/graphql/codegen/src/core/introspect/source/index.ts index 8587d0bf19..a8ad25a509 100644 --- a/graphql/codegen/src/core/introspect/source/index.ts +++ b/graphql/codegen/src/core/introspect/source/index.ts @@ -146,49 +146,49 @@ export function createSchemaSource( const mode = detectSourceMode(options); switch (mode) { - case 'schemaFile': - return new FileSchemaSource({ - schemaPath: options.schemaFile!, - }); + case 'schemaFile': + return new FileSchemaSource({ + schemaPath: options.schemaFile!, + }); - case 'endpoint': - return new EndpointSchemaSource({ - endpoint: options.endpoint!, - authorization: options.authorization, - headers: options.headers, - timeout: options.timeout, - }); + case 'endpoint': + return new EndpointSchemaSource({ + endpoint: options.endpoint!, + authorization: options.authorization, + headers: options.headers, + timeout: options.timeout, + }); - case 'database': - // Database mode uses db.config for connection (falls back to env vars) - // and db.schemas or db.apiNames for schema selection - return new DatabaseSchemaSource({ - database: options.db?.config?.database ?? '', - schemas: options.db?.schemas, - apiNames: options.db?.apiNames, - }); + case 'database': + // Database mode uses db.config for connection (falls back to env vars) + // and db.schemas or db.apiNames for schema selection + return new DatabaseSchemaSource({ + database: options.db?.config?.database ?? '', + schemas: options.db?.schemas, + apiNames: options.db?.apiNames, + }); - case 'pgpm-module': - return new PgpmModuleSchemaSource({ - pgpmModulePath: options.db!.pgpm!.modulePath!, - schemas: options.db?.schemas, - apiNames: options.db?.apiNames, - keepDb: options.db?.keepDb, - }); + case 'pgpm-module': + return new PgpmModuleSchemaSource({ + pgpmModulePath: options.db!.pgpm!.modulePath!, + schemas: options.db?.schemas, + apiNames: options.db?.apiNames, + keepDb: options.db?.keepDb, + }); - case 'pgpm-workspace': - return new PgpmModuleSchemaSource({ - pgpmWorkspacePath: options.db!.pgpm!.workspacePath!, - pgpmModuleName: options.db!.pgpm!.moduleName!, - schemas: options.db?.schemas, - apiNames: options.db?.apiNames, - keepDb: options.db?.keepDb, - }); + case 'pgpm-workspace': + return new PgpmModuleSchemaSource({ + pgpmWorkspacePath: options.db!.pgpm!.workspacePath!, + pgpmModuleName: options.db!.pgpm!.moduleName!, + schemas: options.db?.schemas, + apiNames: options.db?.apiNames, + keepDb: options.db?.keepDb, + }); - default: - throw new Error( - 'No source specified. Use one of: endpoint, schemaFile, or db (with optional pgpm for module deployment).', - ); + default: + throw new Error( + 'No source specified. Use one of: endpoint, schemaFile, or db (with optional pgpm for module deployment).', + ); } } diff --git a/graphql/codegen/src/core/introspect/source/pgpm-module.ts b/graphql/codegen/src/core/introspect/source/pgpm-module.ts index 9d25fe782d..9cf5245a15 100644 --- a/graphql/codegen/src/core/introspect/source/pgpm-module.ts +++ b/graphql/codegen/src/core/introspect/source/pgpm-module.ts @@ -8,13 +8,12 @@ * 4. Cleaning up the ephemeral database (unless keepDb is true) */ import { PgpmPackage } from '@pgpmjs/core'; +import { buildSchemaSDL } from 'graphile-schema'; import { buildSchema, introspectionFromSchema } from 'graphql'; import { getPgPool, pgCache } from 'pg-cache'; import { createEphemeralDb, type EphemeralDbResult } from 'pgsql-client'; import { deployPgpm } from 'pgsql-seed'; -import { buildSchemaSDL } from 'graphile-schema'; - import type { IntrospectionQueryResponse } from '../../../types/introspection'; import { resolveApiSchemas, validateRoutingSchemas } from './api-schemas'; import type { SchemaSource, SchemaSourceResult } from './types'; diff --git a/graphql/codegen/src/core/introspect/transform-schema.ts b/graphql/codegen/src/core/introspect/transform-schema.ts index 0050493228..a7680332e5 100644 --- a/graphql/codegen/src/core/introspect/transform-schema.ts +++ b/graphql/codegen/src/core/introspect/transform-schema.ts @@ -3,14 +3,14 @@ */ export { buildTypeRegistry, - transformSchemaToOperations, filterOperations, - getTableOperationNames, - isTableOperation, - getCustomOperations, getBaseTypeName, + getCustomOperations, + getTableOperationNames, isNonNull, - unwrapType, - type TransformSchemaResult, + isTableOperation, type TableOperationNames, + type TransformSchemaResult, + transformSchemaToOperations, + unwrapType, } from '@constructive-io/graphql-query'; diff --git a/graphql/codegen/src/core/types.ts b/graphql/codegen/src/core/types.ts index 99bb4d4922..f401565645 100644 --- a/graphql/codegen/src/core/types.ts +++ b/graphql/codegen/src/core/types.ts @@ -4,29 +4,29 @@ // Re-export everything from the canonical source export { + type ASTFunctionParams, type ASTNode, - type NestedProperties, - type QueryProperty, - type QueryDefinition, - type MutationDefinition, - type MetaFieldType, - type MetaField, + type GraphQLVariables, + type GraphQLVariableValue, + type IQueryBuilder, + isGraphQLVariables, + isGraphQLVariableValue, type MetaConstraint, + type MetaField, + type MetaFieldType, type MetaForeignConstraint, - type MetaTable, type MetaObject, - type GraphQLVariableValue, - type GraphQLVariables, - type QueryFieldSelection, - type QuerySelectionOptions, - type QueryBuilderInstance, - type ASTFunctionParams, + type MetaTable, type MutationASTParams, + type MutationDefinition, + type NestedProperties, + type ObjectArrayItem, + type QueryBuilderInstance, type QueryBuilderOptions, type QueryBuilderResult, - type IQueryBuilder, - type ObjectArrayItem, - isGraphQLVariableValue, - isGraphQLVariables, + type QueryDefinition, + type QueryFieldSelection, + type QueryProperty, + type QuerySelectionOptions, type StrictRecord, } from '@constructive-io/graphql-query'; diff --git a/graphql/codegen/src/core/watch/orchestrator.ts b/graphql/codegen/src/core/watch/orchestrator.ts index 93f1f8a80b..9195e49988 100644 --- a/graphql/codegen/src/core/watch/orchestrator.ts +++ b/graphql/codegen/src/core/watch/orchestrator.ts @@ -217,22 +217,22 @@ export class WatchOrchestrator { let outputDir: string | undefined; switch (this.options.generatorType) { - case 'react-query': - generateFn = this.options.generateReactQuery; - // React Query hooks go to {output}/hooks - outputDir = + case 'react-query': + generateFn = this.options.generateReactQuery; + // React Query hooks go to {output}/hooks + outputDir = this.options.outputDir ?? `${this.options.config.output}/hooks`; - break; - case 'orm': - generateFn = this.options.generateOrm; - // ORM client goes to {output}/orm - outputDir = + break; + case 'orm': + generateFn = this.options.generateOrm; + // ORM client goes to {output}/orm + outputDir = this.options.outputDir ?? `${this.options.config.output}/orm`; - break; - default: - throw new Error( - `Unknown generator type: ${this.options.generatorType}`, - ); + break; + default: + throw new Error( + `Unknown generator type: ${this.options.generatorType}`, + ); } const result = await generateFn({ @@ -291,16 +291,16 @@ export class WatchOrchestrator { private logHeader(): void { let generatorName: string; switch (this.options.generatorType) { - case 'react-query': - generatorName = 'React Query hooks'; - break; - case 'orm': - generatorName = 'ORM client'; - break; - default: - throw new Error( - `Unknown generator type: ${this.options.generatorType}`, - ); + case 'react-query': + generatorName = 'React Query hooks'; + break; + case 'orm': + generatorName = 'ORM client'; + break; + default: + throw new Error( + `Unknown generator type: ${this.options.generatorType}`, + ); } console.log(`\n${'─'.repeat(50)}`); console.log(`graphql-codegen watch mode (${generatorName})`); diff --git a/graphql/codegen/src/core/workspace.ts b/graphql/codegen/src/core/workspace.ts index 27f1df745b..652342c279 100644 --- a/graphql/codegen/src/core/workspace.ts +++ b/graphql/codegen/src/core/workspace.ts @@ -8,7 +8,7 @@ * Inspired by @pgpmjs/env walkUp / resolvePnpmWorkspace patterns. */ import { existsSync, readFileSync } from 'node:fs'; -import { dirname, resolve, parse as parsePath } from 'node:path'; +import { dirname, parse as parsePath,resolve } from 'node:path'; /** * Walk up directories from startDir looking for a file. diff --git a/graphql/codegen/src/generators/field-selector.ts b/graphql/codegen/src/generators/field-selector.ts index a4752e1440..f31b05c68c 100644 --- a/graphql/codegen/src/generators/field-selector.ts +++ b/graphql/codegen/src/generators/field-selector.ts @@ -6,7 +6,7 @@ */ export { convertToSelectionOptions, - isRelationalField, getAvailableRelations, + isRelationalField, validateFieldSelection, } from '@constructive-io/graphql-query'; diff --git a/graphql/codegen/src/generators/mutations.ts b/graphql/codegen/src/generators/mutations.ts index 57fbd69a77..f45635b9f1 100644 --- a/graphql/codegen/src/generators/mutations.ts +++ b/graphql/codegen/src/generators/mutations.ts @@ -6,6 +6,6 @@ */ export { buildPostGraphileCreate, - buildPostGraphileUpdate, buildPostGraphileDelete, + buildPostGraphileUpdate, } from '@constructive-io/graphql-query'; diff --git a/graphql/codegen/src/generators/naming-helpers.ts b/graphql/codegen/src/generators/naming-helpers.ts index 70e72ee623..815c600881 100644 --- a/graphql/codegen/src/generators/naming-helpers.ts +++ b/graphql/codegen/src/generators/naming-helpers.ts @@ -6,13 +6,13 @@ export { normalizeInflectionValue, toCamelCaseSingular, - toCreateMutationName, - toUpdateMutationName, - toDeleteMutationName, toCreateInputTypeName, - toUpdateInputTypeName, + toCreateMutationName, toDeleteInputTypeName, + toDeleteMutationName, toFilterTypeName, - toPatchFieldName, toOrderByEnumValue, + toPatchFieldName, + toUpdateInputTypeName, + toUpdateMutationName, } from '@constructive-io/graphql-query'; diff --git a/graphql/codegen/src/generators/select.ts b/graphql/codegen/src/generators/select.ts index 7b0f06a08b..ae3bf90295 100644 --- a/graphql/codegen/src/generators/select.ts +++ b/graphql/codegen/src/generators/select.ts @@ -6,9 +6,9 @@ * toCamelCasePlural, and toOrderByTypeName now live in graphql-query. */ export { - buildSelect, - buildFindOne, buildCount, + buildFindOne, + buildSelect, cleanTableToMetaObject, createASTQueryBuilder, generateIntrospectionSchema, diff --git a/graphql/codegen/src/index.ts b/graphql/codegen/src/index.ts index 4d54cb5bee..385ee239d8 100644 --- a/graphql/codegen/src/index.ts +++ b/graphql/codegen/src/index.ts @@ -22,8 +22,8 @@ export * from './client'; export { defineConfig } from './types/config'; // Main generate function (orchestrates the entire pipeline) -export type { GenerateOptions, GenerateResult, GenerateMultiOptions, GenerateMultiResult } from './core/generate'; -export { generate, generateMulti, expandApiNamesToMultiTarget, expandSchemaDirToMultiTarget, removeStaleTargetDirs, TARGETS_MANIFEST } from './core/generate'; +export type { GenerateMultiOptions, GenerateMultiResult,GenerateOptions, GenerateResult } from './core/generate'; +export { expandApiNamesToMultiTarget, expandSchemaDirToMultiTarget, generate, generateMulti, removeStaleTargetDirs, TARGETS_MANIFEST } from './core/generate'; // Config utilities export { findConfigFile, loadConfigFile } from './core/config'; diff --git a/graphql/codegen/src/types/index.ts b/graphql/codegen/src/types/index.ts index 0d1272b6d6..13079ba14b 100644 --- a/graphql/codegen/src/types/index.ts +++ b/graphql/codegen/src/types/index.ts @@ -5,15 +5,15 @@ // Schema types export type { BelongsToRelation, + ConstraintInfo, Field, FieldType, + ForeignKeyConstraint, HasManyRelation, HasOneRelation, ManyToManyRelation, Relations, Table, - ConstraintInfo, - ForeignKeyConstraint, TableConstraints, TableInflection, TableQueryNames, diff --git a/graphql/dev-server/src/index.ts b/graphql/dev-server/src/index.ts index a1a1c09159..fea3ad87e7 100644 --- a/graphql/dev-server/src/index.ts +++ b/graphql/dev-server/src/index.ts @@ -1,4 +1,4 @@ -export { createDevServer } from './server'; -export { buildDevPreset } from './preset'; export type { DevPresetInput } from './preset'; +export { buildDevPreset } from './preset'; +export { createDevServer } from './server'; export type { DevServerInfo, DevServerOptions } from './types'; diff --git a/graphql/env/src/index.ts b/graphql/env/src/index.ts index b199376324..50627b7d54 100644 --- a/graphql/env/src/index.ts +++ b/graphql/env/src/index.ts @@ -1,4 +1,4 @@ // Export Constructive-specific env functions -export { getEnvOptions, getConstructiveEnvOptions } from './merge'; export { getGraphQLEnvVars } from './env'; +export { getConstructiveEnvOptions,getEnvOptions } from './merge'; export type { DevSmsOptions, SmsOptions } from '@constructive-io/graphql-types'; diff --git a/graphql/env/src/merge.ts b/graphql/env/src/merge.ts index ef661777cb..15f1402c53 100644 --- a/graphql/env/src/merge.ts +++ b/graphql/env/src/merge.ts @@ -1,6 +1,7 @@ -import deepmerge from 'deepmerge'; -import { ConstructiveOptions, constructiveGraphqlDefaults } from '@constructive-io/graphql-types'; +import { constructiveGraphqlDefaults,ConstructiveOptions } from '@constructive-io/graphql-types'; import { getEnvOptions as getPgpmEnvOptions, loadConfigSync, replaceArrays } from '@pgpmjs/env'; +import deepmerge from 'deepmerge'; + import { getGraphQLEnvVars } from './env'; /** diff --git a/graphql/explorer/src/resolvers/uploads.ts b/graphql/explorer/src/resolvers/uploads.ts index 54dad0c9e1..3004ce2aee 100644 --- a/graphql/explorer/src/resolvers/uploads.ts +++ b/graphql/explorer/src/resolvers/uploads.ts @@ -1,8 +1,8 @@ import Streamer from '@constructive-io/s3-streamer'; import uploadNames from '@constructive-io/upload-names'; +import type { BucketProvider } from '@pgpmjs/types'; import { ReadStream } from 'fs'; import type { GraphQLResolveInfo } from 'graphql'; -import type { BucketProvider } from '@pgpmjs/types'; interface UploaderOptions { bucketName: string; diff --git a/graphql/explorer/src/server.ts b/graphql/explorer/src/server.ts index 60a3b6fad0..26035d5e12 100644 --- a/graphql/explorer/src/server.ts +++ b/graphql/explorer/src/server.ts @@ -1,11 +1,11 @@ import { getEnvOptions } from '@constructive-io/graphql-env'; import type { ConstructiveOptions } from '@constructive-io/graphql-types'; -import { cors, healthz, poweredBy } from '@pgpmjs/server-utils'; import { middleware as parseDomains } from '@constructive-io/url-domains'; +import { cors, healthz, poweredBy } from '@pgpmjs/server-utils'; import express, { Express, NextFunction, Request, Response } from 'express'; import { createGraphileInstance, graphileCache, GraphileCacheEntry } from 'graphile-cache'; -import { makePgService } from 'graphile-settings'; import type { GraphileConfig } from 'graphile-config'; +import { makePgService } from 'graphile-settings'; import { getPgPool } from 'pg-cache'; import { getPgEnvOptions } from 'pg-env'; diff --git a/graphql/explorer/src/settings.ts b/graphql/explorer/src/settings.ts index 5474bcf069..4d2047f9f1 100644 --- a/graphql/explorer/src/settings.ts +++ b/graphql/explorer/src/settings.ts @@ -1,7 +1,7 @@ -import { ConstructiveOptions } from '@constructive-io/graphql-types'; import { getEnvOptions } from '@constructive-io/graphql-env'; -import { ConstructivePreset } from 'graphile-settings'; +import { ConstructiveOptions } from '@constructive-io/graphql-types'; import type { GraphileConfig } from 'graphile-config'; +import { ConstructivePreset } from 'graphile-settings'; /** * Get a GraphileConfig.Preset for the explorer with grafast context configured. diff --git a/graphql/orm-test/__tests__/helpers/graphile-adapter.ts b/graphql/orm-test/__tests__/helpers/graphile-adapter.ts index c2c0244370..c76a27d333 100644 --- a/graphql/orm-test/__tests__/helpers/graphile-adapter.ts +++ b/graphql/orm-test/__tests__/helpers/graphile-adapter.ts @@ -6,12 +6,12 @@ * models to execute queries against a real PostGraphile schema * running on a live PostgreSQL database. */ -import type { GraphQLQueryFnObj } from 'graphile-test'; import type { GraphQLAdapter, GraphQLError, QueryResult, } from '@constructive-io/graphql-types'; +import type { GraphQLQueryFnObj } from 'graphile-test'; export class GraphileTestAdapter implements GraphQLAdapter { constructor(private queryFn: GraphQLQueryFnObj) {} diff --git a/graphql/orm-test/__tests__/mega-query.test.ts b/graphql/orm-test/__tests__/mega-query.test.ts index 9289bcc344..e89614f0a8 100644 --- a/graphql/orm-test/__tests__/mega-query.test.ts +++ b/graphql/orm-test/__tests__/mega-query.test.ts @@ -16,11 +16,12 @@ * * Requires postgres-plus:18 image with postgis, vector, pg_textsearch, pg_trgm. */ -import { join } from 'path'; -import { getConnectionsObject, seed } from 'graphile-test'; -import type { GraphQLQueryFnObj, GraphQLResponse } from 'graphile-test'; -import { ConstructivePreset } from 'graphile-settings'; import { runCodegenAndLoad } from '@constructive-io/graphql-test'; +import { ConstructivePreset } from 'graphile-settings'; +import type { GraphQLQueryFnObj, GraphQLResponse } from 'graphile-test'; +import { getConnectionsObject, seed } from 'graphile-test'; +import { join } from 'path'; + import { GraphileTestAdapter } from './helpers/graphile-adapter'; jest.setTimeout(120000); diff --git a/graphql/orm-test/__tests__/orm-m2n.test.ts b/graphql/orm-test/__tests__/orm-m2n.test.ts index 05768ead31..8e854c2702 100644 --- a/graphql/orm-test/__tests__/orm-m2n.test.ts +++ b/graphql/orm-test/__tests__/orm-m2n.test.ts @@ -11,12 +11,13 @@ * This validates that the codegen pipeline produces valid ORM code that * works against a real PostGraphile schema with ConstructivePreset enabled. */ -import path from 'path'; -import { getConnectionsObject, seed } from 'graphile-test'; +import { runCodegenAndLoad } from '@constructive-io/graphql-test'; +import { ConstructivePreset } from 'graphile-settings'; import type { GraphQLQueryFnObj } from 'graphile-test'; +import { getConnectionsObject, seed } from 'graphile-test'; +import path from 'path'; import type { PgTestClient } from 'pgsql-test'; -import { ConstructivePreset } from 'graphile-settings'; -import { runCodegenAndLoad } from '@constructive-io/graphql-test'; + import { GraphileTestAdapter } from './helpers/graphile-adapter'; jest.setTimeout(120000); diff --git a/graphql/orm-test/__tests__/postgis-spatial-relations.test.ts b/graphql/orm-test/__tests__/postgis-spatial-relations.test.ts index 403ec2282b..36a796d773 100644 --- a/graphql/orm-test/__tests__/postgis-spatial-relations.test.ts +++ b/graphql/orm-test/__tests__/postgis-spatial-relations.test.ts @@ -13,11 +13,12 @@ * @spatialRelation coveringCounty counties.geom st_coveredby * @spatialRelation nearbyClinic telemedicine_clinics.location st_dwithin distance */ -import { join } from 'path'; -import { getConnectionsObject, seed } from 'graphile-test'; -import type { GraphQLQueryFnObj } from 'graphile-test'; -import { ConstructivePreset } from 'graphile-settings'; import { runCodegenAndLoad } from '@constructive-io/graphql-test'; +import { ConstructivePreset } from 'graphile-settings'; +import type { GraphQLQueryFnObj } from 'graphile-test'; +import { getConnectionsObject, seed } from 'graphile-test'; +import { join } from 'path'; + import { GraphileTestAdapter } from './helpers/graphile-adapter'; jest.setTimeout(120000); diff --git a/graphql/orm-test/__tests__/postgis-spatial.test.ts b/graphql/orm-test/__tests__/postgis-spatial.test.ts index 9e4da84575..ed9ffef0d9 100644 --- a/graphql/orm-test/__tests__/postgis-spatial.test.ts +++ b/graphql/orm-test/__tests__/postgis-spatial.test.ts @@ -20,11 +20,12 @@ * * Requires postgres-plus image with the `postgis` extension. */ -import { join } from 'path'; -import { getConnectionsObject, seed } from 'graphile-test'; -import type { GraphQLQueryFnObj } from 'graphile-test'; -import { ConstructivePreset } from 'graphile-settings'; import { runCodegenAndLoad } from '@constructive-io/graphql-test'; +import { ConstructivePreset } from 'graphile-settings'; +import type { GraphQLQueryFnObj } from 'graphile-test'; +import { getConnectionsObject, seed } from 'graphile-test'; +import { join } from 'path'; + import { GraphileTestAdapter } from './helpers/graphile-adapter'; jest.setTimeout(120000); diff --git a/graphql/playwright-test/__tests__/server.playwright.test.ts b/graphql/playwright-test/__tests__/server.playwright.test.ts index c294a98c37..1136379d16 100644 --- a/graphql/playwright-test/__tests__/server.playwright.test.ts +++ b/graphql/playwright-test/__tests__/server.playwright.test.ts @@ -1,4 +1,4 @@ -import { test, expect } from '@playwright/test'; +import { expect,test } from '@playwright/test'; import { join } from 'path'; import { seed } from 'pgsql-test'; diff --git a/graphql/playwright-test/src/index.ts b/graphql/playwright-test/src/index.ts index 250367edb3..265e4cbf5e 100644 --- a/graphql/playwright-test/src/index.ts +++ b/graphql/playwright-test/src/index.ts @@ -1,13 +1,13 @@ // Re-export types from graphql-test for convenience export { - type GraphQLQueryOptions, - type GraphQLTestContext, type GetConnectionsInput, - type GraphQLResponse, type GraphQLQueryFn, type GraphQLQueryFnObj, + type GraphQLQueryOptions, type GraphQLQueryUnwrappedFn, type GraphQLQueryUnwrappedFnObj, + type GraphQLResponse, + type GraphQLTestContext, } from '@constructive-io/graphql-test'; // Export our types diff --git a/graphql/playwright-test/src/types.ts b/graphql/playwright-test/src/types.ts index 77c0c2057a..1e62795919 100644 --- a/graphql/playwright-test/src/types.ts +++ b/graphql/playwright-test/src/types.ts @@ -1,7 +1,7 @@ +import type { GetConnectionsInput, GraphQLQueryFn, GraphQLQueryFnObj } from '@constructive-io/graphql-test'; +import type { ApiOptions } from '@constructive-io/graphql-types'; import type { Server } from 'http'; import type { PgTestClient } from 'pgsql-test/test-client'; -import type { ApiOptions } from '@constructive-io/graphql-types'; -import type { GetConnectionsInput, GraphQLQueryFn, GraphQLQueryFnObj } from '@constructive-io/graphql-test'; /** * Options for creating a Playwright test server diff --git a/graphql/query/src/ast.ts b/graphql/query/src/ast.ts index 7ca587a039..31791141b1 100644 --- a/graphql/query/src/ast.ts +++ b/graphql/query/src/ast.ts @@ -1,5 +1,4 @@ import * as t from 'gql-ast'; -import { OperationTypeNode } from 'graphql'; import type { ArgumentNode, DocumentNode, @@ -8,7 +7,8 @@ import type { ValueNode, VariableDefinitionNode, } from 'graphql'; -import { toCamelCase, toPascalCase, singularize } from 'inflekt'; +import { OperationTypeNode } from 'graphql'; +import { singularize,toCamelCase } from 'inflekt'; import { getCustomAst } from './custom-ast'; import type { @@ -54,28 +54,28 @@ const createGqlMutation = ({ }: CreateGqlMutationParams): DocumentNode => { const opSel: FieldNode[] = !modelName ? [ - t.field({ - name: operationName, - args: selectArgs, - selectionSet: t.selectionSet({ selections }), - }), - ] + t.field({ + name: operationName, + args: selectArgs, + selectionSet: t.selectionSet({ selections }), + }), + ] : [ - t.field({ - name: operationName, - args: selectArgs, - selectionSet: t.selectionSet({ - selections: useModel - ? [ - t.field({ - name: modelName, - selectionSet: t.selectionSet({ selections }), - }), - ] - : selections, - }), + t.field({ + name: operationName, + args: selectArgs, + selectionSet: t.selectionSet({ + selections: useModel + ? [ + t.field({ + name: modelName, + selectionSet: t.selectionSet({ selections }), + }), + ] + : selections, }), - ]; + }), + ]; return t.document({ definitions: [ @@ -254,21 +254,21 @@ export const getMany = ({ const dataField: FieldNode = builder?._edges ? t.field({ - name: 'edges', - selectionSet: t.selectionSet({ - selections: [ - t.field({ name: 'cursor' }), - t.field({ - name: 'node', - selectionSet: t.selectionSet({ selections }), - }), - ], - }), - }) + name: 'edges', + selectionSet: t.selectionSet({ + selections: [ + t.field({ name: 'cursor' }), + t.field({ + name: 'node', + selectionSet: t.selectionSet({ selections }), + }), + ], + }), + }) : t.field({ - name: 'nodes', - selectionSet: t.selectionSet({ selections }), - }); + name: 'nodes', + selectionSet: t.selectionSet({ selections }), + }); const connectionFields: FieldNode[] = [ t.field({ name: 'totalCount' }), @@ -620,14 +620,14 @@ export function getSelections( const selectionSet = isBelongTo ? t.selectionSet({ selections: subSelections }) : t.selectionSet({ - selections: [ - t.field({ name: 'totalCount' }), - t.field({ - name: 'nodes', - selectionSet: t.selectionSet({ selections: subSelections }), - }), - ], - }); + selections: [ + t.field({ name: 'totalCount' }), + t.field({ + name: 'nodes', + selectionSet: t.selectionSet({ selections: subSelections }), + }), + ], + }); return t.field({ name, diff --git a/graphql/query/src/client/error.ts b/graphql/query/src/client/error.ts index c13042a970..3d2f262a67 100644 --- a/graphql/query/src/client/error.ts +++ b/graphql/query/src/client/error.ts @@ -19,13 +19,13 @@ import { } from '@constructive-io/errors'; export { - ConstructiveError, classify, + ConstructiveError, + type ErrorClass, + type ErrorContext, format, isPublicCode, parse, - type ErrorClass, - type ErrorContext, type ParsedError, toError, } from '@constructive-io/errors'; diff --git a/graphql/query/src/client/index.ts b/graphql/query/src/client/index.ts index 18800e3784..d53530f015 100644 --- a/graphql/query/src/client/index.ts +++ b/graphql/query/src/client/index.ts @@ -5,33 +5,31 @@ */ export { - TypedDocumentString, - type DocumentTypeDecoration, -} from './typed-document'; - -export { - ConstructiveError, classify, + ConstructiveError, createError, + type ErrorClass, + type ErrorContext, format, + type GraphQLError, isConstructiveError, isPublicCode, isPublicError, isRetryable, parse, + type ParsedError, parseGraphQLError, toError, - type ErrorClass, - type ErrorContext, - type GraphQLError, - type ParsedError, } from './error'; - export { - execute, createGraphQLClient, + execute, type ExecuteOptions, - type GraphQLResponse, - type GraphQLClientOptions, type GraphQLClient, + type GraphQLClientOptions, + type GraphQLResponse, } from './execute'; +export { + type DocumentTypeDecoration, + TypedDocumentString, +} from './typed-document'; diff --git a/graphql/query/src/custom-ast.ts b/graphql/query/src/custom-ast.ts index 76449710fe..364009f137 100644 --- a/graphql/query/src/custom-ast.ts +++ b/graphql/query/src/custom-ast.ts @@ -1,9 +1,9 @@ import * as t from 'gql-ast'; -import { Kind } from 'graphql'; import type { FieldNode, InlineFragmentNode } from 'graphql'; +import { Kind } from 'graphql'; -import type { Field } from './types/schema'; import type { MetaField } from './types'; +import type { Field } from './types/schema'; /** * Get custom AST for MetaField type - handles PostgreSQL types that need subfield selections diff --git a/graphql/query/src/executor.ts b/graphql/query/src/executor.ts index f7eb038e7b..33631f96e0 100644 --- a/graphql/query/src/executor.ts +++ b/graphql/query/src/executor.ts @@ -6,16 +6,16 @@ */ import { execute } from 'grafast'; -import { postgraphile, type PostGraphileInstance } from 'postgraphile'; -import { ConstructivePreset, makePgService } from 'graphile-settings'; import { withPgClientFromPgService } from 'graphile-build-pg'; +import type { GraphileConfig } from 'graphile-config'; +import { ConstructivePreset, makePgService } from 'graphile-settings'; import type { DocumentNode, ExecutionResult, GraphQLSchema, } from 'graphql'; -import type { GraphileConfig } from 'graphile-config'; import { LRUCache } from 'lru-cache'; +import { postgraphile, type PostGraphileInstance } from 'postgraphile'; /** * Configuration options for QueryExecutor diff --git a/graphql/query/src/generators/field-selector.ts b/graphql/query/src/generators/field-selector.ts index 9eadbb8e82..539f6ad458 100644 --- a/graphql/query/src/generators/field-selector.ts +++ b/graphql/query/src/generators/field-selector.ts @@ -2,6 +2,8 @@ * Simplified field selection system * Converts user-friendly selection options to internal SelectionOptions format */ +import { fuzzyFindByName } from 'inflekt'; + import type { QuerySelectionOptions } from '../types'; import type { Table } from '../types/schema'; import type { @@ -9,7 +11,6 @@ import type { FieldSelectionPreset, SimpleFieldSelection, } from '../types/selection'; -import { fuzzyFindByName } from 'inflekt'; const relationalFieldSetCache = new WeakMap>(); @@ -65,47 +66,47 @@ function convertPresetToSelection( const options: QuerySelectionOptions = {}; switch (preset) { - case 'minimal': { - // Just id and first display field - const minimalFields = getMinimalFields(table); - minimalFields.forEach((field) => { - options[field] = true; - }); - break; - } + case 'minimal': { + // Just id and first display field + const minimalFields = getMinimalFields(table); + minimalFields.forEach((field) => { + options[field] = true; + }); + break; + } - case 'display': { - // Common display fields - const displayFields = getDisplayFields(table); - displayFields.forEach((field) => { - options[field] = true; - }); - break; - } + case 'display': { + // Common display fields + const displayFields = getDisplayFields(table); + displayFields.forEach((field) => { + options[field] = true; + }); + break; + } - case 'all': { - // All non-relational fields (includes complex fields like JSON, geometry, etc.) - const allFields = getNonRelationalFields(table); - allFields.forEach((field) => { - options[field] = true; - }); - break; - } + case 'all': { + // All non-relational fields (includes complex fields like JSON, geometry, etc.) + const allFields = getNonRelationalFields(table); + allFields.forEach((field) => { + options[field] = true; + }); + break; + } - case 'full': - // All fields including basic relations - table.fields.forEach((field) => { - options[field.name] = true; - }); - break; + case 'full': + // All fields including basic relations + table.fields.forEach((field) => { + options[field.name] = true; + }); + break; - default: { - // Default to display - const defaultFields = getDisplayFields(table); - defaultFields.forEach((field) => { - options[field] = true; - }); - } + default: { + // Default to display + const defaultFields = getDisplayFields(table); + defaultFields.forEach((field) => { + options[field] = true; + }); + } } return options; diff --git a/graphql/query/src/generators/index.ts b/graphql/query/src/generators/index.ts index 94d2a372a1..4996e2d749 100644 --- a/graphql/query/src/generators/index.ts +++ b/graphql/query/src/generators/index.ts @@ -6,9 +6,9 @@ // SELECT, FindOne, Count query generators export { - buildSelect, - buildFindOne, buildCount, + buildFindOne, + buildSelect, cleanTableToMetaObject, createASTQueryBuilder, generateIntrospectionSchema, @@ -17,15 +17,15 @@ export { // Mutation generators (CREATE, UPDATE, DELETE) export { buildPostGraphileCreate, - buildPostGraphileUpdate, buildPostGraphileDelete, + buildPostGraphileUpdate, } from './mutations'; // Field selection utilities export { convertToSelectionOptions, - isRelationalField, getAvailableRelations, + isRelationalField, validateFieldSelection, } from './field-selector'; @@ -34,14 +34,14 @@ export { normalizeInflectionValue, toCamelCasePlural, toCamelCaseSingular, - toCreateMutationName, - toUpdateMutationName, - toDeleteMutationName, toCreateInputTypeName, - toUpdateInputTypeName, + toCreateMutationName, toDeleteInputTypeName, + toDeleteMutationName, toFilterTypeName, + toOrderByEnumValue, toOrderByTypeName, toPatchFieldName, - toOrderByEnumValue, + toUpdateInputTypeName, + toUpdateMutationName, } from './naming-helpers'; diff --git a/graphql/query/src/generators/mutations.ts b/graphql/query/src/generators/mutations.ts index f9a27d90b5..6dba68fbd8 100644 --- a/graphql/query/src/generators/mutations.ts +++ b/graphql/query/src/generators/mutations.ts @@ -3,8 +3,8 @@ * Uses AST-based approach for PostGraphile-compatible mutations */ import * as t from 'gql-ast'; -import { OperationTypeNode, print } from 'graphql'; import type { ArgumentNode, FieldNode, VariableDefinitionNode } from 'graphql'; +import { OperationTypeNode, print } from 'graphql'; import { TypedDocumentString } from '../client/typed-document'; import { diff --git a/graphql/query/src/generators/naming-helpers.ts b/graphql/query/src/generators/naming-helpers.ts index be17256ac8..6a161e753f 100644 --- a/graphql/query/src/generators/naming-helpers.ts +++ b/graphql/query/src/generators/naming-helpers.ts @@ -7,7 +7,7 @@ * * Back-ported from Dashboard's `packages/data/src/query-generator.ts`. */ -import { toCamelCase, toConstantCase, pluralize } from 'inflekt'; +import { pluralize,toCamelCase, toConstantCase } from 'inflekt'; import type { Table } from '../types/schema'; diff --git a/graphql/query/src/generators/select.ts b/graphql/query/src/generators/select.ts index 1d098d89d0..13ba18abcf 100644 --- a/graphql/query/src/generators/select.ts +++ b/graphql/query/src/generators/select.ts @@ -3,8 +3,9 @@ * Uses AST-based approach for all query generation */ import * as t from 'gql-ast'; -import { Kind, OperationTypeNode, print } from 'graphql'; import type { ArgumentNode, FieldNode, TypeNode, VariableDefinitionNode } from 'graphql'; +import { Kind, OperationTypeNode, print } from 'graphql'; +import { fuzzyFindByName } from 'inflekt'; import { TypedDocumentString } from '../client/typed-document'; import { @@ -25,7 +26,6 @@ import type { QueryOptions } from '../types/query'; import type { Table, TypeRef } from '../types/schema'; import type { FieldSelection } from '../types/selection'; import { convertToSelectionOptions, isRelationalField } from './field-selector'; -import { fuzzyFindByName } from 'inflekt'; import { normalizeInflectionValue, toCamelCasePlural, diff --git a/graphql/query/src/index.ts b/graphql/query/src/index.ts index d4694a51c4..4ad3669e77 100644 --- a/graphql/query/src/index.ts +++ b/graphql/query/src/index.ts @@ -14,7 +14,7 @@ export { QueryBuilder } from './query-builder'; // QueryExecutor (server-side execution via PostGraphile) -export { QueryExecutor, createExecutor } from './executor'; +export { createExecutor,QueryExecutor } from './executor'; // AST builders (getAll, getMany, getOne, createOne, patchOne, deleteOne) export * from './ast'; diff --git a/graphql/query/src/introspect/index.ts b/graphql/query/src/introspect/index.ts index 037a8d5472..e2728d508d 100644 --- a/graphql/query/src/introspect/index.ts +++ b/graphql/query/src/introspect/index.ts @@ -5,6 +5,6 @@ */ export * from './infer-tables'; +export * from './schema-query'; export * from './transform'; export * from './transform-schema'; -export * from './schema-query'; diff --git a/graphql/query/src/introspect/infer-tables.ts b/graphql/query/src/introspect/infer-tables.ts index 51c10e9432..98013c0edf 100644 --- a/graphql/query/src/introspect/infer-tables.ts +++ b/graphql/query/src/introspect/infer-tables.ts @@ -14,8 +14,6 @@ */ import { lcFirst, pluralize, singularize, ucFirst } from 'inflekt'; -import { parseSmartTags, stripSmartComments } from '../utils'; - import type { IntrospectionField, IntrospectionInputValue, @@ -26,6 +24,7 @@ import type { import { getBaseTypeName, isList, isNonNull, unwrapType } from '../types/introspection'; import type { BelongsToRelation, + ConstraintInfo, Field, FieldArgument, FieldType, @@ -33,12 +32,12 @@ import type { ManyToManyRelation, Relations, Table, - ConstraintInfo, TableConstraints, TableInflection, TableQueryNames, TypeRef, } from '../types/schema'; +import { parseSmartTags, stripSmartComments } from '../utils'; // ============================================================================ // Pattern Matching Constants diff --git a/graphql/query/src/introspect/transform-schema.ts b/graphql/query/src/introspect/transform-schema.ts index c0bc501d7a..365b2ce1bb 100644 --- a/graphql/query/src/introspect/transform-schema.ts +++ b/graphql/query/src/introspect/transform-schema.ts @@ -20,8 +20,8 @@ import type { Argument, ObjectField, Operation, - TypeRef, ResolvedType, + TypeRef, TypeRegistry, } from '../types/schema'; @@ -169,15 +169,15 @@ export function transformSchemaToOperations( // Transform queries const queries: Operation[] = queryTypeDef?.fields ? queryTypeDef.fields.map((field) => - transformFieldToCleanOperation(field, 'query', types), - ) + transformFieldToCleanOperation(field, 'query', types), + ) : []; // Transform mutations const mutations: Operation[] = mutationTypeDef?.fields ? mutationTypeDef.fields.map((field) => - transformFieldToCleanOperation(field, 'mutation', types), - ) + transformFieldToCleanOperation(field, 'mutation', types), + ) : []; return { queries, mutations, typeRegistry }; diff --git a/graphql/query/src/query-builder.ts b/graphql/query/src/query-builder.ts index 9aa6ce8aa5..d34d57b647 100644 --- a/graphql/query/src/query-builder.ts +++ b/graphql/query/src/query-builder.ts @@ -1,5 +1,5 @@ import { DocumentNode, print as gqlPrint } from 'graphql'; -import { toCamelCase, toPascalCase, toSnakeCase, pluralize } from 'inflekt'; +import { pluralize,toCamelCase, toPascalCase, toSnakeCase } from 'inflekt'; import { createOne, @@ -144,17 +144,17 @@ export class QueryBuilder { // We only need deleteAction from all of [deleteAction, deleteActionBySlug, deleteActionByName] const getInputName = (mutationType: string): string => { switch (mutationType) { - case 'delete': { - return `Delete${toPascalCase(this._model)}Input`; - } - case 'create': { - return `Create${toPascalCase(this._model)}Input`; - } - case 'patch': { - return `Update${toPascalCase(this._model)}Input`; - } - default: - throw new Error('Unhandled mutation type' + mutationType); + case 'delete': { + return `Delete${toPascalCase(this._model)}Input`; + } + case 'create': { + return `Create${toPascalCase(this._model)}Input`; + } + case 'patch': { + return `Update${toPascalCase(this._model)}Input`; + } + default: + throw new Error('Unhandled mutation type' + mutationType); } }; diff --git a/graphql/query/src/runtime/index.ts b/graphql/query/src/runtime/index.ts index 50bc39720c..e8fa889d7d 100644 --- a/graphql/query/src/runtime/index.ts +++ b/graphql/query/src/runtime/index.ts @@ -18,8 +18,6 @@ */ export { parseType, print } from '@0no-co/graphql.web'; - -export type { GraphQLAdapter, GraphQLError, QueryResult } from '@constructive-io/graphql-types'; - -export { createFetch } from '@constructive-io/fetch'; export type { FetchFunction } from '@constructive-io/fetch'; +export { createFetch } from '@constructive-io/fetch'; +export type { GraphQLAdapter, GraphQLError, QueryResult } from '@constructive-io/graphql-types'; diff --git a/graphql/react/__tests__/basic.test.tsx b/graphql/react/__tests__/basic.test.tsx index d0090efc69..681218ba85 100644 --- a/graphql/react/__tests__/basic.test.tsx +++ b/graphql/react/__tests__/basic.test.tsx @@ -1,16 +1,18 @@ // @ts-nocheck jest.setTimeout(20000); -import React from 'react'; -import { render, cleanup } from '@testing-library/react'; import '@testing-library/jest-dom/extend-expect'; + +import { cleanup,render } from '@testing-library/react'; +import React from 'react'; +import { QueryClient,QueryClientProvider } from 'react-query'; +import { useQuery } from 'react-query'; + import { LqlProvider, - useGraphqlClient, useConstructiveQuery, + useGraphqlClient, useTableRowsPaginated } from '../src'; -import { QueryClientProvider, QueryClient } from 'react-query'; -import { useQuery } from 'react-query'; const TESTING_URL = process.env.TESTING_URL; if (!TESTING_URL) { diff --git a/graphql/react/jest.config.js b/graphql/react/jest.config.js index 0aa3aaa499..057a9420ed 100644 --- a/graphql/react/jest.config.js +++ b/graphql/react/jest.config.js @@ -1,18 +1,18 @@ /** @type {import('ts-jest').JestConfigWithTsJest} */ module.exports = { - preset: "ts-jest", - testEnvironment: "node", - transform: { - "^.+\\.tsx?$": [ - "ts-jest", - { - babelConfig: false, - tsconfig: "tsconfig.json", - }, - ], - }, - transformIgnorePatterns: [`/node_modules/*`], - testRegex: "(/__tests__/.*|(\\.|/)(test|spec))\\.(jsx?|tsx?)$", - moduleFileExtensions: ["ts", "tsx", "js", "jsx", "json", "node"], - modulePathIgnorePatterns: ["dist/*"] + preset: 'ts-jest', + testEnvironment: 'node', + transform: { + '^.+\\.tsx?$': [ + 'ts-jest', + { + babelConfig: false, + tsconfig: 'tsconfig.json', + }, + ], + }, + transformIgnorePatterns: [`/node_modules/*`], + testRegex: '(/__tests__/.*|(\\.|/)(test|spec))\\.(jsx?|tsx?)$', + moduleFileExtensions: ['ts', 'tsx', 'js', 'jsx', 'json', 'node'], + modulePathIgnorePatterns: ['dist/*'] }; diff --git a/graphql/react/src/index.ts b/graphql/react/src/index.ts index 6f9f53c06a..87b02526af 100644 --- a/graphql/react/src/index.ts +++ b/graphql/react/src/index.ts @@ -1,7 +1,7 @@ -export * from './use-graphql-client'; +export * from './context'; +export * from './provider'; export * from './use-constructive-client'; +export * from './use-graphql-client'; export * from './use-introspection'; export * from './use-schema-meta'; export * from './use-table-rows'; -export * from './provider'; -export * from './context'; diff --git a/graphql/react/src/provider.tsx b/graphql/react/src/provider.tsx index c78d51090e..f593acae7d 100644 --- a/graphql/react/src/provider.tsx +++ b/graphql/react/src/provider.tsx @@ -1,5 +1,6 @@ // @ts-nocheck import React from 'react'; + import { getLqlContext } from './context'; export const LqlProvider = ({ endpointUrl, children }) => { diff --git a/graphql/react/src/use-constructive-client.ts b/graphql/react/src/use-constructive-client.ts index 6f6451b48c..0a9882db64 100644 --- a/graphql/react/src/use-constructive-client.ts +++ b/graphql/react/src/use-constructive-client.ts @@ -1,5 +1,6 @@ +import { MetaObject,QueryBuilder } from '@constructive-io/graphql-query'; import { useMemo } from 'react'; -import { QueryBuilder, MetaObject } from '@constructive-io/graphql-query'; + import { useIntrospection } from './use-introspection'; import { useSchemaMeta } from './use-schema-meta'; diff --git a/graphql/react/src/use-graphql-client.ts b/graphql/react/src/use-graphql-client.ts index a1abe5d982..f3ca72ae07 100644 --- a/graphql/react/src/use-graphql-client.ts +++ b/graphql/react/src/use-graphql-client.ts @@ -1,6 +1,7 @@ // @ts-nocheck -import { useState, useMemo, useContext } from 'react'; import { GraphQLClient } from 'graphql-request'; +import { useContext,useMemo, useState } from 'react'; + import { getLqlContext } from './context'; export const useGraphqlClient = () => { diff --git a/graphql/react/src/use-introspection.ts b/graphql/react/src/use-introspection.ts index b280f95b35..d365363b28 100644 --- a/graphql/react/src/use-introspection.ts +++ b/graphql/react/src/use-introspection.ts @@ -1,7 +1,8 @@ -import { useEffect } from 'react'; -import { useQuery } from 'react-query'; // @ts-ignore import { IntrospectionQuery, parseGraphQuery } from 'introspectron'; +import { useEffect } from 'react'; +import { useQuery } from 'react-query'; + import { useGraphqlClient } from './use-graphql-client'; const noop = () => {}; diff --git a/graphql/react/src/use-schema-meta.ts b/graphql/react/src/use-schema-meta.ts index 69ac989e51..ea95a53975 100644 --- a/graphql/react/src/use-schema-meta.ts +++ b/graphql/react/src/use-schema-meta.ts @@ -1,7 +1,8 @@ // @ts-nocheck -import { useEffect } from 'react'; import { gql } from 'graphql-request'; +import { useEffect } from 'react'; import { useQuery } from 'react-query'; + import { useGraphqlClient } from './use-graphql-client'; const fieldFragment = ` diff --git a/graphql/react/src/use-table-rows.ts b/graphql/react/src/use-table-rows.ts index ef173bf00c..68cc8b90d4 100644 --- a/graphql/react/src/use-table-rows.ts +++ b/graphql/react/src/use-table-rows.ts @@ -1,13 +1,14 @@ // @ts-nocheck import { useMemo } from 'react'; import { - useQuery, useInfiniteQuery, useMutation, + useQuery, useQueryClient } from 'react-query'; -import { useGraphqlClient } from './use-graphql-client'; + import { useConstructiveQuery } from './use-constructive-client'; +import { useGraphqlClient } from './use-graphql-client'; const noop = () => {}; export function useTableRowsPaginated(options = {}) { diff --git a/graphql/realtime-test/src/graphile-test.ts b/graphql/realtime-test/src/graphile-test.ts index efe9f4f595..9f4848e959 100644 --- a/graphql/realtime-test/src/graphile-test.ts +++ b/graphql/realtime-test/src/graphile-test.ts @@ -1,4 +1,4 @@ -import type { RealtimeTestInput, RealtimeTestContext } from 'graphile-realtime-test'; +import type { RealtimeTestContext,RealtimeTestInput } from 'graphile-realtime-test'; import { createRealtimeTestContext } from 'graphile-realtime-test'; import { ConstructivePreset } from 'graphile-settings'; import type { SeedAdapter } from 'pgsql-test/seed/types'; diff --git a/graphql/realtime-test/src/index.ts b/graphql/realtime-test/src/index.ts index 22408d771f..0898583737 100644 --- a/graphql/realtime-test/src/index.ts +++ b/graphql/realtime-test/src/index.ts @@ -1,56 +1,49 @@ // Re-export types from graphile-realtime-test export type { - RealtimeTestInput, RealtimeTestContext, + RealtimeTestInput, } from 'graphile-realtime-test'; - export type { GetConnectionsInput, GetConnectionsResult, WsHandle, } from 'graphile-realtime-test'; - export type { - SubscriptionEvent, SubscribeOptions, + SubscriptionEvent, } from 'graphile-realtime-test'; - export type { - WsTestServerInput, WsTestServer, + WsTestServerInput, } from 'graphile-realtime-test'; // Re-export low-level utilities that don't need Constructive wrapping export { + collectEvents, subscribe, waitForEvent, - collectEvents, } from 'graphile-realtime-test'; - export { + buildInvalidatePayload, + buildPayload, notify, notifyChange, notifyInvalidate, - buildPayload, - buildInvalidatePayload, } from 'graphile-realtime-test'; - export { - nextEvent, collectWsEvents, delay, + nextEvent, } from 'graphile-realtime-test'; - export { createWsTestServer } from 'graphile-realtime-test'; - export { makeRealtimeSmartTagsPlugin } from 'graphile-realtime-test'; // Re-export low-level DB connection utilities for advanced two-phase patterns +export type { GetConnectionOpts,GetConnectionResult } from 'pgsql-test'; export { getConnections as getDbConnections } from 'pgsql-test'; -export type { GetConnectionResult, GetConnectionOpts } from 'pgsql-test'; -export type { PgTestClient } from 'pgsql-test/test-client'; export { seed, snapshot } from 'pgsql-test'; +export type { PgTestClient } from 'pgsql-test/test-client'; // Override with our Constructive-specific implementations -export { createConstructiveRealtimeTestContext } from './graphile-test'; export { getConnections } from './get-connections'; +export { createConstructiveRealtimeTestContext } from './graphile-test'; diff --git a/graphql/server-test/src/get-connections.ts b/graphql/server-test/src/get-connections.ts index 0bf1ce214e..875c30b9cd 100644 --- a/graphql/server-test/src/get-connections.ts +++ b/graphql/server-test/src/get-connections.ts @@ -1,10 +1,10 @@ +import { getEnvOptions } from '@constructive-io/graphql-env'; import type { GetConnectionOpts, GetConnectionResult } from 'pgsql-test'; import { getConnections as getPgConnections } from 'pgsql-test'; import type { SeedAdapter } from 'pgsql-test/seed/types'; -import { getEnvOptions } from '@constructive-io/graphql-env'; import { createDevTestServer, createTestServer } from './server'; -import { createSuperTestAgent, createQueryFn } from './supertest'; +import { createQueryFn,createSuperTestAgent } from './supertest'; import type { GetConnectionsInput, GetConnectionsResult } from './types'; /** diff --git a/graphql/server-test/src/supertest.ts b/graphql/server-test/src/supertest.ts index c0788de322..fd6c513d7b 100644 --- a/graphql/server-test/src/supertest.ts +++ b/graphql/server-test/src/supertest.ts @@ -3,10 +3,9 @@ import { print } from 'graphql'; import supertest from 'supertest'; import type { - ServerInfo, + GraphQLQueryFn, GraphQLResponse, - GraphQLQueryFn -} from './types'; + ServerInfo} from './types'; /** * Create a SuperTest agent for the given server diff --git a/graphql/server/src/diagnostics/debug-db-snapshot.ts b/graphql/server/src/diagnostics/debug-db-snapshot.ts index 218868ef1a..666ad9619b 100644 --- a/graphql/server/src/diagnostics/debug-db-snapshot.ts +++ b/graphql/server/src/diagnostics/debug-db-snapshot.ts @@ -1,7 +1,7 @@ import type { ConstructiveOptions } from '@constructive-io/graphql-types'; +import { Pool, type PoolClient } from 'pg'; import { buildConnectionString, getPgPool } from 'pg-cache'; import { getPgEnvOptions } from 'pg-env'; -import { Pool, type PoolClient } from 'pg'; const ACTIVE_ACTIVITY_SQL = ` select diff --git a/graphql/server/src/diagnostics/debug-memory-snapshot.ts b/graphql/server/src/diagnostics/debug-memory-snapshot.ts index b3491ee133..b35f5e8779 100644 --- a/graphql/server/src/diagnostics/debug-memory-snapshot.ts +++ b/graphql/server/src/diagnostics/debug-memory-snapshot.ts @@ -1,7 +1,9 @@ import os from 'node:os'; import v8 from 'node:v8'; -import { svcCache, SVC_CACHE_TTL_MS } from '@pgpmjs/server-utils'; + +import { SVC_CACHE_TTL_MS,svcCache } from '@pgpmjs/server-utils'; import { getCacheStats } from 'graphile-cache'; + import { getInFlightCount, getInFlightKeys } from '../middleware/graphile'; import { getGraphileBuildStats } from '../middleware/observability/graphile-build-stats'; diff --git a/graphql/server/src/diagnostics/debug-sampler.ts b/graphql/server/src/diagnostics/debug-sampler.ts index 76ae11de8e..75a9828103 100644 --- a/graphql/server/src/diagnostics/debug-sampler.ts +++ b/graphql/server/src/diagnostics/debug-sampler.ts @@ -1,7 +1,9 @@ import fs from 'node:fs/promises'; import path from 'node:path'; + import type { ConstructiveOptions } from '@constructive-io/graphql-types'; import { Logger } from '@pgpmjs/logger'; + import { getDebugDatabaseSnapshot } from './debug-db-snapshot'; import { getDebugMemorySnapshot } from './debug-memory-snapshot'; import { isGraphqlDebugSamplerEnabled } from './observability'; diff --git a/graphql/server/src/index.ts b/graphql/server/src/index.ts index 53dd89cc1e..edd35483ad 100644 --- a/graphql/server/src/index.ts +++ b/graphql/server/src/index.ts @@ -1,8 +1,8 @@ export * from './server'; // Export middleware for use in testing packages -export { createApiMiddleware, getSubdomain, getApiConfig } from './middleware/api'; +export { createApiMiddleware, getApiConfig,getSubdomain } from './middleware/api'; export { createAuthenticateMiddleware } from './middleware/auth'; export { cors } from './middleware/cors'; -export { graphile } from './middleware/graphile'; export { flush, flushService } from './middleware/flush'; +export { graphile } from './middleware/graphile'; diff --git a/graphql/server/src/middleware/__tests__/auth-device-token.test.ts b/graphql/server/src/middleware/__tests__/auth-device-token.test.ts index 6307d4965c..9f33c64025 100644 --- a/graphql/server/src/middleware/__tests__/auth-device-token.test.ts +++ b/graphql/server/src/middleware/__tests__/auth-device-token.test.ts @@ -1,4 +1,5 @@ -import type { Request, Response, NextFunction } from 'express'; +import type {Request } from 'express'; + import { DEVICE_TOKEN_COOKIE_NAME } from '../cookie'; /** diff --git a/graphql/server/src/middleware/__tests__/cookie.test.ts b/graphql/server/src/middleware/__tests__/cookie.test.ts index 034d268d65..fdecda2337 100644 --- a/graphql/server/src/middleware/__tests__/cookie.test.ts +++ b/graphql/server/src/middleware/__tests__/cookie.test.ts @@ -1,18 +1,19 @@ import type { Request, Response } from 'express'; + +import type { AuthSettings } from '../../types'; import { - SESSION_COOKIE_NAME, + clearDeviceTokenCookie, + clearSessionCookie, DEVICE_TOKEN_COOKIE_NAME, - getSessionCookieConfig, getDeviceTokenCookieConfig, - setSessionCookie, - clearSessionCookie, - setDeviceTokenCookie, - clearDeviceTokenCookie, - parseCookieValue, getDeviceTokenFromRequest, + getSessionCookieConfig, getSessionTokenFromRequest, + parseCookieValue, + SESSION_COOKIE_NAME, + setDeviceTokenCookie, + setSessionCookie, } from '../cookie'; -import type { AuthSettings } from '../../types'; describe('cookie utilities', () => { describe('getSessionCookieConfig', () => { diff --git a/graphql/server/src/middleware/__tests__/csrf-integration.test.ts b/graphql/server/src/middleware/__tests__/csrf-integration.test.ts index 6b11036013..7f3df0eaf5 100644 --- a/graphql/server/src/middleware/__tests__/csrf-integration.test.ts +++ b/graphql/server/src/middleware/__tests__/csrf-integration.test.ts @@ -1,5 +1,6 @@ -import type { Request, Response, NextFunction } from 'express'; import { createCsrfMiddleware } from '@constructive-io/csrf'; +import type {Request, Response } from 'express'; + import { parseCookieValue, SESSION_COOKIE_NAME } from '../cookie'; describe('CSRF middleware integration', () => { diff --git a/graphql/server/src/middleware/auth.ts b/graphql/server/src/middleware/auth.ts index 7e1826a014..ef6da3f3a2 100644 --- a/graphql/server/src/middleware/auth.ts +++ b/graphql/server/src/middleware/auth.ts @@ -1,3 +1,5 @@ +import './types'; // for Request type + import { errors } from '@constructive-io/errors'; import { getNodeEnv } from '@pgpmjs/env'; import { Logger } from '@pgpmjs/logger'; @@ -7,7 +9,6 @@ import { getPgPool } from 'pg-cache'; import pgQueryContext from 'pg-query-context'; import { respondWithGraphQLError } from '../errors/graphql-response'; -import './types'; // for Request type const log = new Logger('auth'); const isDev = () => getNodeEnv() === 'development'; diff --git a/graphql/server/src/middleware/captcha.ts b/graphql/server/src/middleware/captcha.ts index c6d7c7b1f0..7a4da18955 100644 --- a/graphql/server/src/middleware/captcha.ts +++ b/graphql/server/src/middleware/captcha.ts @@ -1,9 +1,10 @@ +import './types'; // for Request type + import { errors } from '@constructive-io/errors'; import { Logger } from '@pgpmjs/logger'; import type { NextFunction, Request, RequestHandler, Response } from 'express'; import { respondWithGraphQLError } from '../errors/graphql-response'; -import './types'; // for Request type const log = new Logger('captcha'); diff --git a/graphql/server/src/middleware/cookie.ts b/graphql/server/src/middleware/cookie.ts index bb92446396..bba9c1e37c 100644 --- a/graphql/server/src/middleware/cookie.ts +++ b/graphql/server/src/middleware/cookie.ts @@ -1,4 +1,5 @@ import type { Request, Response } from 'express'; + import type { AuthSettings } from '../types'; export const SESSION_COOKIE_NAME = 'constructive_session'; diff --git a/graphql/server/src/middleware/cors.ts b/graphql/server/src/middleware/cors.ts index 364453e1a3..8bb7cefebb 100644 --- a/graphql/server/src/middleware/cors.ts +++ b/graphql/server/src/middleware/cors.ts @@ -1,8 +1,10 @@ +import './types'; // for Request type + import { parseUrl } from '@constructive-io/url-domains'; import corsPlugin from 'cors'; import type { Request, RequestHandler } from 'express'; + import type { ApiStructure } from '../types'; -import './types'; // for Request type /** * Unified CORS middleware for Constructive API diff --git a/graphql/server/src/middleware/error-handler.ts b/graphql/server/src/middleware/error-handler.ts index 3820274675..bbf63de194 100644 --- a/graphql/server/src/middleware/error-handler.ts +++ b/graphql/server/src/middleware/error-handler.ts @@ -1,11 +1,12 @@ +import './types'; + import { getNodeEnv } from '@pgpmjs/env'; import { Logger } from '@pgpmjs/logger'; import type { ErrorRequestHandler, NextFunction, Request, Response } from 'express'; -import { isApiError } from '../errors/api-errors'; -import errorPage404Message from '../errors/404-message'; import errorPage50x from '../errors/50x'; -import './types'; +import errorPage404Message from '../errors/404-message'; +import { isApiError } from '../errors/api-errors'; const log = new Logger('error-handler'); diff --git a/graphql/server/src/middleware/fn.ts b/graphql/server/src/middleware/fn.ts index e1f2bd08d0..d9037196dd 100644 --- a/graphql/server/src/middleware/fn.ts +++ b/graphql/server/src/middleware/fn.ts @@ -18,9 +18,9 @@ * transaction — RLS is fully enforced; no superuser or bypass path is used. */ +import { QueryBuilder, type SqlValue } from '@constructive-io/query-builder'; import { Logger } from '@pgpmjs/logger'; import { isUuid } from '@pgpmjs/server-utils'; -import { QueryBuilder, type SqlValue } from '@constructive-io/query-builder'; import express, { Request, Response, Router } from 'express'; const log = new Logger('fn'); diff --git a/graphql/server/src/middleware/graphile.ts b/graphql/server/src/middleware/graphile.ts index 9cc96e341b..e6de98f7ad 100644 --- a/graphql/server/src/middleware/graphile.ts +++ b/graphql/server/src/middleware/graphile.ts @@ -1,7 +1,8 @@ import './types'; // for Request type import crypto from 'node:crypto'; -import { classify, errors, type ErrorContext, parse } from '@constructive-io/errors'; + +import { classify, type ErrorContext, errors, parse } from '@constructive-io/errors'; import type { ComputeConfig } from '@constructive-io/express-context'; import type { ConstructiveOptions } from '@constructive-io/graphql-types'; import { getNodeEnv } from '@pgpmjs/env'; diff --git a/graphql/server/src/middleware/observability/__tests__/guard.test.ts b/graphql/server/src/middleware/observability/__tests__/guard.test.ts index 72edba049f..6473519968 100644 --- a/graphql/server/src/middleware/observability/__tests__/guard.test.ts +++ b/graphql/server/src/middleware/observability/__tests__/guard.test.ts @@ -1,4 +1,5 @@ import type { NextFunction, Request, Response } from 'express'; + import { localObservabilityOnly } from '../guard'; function makeReq(input: { remoteAddress?: string | null; host?: string } = {}): Request { diff --git a/graphql/server/src/middleware/observability/debug-db.ts b/graphql/server/src/middleware/observability/debug-db.ts index f012ffe3b4..0c083ceb17 100644 --- a/graphql/server/src/middleware/observability/debug-db.ts +++ b/graphql/server/src/middleware/observability/debug-db.ts @@ -1,6 +1,7 @@ import type { ConstructiveOptions } from '@constructive-io/graphql-types'; import { Logger } from '@pgpmjs/logger'; import type { RequestHandler } from 'express'; + import { getDebugDatabaseSnapshot } from '../../diagnostics/debug-db-snapshot'; const log = new Logger('debug-db'); diff --git a/graphql/server/src/middleware/observability/debug-memory.ts b/graphql/server/src/middleware/observability/debug-memory.ts index 81372f0354..e85e14006c 100644 --- a/graphql/server/src/middleware/observability/debug-memory.ts +++ b/graphql/server/src/middleware/observability/debug-memory.ts @@ -1,5 +1,6 @@ import { Logger } from '@pgpmjs/logger'; import type { RequestHandler } from 'express'; + import { getDebugMemorySnapshot } from '../../diagnostics/debug-memory-snapshot'; const log = new Logger('debug-memory'); diff --git a/graphql/server/src/middleware/observability/graphile-build-stats.ts b/graphql/server/src/middleware/observability/graphile-build-stats.ts index 9c14b08933..f8825ac011 100644 --- a/graphql/server/src/middleware/observability/graphile-build-stats.ts +++ b/graphql/server/src/middleware/observability/graphile-build-stats.ts @@ -207,7 +207,7 @@ export function getGraphileBuildStats(): { lastDatabaseId: string | null; recentEvents: GraphileBuildEvent[]; byServiceKey: Record; -} { + } { const completed = buildStats.succeeded + buildStats.failed; const withAverages = (map: Map) => Object.fromEntries( diff --git a/graphql/server/src/middleware/observability/guard.ts b/graphql/server/src/middleware/observability/guard.ts index 04d5477ab2..6790e15e15 100644 --- a/graphql/server/src/middleware/observability/guard.ts +++ b/graphql/server/src/middleware/observability/guard.ts @@ -1,4 +1,5 @@ import type { RequestHandler } from 'express'; + import { isLoopbackAddress, isLoopbackHost } from '../../diagnostics/observability'; export const localObservabilityOnly: RequestHandler = (req, res, next) => { diff --git a/graphql/server/src/middleware/observability/request-logger.ts b/graphql/server/src/middleware/observability/request-logger.ts index cc5835ae49..5280a682ab 100644 --- a/graphql/server/src/middleware/observability/request-logger.ts +++ b/graphql/server/src/middleware/observability/request-logger.ts @@ -1,5 +1,5 @@ -import { randomUUID } from 'crypto'; import { Logger } from '@pgpmjs/logger'; +import { randomUUID } from 'crypto'; import type { RequestHandler } from 'express'; const log = new Logger('server'); diff --git a/graphql/server/src/plugins/__tests__/auth-cookie-integration.test.ts b/graphql/server/src/plugins/__tests__/auth-cookie-integration.test.ts index 8d2f02fcac..bd8dbbe451 100644 --- a/graphql/server/src/plugins/__tests__/auth-cookie-integration.test.ts +++ b/graphql/server/src/plugins/__tests__/auth-cookie-integration.test.ts @@ -6,7 +6,7 @@ * grafserv uses Buffer-based responses, not JSON objects. */ -import { SESSION_COOKIE_NAME, DEVICE_TOKEN_COOKIE_NAME } from '../../middleware/cookie'; +import { DEVICE_TOKEN_COOKIE_NAME,SESSION_COOKIE_NAME } from '../../middleware/cookie'; interface BufferResult { type: 'buffer'; diff --git a/graphql/server/src/plugins/__tests__/auth-cookie-plugin.test.ts b/graphql/server/src/plugins/__tests__/auth-cookie-plugin.test.ts index 4e9d4a900f..f4f3ba25bd 100644 --- a/graphql/server/src/plugins/__tests__/auth-cookie-plugin.test.ts +++ b/graphql/server/src/plugins/__tests__/auth-cookie-plugin.test.ts @@ -1,4 +1,4 @@ -import { SESSION_COOKIE_NAME, DEVICE_TOKEN_COOKIE_NAME } from '../../middleware/cookie'; +import { DEVICE_TOKEN_COOKIE_NAME,SESSION_COOKIE_NAME } from '../../middleware/cookie'; /** * Since the AuthCookiePlugin is a grafserv middleware plugin, we test diff --git a/graphql/server/src/plugins/auth-cookie-plugin.ts b/graphql/server/src/plugins/auth-cookie-plugin.ts index c41824c458..6c5a7bce0b 100644 --- a/graphql/server/src/plugins/auth-cookie-plugin.ts +++ b/graphql/server/src/plugins/auth-cookie-plugin.ts @@ -1,14 +1,16 @@ -import type { Request } from 'express'; -import type { GraphileConfig, MiddlewareNext } from 'graphile-config'; -import type { Result, BufferResult } from 'grafserv'; -import { Logger } from '@pgpmjs/logger'; import '../middleware/types'; + +import { Logger } from '@pgpmjs/logger'; +import type { Request } from 'express'; +import type { BufferResult } from 'grafserv'; +import type { GraphileConfig } from 'graphile-config'; + import { - SESSION_COOKIE_NAME, + CookieConfig, DEVICE_TOKEN_COOKIE_NAME, - getSessionCookieConfig, getDeviceTokenCookieConfig, - CookieConfig, + getSessionCookieConfig, + SESSION_COOKIE_NAME, } from '../middleware/cookie'; const log = new Logger('auth-cookie'); diff --git a/graphql/server/src/scripts/create-bucket.ts b/graphql/server/src/scripts/create-bucket.ts index 107de02a38..6975ff4894 100644 --- a/graphql/server/src/scripts/create-bucket.ts +++ b/graphql/server/src/scripts/create-bucket.ts @@ -1,8 +1,8 @@ // Minimal script to create a bucket in MinIO/S3 using @constructive-io/s3-utils -import { createS3Client, createS3Bucket } from '@constructive-io/s3-utils'; -import type { StorageProvider } from '@constructive-io/s3-utils'; import { getEnvOptions } from '@constructive-io/graphql-env'; +import type { StorageProvider } from '@constructive-io/s3-utils'; +import { createS3Bucket,createS3Client } from '@constructive-io/s3-utils'; import { Logger } from '@pgpmjs/logger'; const log = new Logger('create-bucket'); diff --git a/graphql/server/src/types.ts b/graphql/server/src/types.ts index 85d9b64829..c8a15300e4 100644 --- a/graphql/server/src/types.ts +++ b/graphql/server/src/types.ts @@ -1,5 +1,5 @@ -import type { PgpmOptions } from '@pgpmjs/types'; import type { ApiOptions as ApiConfig } from '@constructive-io/graphql-types'; +import type { PgpmOptions } from '@pgpmjs/types'; // Re-export shared types from express-context (single source of truth) export type { diff --git a/graphql/test-app/scripts/analyze-bundle.ts b/graphql/test-app/scripts/analyze-bundle.ts index 7db8f509ec..4c3a5e3490 100644 --- a/graphql/test-app/scripts/analyze-bundle.ts +++ b/graphql/test-app/scripts/analyze-bundle.ts @@ -6,9 +6,10 @@ * * Usage: tsx scripts/analyze-bundle.ts */ -import { build } from 'vite'; +import { brotliCompressSync,gzipSync } from 'node:zlib'; + import react from '@vitejs/plugin-react'; -import { gzipSync, brotliCompressSync } from 'node:zlib'; +import { build } from 'vite'; interface ModuleInfo { originalLength: number; diff --git a/graphql/test-app/src/App.tsx b/graphql/test-app/src/App.tsx index 308ef14463..6eac9feba7 100644 --- a/graphql/test-app/src/App.tsx +++ b/graphql/test-app/src/App.tsx @@ -7,57 +7,49 @@ * Run `pnpm codegen` first to generate the hooks from the live API. */ -import { useState, FormEvent } from 'react'; import { useQueryClient } from '@tanstack/react-query'; +import { FormEvent,useState } from 'react'; import { // Client configuration configure, - - // Auth mutation hooks - useSignUpMutation, - useSignInMutation, - useSignOutMutation, - - // Authenticated query hooks - useCurrentUserQuery, - useCurrentUserIdQuery, - useUsersQuery, - useDatabasesQuery, - useDatabaseQuery, - useSchemasQuery, useApisQuery, - useDomainsQuery, - useTablesQuery, - useFieldsQuery, - - // Session & identity scalar queries - useCurrentIpAddressQuery, - useCurrentUserAgentQuery, - // Entity list queries useAuditLogsQuery, - useEmailsQuery, - useRoleTypesQuery, - - // Authenticated mutation hooks — Users - useCreateUserMutation, - useUpdateUserMutation, - + // Custom mutations + useCheckPasswordMutation, + useCreateApiMutation, // Authenticated mutation hooks — Databases useCreateDatabaseMutation, - useUpdateDatabaseMutation, - useDeleteDatabaseMutation, - + useCreateDomainMutation, // Authenticated mutation hooks — Schemas, APIs, Sites, Domains useCreateSchemaMutation, - useCreateApiMutation, useCreateSiteMutation, - useCreateDomainMutation, - - // Custom mutations - useCheckPasswordMutation, + // Authenticated mutation hooks — Users + useCreateUserMutation, + // Session & identity scalar queries + useCurrentIpAddressQuery, + useCurrentUserAgentQuery, + useCurrentUserIdQuery, + // Authenticated query hooks + useCurrentUserQuery, + useDatabaseQuery, + useDatabasesQuery, + useDeleteDatabaseMutation, + useDomainsQuery, + useEmailsQuery, useExtendTokenExpiresMutation, + useFieldsQuery, + useRoleTypesQuery, + useSchemasQuery, + useSignInMutation, + useSignOutMutation, + // Auth mutation hooks + useSignUpMutation, + useTablesQuery, + useUpdateDatabaseMutation, + useUpdateUserMutation, + useUsersQuery, useVerifyPasswordMutation, } from './generated/hooks'; diff --git a/graphql/test-app/src/main.tsx b/graphql/test-app/src/main.tsx index 040b1e09fe..82e29ba341 100644 --- a/graphql/test-app/src/main.tsx +++ b/graphql/test-app/src/main.tsx @@ -2,8 +2,8 @@ import { QueryClient, QueryClientProvider } from '@tanstack/react-query'; import { StrictMode } from 'react'; import { createRoot } from 'react-dom/client'; -import { configure } from './generated/hooks'; import App from './App.tsx'; +import { configure } from './generated/hooks'; // Configure the generated SDK client (no auth initially — App manages JWT) configure({ diff --git a/graphql/test-app/src/type-tests/react-query-helpers-options.type-test.ts b/graphql/test-app/src/type-tests/react-query-helpers-options.type-test.ts index 7b0ac5252e..e972d44f2b 100644 --- a/graphql/test-app/src/type-tests/react-query-helpers-options.type-test.ts +++ b/graphql/test-app/src/type-tests/react-query-helpers-options.type-test.ts @@ -12,12 +12,12 @@ import { QueryClient } from '@tanstack/react-query'; import { fetchCurrentUserQuery, fetchDatabasesQuery, - fetchUserQuery, fetchStepsRequiredQuery, + fetchUserQuery, prefetchCurrentUserQuery, prefetchDatabasesQuery, - prefetchUserQuery, prefetchStepsRequiredQuery, + prefetchUserQuery, useAppPermissionsGetByMaskQuery, useCurrentUserQuery, useDatabasesQuery, diff --git a/graphql/test-app/tests/app-flow.live.test.ts b/graphql/test-app/tests/app-flow.live.test.ts index 34ee07cfd8..9227ca6b77 100644 --- a/graphql/test-app/tests/app-flow.live.test.ts +++ b/graphql/test-app/tests/app-flow.live.test.ts @@ -12,28 +12,26 @@ import { after, before, describe, test } from 'node:test'; import { act } from 'react-test-renderer'; import { - configure, - useSignUpMutation, - useSignInMutation, - useSignOutMutation, - useCurrentUserQuery, - useCurrentUserIdQuery, - useUsersQuery, + useAuditLogsQuery, useCreateDatabaseMutation, + useCurrentIpAddressQuery, + useCurrentUserAgentQuery, + useCurrentUserIdQuery, + useCurrentUserQuery, useDatabaseQuery, - useUpdateDatabaseMutation, - useDeleteDatabaseMutation, useDatabasesQuery, + useDeleteDatabaseMutation, + useEmailsQuery, + useExtendTokenExpiresMutation, useSchemasQuery, + useSignInMutation, + useSignOutMutation, + useSignUpMutation, useTablesQuery, + useUpdateDatabaseMutation, useUpdateUserMutation, - useCurrentIpAddressQuery, - useCurrentUserAgentQuery, - useExtendTokenExpiresMutation, - useAuditLogsQuery, - useEmailsQuery, + useUsersQuery, } from '../src/generated/hooks'; - import { renderHookWithClient } from './hook-test-utils'; import { assertLiveEnvConfigured, @@ -41,7 +39,6 @@ import { createTestQueryClient, getLiveEnvHelpMessage, getLiveTestEnv, - type AuthSession, signOut, } from './live-test-utils'; diff --git a/graphql/test-app/tests/hook-test-utils.ts b/graphql/test-app/tests/hook-test-utils.ts index 322641aedc..87b0f136d1 100644 --- a/graphql/test-app/tests/hook-test-utils.ts +++ b/graphql/test-app/tests/hook-test-utils.ts @@ -1,9 +1,9 @@ import assert from 'node:assert/strict'; import { + notifyManager, QueryClient, QueryClientProvider, - notifyManager, } from '@tanstack/react-query'; import React from 'react'; import { act, create, type ReactTestRenderer } from 'react-test-renderer'; diff --git a/graphql/test-app/tests/hooks.live.test.ts b/graphql/test-app/tests/hooks.live.test.ts index 8be54dbbd7..1d9db35446 100644 --- a/graphql/test-app/tests/hooks.live.test.ts +++ b/graphql/test-app/tests/hooks.live.test.ts @@ -18,24 +18,23 @@ import { useCurrentUserIdQuery, useCurrentUserQuery, useDatabasesQuery, + userQueryKey, + usersQueryKey, useSignInMutation, useSignOutMutation, useUpdateUserMutation, useUserQuery, useUsersQuery, - userQueryKey, - usersQueryKey, } from '../src/generated/hooks'; import { buildListSelectionArgs } from '../src/generated/hooks/selection'; - import { renderHookWithClient } from './hook-test-utils'; import { assertLiveEnvConfigured, + type AuthSession, configureHooks, createTestQueryClient, getLiveEnvHelpMessage, getLiveTestEnv, - type AuthSession, signIn, signOut, } from './live-test-utils'; diff --git a/graphql/test-app/tests/orm.live.test.ts b/graphql/test-app/tests/orm.live.test.ts index 15577d6f0b..c0baf028ae 100644 --- a/graphql/test-app/tests/orm.live.test.ts +++ b/graphql/test-app/tests/orm.live.test.ts @@ -2,12 +2,11 @@ import assert from 'node:assert/strict'; import { after, describe, test } from 'node:test'; import { createClient } from '../src/generated/orm'; - import { assertLiveEnvConfigured, + type AuthSession, getLiveEnvHelpMessage, getLiveTestEnv, - type AuthSession, signIn, signOut, } from './live-test-utils'; diff --git a/graphql/test-app/tests/type-tests.ts b/graphql/test-app/tests/type-tests.ts index 4ad0961659..a32ce0bacf 100644 --- a/graphql/test-app/tests/type-tests.ts +++ b/graphql/test-app/tests/type-tests.ts @@ -17,29 +17,22 @@ * so `| null` annotations are cosmetic. */ +import { + useCurrentUserIdQuery, + useCurrentUserQuery, + useUpdateUserMutation, + useUserQuery, + useUsersQuery, +} from '../src/generated/hooks'; import { createClient } from '../src/generated/orm'; import type { - UserSelect, - DatabaseSelect, - SchemaSelect, - TableSelect, - FieldSelect, - UserPatch, + DatabaseFilter, DatabasePatch, UserFilter, - DatabaseFilter, + UserPatch, + UserSelect, } from '../src/generated/orm/input-types'; -import type { ConnectionResult, InferSelectResult, PageInfo } from '../src/generated/orm/select-types'; -import type { UserWithRelations, DatabaseWithRelations } from '../src/generated/orm/input-types'; - -import { - useUsersQuery, - useUserQuery, - useDatabasesQuery, - useUpdateUserMutation, - useCurrentUserQuery, - useCurrentUserIdQuery, -} from '../src/generated/hooks'; +import type { PageInfo } from '../src/generated/orm/select-types'; // --------------------------------------------------------------------------- // A. Helper Types diff --git a/graphql/test-app/vite.config.ts b/graphql/test-app/vite.config.ts index 2e3f72d38c..d17d14299e 100644 --- a/graphql/test-app/vite.config.ts +++ b/graphql/test-app/vite.config.ts @@ -1,6 +1,6 @@ import react from '@vitejs/plugin-react'; -import { defineConfig } from 'vite'; import { visualizer } from 'rollup-plugin-visualizer'; +import { defineConfig } from 'vite'; export default defineConfig({ plugins: [ diff --git a/graphql/test/__tests__/graphile-test.graphile-tx.test.ts b/graphql/test/__tests__/graphile-test.graphile-tx.test.ts index a4447b127e..1dd20635c2 100644 --- a/graphql/test/__tests__/graphile-test.graphile-tx.test.ts +++ b/graphql/test/__tests__/graphile-test.graphile-tx.test.ts @@ -1,13 +1,13 @@ process.env.LOG_SCOPE = 'graphile-test'; +import type { GraphQLQueryFn } from 'graphile-test'; import gql from 'graphql-tag'; import { join } from 'path'; import { seed } from 'pgsql-test'; import type { PgTestClient } from 'pgsql-test/test-client'; -import { snapshot } from '../src/utils'; import { getConnections } from '../src/get-connections'; -import type { GraphQLQueryFn } from 'graphile-test'; +import { snapshot } from '../src/utils'; import { logDbSessionInfo } from '../test-utils/utils'; const schemas = ['app_public']; diff --git a/graphql/test/__tests__/graphile-test.graphql.test.ts b/graphql/test/__tests__/graphile-test.graphql.test.ts index 5570584b44..247615f29c 100644 --- a/graphql/test/__tests__/graphile-test.graphql.test.ts +++ b/graphql/test/__tests__/graphile-test.graphql.test.ts @@ -1,13 +1,13 @@ process.env.LOG_SCOPE = 'graphile-test'; +import type { GraphQLQueryFn } from 'graphile-test'; import gql from 'graphql-tag'; import { join } from 'path'; import { seed } from 'pgsql-test'; import type { PgTestClient } from 'pgsql-test/test-client'; -import { snapshot } from '../src/utils'; import { getConnections } from '../src/get-connections'; -import type { GraphQLQueryFn } from 'graphile-test'; +import { snapshot } from '../src/utils'; import { logDbSessionInfo } from '../test-utils/utils'; const schemas = ['app_public']; diff --git a/graphql/test/__tests__/graphile-test.plugins.test.ts b/graphql/test/__tests__/graphile-test.plugins.test.ts index 9a540021b2..15eba82cbf 100644 --- a/graphql/test/__tests__/graphile-test.plugins.test.ts +++ b/graphql/test/__tests__/graphile-test.plugins.test.ts @@ -1,14 +1,14 @@ process.env.LOG_SCOPE = 'graphile-test'; import type { GraphileConfig } from 'graphile-config'; -import gql from 'graphql-tag'; +import type { GraphQLQueryFn } from 'graphile-test'; import { GraphQLString } from 'graphql'; +import gql from 'graphql-tag'; import { join } from 'path'; import { seed } from 'pgsql-test'; import type { PgTestClient } from 'pgsql-test/test-client'; import { getConnections } from '../src/get-connections'; -import type { GraphQLQueryFn } from 'graphile-test'; import { IntrospectionQuery } from '../test-utils/queries'; const schemas = ['app_public']; diff --git a/graphql/test/__tests__/graphile-test.roles.test.ts b/graphql/test/__tests__/graphile-test.roles.test.ts index 1b45bba958..755708c0dd 100644 --- a/graphql/test/__tests__/graphile-test.roles.test.ts +++ b/graphql/test/__tests__/graphile-test.roles.test.ts @@ -1,13 +1,13 @@ process.env.LOG_SCOPE = 'graphile-test'; +import type { GraphQLQueryFn } from 'graphile-test'; import gql from 'graphql-tag'; import { join } from 'path'; import { seed } from 'pgsql-test'; import type { PgTestClient } from 'pgsql-test/test-client'; -import { snapshot } from '../src/utils'; import { getConnections } from '../src/get-connections'; -import type { GraphQLQueryFn } from 'graphile-test'; +import { snapshot } from '../src/utils'; import { logDbSessionInfo } from '../test-utils/utils'; const schemas = ['app_public']; diff --git a/graphql/test/__tests__/graphile-test.test.ts b/graphql/test/__tests__/graphile-test.test.ts index 087e8cc337..62bbed1b77 100644 --- a/graphql/test/__tests__/graphile-test.test.ts +++ b/graphql/test/__tests__/graphile-test.test.ts @@ -1,12 +1,12 @@ process.env.LOG_SCOPE = 'graphile-test'; +import type { GraphQLQueryFn } from 'graphile-test'; import { join } from 'path'; import { seed } from 'pgsql-test'; import type { PgTestClient } from 'pgsql-test/test-client'; -import { snapshot } from '../src/utils'; import { getConnections } from '../src/get-connections'; -import type { GraphQLQueryFn } from 'graphile-test'; +import { snapshot } from '../src/utils'; import { IntrospectionQuery } from '../test-utils/queries'; import { logDbSessionInfo } from '../test-utils/utils'; diff --git a/graphql/test/__tests__/graphile-test.types.positional.test.ts b/graphql/test/__tests__/graphile-test.types.positional.test.ts index f4c94afe4a..c4571c6f81 100644 --- a/graphql/test/__tests__/graphile-test.types.positional.test.ts +++ b/graphql/test/__tests__/graphile-test.types.positional.test.ts @@ -1,12 +1,12 @@ process.env.LOG_SCOPE = 'graphile-test'; +import type { GraphQLQueryFn } from 'graphile-test'; import { join } from 'path'; import { seed } from 'pgsql-test'; import type { PgTestClient } from 'pgsql-test/test-client'; -import { snapshot } from '../src/utils'; import { getConnections } from '../src/get-connections'; -import type { GraphQLQueryFn } from 'graphile-test'; +import { snapshot } from '../src/utils'; const schemas = ['app_public']; const sql = (f: string) => join(__dirname, '/../sql', f); diff --git a/graphql/test/__tests__/graphile-test.types.positional.unwrapped.test.ts b/graphql/test/__tests__/graphile-test.types.positional.unwrapped.test.ts index d39136f2fc..8dd1f8443b 100644 --- a/graphql/test/__tests__/graphile-test.types.positional.unwrapped.test.ts +++ b/graphql/test/__tests__/graphile-test.types.positional.unwrapped.test.ts @@ -1,12 +1,12 @@ process.env.LOG_SCOPE = 'graphile-test'; +import type { GraphQLQueryUnwrappedFn } from 'graphile-test'; import { join } from 'path'; import { seed } from 'pgsql-test'; import type { PgTestClient } from 'pgsql-test/test-client'; -import { snapshot } from '../src/utils'; import { getConnectionsUnwrapped } from '../src/get-connections'; -import type { GraphQLQueryUnwrappedFn } from 'graphile-test'; +import { snapshot } from '../src/utils'; const schemas = ['app_public']; const sql = (f: string) => join(__dirname, '/../sql', f); diff --git a/graphql/test/__tests__/graphile-test.types.test.ts b/graphql/test/__tests__/graphile-test.types.test.ts index 938b84a689..b91149b01c 100644 --- a/graphql/test/__tests__/graphile-test.types.test.ts +++ b/graphql/test/__tests__/graphile-test.types.test.ts @@ -1,12 +1,12 @@ process.env.LOG_SCOPE = 'graphile-test'; +import type { GraphQLQueryFnObj } from 'graphile-test'; import { join } from 'path'; import { seed } from 'pgsql-test'; import type { PgTestClient } from 'pgsql-test/test-client'; -import { snapshot } from '../src/utils'; import { getConnectionsObject } from '../src/get-connections'; -import type { GraphQLQueryFnObj } from 'graphile-test'; +import { snapshot } from '../src/utils'; const schemas = ['app_public']; const sql = (f: string) => join(__dirname, '/../sql', f); diff --git a/graphql/test/__tests__/graphile-test.types.unwrapped.test.ts b/graphql/test/__tests__/graphile-test.types.unwrapped.test.ts index e1975aa64d..42a52b9615 100644 --- a/graphql/test/__tests__/graphile-test.types.unwrapped.test.ts +++ b/graphql/test/__tests__/graphile-test.types.unwrapped.test.ts @@ -1,12 +1,12 @@ process.env.LOG_SCOPE = 'graphile-test'; +import type { GraphQLQueryUnwrappedFnObj } from 'graphile-test'; import { join } from 'path'; import { seed } from 'pgsql-test'; import type { PgTestClient } from 'pgsql-test/test-client'; -import { snapshot } from '../src/utils'; import { getConnectionsObjectUnwrapped } from '../src/get-connections'; -import type { GraphQLQueryUnwrappedFnObj } from 'graphile-test'; +import { snapshot } from '../src/utils'; const schemas = ['app_public']; const sql = (f: string) => join(__dirname, '/../sql', f); diff --git a/graphql/test/src/adapter.ts b/graphql/test/src/adapter.ts index a7ed5b97c3..0310e1dfe4 100644 --- a/graphql/test/src/adapter.ts +++ b/graphql/test/src/adapter.ts @@ -6,12 +6,12 @@ * without needing an HTTP server. */ -import type { GraphQLQueryFn } from 'graphile-test'; import type { GraphQLAdapter, GraphQLError, QueryResult, } from '@constructive-io/graphql-types'; +import type { GraphQLQueryFn } from 'graphile-test'; /** * GraphQL adapter that wraps the graphile-test query function. diff --git a/graphql/test/src/codegen-helper.ts b/graphql/test/src/codegen-helper.ts index b2d07fed63..3f9857e4c0 100644 --- a/graphql/test/src/codegen-helper.ts +++ b/graphql/test/src/codegen-helper.ts @@ -21,18 +21,17 @@ * const orm = codegen.createClient({ adapter }); * const rows = await orm.myTable.findMany({ select: { id: true } }).execute(); */ -import fs from 'fs'; -import path from 'path'; -import ts from 'typescript'; -import type { GraphQLQueryFn, GraphQLQueryFnObj } from 'graphile-test'; +import { generateOrm } from '@constructive-io/graphql-codegen/core/codegen/orm'; +import type { Table } from '@constructive-io/graphql-query'; import { - SCHEMA_INTROSPECTION_QUERY, inferTablesFromIntrospection, + SCHEMA_INTROSPECTION_QUERY, transformSchemaToOperations, } from '@constructive-io/graphql-query'; -import type { Table } from '@constructive-io/graphql-query'; - -import { generateOrm } from '@constructive-io/graphql-codegen/core/codegen/orm'; +import fs from 'fs'; +import type { GraphQLQueryFn, GraphQLQueryFnObj } from 'graphile-test'; +import path from 'path'; +import ts from 'typescript'; export interface CodegenResult { /** Factory function to create an ORM client from a GraphQLAdapter */ diff --git a/graphql/test/src/get-connections.ts b/graphql/test/src/get-connections.ts index 546728f77c..712f2b203e 100644 --- a/graphql/test/src/get-connections.ts +++ b/graphql/test/src/get-connections.ts @@ -1,9 +1,3 @@ -import type { GetConnectionOpts, GetConnectionResult } from 'pgsql-test'; -import { getConnections as getPgConnections } from 'pgsql-test'; -import type { SeedAdapter } from 'pgsql-test/seed/types'; -import type { PgTestClient } from 'pgsql-test/test-client'; - -import { GraphQLTest } from './graphile-test'; import type { GetConnectionsInput, GraphQLQueryFn, @@ -13,6 +7,12 @@ import type { GraphQLQueryUnwrappedFnObj, GraphQLResponse } from 'graphile-test'; +import type { GetConnectionOpts, GetConnectionResult } from 'pgsql-test'; +import { getConnections as getPgConnections } from 'pgsql-test'; +import type { SeedAdapter } from 'pgsql-test/seed/types'; +import type { PgTestClient } from 'pgsql-test/test-client'; + +import { GraphQLTest } from './graphile-test'; // Core unwrapping utility const unwrap = (res: GraphQLResponse): T => { diff --git a/graphql/test/src/graphile-test.ts b/graphql/test/src/graphile-test.ts index 1249340add..69dd26a596 100644 --- a/graphql/test/src/graphile-test.ts +++ b/graphql/test/src/graphile-test.ts @@ -1,11 +1,11 @@ -import type { GraphQLQueryOptions, GraphQLTestContext, GetConnectionsInput, Variables } from 'graphile-test'; -import { ConstructivePreset } from 'graphile-settings'; -import type { GraphQLSchema } from 'graphql'; -import type { GraphileConfig } from 'graphile-config'; -import type { GetConnectionOpts, GetConnectionResult } from 'pgsql-test'; import { makeSchema } from 'graphile-build'; +import type { GraphileConfig } from 'graphile-config'; +import { ConstructivePreset } from 'graphile-settings'; import { makePgService } from 'graphile-settings'; +import type { GetConnectionsInput, GraphQLQueryOptions, GraphQLTestContext, Variables } from 'graphile-test'; import { runGraphQLInContext } from 'graphile-test/context'; +import type { GraphQLSchema } from 'graphql'; +import type { GetConnectionOpts, GetConnectionResult } from 'pgsql-test'; /** * Creates a GraphQL test context using PostGraphile v5 with ConstructivePreset. diff --git a/graphql/test/src/index.ts b/graphql/test/src/index.ts index 55d00e8386..4ef4bd1807 100644 --- a/graphql/test/src/index.ts +++ b/graphql/test/src/index.ts @@ -1,29 +1,29 @@ // Re-export types and utilities from graphile-test (but not get-connections functions) export { - type GraphQLQueryOptions, - type GraphQLTestContext, type GetConnectionsInput, - type GraphQLResponse, type GraphQLQueryFn, type GraphQLQueryFnObj, + type GraphQLQueryOptions, type GraphQLQueryUnwrappedFn, type GraphQLQueryUnwrappedFnObj, + type GraphQLResponse, + type GraphQLTestContext, } from 'graphile-test'; // Override with our custom implementations that use graphile-settings -export { GraphQLTest } from './graphile-test'; export * from './get-connections'; +export { GraphQLTest } from './graphile-test'; export { seed, snapshot } from 'pgsql-test'; // Re-export low-level DB connection utilities for advanced two-phase patterns // (e.g. provision first, then build GraphQL schema over dynamic tables). +export type { GetConnectionOpts,GetConnectionResult } from 'pgsql-test'; export { getConnections as getDbConnections } from 'pgsql-test'; -export type { GetConnectionResult, GetConnectionOpts } from 'pgsql-test'; export type { PgTestClient } from 'pgsql-test/test-client'; // Export GraphQL test adapter for SDK integration export { GraphQLTestAdapter } from './adapter'; // Export codegen-at-test-time helper for dynamic table ORM generation -export { runCodegenAndLoad } from './codegen-helper'; export type { CodegenResult } from './codegen-helper'; +export { runCodegenAndLoad } from './codegen-helper'; diff --git a/graphql/types/src/constructive.ts b/graphql/types/src/constructive.ts index 0fcf331ba5..485a4f4a59 100644 --- a/graphql/types/src/constructive.ts +++ b/graphql/types/src/constructive.ts @@ -1,22 +1,21 @@ -import deepmerge from 'deepmerge'; -import { PgConfig } from 'pg-env'; import { - PgpmOptions, + CDNOptions, + DeploymentOptions, + MigrationOptions, pgpmDefaults, + PgpmOptions, PgTestConnectionOptions, - DeploymentOptions, - ServerOptions, - CDNOptions, - MigrationOptions -} from '@pgpmjs/types'; + ServerOptions} from '@pgpmjs/types'; +import deepmerge from 'deepmerge'; +import { PgConfig } from 'pg-env'; + import { - GraphileOptions, - GraphileFeatureOptions, + apiDefaults, ApiOptions, graphileDefaults, graphileFeatureDefaults, - apiDefaults -} from './graphile'; + GraphileFeatureOptions, + GraphileOptions} from './graphile'; import { LlmOptions } from './llm'; import { SmsOptions } from './sms'; diff --git a/graphql/types/src/index.ts b/graphql/types/src/index.ts index c64934e7e0..895604e137 100644 --- a/graphql/types/src/index.ts +++ b/graphql/types/src/index.ts @@ -1,20 +1,18 @@ // Export GraphQL/Graphile specific types export { - GraphileOptions, - GraphileFeatureOptions, + apiDefaults, ApiOptions, graphileDefaults, graphileFeatureDefaults, - apiDefaults -} from './graphile'; + GraphileFeatureOptions, + GraphileOptions} from './graphile'; // Export Constructive combined types export { - ConstructiveGraphQLOptions, - ConstructiveOptions, + constructiveDefaults, constructiveGraphqlDefaults, - constructiveDefaults -} from './constructive'; + ConstructiveGraphQLOptions, + ConstructiveOptions} from './constructive'; // Export GraphQL adapter types export { @@ -25,13 +23,11 @@ export { // Export LLM types export { - LlmOptions, + LlmChatOptions, LlmEmbedderOptions, - LlmChatOptions -} from './llm'; + LlmOptions} from './llm'; // Export SMS types export { - SmsOptions, - DevSmsOptions -} from './sms'; + DevSmsOptions, + SmsOptions} from './sms'; diff --git a/package.json b/package.json index f1929482ca..197e3b3514 100644 --- a/package.json +++ b/package.json @@ -25,6 +25,7 @@ "fixtures:install:force": "node pgpm/cli/dist/index.js install -W --force" }, "devDependencies": { + "@constructive-io/eslint-config": "^0.2.0", "@jest/test-sequencer": "^30.4.1", "@types/jest": "^30.0.0", "@types/jest-in-case": "^1.0.9", diff --git a/packages/bucket-provisioner/__tests__/client.test.ts b/packages/bucket-provisioner/__tests__/client.test.ts index facea29f37..6afd559a68 100644 --- a/packages/bucket-provisioner/__tests__/client.test.ts +++ b/packages/bucket-provisioner/__tests__/client.test.ts @@ -3,8 +3,8 @@ */ import { createS3Client } from '../src/client'; -import { ProvisionerError } from '../src/types'; import type { StorageConnectionConfig } from '../src/types'; +import { ProvisionerError } from '../src/types'; describe('createS3Client', () => { const baseConfig: StorageConnectionConfig = { diff --git a/packages/bucket-provisioner/__tests__/cors.test.ts b/packages/bucket-provisioner/__tests__/cors.test.ts index ab6049845e..94a01fd3d1 100644 --- a/packages/bucket-provisioner/__tests__/cors.test.ts +++ b/packages/bucket-provisioner/__tests__/cors.test.ts @@ -2,7 +2,7 @@ * Tests for CORS configuration builders. */ -import { buildUploadCorsRules, buildPrivateCorsRules } from '../src/cors'; +import { buildPrivateCorsRules,buildUploadCorsRules } from '../src/cors'; describe('buildUploadCorsRules', () => { it('builds rules with allowed origins', () => { diff --git a/packages/bucket-provisioner/__tests__/lifecycle.test.ts b/packages/bucket-provisioner/__tests__/lifecycle.test.ts index 7af21e98b7..af98ccbf67 100644 --- a/packages/bucket-provisioner/__tests__/lifecycle.test.ts +++ b/packages/bucket-provisioner/__tests__/lifecycle.test.ts @@ -2,7 +2,7 @@ * Tests for lifecycle rule builders. */ -import { buildTempCleanupRule, buildAbortIncompleteMultipartRule } from '../src/lifecycle'; +import { buildAbortIncompleteMultipartRule,buildTempCleanupRule } from '../src/lifecycle'; describe('buildTempCleanupRule', () => { it('builds rule with default 1-day expiration', () => { diff --git a/packages/bucket-provisioner/__tests__/policies.test.ts b/packages/bucket-provisioner/__tests__/policies.test.ts index 82247fd6b8..dac306d6b3 100644 --- a/packages/bucket-provisioner/__tests__/policies.test.ts +++ b/packages/bucket-provisioner/__tests__/policies.test.ts @@ -3,10 +3,10 @@ */ import { - getPublicAccessBlock, - buildPublicReadPolicy, buildCloudFrontOacPolicy, buildPresignedUrlIamPolicy, + buildPublicReadPolicy, + getPublicAccessBlock, } from '../src/policies'; describe('getPublicAccessBlock', () => { diff --git a/packages/bucket-provisioner/__tests__/provisioner.test.ts b/packages/bucket-provisioner/__tests__/provisioner.test.ts index 64023153a1..fa75e004e9 100644 --- a/packages/bucket-provisioner/__tests__/provisioner.test.ts +++ b/packages/bucket-provisioner/__tests__/provisioner.test.ts @@ -6,8 +6,8 @@ * are sent with the right parameters. */ -import { BucketProvisioner } from '../src/provisioner'; import type { BucketProvisionerOptions } from '../src/provisioner'; +import { BucketProvisioner } from '../src/provisioner'; import { ProvisionerError } from '../src/types'; // We mock the S3Client.send at the instance level diff --git a/packages/bucket-provisioner/__tests__/types.test.ts b/packages/bucket-provisioner/__tests__/types.test.ts index adf8da2d93..84f4f37e6d 100644 --- a/packages/bucket-provisioner/__tests__/types.test.ts +++ b/packages/bucket-provisioner/__tests__/types.test.ts @@ -2,17 +2,17 @@ * Tests for types and error classes. */ -import { ProvisionerError } from '../src/types'; import type { - StorageProvider, - StorageConnectionConfig, BucketAccessType, - CreateBucketOptions, CorsRule, + CreateBucketOptions, LifecycleRule, - ProvisionResult, ProvisionerErrorCode, + ProvisionResult, + StorageConnectionConfig, + StorageProvider, } from '../src/types'; +import { ProvisionerError } from '../src/types'; describe('ProvisionerError', () => { it('creates error with code and message', () => { diff --git a/packages/bucket-provisioner/src/client.ts b/packages/bucket-provisioner/src/client.ts index 1dd13b4ba4..ebeb4e2904 100644 --- a/packages/bucket-provisioner/src/client.ts +++ b/packages/bucket-provisioner/src/client.ts @@ -6,11 +6,12 @@ * continue to work without changes. */ -import { createS3Client as createS3ClientFromUtils, S3ConfigError } from '@constructive-io/s3-utils'; import type { S3Client } from '@aws-sdk/client-s3'; +import { createS3Client as createS3ClientFromUtils, S3ConfigError } from '@constructive-io/s3-utils'; + import type { StorageConnectionConfig } from './types'; -import { ProvisionerError } from './types'; import type { ProvisionerErrorCode } from './types'; +import { ProvisionerError } from './types'; /** * Create an S3Client from a storage connection config. diff --git a/packages/bucket-provisioner/src/index.ts b/packages/bucket-provisioner/src/index.ts index 9fdd9700fe..a9e625489d 100644 --- a/packages/bucket-provisioner/src/index.ts +++ b/packages/bucket-provisioner/src/index.ts @@ -28,41 +28,41 @@ */ // Core provisioner -export { BucketProvisioner } from './provisioner'; export type { BucketProvisionerOptions } from './provisioner'; +export { BucketProvisioner } from './provisioner'; // S3 client factory export { createS3Client } from './client'; // Policy builders -export { - getPublicAccessBlock, - buildPublicReadPolicy, - buildCloudFrontOacPolicy, - buildPresignedUrlIamPolicy, -} from './policies'; export type { - PublicAccessBlockConfig, BucketPolicyDocument, BucketPolicyStatement, + PublicAccessBlockConfig, +} from './policies'; +export { + buildCloudFrontOacPolicy, + buildPresignedUrlIamPolicy, + buildPublicReadPolicy, + getPublicAccessBlock, } from './policies'; // CORS builders -export { buildUploadCorsRules, buildPrivateCorsRules } from './cors'; +export { buildPrivateCorsRules,buildUploadCorsRules } from './cors'; // Lifecycle builders -export { buildTempCleanupRule, buildAbortIncompleteMultipartRule } from './lifecycle'; +export { buildAbortIncompleteMultipartRule,buildTempCleanupRule } from './lifecycle'; // Types export type { - StorageProvider, - StorageConnectionConfig, BucketAccessType, - CreateBucketOptions, - UpdateCorsOptions, CorsRule, + CreateBucketOptions, LifecycleRule, - ProvisionResult, ProvisionerErrorCode, + ProvisionResult, + StorageConnectionConfig, + StorageProvider, + UpdateCorsOptions, } from './types'; export { ProvisionerError } from './types'; diff --git a/packages/bucket-provisioner/src/provisioner.ts b/packages/bucket-provisioner/src/provisioner.ts index 8e12ff5dc4..de6a45cf2a 100644 --- a/packages/bucket-provisioner/src/provisioner.ts +++ b/packages/bucket-provisioner/src/provisioner.ts @@ -10,38 +10,38 @@ * - Public buckets: Block Public Access partially relaxed, public-read bucket policy applied */ +import type { S3Client } from '@aws-sdk/client-s3'; import { CreateBucketCommand, - PutPublicAccessBlockCommand, - PutBucketPolicyCommand, DeleteBucketPolicyCommand, - PutBucketCorsCommand, - PutBucketVersioningCommand, - PutBucketLifecycleConfigurationCommand, - HeadBucketCommand, - GetBucketPolicyCommand, GetBucketCorsCommand, - GetBucketVersioningCommand, GetBucketLifecycleConfigurationCommand, + GetBucketPolicyCommand, + GetBucketVersioningCommand, GetPublicAccessBlockCommand, + HeadBucketCommand, + PutBucketCorsCommand, + PutBucketLifecycleConfigurationCommand, + PutBucketPolicyCommand, + PutBucketVersioningCommand, + PutPublicAccessBlockCommand, } from '@aws-sdk/client-s3'; -import type { S3Client } from '@aws-sdk/client-s3'; +import { createS3Client } from './client'; +import { buildPrivateCorsRules,buildUploadCorsRules } from './cors'; +import { buildTempCleanupRule } from './lifecycle'; +import type { BucketPolicyDocument, PublicAccessBlockConfig } from './policies'; +import { buildPublicReadPolicy,getPublicAccessBlock } from './policies'; import type { - StorageConnectionConfig, - CreateBucketOptions, - UpdateCorsOptions, + BucketAccessType, CorsRule, + CreateBucketOptions, LifecycleRule, ProvisionResult, - BucketAccessType, + StorageConnectionConfig, + UpdateCorsOptions, } from './types'; import { ProvisionerError } from './types'; -import { createS3Client } from './client'; -import { getPublicAccessBlock, buildPublicReadPolicy } from './policies'; -import type { BucketPolicyDocument, PublicAccessBlockConfig } from './policies'; -import { buildUploadCorsRules, buildPrivateCorsRules } from './cors'; -import { buildTempCleanupRule } from './lifecycle'; /** * Options for the BucketProvisioner constructor. diff --git a/packages/cli/__tests__/codegen.test.ts b/packages/cli/__tests__/codegen.test.ts index 9282a84879..239825bbcd 100644 --- a/packages/cli/__tests__/codegen.test.ts +++ b/packages/cli/__tests__/codegen.test.ts @@ -1,5 +1,6 @@ -import type { ParsedArgs } from 'inquirerer' -import codegenCommand from '../src/commands/codegen' +import type { ParsedArgs } from 'inquirerer'; + +import codegenCommand from '../src/commands/codegen'; const mockRunCodegenHandler = jest.fn, [Record, unknown]>(); @@ -13,25 +14,25 @@ const createMockPrompter = () => ({ describe('codegen command', () => { beforeEach(() => { - jest.clearAllMocks() - }) + jest.clearAllMocks(); + }); it('prints usage and exits with code 0 when --help is set', async () => { - const spyLog = jest.spyOn(console, 'log').mockImplementation(() => {}) - const spyExit = jest.spyOn(process, 'exit').mockImplementation(((code?: number) => { throw new Error('exit:' + code) }) as any) + const spyLog = jest.spyOn(console, 'log').mockImplementation(() => {}); + const spyExit = jest.spyOn(process, 'exit').mockImplementation(((code?: number) => { throw new Error('exit:' + code); }) as any); - const argv: Partial = { help: true } - const mockPrompter = createMockPrompter() + const argv: Partial = { help: true }; + const mockPrompter = createMockPrompter(); - await expect(codegenCommand(argv, mockPrompter as any, {} as any)).rejects.toThrow('exit:0') - expect(spyLog).toHaveBeenCalled() - const first = (spyLog.mock.calls[0]?.[0] as string) || '' - expect(first).toContain('Constructive GraphQL Codegen') - expect(mockRunCodegenHandler).not.toHaveBeenCalled() + await expect(codegenCommand(argv, mockPrompter as any, {} as any)).rejects.toThrow('exit:0'); + expect(spyLog).toHaveBeenCalled(); + const first = (spyLog.mock.calls[0]?.[0] as string) || ''; + expect(first).toContain('Constructive GraphQL Codegen'); + expect(mockRunCodegenHandler).not.toHaveBeenCalled(); - spyLog.mockRestore() - spyExit.mockRestore() - }) + spyLog.mockRestore(); + spyExit.mockRestore(); + }); it('delegates to runCodegenHandler for endpoint flow', async () => { const argv: Partial = { @@ -41,24 +42,24 @@ describe('codegen command', () => { verbose: true, dryRun: true, reactQuery: true, - } - const mockPrompter = createMockPrompter() + }; + const mockPrompter = createMockPrompter(); - await codegenCommand(argv, mockPrompter as any, {} as any) + await codegenCommand(argv, mockPrompter as any, {} as any); - expect(mockRunCodegenHandler).toHaveBeenCalledWith(argv, mockPrompter) - }) + expect(mockRunCodegenHandler).toHaveBeenCalledWith(argv, mockPrompter); + }); it('delegates to runCodegenHandler for db options', async () => { const argv: Partial = { schemas: 'public,app', output: 'graphql/codegen/dist', reactQuery: true, - } - const mockPrompter = createMockPrompter() + }; + const mockPrompter = createMockPrompter(); - await codegenCommand(argv, mockPrompter as any, {} as any) + await codegenCommand(argv, mockPrompter as any, {} as any); - expect(mockRunCodegenHandler).toHaveBeenCalledWith(argv, mockPrompter) - }) -}) + expect(mockRunCodegenHandler).toHaveBeenCalledWith(argv, mockPrompter); + }); +}); diff --git a/packages/cli/src/commands.ts b/packages/cli/src/commands.ts index c4cffea298..63f70b7731 100644 --- a/packages/cli/src/commands.ts +++ b/packages/cli/src/commands.ts @@ -1,5 +1,5 @@ import { checkForUpdates } from '@inquirerer/utils'; -import { CLIOptions, Inquirerer, ParsedArgs, cliExitWithError, extractFirst, getPackageJson } from 'inquirerer'; +import { cliExitWithError, CLIOptions, extractFirst, getPackageJson,Inquirerer, ParsedArgs } from 'inquirerer'; import auth from './commands/auth'; import codegen from './commands/codegen'; diff --git a/packages/cli/src/commands/auth.ts b/packages/cli/src/commands/auth.ts index 43544fd1f5..2fdf2c58ae 100644 --- a/packages/cli/src/commands/auth.ts +++ b/packages/cli/src/commands/auth.ts @@ -2,17 +2,18 @@ * Authentication commands for the CNC execution engine */ -import { CLIOptions, Inquirerer, extractFirst } from 'inquirerer'; +import { CLIOptions, extractFirst,Inquirerer } from 'inquirerer'; import chalk from 'yanse'; + import { - getCurrentContext, - loadContext, - listContexts, getContextCredentials, - setContextCredentials, - removeContextCredentials, + getCurrentContext, hasValidCredentials, + listContexts, + loadContext, loadSettings, + removeContextCredentials, + setContextCredentials, } from '../config'; const usage = ` @@ -71,16 +72,16 @@ async function handleSubcommand( prompter: Inquirerer ) { switch (subcommand) { - case 'set-token': - return handleSetToken(argv, prompter); - case 'status': - return handleStatus(argv); - case 'logout': - return handleLogout(argv, prompter); - default: - console.log(usage); - console.error(chalk.red(`Unknown subcommand: ${subcommand}`)); - process.exit(1); + case 'set-token': + return handleSetToken(argv, prompter); + case 'status': + return handleStatus(argv); + case 'logout': + return handleLogout(argv, prompter); + default: + console.log(usage); + console.error(chalk.red(`Unknown subcommand: ${subcommand}`)); + process.exit(1); } } diff --git a/packages/cli/src/commands/codegen.ts b/packages/cli/src/commands/codegen.ts index 062656f64a..fc7baaf380 100644 --- a/packages/cli/src/commands/codegen.ts +++ b/packages/cli/src/commands/codegen.ts @@ -1,5 +1,5 @@ -import type { CLIOptions, Inquirerer } from 'inquirerer'; import { runCodegenHandler } from '@constructive-io/graphql-codegen'; +import type { CLIOptions, Inquirerer } from 'inquirerer'; const usage = ` Constructive GraphQL Codegen: diff --git a/packages/cli/src/commands/context.ts b/packages/cli/src/commands/context.ts index d91b711112..1df7078731 100644 --- a/packages/cli/src/commands/context.ts +++ b/packages/cli/src/commands/context.ts @@ -3,19 +3,20 @@ * Similar to kubectl contexts - manages named endpoint + credential configurations */ -import { CLIOptions, Inquirerer, extractFirst } from 'inquirerer'; +import { CLIOptions, extractFirst,Inquirerer } from 'inquirerer'; import chalk from 'yanse'; + import { createContext, - listContexts, - loadContext, deleteContext, + getContextCredentials, getCurrentContext, - setCurrentContext, + hasValidCredentials, + listContexts, + loadContext, loadSettings, saveSettings, - getContextCredentials, - hasValidCredentials, + setCurrentContext, } from '../config'; const usage = ` @@ -76,20 +77,20 @@ async function handleSubcommand( prompter: Inquirerer ) { switch (subcommand) { - case 'create': - return handleCreate(argv, prompter); - case 'list': - return handleList(); - case 'use': - return handleUse(argv, prompter); - case 'current': - return handleCurrent(); - case 'delete': - return handleDelete(argv, prompter); - default: - console.log(usage); - console.error(chalk.red(`Unknown subcommand: ${subcommand}`)); - process.exit(1); + case 'create': + return handleCreate(argv, prompter); + case 'list': + return handleList(); + case 'use': + return handleUse(argv, prompter); + case 'current': + return handleCurrent(); + case 'delete': + return handleDelete(argv, prompter); + default: + console.log(usage); + console.error(chalk.red(`Unknown subcommand: ${subcommand}`)); + process.exit(1); } } diff --git a/packages/cli/src/commands/execute.ts b/packages/cli/src/commands/execute.ts index 69e8859da8..6541c08e1e 100644 --- a/packages/cli/src/commands/execute.ts +++ b/packages/cli/src/commands/execute.ts @@ -5,6 +5,7 @@ import * as fs from 'fs'; import { CLIOptions, Inquirerer } from 'inquirerer'; import chalk from 'yanse'; + import { execute, getExecutionContext } from '../sdk'; const usage = ` diff --git a/packages/cli/src/config/config-manager.ts b/packages/cli/src/config/config-manager.ts index 2dbe2c9130..54dddc80d0 100644 --- a/packages/cli/src/config/config-manager.ts +++ b/packages/cli/src/config/config-manager.ts @@ -3,14 +3,15 @@ * Uses appstash for directory resolution */ +import { appstash, resolve } from 'appstash'; import * as fs from 'fs'; import * as path from 'path'; -import { appstash, resolve } from 'appstash'; + import type { ContextConfig, - GlobalSettings, - Credentials, ContextCredentials, + Credentials, + GlobalSettings, } from './types'; import { DEFAULT_SETTINGS } from './types'; diff --git a/packages/cli/src/config/index.ts b/packages/cli/src/config/index.ts index a1c6f42014..584cfa651c 100644 --- a/packages/cli/src/config/index.ts +++ b/packages/cli/src/config/index.ts @@ -2,5 +2,5 @@ * Config module exports */ -export * from './types'; export * from './config-manager'; +export * from './types'; diff --git a/packages/cli/src/sdk/executor.ts b/packages/cli/src/sdk/executor.ts index e39b0f6660..08188beca5 100644 --- a/packages/cli/src/sdk/executor.ts +++ b/packages/cli/src/sdk/executor.ts @@ -3,14 +3,14 @@ * Executes raw GraphQL queries against configured endpoints */ -import { executeGraphQL, QueryResult } from './client'; +import type { ContextConfig } from '../config'; import { - getCurrentContext, - loadContext, getContextCredentials, + getCurrentContext, hasValidCredentials, + loadContext, } from '../config'; -import type { ContextConfig } from '../config'; +import { executeGraphQL, QueryResult } from './client'; /** * Execution context - bundles context config with credentials diff --git a/packages/cli/test-utils/fixtures.ts b/packages/cli/test-utils/fixtures.ts index 1d95363892..f9082438ff 100644 --- a/packages/cli/test-utils/fixtures.ts +++ b/packages/cli/test-utils/fixtures.ts @@ -1,5 +1,5 @@ -import path from 'path'; import { createTestFixture, TestFixture as BaseTestFixture, TestFixtureOptions } from '@inquirerer/test'; +import path from 'path'; import { commands } from '../src/commands'; diff --git a/packages/csrf/__tests__/csrf.test.ts b/packages/csrf/__tests__/csrf.test.ts index cf884c4e1d..71befb43fd 100644 --- a/packages/csrf/__tests__/csrf.test.ts +++ b/packages/csrf/__tests__/csrf.test.ts @@ -1,4 +1,4 @@ -import { generateToken, verifyToken, createCsrfMiddleware } from '../src'; +import { createCsrfMiddleware,generateToken, verifyToken } from '../src'; describe('token utilities', () => { describe('generateToken', () => { diff --git a/packages/csrf/src/index.ts b/packages/csrf/src/index.ts index 3f778eac4d..5be66dcd2e 100644 --- a/packages/csrf/src/index.ts +++ b/packages/csrf/src/index.ts @@ -1,11 +1,9 @@ -export { CsrfConfig, CookieOptions, CsrfError, createCsrfError } from './types'; - -export { generateToken, verifyToken } from './token'; - export { createCsrfMiddleware, csrfErrorHandler, + CsrfMiddlewareResult, CsrfRequest, CsrfResponse, - CsrfMiddlewareResult, } from './middleware'; +export { generateToken, verifyToken } from './token'; +export { CookieOptions, createCsrfError,CsrfConfig, CsrfError } from './types'; diff --git a/packages/csrf/src/middleware.ts b/packages/csrf/src/middleware.ts index eb7eab28a0..c8dbe74fca 100644 --- a/packages/csrf/src/middleware.ts +++ b/packages/csrf/src/middleware.ts @@ -1,5 +1,5 @@ -import { CsrfConfig, CookieOptions, createCsrfError } from './types'; import { generateToken, verifyToken } from './token'; +import { CookieOptions, createCsrfError,CsrfConfig } from './types'; const DEFAULT_CONFIG: Required = { cookieName: 'csrf_token', diff --git a/packages/csv-to-pg/__tests__/csv2pg.test.ts b/packages/csv-to-pg/__tests__/csv2pg.test.ts index 3c0ecd6e09..7958e403ae 100644 --- a/packages/csv-to-pg/__tests__/csv2pg.test.ts +++ b/packages/csv-to-pg/__tests__/csv2pg.test.ts @@ -1,10 +1,11 @@ // @ts-nocheck -import { parse, parseTypes } from '../src'; +import { nodes } from '@pgsql/utils'; +import cases from 'jest-in-case'; import { resolve } from 'path'; import { deparse } from 'pgsql-deparser'; -import { InsertOne, InsertMany } from '../src/utils'; -import cases from 'jest-in-case'; -import { nodes } from '@pgsql/utils'; + +import { parse, parseTypes } from '../src'; +import { InsertMany,InsertOne } from '../src/utils'; const zips = resolve(__dirname + '/../__fixtures__/zip.csv'); const withHeaders = resolve(__dirname + '/../__fixtures__/headers.csv'); diff --git a/packages/csv-to-pg/__tests__/export.test.ts b/packages/csv-to-pg/__tests__/export.test.ts index eaa8ad4729..dd396c2481 100644 --- a/packages/csv-to-pg/__tests__/export.test.ts +++ b/packages/csv-to-pg/__tests__/export.test.ts @@ -1,10 +1,11 @@ // @ts-nocheck -import { parse, parseTypes } from '../src'; import { resolve } from 'path'; import { deparse } from 'pgsql-deparser'; -import { InsertOne, InsertMany } from '../src/utils'; + +import { parse, parseTypes } from '../src'; import { Parser } from '../src/parser'; +import { InsertMany } from '../src/utils'; const testCase = resolve(__dirname + '/../__fixtures__/test-case.csv'); @@ -45,337 +46,337 @@ it('noop', () => { expect(true).toBe(true); }); describe('test case', () => { -it('test case', async () => { - const records = await parse(testCase, { headers: config.headers }); - const types = parseTypes(config); - const stmt = InsertMany({ - schema: config.schema, - table: config.table, - types, - records + it('test case', async () => { + const records = await parse(testCase, { headers: config.headers }); + const types = parseTypes(config); + const stmt = InsertMany({ + schema: config.schema, + table: config.table, + types, + records + }); + + expect(deparse([stmt])).toMatchSnapshot(); }); - expect(deparse([stmt])).toMatchSnapshot(); -}); - -it('test case parser', async () => { - const parser = new Parser(config); - - const sql = await parser.parse([ - { - id: '450e3b3b-b68d-4abc-990c-65cb8a1dcdb4', - database_id: '450e3b3b-b68d-4abc-990c-65cb8a1dcdb4', - table_id: '450e3b3b-b68d-4abc-990c-65cb8a1dcdb4', - name: 'name here', - description: 'description' - } - ]); + it('test case parser', async () => { + const parser = new Parser(config); - expect(sql).toMatchSnapshot(); -}); + const sql = await parser.parse([ + { + id: '450e3b3b-b68d-4abc-990c-65cb8a1dcdb4', + database_id: '450e3b3b-b68d-4abc-990c-65cb8a1dcdb4', + table_id: '450e3b3b-b68d-4abc-990c-65cb8a1dcdb4', + name: 'name here', + description: 'description' + } + ]); -it('jsonb/json', async () => { - const parser = new Parser({ - schema: 'metaschema_public', - singleStmts: true, - table: 'field', - fields: { - id: 'uuid', - name: 'text', - data: 'jsonb' - } + expect(sql).toMatchSnapshot(); }); - const sql = await parser.parse([ - { - id: '450e3b3b-b68d-4abc-990c-65cb8a1dcdb4', - name: 'name here', - data: { - a: 1 + it('jsonb/json', async () => { + const parser = new Parser({ + schema: 'metaschema_public', + singleStmts: true, + table: 'field', + fields: { + id: 'uuid', + name: 'text', + data: 'jsonb' } - } - ]); - - expect(sql).toMatchSnapshot(); -}); + }); + + const sql = await parser.parse([ + { + id: '450e3b3b-b68d-4abc-990c-65cb8a1dcdb4', + name: 'name here', + data: { + a: 1 + } + } + ]); -it('image/attachment', async () => { - const parser = new Parser({ - schema: 'metaschema_public', - singleStmts: true, - table: 'field', - fields: { - id: 'uuid', - name: 'text', - image: 'image', - upload: 'attachment' - } + expect(sql).toMatchSnapshot(); }); - const sql = await parser.parse([ - { - id: '450e3b3b-b68d-4abc-990c-65cb8a1dcdb4', - name: 'name here', - image: { - url: 'http://path/to/image.jpg' - }, - upload: { - url: 'http://path/to/image.jpg' + it('image/attachment', async () => { + const parser = new Parser({ + schema: 'metaschema_public', + singleStmts: true, + table: 'field', + fields: { + id: 'uuid', + name: 'text', + image: 'image', + upload: 'attachment' } - } - ]); - - expect(sql).toMatchSnapshot(); -}); + }); + + const sql = await parser.parse([ + { + id: '450e3b3b-b68d-4abc-990c-65cb8a1dcdb4', + name: 'name here', + image: { + url: 'http://path/to/image.jpg' + }, + upload: { + url: 'http://path/to/image.jpg' + } + } + ]); -it('arrays', async () => { - const parser = new Parser({ - schema: 'metaschema_public', - singleStmts: true, - table: 'field', - fields: { - id: 'uuid', - schemas: 'text[]' - } + expect(sql).toMatchSnapshot(); }); - const sql = await parser.parse([ - { - id: '450e3b3b-b68d-4abc-990c-65cb8a1dcdb4', - schemas: ['a', 'b'] - } - ]); + it('arrays', async () => { + const parser = new Parser({ + schema: 'metaschema_public', + singleStmts: true, + table: 'field', + fields: { + id: 'uuid', + schemas: 'text[]' + } + }); - expect(sql).toMatchSnapshot(); - }); + const sql = await parser.parse([ + { + id: '450e3b3b-b68d-4abc-990c-65cb8a1dcdb4', + schemas: ['a', 'b'] + } + ]); -it('uuid[] arrays', async () => { - const parser = new Parser({ - schema: 'metaschema_public', - singleStmts: true, - table: 'primary_key_constraint', - fields: { - id: 'uuid', - database_id: 'uuid', - table_id: 'uuid', - name: 'text', - field_ids: 'uuid[]' - } + expect(sql).toMatchSnapshot(); }); - const sql = await parser.parse([ - { - id: 'cdc96a32-572c-4f69-8bce-4c7bd4024a4e', - database_id: '8e739194-ced7-479b-b46c-e6b06146ac11', - table_id: '6616358d-8da8-45e4-834f-d735a0f02acc', - name: 'object_pkey', - field_ids: ['f853daae-f563-447d-ac09-901ddd68586e', 'a4257181-147d-4558-a51f-4b43246527a2'] - }, - { - id: '03d7007c-5262-4250-9ce1-efcabc5bedea', - database_id: '8e739194-ced7-479b-b46c-e6b06146ac11', - table_id: '535d5894-679a-4a7b-aa5a-bd07cce8a505', - name: 'ref_pkey', - field_ids: ['8cc2da93-a8e0-4565-9d14-f814c3a1432d', '40a34889-eb4c-4833-8daf-b99441962971'] - } - ]); - - expect(sql).toMatchSnapshot(); -}); + it('uuid[] arrays', async () => { + const parser = new Parser({ + schema: 'metaschema_public', + singleStmts: true, + table: 'primary_key_constraint', + fields: { + id: 'uuid', + database_id: 'uuid', + table_id: 'uuid', + name: 'text', + field_ids: 'uuid[]' + } + }); + + const sql = await parser.parse([ + { + id: 'cdc96a32-572c-4f69-8bce-4c7bd4024a4e', + database_id: '8e739194-ced7-479b-b46c-e6b06146ac11', + table_id: '6616358d-8da8-45e4-834f-d735a0f02acc', + name: 'object_pkey', + field_ids: ['f853daae-f563-447d-ac09-901ddd68586e', 'a4257181-147d-4558-a51f-4b43246527a2'] + }, + { + id: '03d7007c-5262-4250-9ce1-efcabc5bedea', + database_id: '8e739194-ced7-479b-b46c-e6b06146ac11', + table_id: '535d5894-679a-4a7b-aa5a-bd07cce8a505', + name: 'ref_pkey', + field_ids: ['8cc2da93-a8e0-4565-9d14-f814c3a1432d', '40a34889-eb4c-4833-8daf-b99441962971'] + } + ]); -it('interval type', async () => { - const parser = new Parser({ - schema: 'metaschema_modules_public', - singleStmts: true, - table: 'tokens_module', - fields: { - id: 'uuid', - database_id: 'uuid', - tokens_default_expiration: 'interval', - tokens_table: 'text' - } + expect(sql).toMatchSnapshot(); }); - const sql = await parser.parse([ - { - id: '42aaba39-de20-4be0-95a1-4873d7d4b6d4', - database_id: '8e739194-ced7-479b-b46c-e6b06146ac11', - tokens_default_expiration: { hours: 24 }, - tokens_table: 'api_tokens' - }, - { - id: '550e8400-e29b-41d4-a716-446655440000', - database_id: '8e739194-ced7-479b-b46c-e6b06146ac11', - tokens_default_expiration: { days: 7, hours: 12, minutes: 30 }, - tokens_table: 'refresh_tokens' - }, - { - id: '6ba7b810-9dad-11d1-80b4-00c04fd430c8', - database_id: '8e739194-ced7-479b-b46c-e6b06146ac11', - tokens_default_expiration: { years: 1, months: 6 }, - tokens_table: 'long_lived_tokens' - } - ]); - - expect(sql).toMatchSnapshot(); -}); + it('interval type', async () => { + const parser = new Parser({ + schema: 'metaschema_modules_public', + singleStmts: true, + table: 'tokens_module', + fields: { + id: 'uuid', + database_id: 'uuid', + tokens_default_expiration: 'interval', + tokens_table: 'text' + } + }); + + const sql = await parser.parse([ + { + id: '42aaba39-de20-4be0-95a1-4873d7d4b6d4', + database_id: '8e739194-ced7-479b-b46c-e6b06146ac11', + tokens_default_expiration: { hours: 24 }, + tokens_table: 'api_tokens' + }, + { + id: '550e8400-e29b-41d4-a716-446655440000', + database_id: '8e739194-ced7-479b-b46c-e6b06146ac11', + tokens_default_expiration: { days: 7, hours: 12, minutes: 30 }, + tokens_table: 'refresh_tokens' + }, + { + id: '6ba7b810-9dad-11d1-80b4-00c04fd430c8', + database_id: '8e739194-ced7-479b-b46c-e6b06146ac11', + tokens_default_expiration: { years: 1, months: 6 }, + tokens_table: 'long_lived_tokens' + } + ]); -it('null array fields emit empty array literal instead of NULL', async () => { - const parser = new Parser({ - schema: 'metaschema_modules_public', - singleStmts: true, - table: 'secure_table_provision', - fields: { - id: 'uuid', - node_type: 'text', - fields: 'jsonb[]', - out_fields: 'uuid[]' - } + expect(sql).toMatchSnapshot(); }); - const sql = await parser.parse([ - { - id: '450e3b3b-b68d-4abc-990c-65cb8a1dcdb4', - node_type: 'DataTimestamps', - fields: null, - out_fields: null - } - ]); - - // Should emit '{}' for array columns instead of NULL - expect(sql).toContain("'{}'"); - expect(sql).not.toContain('NULL'); - expect(sql).toMatchSnapshot(); -}); + it('null array fields emit empty array literal instead of NULL', async () => { + const parser = new Parser({ + schema: 'metaschema_modules_public', + singleStmts: true, + table: 'secure_table_provision', + fields: { + id: 'uuid', + node_type: 'text', + fields: 'jsonb[]', + out_fields: 'uuid[]' + } + }); + + const sql = await parser.parse([ + { + id: '450e3b3b-b68d-4abc-990c-65cb8a1dcdb4', + node_type: 'DataTimestamps', + fields: null, + out_fields: null + } + ]); -it('empty array fields emit empty array literal', async () => { - const parser = new Parser({ - schema: 'metaschema_modules_public', - singleStmts: true, - table: 'secure_table_provision', - fields: { - id: 'uuid', - node_type: 'text', - fields: 'jsonb[]', - out_fields: 'uuid[]' - } + // Should emit '{}' for array columns instead of NULL + expect(sql).toContain("'{}'"); + expect(sql).not.toContain('NULL'); + expect(sql).toMatchSnapshot(); }); - const sql = await parser.parse([ - { - id: '450e3b3b-b68d-4abc-990c-65cb8a1dcdb4', - node_type: 'DataTimestamps', - fields: [], - out_fields: [] - } - ]); - - // Empty arrays should also emit '{}' not NULL - expect(sql).toContain("'{}'"); - expect(sql).not.toContain('NULL'); - expect(sql).toMatchSnapshot(); -}); + it('empty array fields emit empty array literal', async () => { + const parser = new Parser({ + schema: 'metaschema_modules_public', + singleStmts: true, + table: 'secure_table_provision', + fields: { + id: 'uuid', + node_type: 'text', + fields: 'jsonb[]', + out_fields: 'uuid[]' + } + }); + + const sql = await parser.parse([ + { + id: '450e3b3b-b68d-4abc-990c-65cb8a1dcdb4', + node_type: 'DataTimestamps', + fields: [], + out_fields: [] + } + ]); -it('text fields preserve empty strings by default', async () => { - const parser = new Parser({ - schema: 'app_public', - singleStmts: true, - table: 'webauthn_settings', - fields: { - id: 'uuid', - database_id: 'uuid', - rp_id: 'text', - rp_name: 'text' - } + // Empty arrays should also emit '{}' not NULL + expect(sql).toContain("'{}'"); + expect(sql).not.toContain('NULL'); + expect(sql).toMatchSnapshot(); }); - const sql = await parser.parse([ - { - id: '450e3b3b-b68d-4abc-990c-65cb8a1dcdb4', - database_id: '550e8400-e29b-41d4-a716-446655440000', - rp_id: '', - rp_name: '' - } - ]); - - // Default: empty strings are preserved as '' - expect(sql).not.toContain('NULL'); - expect(sql).toMatchSnapshot(); -}); + it('text fields preserve empty strings by default', async () => { + const parser = new Parser({ + schema: 'app_public', + singleStmts: true, + table: 'webauthn_settings', + fields: { + id: 'uuid', + database_id: 'uuid', + rp_id: 'text', + rp_name: 'text' + } + }); + + const sql = await parser.parse([ + { + id: '450e3b3b-b68d-4abc-990c-65cb8a1dcdb4', + database_id: '550e8400-e29b-41d4-a716-446655440000', + rp_id: '', + rp_name: '' + } + ]); -it('text fields convert empty strings to NULL when preserveEmptyStrings is false', async () => { - const parser = new Parser({ - schema: 'app_public', - singleStmts: true, - table: 'webauthn_settings', - preserveEmptyStrings: false, - fields: { - id: 'uuid', - database_id: 'uuid', - rp_id: 'text', - rp_name: 'text' - } + // Default: empty strings are preserved as '' + expect(sql).not.toContain('NULL'); + expect(sql).toMatchSnapshot(); }); - const sql = await parser.parse([ - { - id: '450e3b3b-b68d-4abc-990c-65cb8a1dcdb4', - database_id: '550e8400-e29b-41d4-a716-446655440000', - rp_id: '', - rp_name: '' - } - ]); - - // Opt-in: empty strings treated as NULL (CSV convention) - expect(sql).toContain('NULL'); - expect(sql).toMatchSnapshot(); -}); + it('text fields convert empty strings to NULL when preserveEmptyStrings is false', async () => { + const parser = new Parser({ + schema: 'app_public', + singleStmts: true, + table: 'webauthn_settings', + preserveEmptyStrings: false, + fields: { + id: 'uuid', + database_id: 'uuid', + rp_id: 'text', + rp_name: 'text' + } + }); + + const sql = await parser.parse([ + { + id: '450e3b3b-b68d-4abc-990c-65cb8a1dcdb4', + database_id: '550e8400-e29b-41d4-a716-446655440000', + rp_id: '', + rp_name: '' + } + ]); -it('text fields with null values produce NULL', async () => { - const parser = new Parser({ - schema: 'app_public', - singleStmts: true, - table: 'webauthn_settings', - fields: { - id: 'uuid', - database_id: 'uuid', - rp_id: 'text', - rp_name: 'text' - } + // Opt-in: empty strings treated as NULL (CSV convention) + expect(sql).toContain('NULL'); + expect(sql).toMatchSnapshot(); }); - const sql = await parser.parse([ - { - id: '450e3b3b-b68d-4abc-990c-65cb8a1dcdb4', - database_id: '550e8400-e29b-41d4-a716-446655440000', - rp_id: null, - rp_name: null - } - ]); - - // Actual null values should still produce NULL - expect(sql).toContain('NULL'); - expect(sql).toMatchSnapshot(); -}); + it('text fields with null values produce NULL', async () => { + const parser = new Parser({ + schema: 'app_public', + singleStmts: true, + table: 'webauthn_settings', + fields: { + id: 'uuid', + database_id: 'uuid', + rp_id: 'text', + rp_name: 'text' + } + }); + + const sql = await parser.parse([ + { + id: '450e3b3b-b68d-4abc-990c-65cb8a1dcdb4', + database_id: '550e8400-e29b-41d4-a716-446655440000', + rp_id: null, + rp_name: null + } + ]); -it('interval type with string value', async () => { - const parser = new Parser({ - schema: 'metaschema_modules_public', - singleStmts: true, - table: 'tokens_module', - fields: { - id: 'uuid', - tokens_default_expiration: 'interval' - } + // Actual null values should still produce NULL + expect(sql).toContain('NULL'); + expect(sql).toMatchSnapshot(); }); - const sql = await parser.parse([ - { - id: '42aaba39-de20-4be0-95a1-4873d7d4b6d4', - tokens_default_expiration: '1 day 02:30:00' - } - ]); + it('interval type with string value', async () => { + const parser = new Parser({ + schema: 'metaschema_modules_public', + singleStmts: true, + table: 'tokens_module', + fields: { + id: 'uuid', + tokens_default_expiration: 'interval' + } + }); - expect(sql).toMatchSnapshot(); -}); + const sql = await parser.parse([ + { + id: '42aaba39-de20-4be0-95a1-4873d7d4b6d4', + tokens_default_expiration: '1 day 02:30:00' + } + ]); + + expect(sql).toMatchSnapshot(); + }); }); diff --git a/packages/csv-to-pg/jest.config.js b/packages/csv-to-pg/jest.config.js index 0aa3aaa499..057a9420ed 100644 --- a/packages/csv-to-pg/jest.config.js +++ b/packages/csv-to-pg/jest.config.js @@ -1,18 +1,18 @@ /** @type {import('ts-jest').JestConfigWithTsJest} */ module.exports = { - preset: "ts-jest", - testEnvironment: "node", - transform: { - "^.+\\.tsx?$": [ - "ts-jest", - { - babelConfig: false, - tsconfig: "tsconfig.json", - }, - ], - }, - transformIgnorePatterns: [`/node_modules/*`], - testRegex: "(/__tests__/.*|(\\.|/)(test|spec))\\.(jsx?|tsx?)$", - moduleFileExtensions: ["ts", "tsx", "js", "jsx", "json", "node"], - modulePathIgnorePatterns: ["dist/*"] + preset: 'ts-jest', + testEnvironment: 'node', + transform: { + '^.+\\.tsx?$': [ + 'ts-jest', + { + babelConfig: false, + tsconfig: 'tsconfig.json', + }, + ], + }, + transformIgnorePatterns: [`/node_modules/*`], + testRegex: '(/__tests__/.*|(\\.|/)(test|spec))\\.(jsx?|tsx?)$', + moduleFileExtensions: ['ts', 'tsx', 'js', 'jsx', 'json', 'node'], + modulePathIgnorePatterns: ['dist/*'] }; diff --git a/packages/csv-to-pg/src/cli.ts b/packages/csv-to-pg/src/cli.ts index c7f6c1a80d..98552a0f4b 100644 --- a/packages/csv-to-pg/src/cli.ts +++ b/packages/csv-to-pg/src/cli.ts @@ -1,10 +1,11 @@ #!/usr/bin/env node +import { writeFileSync } from 'fs'; import { CLI, type CommandHandler } from 'inquirerer'; +import { dirname } from 'path'; + import { readConfig } from './parse'; import { Parser } from './parser'; import { normalizePath } from './utils'; -import { dirname } from 'path'; -import { writeFileSync } from 'fs'; interface ConfigFile { input?: string; diff --git a/packages/csv-to-pg/src/parse.ts b/packages/csv-to-pg/src/parse.ts index 7e74e2bbf4..320a58299f 100644 --- a/packages/csv-to-pg/src/parse.ts +++ b/packages/csv-to-pg/src/parse.ts @@ -1,12 +1,13 @@ +import type { Node } from '@pgsql/types'; +import { ast, nodes } from '@pgsql/utils'; import csv from 'csv-parser'; import { createReadStream, readFileSync } from 'fs'; import { load as parseYAML } from 'js-yaml'; -import { ast, nodes } from '@pgsql/utils'; -import type { Node } from '@pgsql/types'; + import { + getRelatedField, makeBoundingBox, makeLocation, - getRelatedField, wrapValue } from './utils'; @@ -244,282 +245,282 @@ const getCoercionFunc = (type: string, from: string[], opts: FieldOptions, field const required = opts.required || false; switch (type) { - case 'int': - return (record: Record): Node => { - const rawValue = record[from[0]]; - const value = parseFn(rawValue); - if (isEmpty(value) || isNullToken(rawValue)) { - return makeNullOrThrow(fieldName, rawValue, type, required, 'value is empty or null'); - } - if (!isNumeric(value)) { - return makeNullOrThrow(fieldName, rawValue, type, required, 'value is not numeric'); - } - const val = nodes.aConst({ - ival: ast.integer({ ival: Number(value) }) - }); - return wrapValue(val, opts); - }; - case 'float': - return (record: Record): Node => { - const rawValue = record[from[0]]; - const value = parseFn(rawValue); - if (isEmpty(value) || isNullToken(rawValue)) { - return makeNullOrThrow(fieldName, rawValue, type, required, 'value is empty or null'); - } - if (!isNumeric(value)) { - return makeNullOrThrow(fieldName, rawValue, type, required, 'value is not numeric'); - } + case 'int': + return (record: Record): Node => { + const rawValue = record[from[0]]; + const value = parseFn(rawValue); + if (isEmpty(value) || isNullToken(rawValue)) { + return makeNullOrThrow(fieldName, rawValue, type, required, 'value is empty or null'); + } + if (!isNumeric(value)) { + return makeNullOrThrow(fieldName, rawValue, type, required, 'value is not numeric'); + } + const val = nodes.aConst({ + ival: ast.integer({ ival: Number(value) }) + }); + return wrapValue(val, opts); + }; + case 'float': + return (record: Record): Node => { + const rawValue = record[from[0]]; + const value = parseFn(rawValue); + if (isEmpty(value) || isNullToken(rawValue)) { + return makeNullOrThrow(fieldName, rawValue, type, required, 'value is empty or null'); + } + if (!isNumeric(value)) { + return makeNullOrThrow(fieldName, rawValue, type, required, 'value is not numeric'); + } - const val = nodes.aConst({ - fval: ast.float({ fval: String(value) }) - }); - return wrapValue(val, opts); - }; - case 'boolean': - case 'bool': - return (record: Record): Node => { - const rawValue = record[from[0]]; - const value = parseFn(parseBoolean(rawValue)); - - if (isEmpty(value)) { - return makeNullOrThrow(fieldName, rawValue, type, required, 'value is not a valid boolean'); - } + const val = nodes.aConst({ + fval: ast.float({ fval: String(value) }) + }); + return wrapValue(val, opts); + }; + case 'boolean': + case 'bool': + return (record: Record): Node => { + const rawValue = record[from[0]]; + const value = parseFn(parseBoolean(rawValue)); + + if (isEmpty(value)) { + return makeNullOrThrow(fieldName, rawValue, type, required, 'value is not a valid boolean'); + } - // Use proper boolean constant for PG17 AST - const val = nodes.aConst({ - boolval: ast.boolean({ boolval: Boolean(value) }) - }); - return wrapValue(val, opts); - }; - case 'bbox': - // do bbox magic with args from the fields - return (record: Record): Node => { - const val = makeBoundingBox(String(parseFn(record[from[0]]))); - return wrapValue(val, opts); - }; - case 'location': - return (record: Record): Node => { - const [lon, lat] = getValuesFromKeys(record, from); - if (lon === undefined || lon === null || isNullToken(lon)) { - return makeNullOrThrow(fieldName, { lon, lat }, type, required, 'longitude is missing or null'); - } - if (lat === undefined || lat === null || isNullToken(lat)) { - return makeNullOrThrow(fieldName, { lon, lat }, type, required, 'latitude is missing or null'); - } - if (!isNumeric(lon) || !isNumeric(lat)) { - return makeNullOrThrow(fieldName, { lon, lat }, type, required, 'longitude or latitude is not numeric'); - } + // Use proper boolean constant for PG17 AST + const val = nodes.aConst({ + boolval: ast.boolean({ boolval: Boolean(value) }) + }); + return wrapValue(val, opts); + }; + case 'bbox': + // do bbox magic with args from the fields + return (record: Record): Node => { + const val = makeBoundingBox(String(parseFn(record[from[0]]))); + return wrapValue(val, opts); + }; + case 'location': + return (record: Record): Node => { + const [lon, lat] = getValuesFromKeys(record, from); + if (lon === undefined || lon === null || isNullToken(lon)) { + return makeNullOrThrow(fieldName, { lon, lat }, type, required, 'longitude is missing or null'); + } + if (lat === undefined || lat === null || isNullToken(lat)) { + return makeNullOrThrow(fieldName, { lon, lat }, type, required, 'latitude is missing or null'); + } + if (!isNumeric(lon) || !isNumeric(lat)) { + return makeNullOrThrow(fieldName, { lon, lat }, type, required, 'longitude or latitude is not numeric'); + } - // NO parse here... - const val = makeLocation(lon as string | number, lat as string | number); - return wrapValue(val, opts); - }; - case 'related': - return (record: Record): Node => { - return getRelatedField({ - schema: opts.schema, - table: opts.table!, - refType: opts.refType!, - refKey: opts.refKey!, - refField: opts.refField!, - wrap: opts.wrap, - wrapAst: opts.wrapAst, - cast: opts.cast, - record, - parse: parseFn, - from - }); - }; - case 'uuid': - return (record: Record): Node => { - const rawValue = record[from[0]]; - if (isNullToken(rawValue)) { - return makeNullOrThrow(fieldName, rawValue, type, required, 'value is empty or null'); - } - const value = parseFn(rawValue); - if (isEmpty(value)) { - return makeNullOrThrow(fieldName, rawValue, type, required, 'value is empty'); - } - if (!/^([0-9a-fA-F]{8})-(([0-9a-fA-F]{4}-){3})([0-9a-fA-F]{12})$/i.test(String(value))) { - return makeNullOrThrow(fieldName, rawValue, type, required, 'value is not a valid UUID'); - } - const val = nodes.aConst({ - sval: ast.string({ sval: String(value) }) - }); - return wrapValue(val, opts); - }; - case 'uuid[]': - return (record: Record): Node => { - const rawValue = record[from[0]]; - if (isNullToken(rawValue)) { - return makeNullOrThrow(fieldName, rawValue, type, required, 'value is empty or null'); + // NO parse here... + const val = makeLocation(lon as string | number, lat as string | number); + return wrapValue(val, opts); + }; + case 'related': + return (record: Record): Node => { + return getRelatedField({ + schema: opts.schema, + table: opts.table!, + refType: opts.refType!, + refKey: opts.refKey!, + refField: opts.refField!, + wrap: opts.wrap, + wrapAst: opts.wrapAst, + cast: opts.cast, + record, + parse: parseFn, + from + }); + }; + case 'uuid': + return (record: Record): Node => { + const rawValue = record[from[0]]; + if (isNullToken(rawValue)) { + return makeNullOrThrow(fieldName, rawValue, type, required, 'value is empty or null'); + } + const value = parseFn(rawValue); + if (isEmpty(value)) { + return makeNullOrThrow(fieldName, rawValue, type, required, 'value is empty'); + } + if (!/^([0-9a-fA-F]{8})-(([0-9a-fA-F]{4}-){3})([0-9a-fA-F]{12})$/i.test(String(value))) { + return makeNullOrThrow(fieldName, rawValue, type, required, 'value is not a valid UUID'); + } + const val = nodes.aConst({ + sval: ast.string({ sval: String(value) }) + }); + return wrapValue(val, opts); + }; + case 'uuid[]': + return (record: Record): Node => { + const rawValue = record[from[0]]; + if (isNullToken(rawValue)) { + return makeNullOrThrow(fieldName, rawValue, type, required, 'value is empty or null'); + } + // Handle array values - validate each UUID + if (Array.isArray(rawValue)) { + if (rawValue.length === 0) { + return makeNullOrThrow(fieldName, rawValue, type, required, 'array is empty'); } - // Handle array values - validate each UUID - if (Array.isArray(rawValue)) { - if (rawValue.length === 0) { - return makeNullOrThrow(fieldName, rawValue, type, required, 'array is empty'); - } - const uuidRegex = /^([0-9a-fA-F]{8})-(([0-9a-fA-F]{4}-){3})([0-9a-fA-F]{12})$/i; - for (const item of rawValue) { - if (!uuidRegex.test(String(item))) { - return makeNullOrThrow(fieldName, rawValue, type, required, `array contains invalid UUID: ${item}`); - } + const uuidRegex = /^([0-9a-fA-F]{8})-(([0-9a-fA-F]{4}-){3})([0-9a-fA-F]{12})$/i; + for (const item of rawValue) { + if (!uuidRegex.test(String(item))) { + return makeNullOrThrow(fieldName, rawValue, type, required, `array contains invalid UUID: ${item}`); } - const arrayLiteral = psqlArray(rawValue); - if (isEmpty(arrayLiteral)) { - return makeNullOrThrow(fieldName, rawValue, type, required, 'failed to format array'); - } - const val = nodes.aConst({ - sval: ast.string({ sval: String(arrayLiteral) }) - }); - return wrapValue(val, opts); - } - // If not an array, treat as empty/null - return makeNullOrThrow(fieldName, rawValue, type, required, 'value is not an array'); - }; - case 'interval': - return (record: Record): Node => { - const rawValue = record[from[0]]; - if (isNullToken(rawValue)) { - return makeNullOrThrow(fieldName, rawValue, type, required, 'value is empty or null'); } - const value = formatInterval(rawValue); - if (isEmpty(value)) { - return makeNullOrThrow(fieldName, rawValue, type, required, 'value is empty or invalid interval'); + const arrayLiteral = psqlArray(rawValue); + if (isEmpty(arrayLiteral)) { + return makeNullOrThrow(fieldName, rawValue, type, required, 'failed to format array'); } const val = nodes.aConst({ - sval: ast.string({ sval: String(value) }) + sval: ast.string({ sval: String(arrayLiteral) }) }); return wrapValue(val, opts); - }; - case 'timestamp': - case 'timestamptz': - case 'date': - return (record: Record): Node => { - const rawValue = record[from[0]]; - if (isNullToken(rawValue)) { - return makeNullOrThrow(fieldName, rawValue, type, required, 'value is empty or null'); - } - const value = parseFn(rawValue); - if (isEmpty(value)) { - return makeNullOrThrow(fieldName, rawValue, type, required, 'value is empty'); - } + } + // If not an array, treat as empty/null + return makeNullOrThrow(fieldName, rawValue, type, required, 'value is not an array'); + }; + case 'interval': + return (record: Record): Node => { + const rawValue = record[from[0]]; + if (isNullToken(rawValue)) { + return makeNullOrThrow(fieldName, rawValue, type, required, 'value is empty or null'); + } + const value = formatInterval(rawValue); + if (isEmpty(value)) { + return makeNullOrThrow(fieldName, rawValue, type, required, 'value is empty or invalid interval'); + } + const val = nodes.aConst({ + sval: ast.string({ sval: String(value) }) + }); + return wrapValue(val, opts); + }; + case 'timestamp': + case 'timestamptz': + case 'date': + return (record: Record): Node => { + const rawValue = record[from[0]]; + if (isNullToken(rawValue)) { + return makeNullOrThrow(fieldName, rawValue, type, required, 'value is empty or null'); + } + const value = parseFn(rawValue); + if (isEmpty(value)) { + return makeNullOrThrow(fieldName, rawValue, type, required, 'value is empty'); + } - // Try to parse as a date to validate - const strValue = String(value); - const dateObj = new Date(strValue); + // Try to parse as a date to validate + const strValue = String(value); + const dateObj = new Date(strValue); - // Check if the date is valid - if (isNaN(dateObj.getTime())) { - // Try parsing as epoch timestamp (seconds or milliseconds) - const numValue = Number(strValue); - if (!isNaN(numValue)) { - // Assume milliseconds if > 10 billion, otherwise seconds - const ms = numValue > 10000000000 ? numValue : numValue * 1000; - const epochDate = new Date(ms); - if (!isNaN(epochDate.getTime())) { - const val = nodes.aConst({ - sval: ast.string({ sval: epochDate.toISOString() }) - }); - return wrapValue(val, opts); - } + // Check if the date is valid + if (isNaN(dateObj.getTime())) { + // Try parsing as epoch timestamp (seconds or milliseconds) + const numValue = Number(strValue); + if (!isNaN(numValue)) { + // Assume milliseconds if > 10 billion, otherwise seconds + const ms = numValue > 10000000000 ? numValue : numValue * 1000; + const epochDate = new Date(ms); + if (!isNaN(epochDate.getTime())) { + const val = nodes.aConst({ + sval: ast.string({ sval: epochDate.toISOString() }) + }); + return wrapValue(val, opts); } - throw new Error(`Invalid ${type} value: "${strValue}" is not a valid date/timestamp`); } + throw new Error(`Invalid ${type} value: "${strValue}" is not a valid date/timestamp`); + } - // Use ISO format for consistency - const val = nodes.aConst({ - sval: ast.string({ sval: type === 'date' ? dateObj.toISOString().split('T')[0] : dateObj.toISOString() }) - }); - return wrapValue(val, opts); - }; - case 'text': - return (record: Record): Node => { - const rawValue = record[from[0]]; - const preserve = globalOpts?.preserveEmptyStrings !== false; - const cleansed = preserve ? rawValue : cleanseEmptyStrings(rawValue); - const value = parseFn(cleansed); - if (isEmpty(value)) { - return makeNullOrThrow(fieldName, rawValue, type, required, 'value is empty or null'); - } - const val = nodes.aConst({ - sval: ast.string({ sval: String(value) }) - }); - return wrapValue(val, opts); - }; - - case 'text[]': - return (record: Record): Node => { - const rawValue = record[from[0]]; - const value = parseFn(psqlArray(cleanseEmptyStrings(rawValue))); - if (isEmpty(value)) { - return makeNullOrThrow(fieldName, rawValue, type, required, 'value is empty or null'); + // Use ISO format for consistency + const val = nodes.aConst({ + sval: ast.string({ sval: type === 'date' ? dateObj.toISOString().split('T')[0] : dateObj.toISOString() }) + }); + return wrapValue(val, opts); + }; + case 'text': + return (record: Record): Node => { + const rawValue = record[from[0]]; + const preserve = globalOpts?.preserveEmptyStrings !== false; + const cleansed = preserve ? rawValue : cleanseEmptyStrings(rawValue); + const value = parseFn(cleansed); + if (isEmpty(value)) { + return makeNullOrThrow(fieldName, rawValue, type, required, 'value is empty or null'); + } + const val = nodes.aConst({ + sval: ast.string({ sval: String(value) }) + }); + return wrapValue(val, opts); + }; + + case 'text[]': + return (record: Record): Node => { + const rawValue = record[from[0]]; + const value = parseFn(psqlArray(cleanseEmptyStrings(rawValue))); + if (isEmpty(value)) { + return makeNullOrThrow(fieldName, rawValue, type, required, 'value is empty or null'); + } + const val = nodes.aConst({ + sval: ast.string({ sval: String(value) }) + }); + return wrapValue(val, opts); + }; + case 'image': + case 'attachment': + case 'json': + case 'jsonb': + return (record: Record): Node => { + const rawValue = record[from[0]]; + const value = parseFn(parseJson(cleanseEmptyStrings(rawValue))); + if (isEmpty(value)) { + return makeNullOrThrow(fieldName, rawValue, type, required, 'value is empty or null'); + } + const val = nodes.aConst({ + sval: ast.string({ sval: String(value) }) + }); + return wrapValue(val, opts); + }; + case 'jsonb[]': + return (record: Record): Node => { + const rawValue = record[from[0]]; + if (isNullToken(rawValue)) { + return makeNullOrThrow(fieldName, rawValue, type, required, 'value is empty or null'); + } + if (Array.isArray(rawValue)) { + if (rawValue.length === 0) { + return makeNullOrThrow(fieldName, rawValue, type, required, 'array is empty'); } - const val = nodes.aConst({ - sval: ast.string({ sval: String(value) }) - }); - return wrapValue(val, opts); - }; - case 'image': - case 'attachment': - case 'json': - case 'jsonb': - return (record: Record): Node => { - const rawValue = record[from[0]]; - const value = parseFn(parseJson(cleanseEmptyStrings(rawValue))); - if (isEmpty(value)) { - return makeNullOrThrow(fieldName, rawValue, type, required, 'value is empty or null'); + const elements = rawValue.map(el => JSON.stringify(el)); + const arrayLiteral = psqlArray(elements); + if (isEmpty(arrayLiteral)) { + return makeNullOrThrow(fieldName, rawValue, type, required, 'failed to format array'); } const val = nodes.aConst({ - sval: ast.string({ sval: String(value) }) + sval: ast.string({ sval: String(arrayLiteral) }) }); return wrapValue(val, opts); - }; - case 'jsonb[]': - return (record: Record): Node => { - const rawValue = record[from[0]]; - if (isNullToken(rawValue)) { - return makeNullOrThrow(fieldName, rawValue, type, required, 'value is empty or null'); - } - if (Array.isArray(rawValue)) { - if (rawValue.length === 0) { - return makeNullOrThrow(fieldName, rawValue, type, required, 'array is empty'); - } - const elements = rawValue.map(el => JSON.stringify(el)); - const arrayLiteral = psqlArray(elements); - if (isEmpty(arrayLiteral)) { - return makeNullOrThrow(fieldName, rawValue, type, required, 'failed to format array'); - } - const val = nodes.aConst({ - sval: ast.string({ sval: String(arrayLiteral) }) - }); - return wrapValue(val, opts); - } - // If it's a string, try to parse as JSON array - if (typeof rawValue === 'string') { - const parsed = parseJson(cleanseEmptyStrings(rawValue)); - if (isEmpty(parsed)) { - return makeNullOrThrow(fieldName, rawValue, type, required, 'value is empty or null'); - } - const val = nodes.aConst({ - sval: ast.string({ sval: String(parsed) }) - }); - return wrapValue(val, opts); - } - return makeNullOrThrow(fieldName, rawValue, type, required, 'value is not an array'); - }; - default: - return (record: Record): Node => { - const rawValue = record[from[0]]; - const value = parseFn(cleanseEmptyStrings(rawValue)); - if (isEmpty(value)) { + } + // If it's a string, try to parse as JSON array + if (typeof rawValue === 'string') { + const parsed = parseJson(cleanseEmptyStrings(rawValue)); + if (isEmpty(parsed)) { return makeNullOrThrow(fieldName, rawValue, type, required, 'value is empty or null'); } const val = nodes.aConst({ - sval: ast.string({ sval: String(value) }) + sval: ast.string({ sval: String(parsed) }) }); return wrapValue(val, opts); - }; + } + return makeNullOrThrow(fieldName, rawValue, type, required, 'value is not an array'); + }; + default: + return (record: Record): Node => { + const rawValue = record[from[0]]; + const value = parseFn(cleanseEmptyStrings(rawValue)); + if (isEmpty(value)) { + return makeNullOrThrow(fieldName, rawValue, type, required, 'value is empty or null'); + } + const val = nodes.aConst({ + sval: ast.string({ sval: String(value) }) + }); + return wrapValue(val, opts); + }; } }; diff --git a/packages/csv-to-pg/src/parser.ts b/packages/csv-to-pg/src/parser.ts index 1ea08be799..c1f2355682 100644 --- a/packages/csv-to-pg/src/parser.ts +++ b/packages/csv-to-pg/src/parser.ts @@ -1,7 +1,8 @@ import { readFileSync } from 'fs'; -import { parse, parseTypes } from './index'; import { deparse } from 'pgsql-deparser'; -import { InsertOne, InsertMany } from './utils'; + +import { parse, parseTypes } from './index'; +import { InsertMany,InsertOne } from './utils'; interface ParserConfig { schema?: string; diff --git a/packages/csv-to-pg/src/utils.ts b/packages/csv-to-pg/src/utils.ts index 6bed31b187..3a882ecc06 100644 --- a/packages/csv-to-pg/src/utils.ts +++ b/packages/csv-to-pg/src/utils.ts @@ -1,5 +1,5 @@ -import { ast, nodes } from '@pgsql/utils'; import type { Node } from '@pgsql/types'; +import { ast, nodes } from '@pgsql/utils'; import { join, resolve } from 'path'; export const normalizePath = (path: string, cwd?: string): string => @@ -309,20 +309,20 @@ export const getRelatedField = ({ } switch (refType) { - case 'int': - val = nodes.aConst({ ival: ast.integer({ ival: value as number }) }); - break; - case 'float': - val = nodes.aConst({ fval: ast.float({ fval: String(value) }) }); - break; - case 'boolean': - case 'bool': - // Use proper boolean constant for PG17 AST - val = nodes.aConst({ boolval: ast.boolean({ boolval: Boolean(value) }) }); - break; - case 'text': - default: - val = nodes.aConst({ sval: ast.string({ sval: String(value) }) }); + case 'int': + val = nodes.aConst({ ival: ast.integer({ ival: value as number }) }); + break; + case 'float': + val = nodes.aConst({ fval: ast.float({ fval: String(value) }) }); + break; + case 'boolean': + case 'bool': + // Use proper boolean constant for PG17 AST + val = nodes.aConst({ boolval: ast.boolean({ boolval: Boolean(value) }) }); + break; + case 'text': + default: + val = nodes.aConst({ sval: ast.string({ sval: String(value) }) }); } val = wrapValue(val, { wrap, wrapAst }); diff --git a/packages/express-context/src/index.ts b/packages/express-context/src/index.ts index ef35b2c415..dd98c85077 100644 --- a/packages/express-context/src/index.ts +++ b/packages/express-context/src/index.ts @@ -93,9 +93,9 @@ export { createModuleLoader, databaseSettingsLoader, inferenceLogLoader, + llmLoader, pubkeyLoader, rlsLoader, - llmLoader, webauthnLoader, } from './loaders'; diff --git a/packages/express-context/src/loaders/agent-chat.ts b/packages/express-context/src/loaders/agent-chat.ts index 9a3b8ea2e6..14050a4d92 100644 --- a/packages/express-context/src/loaders/agent-chat.ts +++ b/packages/express-context/src/loaders/agent-chat.ts @@ -6,8 +6,8 @@ */ import type { AgentChatConfig } from '../types'; -import type { LoaderContext, ModuleLoader } from './types'; import { createModuleLoader } from './create-loader'; +import type { LoaderContext, ModuleLoader } from './types'; // ─── SQL ──────────────────────────────────────────────────────────────────── diff --git a/packages/express-context/src/loaders/billing.ts b/packages/express-context/src/loaders/billing.ts index 48aa2b2d95..3e743499fb 100644 --- a/packages/express-context/src/loaders/billing.ts +++ b/packages/express-context/src/loaders/billing.ts @@ -6,8 +6,8 @@ */ import type { BillingConfig } from '../types'; -import type { LoaderContext, ModuleLoader } from './types'; import { createModuleLoader } from './create-loader'; +import type { LoaderContext, ModuleLoader } from './types'; // ─── SQL ──────────────────────────────────────────────────────────────────── diff --git a/packages/express-context/src/loaders/compute.ts b/packages/express-context/src/loaders/compute.ts index ec11b7aec8..b9b52ca013 100644 --- a/packages/express-context/src/loaders/compute.ts +++ b/packages/express-context/src/loaders/compute.ts @@ -13,8 +13,8 @@ */ import type { ComputeConfig } from '../types'; -import type { LoaderContext, ModuleLoader } from './types'; import { createModuleLoader } from './create-loader'; +import type { LoaderContext, ModuleLoader } from './types'; // ─── SQL ──────────────────────────────────────────────────────────────────── diff --git a/packages/express-context/src/loaders/create-loader.ts b/packages/express-context/src/loaders/create-loader.ts index 68dc1ccf47..25aabd333e 100644 --- a/packages/express-context/src/loaders/create-loader.ts +++ b/packages/express-context/src/loaders/create-loader.ts @@ -6,8 +6,8 @@ * max entries. */ -import { LRUCache } from 'lru-cache'; import { Logger } from '@pgpmjs/logger'; +import { LRUCache } from 'lru-cache'; import type { LoaderContext, ModuleLoader } from './types'; diff --git a/packages/express-context/src/loaders/inference-log.ts b/packages/express-context/src/loaders/inference-log.ts index 811963815e..2488792460 100644 --- a/packages/express-context/src/loaders/inference-log.ts +++ b/packages/express-context/src/loaders/inference-log.ts @@ -6,8 +6,8 @@ */ import type { InferenceLogConfig } from '../types'; -import type { LoaderContext, ModuleLoader } from './types'; import { createModuleLoader } from './create-loader'; +import type { LoaderContext, ModuleLoader } from './types'; // ─── SQL ──────────────────────────────────────────────────────────────────── diff --git a/packages/express-context/src/loaders/llm.ts b/packages/express-context/src/loaders/llm.ts index f28fc7cb49..33cb28f51d 100644 --- a/packages/express-context/src/loaders/llm.ts +++ b/packages/express-context/src/loaders/llm.ts @@ -9,8 +9,8 @@ */ import type { LlmConfig } from '../types'; -import type { LoaderContext, ModuleLoader } from './types'; import { createModuleLoader } from './create-loader'; +import type { LoaderContext, ModuleLoader } from './types'; // ─── SQL ──────────────────────────────────────────────────────────────────── diff --git a/packages/llm-env/__tests__/llm-env.test.ts b/packages/llm-env/__tests__/llm-env.test.ts index 041c9c3eb3..413211fb3e 100644 --- a/packages/llm-env/__tests__/llm-env.test.ts +++ b/packages/llm-env/__tests__/llm-env.test.ts @@ -1,4 +1,4 @@ -import { getEnvVars, getEnvOptions, getLlmEnvOptions, llmDefaults } from '../src'; +import { getEnvOptions, getEnvVars, getLlmEnvOptions, llmDefaults } from '../src'; describe('getEnvVars', () => { it('returns empty object when no env vars are set', () => { diff --git a/packages/oauth/__tests__/oauth-client.test.ts b/packages/oauth/__tests__/oauth-client.test.ts index 129701d874..541192de35 100644 --- a/packages/oauth/__tests__/oauth-client.test.ts +++ b/packages/oauth/__tests__/oauth-client.test.ts @@ -1,4 +1,4 @@ -import { OAuthClient, createOAuthClient } from '../src/oauth-client'; +import { createOAuthClient } from '../src/oauth-client'; import { getProvider, getProviderIds } from '../src/providers'; import { generateState, verifyState } from '../src/utils/state'; diff --git a/packages/oauth/src/index.ts b/packages/oauth/src/index.ts index 4461826c81..42d1c94d82 100644 --- a/packages/oauth/src/index.ts +++ b/packages/oauth/src/index.ts @@ -1,33 +1,30 @@ export { - OAuthProviderConfig, - OAuthProfile, - OAuthCredentials, - OAuthClientConfig, - TokenResponse, - AuthorizationUrlParams, - CallbackParams, - OAuthError, - createOAuthError, -} from './types'; - -export { OAuthClient, createOAuthClient } from './oauth-client'; - + createOAuthMiddleware, + generateState, + OAuthCallbackContext, + OAuthErrorContext, + OAuthMiddlewareConfig, + OAuthRouteHandlers, + verifyState, +} from './middleware/express'; +export { createOAuthClient,OAuthClient } from './oauth-client'; export { - providers, + facebookProvider, getProvider, getProviderIds, - googleProvider, githubProvider, - facebookProvider, + googleProvider, linkedinProvider, + providers, } from './providers'; - export { - createOAuthMiddleware, - OAuthMiddlewareConfig, - OAuthCallbackContext, - OAuthErrorContext, - OAuthRouteHandlers, - generateState, - verifyState, -} from './middleware/express'; + AuthorizationUrlParams, + CallbackParams, + createOAuthError, + OAuthClientConfig, + OAuthCredentials, + OAuthError, + OAuthProfile, + OAuthProviderConfig, + TokenResponse, +} from './types'; diff --git a/packages/oauth/src/middleware/express.ts b/packages/oauth/src/middleware/express.ts index 889911e8d5..607d2d76a4 100644 --- a/packages/oauth/src/middleware/express.ts +++ b/packages/oauth/src/middleware/express.ts @@ -1,7 +1,7 @@ import { OAuthClient } from '../oauth-client'; -import { OAuthClientConfig, OAuthProfile, createOAuthError } from '../types'; -import { generateState, verifyState } from '../utils/state'; import { getProviderIds } from '../providers'; +import { createOAuthError,OAuthClientConfig, OAuthProfile } from '../types'; +import { generateState, verifyState } from '../utils/state'; export interface OAuthMiddlewareConfig extends OAuthClientConfig { onSuccess: (profile: OAuthProfile, context: OAuthCallbackContext) => Promise; diff --git a/packages/oauth/src/oauth-client.ts b/packages/oauth/src/oauth-client.ts index 3f53bdf292..cbdd348e50 100644 --- a/packages/oauth/src/oauth-client.ts +++ b/packages/oauth/src/oauth-client.ts @@ -1,13 +1,12 @@ +import { extractPrimaryEmail,getProvider, GITHUB_EMAILS_URL } from './providers'; import { - OAuthClientConfig, - OAuthCredentials, - OAuthProfile, - TokenResponse, AuthorizationUrlParams, CallbackParams, createOAuthError, + OAuthClientConfig, + OAuthProfile, + TokenResponse, } from './types'; -import { getProvider, GITHUB_EMAILS_URL, extractPrimaryEmail } from './providers'; import { generateState } from './utils/state'; export class OAuthClient { diff --git a/packages/oauth/src/providers/facebook.ts b/packages/oauth/src/providers/facebook.ts index 56c146dd1c..41ed451bff 100644 --- a/packages/oauth/src/providers/facebook.ts +++ b/packages/oauth/src/providers/facebook.ts @@ -1,4 +1,4 @@ -import { OAuthProviderConfig, OAuthProfile } from '../types'; +import { OAuthProfile,OAuthProviderConfig } from '../types'; interface FacebookProfile { id: string; diff --git a/packages/oauth/src/providers/github.ts b/packages/oauth/src/providers/github.ts index 04ba3a5290..72ec51c4aa 100644 --- a/packages/oauth/src/providers/github.ts +++ b/packages/oauth/src/providers/github.ts @@ -1,4 +1,4 @@ -import { OAuthProviderConfig, OAuthProfile } from '../types'; +import { OAuthProfile,OAuthProviderConfig } from '../types'; interface GitHubProfile { id: number; diff --git a/packages/oauth/src/providers/google.ts b/packages/oauth/src/providers/google.ts index eaeac0a11d..dd1c399bb8 100644 --- a/packages/oauth/src/providers/google.ts +++ b/packages/oauth/src/providers/google.ts @@ -1,4 +1,4 @@ -import { OAuthProviderConfig, OAuthProfile } from '../types'; +import { OAuthProfile,OAuthProviderConfig } from '../types'; interface GoogleProfile { sub: string; diff --git a/packages/oauth/src/providers/index.ts b/packages/oauth/src/providers/index.ts index ec0a37f564..23927d410c 100644 --- a/packages/oauth/src/providers/index.ts +++ b/packages/oauth/src/providers/index.ts @@ -1,7 +1,7 @@ import { OAuthProviderConfig } from '../types'; -import { googleProvider } from './google'; -import { githubProvider, GITHUB_EMAILS_URL, extractPrimaryEmail } from './github'; import { facebookProvider } from './facebook'; +import { extractPrimaryEmail,GITHUB_EMAILS_URL, githubProvider } from './github'; +import { googleProvider } from './google'; import { linkedinProvider } from './linkedin'; export const providers: Record = { @@ -20,10 +20,10 @@ export function getProviderIds(): string[] { } export { - googleProvider, - githubProvider, + extractPrimaryEmail, facebookProvider, - linkedinProvider, GITHUB_EMAILS_URL, - extractPrimaryEmail, + githubProvider, + googleProvider, + linkedinProvider, }; diff --git a/packages/oauth/src/providers/linkedin.ts b/packages/oauth/src/providers/linkedin.ts index a7658c859b..9050c9be6a 100644 --- a/packages/oauth/src/providers/linkedin.ts +++ b/packages/oauth/src/providers/linkedin.ts @@ -1,4 +1,4 @@ -import { OAuthProviderConfig, OAuthProfile } from '../types'; +import { OAuthProfile,OAuthProviderConfig } from '../types'; interface LinkedInProfile { sub: string; diff --git a/packages/postmaster/src/index.ts b/packages/postmaster/src/index.ts index 77eefeaea5..b06a752502 100644 --- a/packages/postmaster/src/index.ts +++ b/packages/postmaster/src/index.ts @@ -1,8 +1,7 @@ -import Mailgun from 'mailgun.js'; -import type { MailgunMessageData } from 'mailgun.js'; +import {email, env, host, str } from '12factor-env'; import FormData from 'form-data'; -import { str, email, host, env, cleanEnv } from '12factor-env'; -import type { CleanedEnv, ValidatorSpec } from '12factor-env'; +import type { MailgunMessageData } from 'mailgun.js'; +import Mailgun from 'mailgun.js'; /** * Mailgun configuration options diff --git a/packages/query-spec/__tests__/query-spec.test.ts b/packages/query-spec/__tests__/query-spec.test.ts index ca2975aa1b..05c0a52acd 100644 --- a/packages/query-spec/__tests__/query-spec.test.ts +++ b/packages/query-spec/__tests__/query-spec.test.ts @@ -1,7 +1,7 @@ import { COMPARISON_FILTER_OPERATORS, - FILTER_OPERATORS, Filter, + FILTER_OPERATORS, isFilterOperator, isLogicalOperator, OrderByItem diff --git a/packages/safegres/__tests__/sarif.test.ts b/packages/safegres/__tests__/sarif.test.ts index 0e258c9aa5..ced0c423f1 100644 --- a/packages/safegres/__tests__/sarif.test.ts +++ b/packages/safegres/__tests__/sarif.test.ts @@ -1,4 +1,4 @@ -import { mkdtempSync, mkdirSync, writeFileSync } from 'fs'; +import { mkdirSync, mkdtempSync, writeFileSync } from 'fs'; import { tmpdir } from 'os'; import { join } from 'path'; diff --git a/packages/safegres/src/commands/audit.ts b/packages/safegres/src/commands/audit.ts index 9d9b9e698c..389cfe7f1b 100644 --- a/packages/safegres/src/commands/audit.ts +++ b/packages/safegres/src/commands/audit.ts @@ -30,7 +30,6 @@ import { collectPredicateColumns, type PredicateColumn } from '../checks/policy-index'; -import { checkStats, DEFAULT_STATS_THRESHOLDS, type StatsThresholds } from '../checks/stats'; import { checkGrantsWithoutRls, checkRlsEnabledNoPolicies, @@ -42,13 +41,14 @@ import { checkUntrustedRoleWrites, type RoleTrustOptions } from '../checks/role-trust'; +import { checkStats, DEFAULT_STATS_THRESHOLDS, type StatsThresholds } from '../checks/stats'; import { allAstRulesDisabled, applyRulesToFindings, matchTablePattern, resolveRules, rulesForTable } from '../config/resolve'; import type { ExposureConfig, SafegresConfig } from '../config/types'; +import { type ExplainReport, proveFindings } from '../perf/explain'; import { resolveExposure } from '../pg/exposure'; import { introspectFunctions } from '../pg/functions'; import { introspectIndexes, type TableIndexSnapshot } from '../pg/indexes'; import { asExecutor, type IntrospectOptions, introspectTables, type QueryExecutor, type TableSnapshot } from '../pg/introspect'; -import { type ExplainReport, proveFindings } from '../perf/explain'; import { lookupVolatility, type ProcVolatility } from '../pg/proc'; import { listAuditableRoles, resolveRoles } from '../pg/roles'; import { introspectStats, type StatsSnapshot } from '../pg/stats'; diff --git a/packages/safegres/src/index.ts b/packages/safegres/src/index.ts index 87d99adf8b..c446d3bea5 100644 --- a/packages/safegres/src/index.ts +++ b/packages/safegres/src/index.ts @@ -34,15 +34,6 @@ export { checkUnindexedSortColumns } from './checks/indexes'; export type { PolicyClause, PredicateColumn } from './checks/policy-index'; -export type { StatsThresholds } from './checks/stats'; -export { - checkDeadTuples, - checkSeqScanDominant, - checkStats, - checkTopStatements, - checkUnusedIndexes, - DEFAULT_STATS_THRESHOLDS -} from './checks/stats'; export { checkNonLeakproofPolicyFunctions, checkPolicyColumnCasts, @@ -55,6 +46,15 @@ export { checkUntrustedRolePolicies, checkUntrustedRoleWrites } from './checks/role-trust'; +export type { StatsThresholds } from './checks/stats'; +export { + checkDeadTuples, + checkSeqScanDominant, + checkStats, + checkTopStatements, + checkUnusedIndexes, + DEFAULT_STATS_THRESHOLDS +} from './checks/stats'; export type { AuditOptions } from './commands/audit'; export { audit } from './commands/audit'; export type { DoctorCheck, DoctorOptions, DoctorReport, DoctorStatus } from './commands/doctor'; @@ -84,21 +84,24 @@ export type { SafegresConfig, ScoringConfig } from './config/types'; +export type { BaselineFinding, PerfBaseline, PerfDiff } from './perf/baseline'; +export { + diffPerf, + findingKey, + parsePerfBaseline, + serializePerfBaseline, + subjectOf, + toBaselineFinding, + toPerfBaseline +} from './perf/baseline'; +export type { ExplainOptions, ExplainReport } from './perf/explain'; +export { proveFindings } from './perf/explain'; export type { ResolvedExposure } from './pg/exposure'; export { resolveConstructiveExposure, resolveExposure, UNKNOWN_EXPOSURE } from './pg/exposure'; export type { FunctionGrant, FunctionSnapshot, IntrospectFunctionOptions } from './pg/functions'; export { introspectFunctions } from './pg/functions'; export type { ColumnInfo, ForeignKeyInfo, IndexInfo, TableIndexSnapshot } from './pg/indexes'; export { introspectIndexes } from './pg/indexes'; -export type { - IndexUsage, - StatementUsage, - StatsSnapshot, - TableUsage -} from './pg/stats'; -export { introspectStats } from './pg/stats'; -export type { ExplainOptions, ExplainReport } from './perf/explain'; -export { proveFindings } from './perf/explain'; export { type IntrospectOptions, introspectTables, @@ -109,16 +112,13 @@ export { type TableSnapshot } from './pg/introspect'; export { listAuditableRoles, resolveRoles } from './pg/roles'; -export type { BaselineFinding, PerfBaseline, PerfDiff } from './perf/baseline'; -export { - diffPerf, - findingKey, - parsePerfBaseline, - serializePerfBaseline, - subjectOf, - toBaselineFinding, - toPerfBaseline -} from './perf/baseline'; +export type { + IndexUsage, + StatementUsage, + StatsSnapshot, + TableUsage +} from './pg/stats'; +export { introspectStats } from './pg/stats'; export { renderCallGraph, renderCallGraphDiff } from './report/callgraph'; export { renderJson } from './report/json'; export type { RenderMarkdownOptions } from './report/markdown'; diff --git a/packages/safegres/src/perf/explain.ts b/packages/safegres/src/perf/explain.ts index 2c284438d9..f0fae27fe9 100644 --- a/packages/safegres/src/perf/explain.ts +++ b/packages/safegres/src/perf/explain.ts @@ -18,8 +18,8 @@ * know nothing about. That requires PostgreSQL 16+. */ -import type { QueryExecutor } from '../pg/introspect'; import type { TableIndexSnapshot } from '../pg/indexes'; +import type { QueryExecutor } from '../pg/introspect'; import type { Finding, FindingEvidence } from '../types'; export interface ExplainOptions { @@ -134,50 +134,50 @@ function buildProbe(finding: Finding, table: TableIndexSnapshot): Probe | null { const context = finding.context ?? {}; switch (finding.code) { - case 'X1': { - const columns = asStringArray(context.columns); - if (columns.length === 0) return null; - const predicates = columns - .map((name, i) => equality(table, name, i + 1)) - .filter((p): p is string => p !== null); - if (predicates.length !== columns.length) return null; - return { sql: `SELECT 1 FROM ${relation} WHERE ${predicates.join(' AND ')}`, expect: 'seq-scan' }; - } - case 'X2': { - const predicate = typeof context.column === 'string' - ? equality(table, context.column, 1) - : null; - if (!predicate) return null; - return { sql: `SELECT 1 FROM ${relation} WHERE ${predicate}`, expect: 'seq-scan' }; - } - case 'X7': { - const column = typeof context.column === 'string' ? context.column : null; - if (!column) return null; - const type = columnType(table, column); - if (!type) return null; - if (type === 'tsvector') { - return { - sql: `SELECT 1 FROM ${relation} WHERE ${quote(column)} @@ $1::tsquery`, - expect: 'seq-scan' - }; - } - // Vector search is an ordering, not a filter: the index either serves - // the distance order or the plan sorts every row. - return { - sql: `SELECT 1 FROM ${relation} ORDER BY ${quote(column)} <-> $1::${type} LIMIT 10`, - expect: 'sort' - }; - } - case 'X8': { - const column = typeof context.column === 'string' ? context.column : null; - if (!column) return null; + case 'X1': { + const columns = asStringArray(context.columns); + if (columns.length === 0) return null; + const predicates = columns + .map((name, i) => equality(table, name, i + 1)) + .filter((p): p is string => p !== null); + if (predicates.length !== columns.length) return null; + return { sql: `SELECT 1 FROM ${relation} WHERE ${predicates.join(' AND ')}`, expect: 'seq-scan' }; + } + case 'X2': { + const predicate = typeof context.column === 'string' + ? equality(table, context.column, 1) + : null; + if (!predicate) return null; + return { sql: `SELECT 1 FROM ${relation} WHERE ${predicate}`, expect: 'seq-scan' }; + } + case 'X7': { + const column = typeof context.column === 'string' ? context.column : null; + if (!column) return null; + const type = columnType(table, column); + if (!type) return null; + if (type === 'tsvector') { return { - sql: `SELECT 1 FROM ${relation} ORDER BY ${quote(column)} DESC LIMIT 100`, - expect: 'sort' + sql: `SELECT 1 FROM ${relation} WHERE ${quote(column)} @@ $1::tsquery`, + expect: 'seq-scan' }; } - default: - return null; + // Vector search is an ordering, not a filter: the index either serves + // the distance order or the plan sorts every row. + return { + sql: `SELECT 1 FROM ${relation} ORDER BY ${quote(column)} <-> $1::${type} LIMIT 10`, + expect: 'sort' + }; + } + case 'X8': { + const column = typeof context.column === 'string' ? context.column : null; + if (!column) return null; + return { + sql: `SELECT 1 FROM ${relation} ORDER BY ${quote(column)} DESC LIMIT 100`, + expect: 'sort' + }; + } + default: + return null; } } diff --git a/packages/safegres/src/report/sarif.ts b/packages/safegres/src/report/sarif.ts index 298ac5e780..04bf7b90ce 100644 --- a/packages/safegres/src/report/sarif.ts +++ b/packages/safegres/src/report/sarif.ts @@ -16,7 +16,7 @@ import { readdirSync, readFileSync, statSync } from 'fs'; import { join, relative, sep } from 'path'; import { findingKey, subjectOf } from '../perf/baseline'; -import { RULES, dimensionOf } from '../rules/registry'; +import { dimensionOf,RULES } from '../rules/registry'; import type { Finding, Report, Severity } from '../types'; const SARIF_VERSION = '2.1.0'; diff --git a/packages/server-utils/src/cors.ts b/packages/server-utils/src/cors.ts index f6c5e479a9..a5625eae76 100644 --- a/packages/server-utils/src/cors.ts +++ b/packages/server-utils/src/cors.ts @@ -14,10 +14,10 @@ export const cors = (app: Express, origin?: string) => { const corsOptions = origin && origin.trim() !== '*' ? { - origin, - credentials: true, - optionsSuccessStatus: 200, - } + origin, + credentials: true, + optionsSuccessStatus: 200, + } : undefined; if (corsOptions) { diff --git a/packages/smtppostmaster/__tests__/send.test.ts b/packages/smtppostmaster/__tests__/send.test.ts index 97ed065d21..bb3848aeeb 100644 --- a/packages/smtppostmaster/__tests__/send.test.ts +++ b/packages/smtppostmaster/__tests__/send.test.ts @@ -1,4 +1,4 @@ -import { send, resetTransport } from '../src/index'; +import { resetTransport,send } from '../src/index'; import { createSmtpCatcher } from './smtp-catcher'; describe('send', () => { diff --git a/packages/smtppostmaster/__tests__/smtp-catcher.ts b/packages/smtppostmaster/__tests__/smtp-catcher.ts index 56c8b41ccc..75a59cfcf9 100644 --- a/packages/smtppostmaster/__tests__/smtp-catcher.ts +++ b/packages/smtppostmaster/__tests__/smtp-catcher.ts @@ -1,6 +1,6 @@ import { AddressInfo } from 'net'; -import { SMTPServer } from 'smtp-server'; import type { SMTPServerSession } from 'smtp-server'; +import { SMTPServer } from 'smtp-server'; export type CapturedMessage = { envelope: SMTPServerSession['envelope']; diff --git a/packages/smtppostmaster/__tests__/test-send.ts b/packages/smtppostmaster/__tests__/test-send.ts index 9a747da343..02d2fe9d1f 100644 --- a/packages/smtppostmaster/__tests__/test-send.ts +++ b/packages/smtppostmaster/__tests__/test-send.ts @@ -1,5 +1,6 @@ import { getEnvOptions } from '@pgpmjs/env'; import { SmtpOptions } from '@pgpmjs/types'; + import { send } from '../src/index'; import { createSmtpCatcher } from './smtp-catcher'; @@ -17,12 +18,12 @@ const main = async () => { const smtpOverrides: SmtpOptions = catcher ? { - host: catcher.host, - port: catcher.port, - secure: false, - tlsRejectUnauthorized: false, - from: smtpFromEnv.from ?? process.env.SMTP_TEST_FROM ?? 'no-reply@example.com' - } + host: catcher.host, + port: catcher.port, + secure: false, + tlsRejectUnauthorized: false, + from: smtpFromEnv.from ?? process.env.SMTP_TEST_FROM ?? 'no-reply@example.com' + } : {}; const to = diff --git a/packages/smtppostmaster/src/index.ts b/packages/smtppostmaster/src/index.ts index de72bc76d1..5d731a71dc 100644 --- a/packages/smtppostmaster/src/index.ts +++ b/packages/smtppostmaster/src/index.ts @@ -1,7 +1,7 @@ -import nodemailer, { SendMailOptions } from 'nodemailer'; -import SMTPTransport from 'nodemailer/lib/smtp-transport'; import { getEnvOptions } from '@pgpmjs/env'; import { SmtpOptions } from '@pgpmjs/types'; +import nodemailer, { SendMailOptions } from 'nodemailer'; +import SMTPTransport from 'nodemailer/lib/smtp-transport'; type SendInput = { to: string | string[]; @@ -36,9 +36,9 @@ const buildTransportOptions = (smtpOpts: SmtpOptions): TransportConfig => { const auth = user ? { - user, - pass: pass ?? '' - } + user, + pass: pass ?? '' + } : undefined; const options: TransportConfig = { diff --git a/packages/upload-client/__tests__/hash.test.ts b/packages/upload-client/__tests__/hash.test.ts index a3a21bdf10..da5eb38664 100644 --- a/packages/upload-client/__tests__/hash.test.ts +++ b/packages/upload-client/__tests__/hash.test.ts @@ -1,6 +1,6 @@ import { hashFile, hashFileChunked } from '../src/hash'; -import { UploadError } from '../src/types'; import type { FileInput } from '../src/types'; +import { UploadError } from '../src/types'; /** * Create a mock FileInput from a string body. diff --git a/packages/upload-client/__tests__/upload.test.ts b/packages/upload-client/__tests__/upload.test.ts index 9c1e8dcfeb..19dd3f3f7c 100644 --- a/packages/upload-client/__tests__/upload.test.ts +++ b/packages/upload-client/__tests__/upload.test.ts @@ -1,7 +1,6 @@ -import { uploadFile } from '../src/upload'; -import { UploadError } from '../src/types'; import { DEFAULT_BUCKET_QUERY_FIELD } from '../src/queries'; -import type { GraphQLExecutor, FileInput } from '../src/types'; +import type { FileInput,GraphQLExecutor } from '../src/types'; +import { uploadFile } from '../src/upload'; /** * Create a mock FileInput from a string body. diff --git a/packages/upload-client/src/hash-content.ts b/packages/upload-client/src/hash-content.ts index 6da206d30e..1bbec1eba2 100644 --- a/packages/upload-client/src/hash-content.ts +++ b/packages/upload-client/src/hash-content.ts @@ -15,6 +15,7 @@ import { sha256 } from '@constructive-io/noble-hashes/sha2'; import { bytesToHex } from '@constructive-io/noble-hashes/utils'; + import { UploadError } from './types'; /** diff --git a/packages/upload-client/src/hash.ts b/packages/upload-client/src/hash.ts index f5f5623b3e..67ae9f96ed 100644 --- a/packages/upload-client/src/hash.ts +++ b/packages/upload-client/src/hash.ts @@ -12,8 +12,9 @@ import { sha256 } from '@constructive-io/noble-hashes/sha2'; import { bytesToHex } from '@constructive-io/noble-hashes/utils'; -import { UploadError } from './types'; + import type { FileInput } from './types'; +import { UploadError } from './types'; /** Default chunk size for chunked hashing: 2MB */ const DEFAULT_CHUNK_SIZE = 2 * 1024 * 1024; diff --git a/packages/upload-client/src/index.ts b/packages/upload-client/src/index.ts index 2b143dfec0..9397cc0c48 100644 --- a/packages/upload-client/src/index.ts +++ b/packages/upload-client/src/index.ts @@ -37,23 +37,22 @@ export { hashFile, hashFileChunked } from './hash'; export { hashContent } from './hash-content'; // Presigned URL helpers -export { putToPresignedUrl, fetchFromUrl } from './put'; +export { fetchFromUrl,putToPresignedUrl } from './put'; // Orchestrator export { uploadFile } from './upload'; // GraphQL query builders (for custom integrations) -export { buildRequestUploadUrlQuery, REQUEST_UPLOAD_URL_QUERY, REQUEST_UPLOAD_URL_MUTATION, DEFAULT_BUCKET_QUERY_FIELD } from './queries'; +export { buildRequestUploadUrlQuery, DEFAULT_BUCKET_QUERY_FIELD,REQUEST_UPLOAD_URL_MUTATION, REQUEST_UPLOAD_URL_QUERY } from './queries'; // Types export type { FileInput, GraphQLExecutor, - UploadFileOptions, - UploadResult, RequestUploadUrlInput, RequestUploadUrlPayload, UploadErrorCode, + UploadFileOptions, + UploadResult, } from './types'; - export { UploadError } from './types'; diff --git a/packages/upload-client/src/put.ts b/packages/upload-client/src/put.ts index 05dbd2b204..274033966b 100644 --- a/packages/upload-client/src/put.ts +++ b/packages/upload-client/src/put.ts @@ -19,6 +19,7 @@ */ import { createFetch } from '@constructive-io/fetch'; + import { UploadError } from './types'; const fetch = createFetch(); diff --git a/packages/upload-client/src/upload.ts b/packages/upload-client/src/upload.ts index bc582ff6d7..7b2b0d316d 100644 --- a/packages/upload-client/src/upload.ts +++ b/packages/upload-client/src/upload.ts @@ -10,12 +10,12 @@ import { hashFile } from './hash'; import { putToPresignedUrl } from './put'; import { buildRequestUploadUrlQuery, DEFAULT_BUCKET_QUERY_FIELD } from './queries'; -import { UploadError } from './types'; import type { + RequestUploadUrlPayload, UploadFileOptions, UploadResult, - RequestUploadUrlPayload, } from './types'; +import { UploadError } from './types'; /** * Upload a file using the presigned URL pipeline. diff --git a/pgpm/ast/__tests__/files/extension/reader.test.ts b/pgpm/ast/__tests__/files/extension/reader.test.ts index ee9c6af9aa..9453f7b878 100644 --- a/pgpm/ast/__tests__/files/extension/reader.test.ts +++ b/pgpm/ast/__tests__/files/extension/reader.test.ts @@ -1,6 +1,7 @@ import fs from 'fs'; import os from 'os'; import path from 'path'; + import { getInstalledExtensions } from '../../../src/files/extension/reader'; describe('getInstalledExtensions', () => { diff --git a/pgpm/ast/__tests__/files/extension/writer.test.ts b/pgpm/ast/__tests__/files/extension/writer.test.ts index 3f57eabf24..4d718bedb8 100644 --- a/pgpm/ast/__tests__/files/extension/writer.test.ts +++ b/pgpm/ast/__tests__/files/extension/writer.test.ts @@ -1,8 +1,9 @@ import fs from 'fs'; import os from 'os'; import path from 'path'; -import { writeExtensions, generateControlFileContent, upsertRequiresLine } from '../../../src/files/extension/writer'; + import { getInstalledExtensions } from '../../../src/files/extension/reader'; +import { generateControlFileContent, upsertRequiresLine,writeExtensions } from '../../../src/files/extension/writer'; describe('extension writer', () => { let tempDir: string; diff --git a/pgpm/ast/__tests__/files/plan/writer.test.ts b/pgpm/ast/__tests__/files/plan/writer.test.ts index 6098333f7e..bb91551236 100644 --- a/pgpm/ast/__tests__/files/plan/writer.test.ts +++ b/pgpm/ast/__tests__/files/plan/writer.test.ts @@ -1,6 +1,7 @@ import fs from 'fs'; import os from 'os'; import path from 'path'; + import { writePgpmPlan } from '../../../src/files/plan/writer'; import { PgpmRow } from '../../../src/files/types'; diff --git a/pgpm/ast/__tests__/plan-rename.test.ts b/pgpm/ast/__tests__/plan-rename.test.ts index 090a25b9ba..6f69acdb06 100644 --- a/pgpm/ast/__tests__/plan-rename.test.ts +++ b/pgpm/ast/__tests__/plan-rename.test.ts @@ -78,7 +78,7 @@ describe('renameInPlanContent', () => { expect(out).toContain(`schemas/mod_${n - 1}/tables/t_${n - 1}`); expect(out).toContain('[schemas/mod_0/tables/t_0]'); // No hyphenated change tokens should remain (metadata/comments still have them). - expect(out).not.toMatch(/(^|[\s\[])schemas\/mod-\d/m); + expect(out).not.toMatch(/(^|[\s[])schemas\/mod-\d/m); expect(elapsedMs).toBeLessThan(2000); }); }); diff --git a/pgpm/ast/src/files/extension/reader.ts b/pgpm/ast/src/files/extension/reader.ts index 91467d8c74..b2d812f853 100644 --- a/pgpm/ast/src/files/extension/reader.ts +++ b/pgpm/ast/src/files/extension/reader.ts @@ -36,13 +36,13 @@ export function parseControlContent(contents: string): { requires: string[]; ver .find((line) => /^requires/.test(line)) ?.split('=')[1] .split(',') - .map((req) => req.replace(/[\'\s]*/g, '').trim()) || []; + .map((req) => req.replace(/['\s]*/g, '').trim()) || []; const version = contents .split('\n') .find((line) => /^default_version/.test(line)) ?.split('=')[1] - .replace(/[\']*/g, '') + .replace(/[']*/g, '') .trim() || ''; return { requires, version }; diff --git a/pgpm/ast/src/files/plan/parser.ts b/pgpm/ast/src/files/plan/parser.ts index feab61c6c0..89547366f8 100644 --- a/pgpm/ast/src/files/plan/parser.ts +++ b/pgpm/ast/src/files/plan/parser.ts @@ -1,8 +1,8 @@ +import { errors } from '@pgpmjs/types'; import { readFileSync } from 'fs'; import { Change, ExtendedPlanFile, ParseError, ParseResult,PlanFile, Tag } from '../types'; import { isValidChangeName, isValidDependency, isValidTagName, parseReference } from './validators'; -import { errors } from '@pgpmjs/types'; /** * Parse a Sqitch plan file with full validation diff --git a/pgpm/ast/src/files/sql/header.ts b/pgpm/ast/src/files/sql/header.ts index 4303d80b38..9932c3aef9 100644 --- a/pgpm/ast/src/files/sql/header.ts +++ b/pgpm/ast/src/files/sql/header.ts @@ -2,7 +2,7 @@ import { readFileSync } from 'fs'; import { join } from 'path'; import { parsePlanFile } from '../plan/parser'; -import { parseReference, ParsedReference } from '../plan/validators'; +import { ParsedReference,parseReference } from '../plan/validators'; /** * A parsed `-- requires:` line from a pgpm SQL script header. @@ -241,7 +241,7 @@ export function scanDeployScript( } if (/:/.test(line)) { - const m2 = line.match(/^-- Deploy ([^:]*):([\w\/]+)(?:\s+to\s+pg)?/); + const m2 = line.match(/^-- Deploy ([^:]*):([\w/]+)(?:\s+to\s+pg)?/); if (m2) { const actualProject = m2[1]; const keyToTest = m2[2]; diff --git a/pgpm/ast/src/index.ts b/pgpm/ast/src/index.ts index 85639531d6..5474a115e2 100644 --- a/pgpm/ast/src/index.ts +++ b/pgpm/ast/src/index.ts @@ -15,5 +15,5 @@ export * from './files'; export * from './hash'; export * from './module'; export * from './plan-rename'; -export { parseAuthor } from './utils/author'; export type { ParsedAuthor } from './utils/author'; +export { parseAuthor } from './utils/author'; diff --git a/pgpm/ast/src/plan-rename.ts b/pgpm/ast/src/plan-rename.ts index a064579d39..b817e2d349 100644 --- a/pgpm/ast/src/plan-rename.ts +++ b/pgpm/ast/src/plan-rename.ts @@ -18,7 +18,7 @@ export function renameInPlanContent(content: string, renames: Map = { const DATA_PART = { name: 'source-plane-data', - deploy: "INSERT INTO auth.users (id) VALUES (1);\n", + deploy: 'INSERT INTO auth.users (id) VALUES (1);\n', revert: 'DELETE FROM auth.users WHERE id IN (1);\n', verify: 'SELECT 1/(count(*) = 1)::int FROM auth.users;\n' }; const FIXTURE_PART = { name: 'seed-roles', - deploy: "INSERT INTO auth.users (id) VALUES (99);\n" + deploy: 'INSERT INTO auth.users (id) VALUES (99);\n' }; function write(rel: string, content: string): void { diff --git a/pgpm/bundle/src/create.ts b/pgpm/bundle/src/create.ts index 178852240d..00ca77abe9 100644 --- a/pgpm/bundle/src/create.ts +++ b/pgpm/bundle/src/create.ts @@ -1,6 +1,7 @@ -import { PgpmModuleAst, PgpmScriptAst } from '@pgpmjs/ast/module/types'; import { hashString } from '@pgpmjs/ast'; +import { PgpmModuleAst, PgpmScriptAst } from '@pgpmjs/ast/module/types'; import { mapScripts } from '@pgpmjs/traverse'; + import { BUNDLE_FORMAT_VERSION, BundleChange, diff --git a/pgpm/bundle/src/diff.ts b/pgpm/bundle/src/diff.ts index 70d6dfbcf5..72b6e9fd53 100644 --- a/pgpm/bundle/src/diff.ts +++ b/pgpm/bundle/src/diff.ts @@ -1,5 +1,6 @@ import { PgpmScriptKind } from '@pgpmjs/ast/module/types'; import { zipScripts } from '@pgpmjs/traverse'; + import { BundleChange, BundleScript, MigrationBundle } from './types'; /** Per-script disposition between two revisions of the same change. */ diff --git a/pgpm/bundle/src/envelope.ts b/pgpm/bundle/src/envelope.ts index 71ff60d538..f695ff8f79 100644 --- a/pgpm/bundle/src/envelope.ts +++ b/pgpm/bundle/src/envelope.ts @@ -9,10 +9,10 @@ * direction intact (`@pgpmjs/export` depends on core, which depends on this * package) while every byte remains digest-covered. */ +import { hashString } from '@pgpmjs/ast'; import { mkdirSync, readdirSync, readFileSync, writeFileSync } from 'fs'; import { dirname, join } from 'path'; -import { hashString } from '@pgpmjs/ast'; import { readBundleFile, writeBundleFile } from './io'; import { MigrationBundle } from './types'; import { BundleIssue, verifyBundle } from './verify'; diff --git a/pgpm/bundle/src/io.ts b/pgpm/bundle/src/io.ts index 84550cb4ff..1713b26f14 100644 --- a/pgpm/bundle/src/io.ts +++ b/pgpm/bundle/src/io.ts @@ -1,6 +1,3 @@ -import { mkdirSync, readFileSync, writeFileSync } from 'fs'; -import { dirname } from 'path'; - import { parseControlContent } from '@pgpmjs/ast/files/extension/reader'; import { parsePlanContent } from '@pgpmjs/ast/files/plan/parser'; import { parsePgpmHeader } from '@pgpmjs/ast/files/sql/header'; @@ -14,6 +11,9 @@ import { } from '@pgpmjs/ast/module/types'; import { writeModule } from '@pgpmjs/ast/module/writer'; import { mapScripts } from '@pgpmjs/traverse'; +import { mkdirSync, readFileSync, writeFileSync } from 'fs'; +import { dirname } from 'path'; + import { createBundle, CreateBundleOptions } from './create'; import { packSingleFileTarGz, unpackSingleFileTarGz } from './tar'; import { BundleScript, MigrationBundle } from './types'; diff --git a/pgpm/bundle/src/transpile.ts b/pgpm/bundle/src/transpile.ts index c0742d4e07..db9c33bb88 100644 --- a/pgpm/bundle/src/transpile.ts +++ b/pgpm/bundle/src/transpile.ts @@ -1,8 +1,9 @@ -import { PgpmScriptKind } from '@pgpmjs/ast/module/types'; -import { parsePgpmHeader, renameInHeader, writePgpmScript } from '@pgpmjs/ast/files/sql/header'; import { hashString } from '@pgpmjs/ast'; import { generatePlanFileContent, parsePlanContent, renameInPlanContent } from '@pgpmjs/ast'; +import { parsePgpmHeader, renameInHeader, writePgpmScript } from '@pgpmjs/ast/files/sql/header'; +import { PgpmScriptKind } from '@pgpmjs/ast/module/types'; import { mapScripts } from '@pgpmjs/traverse'; + import { computeBundleDigest, computeChangeDigest, diff --git a/pgpm/bundle/src/verify.ts b/pgpm/bundle/src/verify.ts index 36b8bb285d..bde94e44e3 100644 --- a/pgpm/bundle/src/verify.ts +++ b/pgpm/bundle/src/verify.ts @@ -1,5 +1,6 @@ import { hashString } from '@pgpmjs/ast'; import { forEachScript } from '@pgpmjs/traverse'; + import { computeBundleDigest, computeChangeDigest } from './create'; import { MigrationBundle } from './types'; diff --git a/pgpm/cli/__tests__/dump.test.ts b/pgpm/cli/__tests__/dump.test.ts index 238d300134..0ec2d6db0e 100644 --- a/pgpm/cli/__tests__/dump.test.ts +++ b/pgpm/cli/__tests__/dump.test.ts @@ -1,7 +1,6 @@ import * as child_process from 'child_process'; import * as fs from 'fs'; -import * as path from 'path'; // Mock child_process jest.mock('child_process'); @@ -9,106 +8,106 @@ jest.mock('child_process'); jest.mock('fs'); // mock utils to avoid loading deep dependencies that cause issues in test environment jest.mock('../src/utils', () => ({ - getTargetDatabase: jest.fn().mockResolvedValue('test_db') + getTargetDatabase: jest.fn().mockResolvedValue('test_db') })); // mock quoteutils jest.mock('@pgsql/quotes', () => ({ - QuoteUtils: { - quoteIdentifier: (s: string) => `"${s}"`, - quoteQualifiedIdentifier: (s: string, t: string) => `"${s}"."${t}"`, - formatEString: (s: string) => `'${s}'` - } + QuoteUtils: { + quoteIdentifier: (s: string) => `"${s}"`, + quoteQualifiedIdentifier: (s: string, t: string) => `"${s}"."${t}"`, + formatEString: (s: string) => `'${s}'` + } })); // mock pg-cache to simulate db results for prune logic const mockPoolQuery = jest.fn(); jest.mock('pg-cache', () => ({ - getPgPool: () => ({ - query: mockPoolQuery - }) + getPgPool: () => ({ + query: mockPoolQuery + }) })); import dumpCmd from '../src/commands/dump'; describe('dump command', () => { - beforeEach(() => { - jest.clearAllMocks(); - }); - - it('should call pg_dump with correct arguments', async () => { - const spawnMock = child_process.spawn as unknown as jest.Mock; - spawnMock.mockImplementation(() => ({ - on: (event: string, cb: any) => { - if (event === 'close') cb(0); - }, - stdout: { pipe: jest.fn() }, - stderr: { pipe: jest.fn() }, - })); - - const fsMkdirSpy = jest.spyOn(fs, 'mkdirSync').mockImplementation(() => undefined as any); - const fsWriteSpy = jest.spyOn(fs, 'writeFileSync').mockImplementation(() => undefined); - const consoleSpy = jest.spyOn(console, 'log').mockImplementation(() => { }); - - const argv = { - database: 'test_db', - out: 'output.sql', - cwd: '/tmp' - }; - const prompter = {} as any; - const options = {} as any; - - await dumpCmd(argv, prompter, options); - - expect(spawnMock).toHaveBeenCalledWith( - 'pg_dump', - expect.arrayContaining([ - '--format=plain', - '--no-owner', - '--no-privileges', - '--file', - expect.stringContaining('output.sql'), - 'test_db' - ]), - expect.objectContaining({ - env: expect.anything() - }) - ); - }); - - it('should generate prune sql when database-id is provided', async () => { - const spawnMock = child_process.spawn as unknown as jest.Mock; - spawnMock.mockImplementation(() => ({ - on: (event: string, cb: any) => { - if (event === 'close') cb(0); - } - })); - - jest.spyOn(fs, 'mkdirSync').mockImplementation(() => undefined as any); - const fsWriteSpy = jest.spyOn(fs, 'writeFileSync').mockImplementation(() => undefined); - jest.spyOn(console, 'log').mockImplementation(() => { }); - - // mock db responses for resolveDatabaseId and buildPruneSql - mockPoolQuery - .mockResolvedValueOnce({ rows: [{ id: 'uuid-123', name: 'test_db_id' }] }) // resolveDatabaseId - .mockResolvedValueOnce({ rows: [{ table_schema: 'public', table_name: 'test_table' }] }); // buildPruneSql - - const argv = { - database: 'test_db', - out: 'output_prune.sql', - 'database-id': 'uuid-123', - cwd: '/tmp' - }; - const prompter = {} as any; - const options = {} as any; - - await dumpCmd(argv, prompter, options); - - // verify prune sql appended - expect(fsWriteSpy).toHaveBeenCalledWith( - expect.stringContaining('output_prune.sql'), - expect.stringContaining('delete from "public"."test_table" where database_id <> \'uuid-123\''), - expect.objectContaining({ flag: 'a' }) - ); - }); + beforeEach(() => { + jest.clearAllMocks(); + }); + + it('should call pg_dump with correct arguments', async () => { + const spawnMock = child_process.spawn as unknown as jest.Mock; + spawnMock.mockImplementation(() => ({ + on: (event: string, cb: any) => { + if (event === 'close') cb(0); + }, + stdout: { pipe: jest.fn() }, + stderr: { pipe: jest.fn() }, + })); + + const fsMkdirSpy = jest.spyOn(fs, 'mkdirSync').mockImplementation(() => undefined as any); + const fsWriteSpy = jest.spyOn(fs, 'writeFileSync').mockImplementation(() => undefined); + const consoleSpy = jest.spyOn(console, 'log').mockImplementation(() => { }); + + const argv = { + database: 'test_db', + out: 'output.sql', + cwd: '/tmp' + }; + const prompter = {} as any; + const options = {} as any; + + await dumpCmd(argv, prompter, options); + + expect(spawnMock).toHaveBeenCalledWith( + 'pg_dump', + expect.arrayContaining([ + '--format=plain', + '--no-owner', + '--no-privileges', + '--file', + expect.stringContaining('output.sql'), + 'test_db' + ]), + expect.objectContaining({ + env: expect.anything() + }) + ); + }); + + it('should generate prune sql when database-id is provided', async () => { + const spawnMock = child_process.spawn as unknown as jest.Mock; + spawnMock.mockImplementation(() => ({ + on: (event: string, cb: any) => { + if (event === 'close') cb(0); + } + })); + + jest.spyOn(fs, 'mkdirSync').mockImplementation(() => undefined as any); + const fsWriteSpy = jest.spyOn(fs, 'writeFileSync').mockImplementation(() => undefined); + jest.spyOn(console, 'log').mockImplementation(() => { }); + + // mock db responses for resolveDatabaseId and buildPruneSql + mockPoolQuery + .mockResolvedValueOnce({ rows: [{ id: 'uuid-123', name: 'test_db_id' }] }) // resolveDatabaseId + .mockResolvedValueOnce({ rows: [{ table_schema: 'public', table_name: 'test_table' }] }); // buildPruneSql + + const argv = { + database: 'test_db', + out: 'output_prune.sql', + 'database-id': 'uuid-123', + cwd: '/tmp' + }; + const prompter = {} as any; + const options = {} as any; + + await dumpCmd(argv, prompter, options); + + // verify prune sql appended + expect(fsWriteSpy).toHaveBeenCalledWith( + expect.stringContaining('output_prune.sql'), + expect.stringContaining('delete from "public"."test_table" where database_id <> \'uuid-123\''), + expect.objectContaining({ flag: 'a' }) + ); + }); }); diff --git a/pgpm/cli/__tests__/init.boilerplate.test.ts b/pgpm/cli/__tests__/init.boilerplate.test.ts index 59ca3a9afb..e8db742860 100644 --- a/pgpm/cli/__tests__/init.boilerplate.test.ts +++ b/pgpm/cli/__tests__/init.boilerplate.test.ts @@ -1,9 +1,8 @@ +import { DEFAULT_TEMPLATE_REPO, TEMPLATE_REPOS } from '@pgpmjs/core'; import fs from 'fs'; import os from 'os'; import path from 'path'; -import { DEFAULT_TEMPLATE_REPO, TEMPLATE_REPOS } from '@pgpmjs/core'; - import { persistBoilerplateSource, readBoilerplateSource, diff --git a/pgpm/cli/__tests__/init.install.test.ts b/pgpm/cli/__tests__/init.install.test.ts index 8ed9b5e87f..caaa23d259 100644 --- a/pgpm/cli/__tests__/init.install.test.ts +++ b/pgpm/cli/__tests__/init.install.test.ts @@ -6,7 +6,7 @@ import * as fs from 'fs'; import * as glob from 'glob'; import * as path from 'path'; -import { TestFixture, normalizePackageJsonForSnapshot } from '../test-utils'; +import { normalizePackageJsonForSnapshot,TestFixture } from '../test-utils'; describe('cmds:install - with initialized workspace and module', () => { let fixture: TestFixture; @@ -119,8 +119,8 @@ describe('cmds:install - with initialized workspace and module', () => { const relativeFiles = installedFiles - .map((f: string) => path.relative(moduleDir, f)) - .sort(); + .map((f: string) => path.relative(moduleDir, f)) + .sort(); expect(relativeFiles).toMatchSnapshot(); diff --git a/pgpm/cli/__tests__/init.templates.test.ts b/pgpm/cli/__tests__/init.templates.test.ts index 98a8b071a0..73938b2c25 100644 --- a/pgpm/cli/__tests__/init.templates.test.ts +++ b/pgpm/cli/__tests__/init.templates.test.ts @@ -1,11 +1,10 @@ jest.setTimeout(30000); +import { scaffoldTemplate } from '@pgpmjs/core'; import fs from 'fs'; import os from 'os'; import path from 'path'; -import { scaffoldTemplate } from '@pgpmjs/core'; - const TEMPLATE_REPO = 'https://github.com/constructive-io/pgpm-boilerplates.git'; describe('Template scaffolding', () => { diff --git a/pgpm/cli/__tests__/init.test.ts b/pgpm/cli/__tests__/init.test.ts index a6f0496869..ac2a4f6455 100644 --- a/pgpm/cli/__tests__/init.test.ts +++ b/pgpm/cli/__tests__/init.test.ts @@ -69,9 +69,9 @@ describe('cmds:init', () => { const normalizedResult = result && typeof result === 'object' ? { - ...result, - cwd: typeof (result as any).cwd === 'string' ? '' : (result as any).cwd - } + ...result, + cwd: typeof (result as any).cwd === 'string' ? '' : (result as any).cwd + } : result; expect(snapshotArgs).toMatchSnapshot(`${label} - argv`); diff --git a/pgpm/cli/__tests__/package-alias.test.ts b/pgpm/cli/__tests__/package-alias.test.ts index a6051a3e9e..397ed357d2 100644 --- a/pgpm/cli/__tests__/package-alias.test.ts +++ b/pgpm/cli/__tests__/package-alias.test.ts @@ -1,5 +1,4 @@ import * as fs from 'fs'; -import * as path from 'path'; import { teardownPgPools } from 'pg-cache'; import { CLIDeployTestFixture } from '../test-utils'; diff --git a/pgpm/cli/src/commands/add.ts b/pgpm/cli/src/commands/add.ts index 79f9f98268..55afebc168 100644 --- a/pgpm/cli/src/commands/add.ts +++ b/pgpm/cli/src/commands/add.ts @@ -1,5 +1,5 @@ import { PgpmPackage } from '@pgpmjs/core'; -import { CLIOptions, Inquirerer, ParsedArgs, extractFirst } from 'inquirerer'; +import { CLIOptions, extractFirst,Inquirerer, ParsedArgs } from 'inquirerer'; import * as path from 'path'; const addUsageText = ` diff --git a/pgpm/cli/src/commands/admin-users.ts b/pgpm/cli/src/commands/admin-users.ts index ee7cf0381b..fdb0b4e374 100644 --- a/pgpm/cli/src/commands/admin-users.ts +++ b/pgpm/cli/src/commands/admin-users.ts @@ -1,4 +1,5 @@ -import { CLIOptions, Inquirerer, ParsedArgs, extractFirst } from 'inquirerer'; +import { CLIOptions, extractFirst,Inquirerer, ParsedArgs } from 'inquirerer'; + import add from './admin-users/add'; import bootstrap from './admin-users/bootstrap'; import remove from './admin-users/remove'; diff --git a/pgpm/cli/src/commands/cache.ts b/pgpm/cli/src/commands/cache.ts index 314e14b8e6..4c1a8a6689 100644 --- a/pgpm/cli/src/commands/cache.ts +++ b/pgpm/cli/src/commands/cache.ts @@ -1,5 +1,5 @@ -import { CLIOptions, Inquirerer, cliExitWithError } from 'inquirerer'; import { CacheManager } from 'genomic'; +import { cliExitWithError,CLIOptions, Inquirerer } from 'inquirerer'; const cacheUsageText = ` Cache Command: diff --git a/pgpm/cli/src/commands/dump.ts b/pgpm/cli/src/commands/dump.ts index 763c7aa935..0791c6bea0 100644 --- a/pgpm/cli/src/commands/dump.ts +++ b/pgpm/cli/src/commands/dump.ts @@ -1,11 +1,11 @@ import { Logger } from '@pgpmjs/logger'; -import { CLIOptions, Inquirerer, ParsedArgs } from 'inquirerer'; -import { getPgEnvOptions, getSpawnEnvWithPg } from 'pg-env'; -import { getPgPool } from 'pg-cache'; +import { QuoteUtils } from '@pgsql/quotes'; import { spawn } from 'child_process'; import fs from 'fs'; +import { CLIOptions, Inquirerer, ParsedArgs } from 'inquirerer'; import path from 'path'; -import { QuoteUtils } from '@pgsql/quotes'; +import { getPgPool } from 'pg-cache'; +import { getPgEnvOptions, getSpawnEnvWithPg } from 'pg-env'; import { getTargetDatabase } from '../utils'; diff --git a/pgpm/cli/src/commands/export.ts b/pgpm/cli/src/commands/export.ts index a2d297fbd5..3fac14a2fa 100644 --- a/pgpm/cli/src/commands/export.ts +++ b/pgpm/cli/src/commands/export.ts @@ -1,6 +1,6 @@ import { PgpmPackage } from '@pgpmjs/core'; -import { exportMigrations, exportGraphQL, GraphQLClient, graphqlRowToPostgresRow, isExportGranularity, EXPORT_GRANULARITIES, parsePartitionConfig, PartitionConfig } from '@pgpmjs/export'; import { getEnvOptions } from '@pgpmjs/env'; +import { EXPORT_GRANULARITIES, exportGraphQL, exportMigrations, GraphQLClient, graphqlRowToPostgresRow, isExportGranularity, parsePartitionConfig, PartitionConfig } from '@pgpmjs/export'; import { getGitConfigInfo } from '@pgpmjs/types'; import { CLIOptions, Inquirerer } from 'inquirerer'; import { resolve } from 'path'; diff --git a/pgpm/cli/src/commands/init/boilerplate.ts b/pgpm/cli/src/commands/init/boilerplate.ts index 53bc0a4a92..8e3463947c 100644 --- a/pgpm/cli/src/commands/init/boilerplate.ts +++ b/pgpm/cli/src/commands/init/boilerplate.ts @@ -1,8 +1,7 @@ +import { DEFAULT_TEMPLATE_REPO, PgpmPackage, TEMPLATE_REPOS } from '@pgpmjs/core'; import fs from 'fs'; import path from 'path'; -import { DEFAULT_TEMPLATE_REPO, PgpmPackage, TEMPLATE_REPOS } from '@pgpmjs/core'; - /** * A template/boilerplate source, recorded on a workspace so that modules * created inside it inherit the same repo without re-specifying flags. diff --git a/pgpm/cli/src/commands/init/index.ts b/pgpm/cli/src/commands/init/index.ts index 38ba8b3670..838eb37c8a 100644 --- a/pgpm/cli/src/commands/init/index.ts +++ b/pgpm/cli/src/commands/init/index.ts @@ -1,7 +1,3 @@ -import { execSync } from 'child_process'; -import fs from 'fs'; -import path from 'path'; - import { BoilerplateSkill, DEFAULT_TEMPLATE_REPO, @@ -16,7 +12,10 @@ import { } from '@pgpmjs/core'; import { resolveWorkspaceByType } from '@pgpmjs/env'; import { errors } from '@pgpmjs/types'; +import { execSync } from 'child_process'; +import fs from 'fs'; import { CLIOptions, Inquirerer, OptionValue, Question, registerDefaultResolver } from 'inquirerer'; +import path from 'path'; import { isNoTtyRequested } from '../../utils'; import { @@ -704,8 +703,8 @@ async function handleModuleInit( const extensions = isPgpmTemplate && answers.extensions ? answers.extensions - .filter((opt: OptionValue) => opt.selected) - .map((opt: OptionValue) => opt.name) + .filter((opt: OptionValue) => opt.selected) + .map((opt: OptionValue) => opt.name) : []; const templateAnswers = { diff --git a/pgpm/cli/src/commands/install.ts b/pgpm/cli/src/commands/install.ts index 7b11268201..d0d9b27f44 100644 --- a/pgpm/cli/src/commands/install.ts +++ b/pgpm/cli/src/commands/install.ts @@ -1,6 +1,6 @@ import { getMissingInstallableModules, PgpmPackage } from '@pgpmjs/core'; import { Logger } from '@pgpmjs/logger'; -import { CLIOptions, Inquirerer, ParsedArgs, createSpinner } from 'inquirerer'; +import { CLIOptions, createSpinner,Inquirerer, ParsedArgs } from 'inquirerer'; const logger = new Logger('pgpm'); diff --git a/pgpm/cli/src/commands/migrate.ts b/pgpm/cli/src/commands/migrate.ts index cbf42ac1dc..03f753be54 100644 --- a/pgpm/cli/src/commands/migrate.ts +++ b/pgpm/cli/src/commands/migrate.ts @@ -1,4 +1,5 @@ -import { CLIOptions, Inquirerer, ParsedArgs, extractFirst } from 'inquirerer'; +import { CLIOptions, extractFirst,Inquirerer, ParsedArgs } from 'inquirerer'; + import deps from './migrate/deps'; // Migrate subcommands import init from './migrate/init'; diff --git a/pgpm/cli/src/commands/package.ts b/pgpm/cli/src/commands/package.ts index 3ae33079c3..7d66e3a82b 100644 --- a/pgpm/cli/src/commands/package.ts +++ b/pgpm/cli/src/commands/package.ts @@ -134,7 +134,6 @@ export default async ( project.ensureModule(); const info = project.getModuleInfo(); - info.version; await writePackage({ version: info.version, diff --git a/pgpm/cli/src/commands/regen.ts b/pgpm/cli/src/commands/regen.ts index 117e1edcff..d9e964bfba 100644 --- a/pgpm/cli/src/commands/regen.ts +++ b/pgpm/cli/src/commands/regen.ts @@ -2,7 +2,7 @@ import { parsePlanFile, PgpmPackage, readScript } from '@pgpmjs/core'; import { Logger } from '@pgpmjs/logger'; import { isStubScript, loadModule, regenerateScripts } from '@pgpmjs/transform'; import * as fs from 'fs'; -import { CLIOptions, cliExitWithError, Inquirerer, ParsedArgs } from 'inquirerer'; +import { cliExitWithError, CLIOptions, Inquirerer, ParsedArgs } from 'inquirerer'; import * as path from 'path'; const log = new Logger('regen'); diff --git a/pgpm/cli/src/commands/remove.ts b/pgpm/cli/src/commands/remove.ts index ca2b0191c4..80ec929c94 100644 --- a/pgpm/cli/src/commands/remove.ts +++ b/pgpm/cli/src/commands/remove.ts @@ -1,7 +1,7 @@ import { PgpmPackage } from '@pgpmjs/core'; import { getEnvOptions } from '@pgpmjs/env'; import { Logger } from '@pgpmjs/logger'; -import { CLIOptions, Inquirerer, Question, cliExitWithError } from 'inquirerer'; +import { cliExitWithError,CLIOptions, Inquirerer, Question } from 'inquirerer'; import { getPgEnvOptions } from 'pg-env'; import { getTargetDatabase } from '../utils'; diff --git a/pgpm/cli/src/commands/rename.ts b/pgpm/cli/src/commands/rename.ts index 7612045876..3326cabdd2 100644 --- a/pgpm/cli/src/commands/rename.ts +++ b/pgpm/cli/src/commands/rename.ts @@ -1,5 +1,5 @@ import { PgpmPackage } from '@pgpmjs/core'; -import { Inquirerer, ParsedArgs, cliExitWithError } from 'inquirerer'; +import { cliExitWithError,Inquirerer, ParsedArgs } from 'inquirerer'; import path from 'path'; export default async (argv: Partial, _prompter: Inquirerer) => { diff --git a/pgpm/cli/src/commands/revert.ts b/pgpm/cli/src/commands/revert.ts index 1bb86e2e97..99e1acd1eb 100644 --- a/pgpm/cli/src/commands/revert.ts +++ b/pgpm/cli/src/commands/revert.ts @@ -1,7 +1,7 @@ import { PgpmPackage } from '@pgpmjs/core'; import { getEnvOptions } from '@pgpmjs/env'; import { Logger } from '@pgpmjs/logger'; -import { CLIOptions, Inquirerer, Question, cliExitWithError } from 'inquirerer'; +import { cliExitWithError,CLIOptions, Inquirerer, Question } from 'inquirerer'; import { getPgEnvOptions } from 'pg-env'; import { getTargetDatabase, resolvePackageAlias } from '../utils'; diff --git a/pgpm/cli/src/commands/slice.ts b/pgpm/cli/src/commands/slice.ts index a0e12bf5ea..578f989df9 100644 --- a/pgpm/cli/src/commands/slice.ts +++ b/pgpm/cli/src/commands/slice.ts @@ -1,9 +1,9 @@ import { PgpmPackage } from '@pgpmjs/core'; import { generateDryRunReport, PatternSlice, SliceConfig, slicePlan, writeSliceResult } from '@pgpmjs/slice'; import { getGitConfigInfo } from '@pgpmjs/types'; +import { existsSync,readFileSync } from 'fs'; import { CLIOptions, Inquirerer } from 'inquirerer'; import { resolve } from 'path'; -import { readFileSync, existsSync } from 'fs'; const sliceUsageText = ` Slice Command: @@ -169,10 +169,10 @@ export default async ( strategy: strategyType === 'pattern' ? { type: 'pattern', slices: patternSlices } : { - type: 'folder', - depth: argv.depth ?? depth ?? 1, - prefixToStrip: argv.prefix ?? prefix ?? 'schemas' - }, + type: 'folder', + depth: argv.depth ?? depth ?? 1, + prefixToStrip: argv.prefix ?? prefix ?? 'schemas' + }, defaultPackage: argv.default ?? defaultPackage ?? 'core', minChangesPerPackage: argv['min-changes'] ?? minChanges ?? 0, useTagsForCrossPackageDeps: argv['use-tags'] ?? useTags ?? false, diff --git a/pgpm/cli/src/commands/tag.ts b/pgpm/cli/src/commands/tag.ts index 5a11c000cd..0c833e92cf 100644 --- a/pgpm/cli/src/commands/tag.ts +++ b/pgpm/cli/src/commands/tag.ts @@ -1,8 +1,9 @@ import { PgpmPackage } from '@pgpmjs/core'; import { Logger } from '@pgpmjs/logger'; import { errors } from '@pgpmjs/types'; -import { CLIOptions, Inquirerer, Question, extractFirst } from 'inquirerer'; +import { CLIOptions, extractFirst,Inquirerer, Question } from 'inquirerer'; import * as path from 'path'; + import { selectPackage } from '../utils/module-utils'; import { resolvePackageAlias } from '../utils/package-alias'; diff --git a/pgpm/cli/src/commands/test-packages.ts b/pgpm/cli/src/commands/test-packages.ts index f23ed69904..defd26e010 100644 --- a/pgpm/cli/src/commands/test-packages.ts +++ b/pgpm/cli/src/commands/test-packages.ts @@ -1,10 +1,10 @@ import { PgpmPackage } from '@pgpmjs/core'; import { getEnvOptions } from '@pgpmjs/env'; import { Logger } from '@pgpmjs/logger'; -import path from 'path'; import { CLIOptions, Inquirerer, ParsedArgs } from 'inquirerer'; -import { getPgEnvOptions } from 'pg-env'; +import path from 'path'; import { getPgPool } from 'pg-cache'; +import { getPgEnvOptions } from 'pg-env'; const log = new Logger('test-packages'); diff --git a/pgpm/cli/src/commands/transform.ts b/pgpm/cli/src/commands/transform.ts index e72af60879..979b83a585 100644 --- a/pgpm/cli/src/commands/transform.ts +++ b/pgpm/cli/src/commands/transform.ts @@ -7,15 +7,15 @@ import { loadModuleSource, parsePartitionConfig, PartitionConfig, - partitionExportRows, PartitionedPackageRows, + partitionExportRows, restructureExportRows, snapshotCatalog } from '@pgpmjs/export'; import { Logger } from '@pgpmjs/logger'; import { PartitionCycleError } from '@pgpmjs/transform'; import * as fs from 'fs'; -import { CLIOptions, cliExitWithError, Inquirerer, ParsedArgs } from 'inquirerer'; +import { cliExitWithError, CLIOptions, Inquirerer, ParsedArgs } from 'inquirerer'; import * as path from 'path'; import { getPgPool } from 'pg-cache'; import type { PgConfig } from 'pg-env'; diff --git a/pgpm/cli/src/commands/update.ts b/pgpm/cli/src/commands/update.ts index 4170691598..a7cc5eb899 100644 --- a/pgpm/cli/src/commands/update.ts +++ b/pgpm/cli/src/commands/update.ts @@ -1,7 +1,8 @@ import { suppressUpdateCheck } from '@inquirerer/utils'; import { Logger } from '@pgpmjs/logger'; -import { CLIOptions, Inquirerer, cliExitWithError, getPackageJson } from 'inquirerer'; import { spawn } from 'child_process'; +import { cliExitWithError, CLIOptions, getPackageJson,Inquirerer } from 'inquirerer'; + import { fetchLatestVersion } from '../utils/npm-version'; const log = new Logger('update'); diff --git a/pgpm/cli/src/commands/upgrade.ts b/pgpm/cli/src/commands/upgrade.ts index a0d0cbff08..4ad1382529 100644 --- a/pgpm/cli/src/commands/upgrade.ts +++ b/pgpm/cli/src/commands/upgrade.ts @@ -1,6 +1,7 @@ import { PgpmPackage } from '@pgpmjs/core'; import { Logger } from '@pgpmjs/logger'; -import { CLIOptions, Inquirerer, PackageInfo, ParsedArgs, createSpinner, upgradePrompt } from 'inquirerer'; +import { CLIOptions, createSpinner, Inquirerer, PackageInfo, ParsedArgs, upgradePrompt } from 'inquirerer'; + import { fetchLatestVersion } from '../utils/npm-version'; const log = new Logger('upgrade'); diff --git a/pgpm/cli/src/commands/verify.ts b/pgpm/cli/src/commands/verify.ts index d1b1e2305b..ea4857c543 100644 --- a/pgpm/cli/src/commands/verify.ts +++ b/pgpm/cli/src/commands/verify.ts @@ -1,7 +1,7 @@ import { PgpmPackage } from '@pgpmjs/core'; import { getEnvOptions } from '@pgpmjs/env'; import { Logger } from '@pgpmjs/logger'; -import { CLIOptions, Inquirerer, Question, cliExitWithError } from 'inquirerer'; +import { cliExitWithError,CLIOptions, Inquirerer, Question } from 'inquirerer'; import { getPgEnvOptions } from 'pg-env'; import { getTargetDatabase, resolvePackageAlias } from '../utils'; diff --git a/pgpm/cli/src/utils/driver.ts b/pgpm/cli/src/utils/driver.ts index 6e71fd68c8..6e4392aa65 100644 --- a/pgpm/cli/src/utils/driver.ts +++ b/pgpm/cli/src/utils/driver.ts @@ -1,11 +1,12 @@ +import { createRequire } from 'node:module'; +import { resolve } from 'node:path'; + import { PGPM_DRIVER_EXPORT, PgpmDriverConfig, PgpmDriverFactory, PgpmDriverSession, } from '@pgpmjs/types'; -import { createRequire } from 'node:module'; -import { resolve } from 'node:path'; /** Package name of the built-in PGlite driver plugin (the `--pglite` alias). */ export const PGLITE_DRIVER_PLUGIN = '@pgpmjs/pglite-adapter'; diff --git a/pgpm/cli/src/utils/engine.ts b/pgpm/cli/src/utils/engine.ts index dc598ad31f..4f0b693682 100644 --- a/pgpm/cli/src/utils/engine.ts +++ b/pgpm/cli/src/utils/engine.ts @@ -1,3 +1,5 @@ +import { resolve } from 'node:path'; + import { getEnvOptions } from '@pgpmjs/env'; import { BUILTIN_ENGINES, @@ -8,7 +10,6 @@ import { PgpmEngineConfig, PgpmOptions, } from '@pgpmjs/types'; -import { resolve } from 'node:path'; import { activateDriver, driverOverrideFromArgv, PGLITE_DRIVER_PLUGIN } from './driver'; diff --git a/pgpm/cli/test-utils/fixtures.ts b/pgpm/cli/test-utils/fixtures.ts index e42d5829ea..f33e14ca15 100644 --- a/pgpm/cli/test-utils/fixtures.ts +++ b/pgpm/cli/test-utils/fixtures.ts @@ -1,7 +1,7 @@ -import path from 'path'; -import { DEFAULT_TEMPLATE_REPO } from '@pgpmjs/core'; import { createTestFixture, TestFixture as BaseTestFixture, TestFixtureOptions } from '@inquirerer/test'; +import { DEFAULT_TEMPLATE_REPO } from '@pgpmjs/core'; import { ParsedArgs } from 'inquirerer'; +import path from 'path'; import { commands } from '../src/commands'; import { withInitDefaults } from './init-argv'; diff --git a/pgpm/cli/test-utils/index.ts b/pgpm/cli/test-utils/index.ts index 690f99bbd3..2b40e35f09 100644 --- a/pgpm/cli/test-utils/index.ts +++ b/pgpm/cli/test-utils/index.ts @@ -4,16 +4,13 @@ export * from './init-argv'; export * from './TestDatabase'; // Re-export test utilities from @inquirerer/test +export type { + InputResponse, + NormalizeOptions, + TestEnvironment} from '@inquirerer/test'; export { - KEY_SEQUENCES, - setupTests, + cleanAnsi, createTestEnvironment, + KEY_SEQUENCES, normalizePackageJsonForSnapshot, - cleanAnsi -} from '@inquirerer/test'; - -export type { - TestEnvironment, - InputResponse, - NormalizeOptions -} from '@inquirerer/test'; + setupTests} from '@inquirerer/test'; diff --git a/pgpm/cli/test-utils/init-argv.ts b/pgpm/cli/test-utils/init-argv.ts index e3d074d419..0c2d71eb28 100644 --- a/pgpm/cli/test-utils/init-argv.ts +++ b/pgpm/cli/test-utils/init-argv.ts @@ -1,5 +1,5 @@ -import { ParsedArgs } from 'inquirerer'; import { DEFAULT_TEMPLATE_REPO } from '@pgpmjs/core'; +import { ParsedArgs } from 'inquirerer'; export const addInitDefaults = (argv: ParsedArgs): ParsedArgs => { const baseName = (argv.moduleName as string) || (argv.name as string) || 'module'; diff --git a/pgpm/core/__tests__/apply/apply-modules.test.ts b/pgpm/core/__tests__/apply/apply-modules.test.ts index 5b42fdf110..2d32e79fa6 100644 --- a/pgpm/core/__tests__/apply/apply-modules.test.ts +++ b/pgpm/core/__tests__/apply/apply-modules.test.ts @@ -1,5 +1,4 @@ import { rmSync } from 'fs'; -import { join } from 'path'; import { clearApplyMaterializationCache, diff --git a/pgpm/core/__tests__/apply/apply-routing.test.ts b/pgpm/core/__tests__/apply/apply-routing.test.ts index 995be398fe..2017aff4d7 100644 --- a/pgpm/core/__tests__/apply/apply-routing.test.ts +++ b/pgpm/core/__tests__/apply/apply-routing.test.ts @@ -6,7 +6,6 @@ import { parseApplySpec, readApplySpec } from '../../src/apply'; -import { PgpmPackage } from '../../src/core/class/pgpm'; import { CoreDeployTestFixture } from '../../test-utils/CoreDeployTestFixture'; import { TestDatabase } from '../../test-utils/TestDatabase'; import { TestFixture } from '../../test-utils/TestFixture'; diff --git a/pgpm/core/__tests__/bundle/bundled-deploy.test.ts b/pgpm/core/__tests__/bundle/bundled-deploy.test.ts index 17d8ea0d46..3ba33fa0ee 100644 --- a/pgpm/core/__tests__/bundle/bundled-deploy.test.ts +++ b/pgpm/core/__tests__/bundle/bundled-deploy.test.ts @@ -1,12 +1,11 @@ -import { readFileSync, writeFileSync } from 'fs'; -import { join } from 'path'; - import { hashString } from '@pgpmjs/ast'; import { readBundleArchiveFile, writeBundleArchiveFile } from '@pgpmjs/bundle'; +import { readFileSync, writeFileSync } from 'fs'; +import { join } from 'path'; import { - bundleArtifactFileName, buildExecutableBundle, + bundleArtifactFileName, resolveBundleArtifactPath, writeBundleArtifact } from '../../src/bundle/artifact'; diff --git a/pgpm/core/__tests__/core/add-functionality.test.ts b/pgpm/core/__tests__/core/add-functionality.test.ts index fca1923186..b8f5d0147e 100644 --- a/pgpm/core/__tests__/core/add-functionality.test.ts +++ b/pgpm/core/__tests__/core/add-functionality.test.ts @@ -1,8 +1,9 @@ +import {mkdirSync, readFileSync, writeFileSync } from 'fs'; +import * as fs from 'fs'; +import { basename, join } from 'path'; + import { PgpmPackage } from '../../src/core/class/pgpm'; import { TestFixture } from '../../test-utils'; -import { readFileSync, writeFileSync, mkdirSync, existsSync } from 'fs'; -import { basename, join } from 'path'; -import * as fs from 'fs'; describe('Add functionality', () => { let fixture: TestFixture; diff --git a/pgpm/core/__tests__/core/analyze-module.test.ts b/pgpm/core/__tests__/core/analyze-module.test.ts index b8e0926b53..9befb2da9e 100644 --- a/pgpm/core/__tests__/core/analyze-module.test.ts +++ b/pgpm/core/__tests__/core/analyze-module.test.ts @@ -1,8 +1,9 @@ +import { parsePlanFile } from '@pgpmjs/ast/files/plan/parser'; +import { writePlanFile } from '@pgpmjs/ast/files/plan/writer'; import fs from 'fs'; import path from 'path'; + import { TestFixture } from '../../test-utils'; -import { parsePlanFile } from '@pgpmjs/ast/files/plan/parser'; -import { writePlanFile } from '@pgpmjs/ast/files/plan/writer'; let fixture: TestFixture; diff --git a/pgpm/core/__tests__/core/constructive-project.test.ts b/pgpm/core/__tests__/core/constructive-project.test.ts index dfc6a188d9..2e0771ecd0 100644 --- a/pgpm/core/__tests__/core/constructive-project.test.ts +++ b/pgpm/core/__tests__/core/constructive-project.test.ts @@ -1,4 +1,4 @@ -import { PgpmPackage, PackageContext } from '../../src/core/class/pgpm'; +import { PackageContext,PgpmPackage } from '../../src/core/class/pgpm'; import { TestFixture } from '../../test-utils'; let fixture: TestFixture; diff --git a/pgpm/core/__tests__/core/rename-module.test.ts b/pgpm/core/__tests__/core/rename-module.test.ts index 845a19aca8..943b503964 100644 --- a/pgpm/core/__tests__/core/rename-module.test.ts +++ b/pgpm/core/__tests__/core/rename-module.test.ts @@ -1,5 +1,6 @@ import fs from 'fs'; import path from 'path'; + import { TestFixture } from '../../test-utils'; let fixture: TestFixture; diff --git a/pgpm/core/__tests__/migrate/error-output-formatting.test.ts b/pgpm/core/__tests__/migrate/error-output-formatting.test.ts index 1e24816a59..576c051902 100644 --- a/pgpm/core/__tests__/migrate/error-output-formatting.test.ts +++ b/pgpm/core/__tests__/migrate/error-output-formatting.test.ts @@ -1,4 +1,4 @@ -import { formatQueryHistory, truncateErrorOutput, QueryHistoryEntry } from '../../src/migrate/utils/transaction'; +import { formatQueryHistory, QueryHistoryEntry,truncateErrorOutput } from '../../src/migrate/utils/transaction'; describe('error output formatting', () => { describe('formatQueryHistory', () => { diff --git a/pgpm/core/__tests__/migrate/tag-fallback.test.ts b/pgpm/core/__tests__/migrate/tag-fallback.test.ts index cea5c587d3..e260213b0a 100644 --- a/pgpm/core/__tests__/migrate/tag-fallback.test.ts +++ b/pgpm/core/__tests__/migrate/tag-fallback.test.ts @@ -1,4 +1,4 @@ -import { mkdtempSync, writeFileSync, mkdirSync } from 'fs'; +import { mkdirSync,mkdtempSync, writeFileSync } from 'fs'; import { tmpdir } from 'os'; import { join } from 'path'; diff --git a/pgpm/core/__tests__/packaging/check.test.ts b/pgpm/core/__tests__/packaging/check.test.ts index c3cbc48f65..9ba3baa6cf 100644 --- a/pgpm/core/__tests__/packaging/check.test.ts +++ b/pgpm/core/__tests__/packaging/check.test.ts @@ -1,6 +1,8 @@ import { readFileSync, rmSync, writeFileSync } from 'fs'; import { join } from 'path'; +import { resolveBundleArtifactPath, writeBundleArtifact } from '../../src/bundle/artifact'; +import { PgpmPackage } from '../../src/core/class/pgpm'; import { addDependents, checkModuleArtifact, @@ -8,8 +10,6 @@ import { enumerateModules, mapFilesToModules, } from '../../src/packaging/check'; -import { resolveBundleArtifactPath, writeBundleArtifact } from '../../src/bundle/artifact'; -import { PgpmPackage } from '../../src/core/class/pgpm'; import { TestFixture } from '../../test-utils'; const MODULES = ['my-first', 'my-second', 'my-third'] as const; diff --git a/pgpm/core/__tests__/projects/clear-functionality.test.ts b/pgpm/core/__tests__/projects/clear-functionality.test.ts index 0af851abbd..95bee0c2c8 100644 --- a/pgpm/core/__tests__/projects/clear-functionality.test.ts +++ b/pgpm/core/__tests__/projects/clear-functionality.test.ts @@ -1,8 +1,8 @@ +import { parsePlanFile } from '@pgpmjs/ast/files/plan/parser'; import fs from 'fs'; import path from 'path'; -import { PgpmPackage } from '../../src/core/class/pgpm'; + import { TestFixture } from '../../test-utils/TestFixture'; -import { parsePlanFile } from '@pgpmjs/ast/files/plan/parser'; describe('Clear Functionality', () => { let fixture: TestFixture; diff --git a/pgpm/core/__tests__/projects/forked-deployment-scenarios.test.ts b/pgpm/core/__tests__/projects/forked-deployment-scenarios.test.ts index 9d0f7b81b2..4afff18ef3 100644 --- a/pgpm/core/__tests__/projects/forked-deployment-scenarios.test.ts +++ b/pgpm/core/__tests__/projects/forked-deployment-scenarios.test.ts @@ -2,6 +2,7 @@ process.env.CONSTRUCTIVE_DEBUG = 'true'; import { readFileSync, writeFileSync } from 'fs'; import { join } from 'path'; + import { TestDatabase } from '../../test-utils'; import { CoreDeployTestFixture } from '../../test-utils/CoreDeployTestFixture'; diff --git a/pgpm/core/__tests__/projects/remove-functionality.test.ts b/pgpm/core/__tests__/projects/remove-functionality.test.ts index fbd26aab8f..94d1a36b1f 100644 --- a/pgpm/core/__tests__/projects/remove-functionality.test.ts +++ b/pgpm/core/__tests__/projects/remove-functionality.test.ts @@ -1,6 +1,6 @@ import fs from 'fs'; import path from 'path'; -import { PgpmPackage } from '../../src/core/class/pgpm'; + import { TestFixture } from '../../test-utils/TestFixture'; describe('Remove Functionality', () => { diff --git a/pgpm/core/__tests__/projects/tag-functionality.test.ts b/pgpm/core/__tests__/projects/tag-functionality.test.ts index 8ee6b2fb95..9654f948b4 100644 --- a/pgpm/core/__tests__/projects/tag-functionality.test.ts +++ b/pgpm/core/__tests__/projects/tag-functionality.test.ts @@ -1,10 +1,11 @@ process.env.CONSTRUCTIVE_DEBUG = 'true'; -import { TestDatabase } from '../../test-utils'; -import { teardownPgPools } from 'pg-cache'; import { readFileSync } from 'fs'; -import { PgpmPackage } from '../../src/core/class/pgpm'; import { join } from 'path'; +import { teardownPgPools } from 'pg-cache'; + +import { PgpmPackage } from '../../src/core/class/pgpm'; +import { TestDatabase } from '../../test-utils'; import { CoreDeployTestFixture } from '../../test-utils/CoreDeployTestFixture'; describe('Tag functionality with CoreDeployTestFixture', () => { diff --git a/pgpm/core/__tests__/projects/workspace-w-exts.test.ts b/pgpm/core/__tests__/projects/workspace-w-exts.test.ts index 54852cc91a..67f04fe403 100644 --- a/pgpm/core/__tests__/projects/workspace-w-exts.test.ts +++ b/pgpm/core/__tests__/projects/workspace-w-exts.test.ts @@ -1,7 +1,7 @@ -import { PgpmPackage, PackageContext } from '../../src/core/class/pgpm'; -import { TestFixture } from '../../test-utils/TestFixture'; -import { CoreDeployTestFixture } from '../../test-utils/CoreDeployTestFixture'; +import { PackageContext,PgpmPackage } from '../../src/core/class/pgpm'; import { TestDatabase } from '../../test-utils'; +import { CoreDeployTestFixture } from '../../test-utils/CoreDeployTestFixture'; +import { TestFixture } from '../../test-utils/TestFixture'; describe('w-exts Fixture Tests', () => { let fixture: TestFixture; diff --git a/pgpm/core/__tests__/resolution/dependency-resolution-basic.test.ts b/pgpm/core/__tests__/resolution/dependency-resolution-basic.test.ts index d325d3dd27..fdbcd83e02 100644 --- a/pgpm/core/__tests__/resolution/dependency-resolution-basic.test.ts +++ b/pgpm/core/__tests__/resolution/dependency-resolution-basic.test.ts @@ -1,5 +1,5 @@ -import { resolveExtensionDependencies, resolveDependencies } from '../../src/resolution/deps'; import { PgpmPackage } from '../../src/core/class/pgpm'; +import { resolveDependencies,resolveExtensionDependencies } from '../../src/resolution/deps'; import { TestFixture } from '../../test-utils'; let fixture: TestFixture; diff --git a/pgpm/core/__tests__/resolution/header-format-compatibility.test.ts b/pgpm/core/__tests__/resolution/header-format-compatibility.test.ts index fea09ee29d..089edadf6f 100644 --- a/pgpm/core/__tests__/resolution/header-format-compatibility.test.ts +++ b/pgpm/core/__tests__/resolution/header-format-compatibility.test.ts @@ -1,7 +1,8 @@ +import { mkdirSync,writeFileSync } from 'fs'; +import { join } from 'path'; + import { resolveDependencies } from '../../src/resolution/deps'; import { TestFixture } from '../../test-utils'; -import { writeFileSync, mkdirSync } from 'fs'; -import { join } from 'path'; describe('Header format compatibility', () => { let fixture: TestFixture; diff --git a/pgpm/core/__tests__/slice/slice-deploy-integration.test.ts b/pgpm/core/__tests__/slice/slice-deploy-integration.test.ts index 1d5f05b837..acbb1880d5 100644 --- a/pgpm/core/__tests__/slice/slice-deploy-integration.test.ts +++ b/pgpm/core/__tests__/slice/slice-deploy-integration.test.ts @@ -1,9 +1,9 @@ -import { join } from 'path'; -import { mkdirSync, writeFileSync, rmSync } from 'fs'; +import { slicePlan, writeSliceResult } from '@pgpmjs/slice'; +import { mkdirSync, rmSync,writeFileSync } from 'fs'; import { tmpdir } from 'os'; +import { join } from 'path'; import { PgpmMigrate } from '../../src/migrate/client'; -import { slicePlan, writeSliceResult } from '@pgpmjs/slice'; import { MigrateTestFixture, teardownAllPools, TestDatabase } from '../../test-utils'; describe('Slice Deploy Integration', () => { diff --git a/pgpm/core/__tests__/workspace/minimal.test.ts b/pgpm/core/__tests__/workspace/minimal.test.ts index a49290c9c2..721c097a12 100644 --- a/pgpm/core/__tests__/workspace/minimal.test.ts +++ b/pgpm/core/__tests__/workspace/minimal.test.ts @@ -2,13 +2,13 @@ import { existsSync, mkdtempSync, readFileSync, rmSync, writeFileSync } from 'fs import { tmpdir } from 'os'; import { join } from 'path'; -import { modulePath, pgpmPath } from '../../src/workspace/paths'; import { generateModuleControl, generateModuleMakefile, writeMinimalModule, writeMinimalWorkspace, } from '../../src/workspace/minimal'; +import { modulePath, pgpmPath } from '../../src/workspace/paths'; let dir: string; diff --git a/pgpm/core/__tests__/workspace/module-utilities.test.ts b/pgpm/core/__tests__/workspace/module-utilities.test.ts index 736594e027..f5d7fdc891 100644 --- a/pgpm/core/__tests__/workspace/module-utilities.test.ts +++ b/pgpm/core/__tests__/workspace/module-utilities.test.ts @@ -1,9 +1,9 @@ +import { PgpmPackage } from '../../src/core/class/pgpm'; import { getExtensionsAndModules, getExtensionsAndModulesChanges, latestChange } from '../../src/modules/modules'; -import { PgpmPackage } from '../../src/core/class/pgpm'; import { TestFixture } from '../../test-utils'; let fixture: TestFixture; diff --git a/pgpm/core/src/apply/index.ts b/pgpm/core/src/apply/index.ts index 2ad31ba17b..492aee75e0 100644 --- a/pgpm/core/src/apply/index.ts +++ b/pgpm/core/src/apply/index.ts @@ -1,5 +1,5 @@ +export * from './apply-spec'; export * from './materialize'; export * from './profile'; -export * from './apply-spec'; export * from './reuse'; export * from './types'; diff --git a/pgpm/core/src/apply/reuse.ts b/pgpm/core/src/apply/reuse.ts index b160f9d395..5ecb35cc39 100644 --- a/pgpm/core/src/apply/reuse.ts +++ b/pgpm/core/src/apply/reuse.ts @@ -1,7 +1,3 @@ -import { mkdtempSync } from 'fs'; -import { tmpdir } from 'os'; -import { join } from 'path'; - import { hashString } from '@pgpmjs/ast'; import { bundleFromModule, @@ -19,6 +15,9 @@ import { SchemaObjectRoute, SchemaTransformPass } from '@pgpmjs/transform'; +import { mkdtempSync } from 'fs'; +import { tmpdir } from 'os'; +import { join } from 'path'; import { ResolvedApplySpec } from './types'; diff --git a/pgpm/core/src/bundle/apply-envelope.ts b/pgpm/core/src/bundle/apply-envelope.ts index d56025289e..4575ca2d81 100644 --- a/pgpm/core/src/bundle/apply-envelope.ts +++ b/pgpm/core/src/bundle/apply-envelope.ts @@ -1,6 +1,3 @@ -import { PgConfig } from 'pg-env'; -import { getPgPool } from 'pg-cache'; - import { BundleEnvelope, EnvelopeIssue, @@ -8,6 +5,8 @@ import { EnvelopeScriptPart, verifyEnvelope } from '@pgpmjs/bundle'; +import { getPgPool } from 'pg-cache'; +import { PgConfig } from 'pg-env'; import { applyBundle, diff --git a/pgpm/core/src/bundle/apply.ts b/pgpm/core/src/bundle/apply.ts index 9f422f091b..77051cb54a 100644 --- a/pgpm/core/src/bundle/apply.ts +++ b/pgpm/core/src/bundle/apply.ts @@ -1,11 +1,10 @@ +import { PgpmScriptKind } from '@pgpmjs/ast/module/types'; +import { BundleIssue, materializeBundle, MigrationBundle, verifyBundle } from '@pgpmjs/bundle'; import { mkdtempSync, rmSync } from 'fs'; import { tmpdir } from 'os'; import { join } from 'path'; import { PgConfig } from 'pg-env'; -import { PgpmScriptKind } from '@pgpmjs/ast/module/types'; -import { BundleIssue, materializeBundle, MigrationBundle, verifyBundle } from '@pgpmjs/bundle'; - import { PgpmMigrate, PgpmMigrateOptions } from '../migrate/client'; import { DeployResult, VerifyResult } from '../migrate/types'; diff --git a/pgpm/core/src/bundle/artifact.ts b/pgpm/core/src/bundle/artifact.ts index 7197d01d5c..264ca33362 100644 --- a/pgpm/core/src/bundle/artifact.ts +++ b/pgpm/core/src/bundle/artifact.ts @@ -1,6 +1,3 @@ -import { existsSync, readdirSync, readFileSync } from 'fs'; -import { join } from 'path'; - import { hashString } from '@pgpmjs/ast'; import { getExtensionName, parseControlContent } from '@pgpmjs/ast/files'; import { @@ -13,6 +10,8 @@ import { withExecutableSql, writeBundleArchiveFile } from '@pgpmjs/bundle'; +import { existsSync, readdirSync, readFileSync } from 'fs'; +import { join } from 'path'; import { cleanSql } from '../migrate/clean'; diff --git a/pgpm/core/src/bundle/deploy-bundled.ts b/pgpm/core/src/bundle/deploy-bundled.ts index 4289990ec9..94381dd117 100644 --- a/pgpm/core/src/bundle/deploy-bundled.ts +++ b/pgpm/core/src/bundle/deploy-bundled.ts @@ -1,10 +1,10 @@ -import { Logger } from '@pgpmjs/logger'; import { BundleChange, MigrationBundle, verifyBundle } from '@pgpmjs/bundle'; +import { Logger } from '@pgpmjs/logger'; import { getPgPool } from 'pg-cache'; import { PgConfig } from 'pg-env'; import { PgpmMigrate } from '../migrate/client'; -import { bundleMatchesModule, buildExecutableBundle, readBundleArtifact } from './artifact'; +import { buildExecutableBundle, bundleMatchesModule, readBundleArtifact } from './artifact'; const log = new Logger('deploy-fast'); diff --git a/pgpm/core/src/core/class/pgpm.ts b/pgpm/core/src/core/class/pgpm.ts index b283e0406c..fdf68d3f91 100644 --- a/pgpm/core/src/core/class/pgpm.ts +++ b/pgpm/core/src/core/class/pgpm.ts @@ -1,3 +1,18 @@ +import { generatePlan, writePlan, writePlanFile } from '@pgpmjs/ast/files'; +import { + ExtensionInfo, + getExtensionInfo, + getExtensionName, + getInstalledExtensions, + parseControlFile, + writeExtensions +} from '@pgpmjs/ast/files'; +import { generateControlFileContent, writeExtensionMakefile } from '@pgpmjs/ast/files/extension/writer'; +import { getNow as getPlanTimestamp } from '@pgpmjs/ast/files/plan/generator'; +import { parsePlanFile } from '@pgpmjs/ast/files/plan/parser'; +import { isValidChangeName, isValidTagName, parseReference } from '@pgpmjs/ast/files/plan/validators'; +import { Change, Tag } from '@pgpmjs/ast/files/types'; +import { PackageAnalysisIssue, PackageAnalysisResult, RenameOptions } from '@pgpmjs/ast/files/types'; import { getExtensionsDir, loadConfigSyncFromDir, resolvePgpmPath,walkUp } from '@pgpmjs/env'; import { Logger } from '@pgpmjs/logger'; import { DEFAULT_EXTENSIONS_DIR,errors, PgpmOptions, PgpmWorkspaceConfig } from '@pgpmjs/types'; @@ -11,26 +26,13 @@ import { getPgPool } from 'pg-cache'; import { PgConfig } from 'pg-env'; import yanse from 'yanse'; -import { resolveEffectiveModulePath } from '../../apply/materialize'; import { hasApplySpec, readApplySpec } from '../../apply/apply-spec'; +import { resolveEffectiveModulePath } from '../../apply/materialize'; import { isReuseSpec, resolveSharedModuleName } from '../../apply/reuse'; import { APPLY_SPEC_FILE, ResolvedApplySpec } from '../../apply/types'; +import { deployModuleFast, isBundledDeployResult } from '../../bundle/deploy-bundled'; import { getAvailableExtensions } from '../../extensions/extensions'; -import { generatePlan, writePlan, writePlanFile } from '@pgpmjs/ast/files'; -import { - ExtensionInfo, - getExtensionInfo, - getExtensionName, - getInstalledExtensions, - parseControlFile, - writeExtensions -} from '@pgpmjs/ast/files'; -import { generateControlFileContent, writeExtensionMakefile } from '@pgpmjs/ast/files/extension/writer'; -import { getNow as getPlanTimestamp } from '@pgpmjs/ast/files/plan/generator'; -import { parsePlanFile } from '@pgpmjs/ast/files/plan/parser'; -import { isValidChangeName, isValidTagName, parseReference } from '@pgpmjs/ast/files/plan/validators'; -import { Change, Tag } from '@pgpmjs/ast/files/types'; -import { PackageAnalysisIssue, PackageAnalysisResult, RenameOptions } from '@pgpmjs/ast/files/types'; +import { findExtensionInstall, roleMapFromRoles } from '../../extensions/resolve-install'; import { PgpmMigrate } from '../../migrate/client'; import { getExtensionsAndModules, @@ -39,9 +41,7 @@ import { latestChangeAndVersion, ModuleMap } from '../../modules/modules'; -import { deployModuleFast, isBundledDeployResult } from '../../bundle/deploy-bundled'; import { syncModuleVersions, SyncVersionsOptions, SyncVersionsResult } from '../../packaging/sync-versions'; -import { findExtensionInstall, roleMapFromRoles } from '../../extensions/resolve-install'; import { resolveDependencies,resolveExtensionDependencies } from '../../resolution/deps'; import { movePath } from '../../utils/fs'; import { globPaths, globPattern, toPosixPath } from '../../utils/glob'; @@ -765,7 +765,9 @@ export class PgpmPackage { } } } - } catch {} + } catch { + // ignore + } } if (!hasTagDependency && !deps[firstKey].includes(depToken)) { diff --git a/pgpm/core/src/core/template-scaffold.ts b/pgpm/core/src/core/template-scaffold.ts index ac7cf5dbeb..09a8a5e4ce 100644 --- a/pgpm/core/src/core/template-scaffold.ts +++ b/pgpm/core/src/core/template-scaffold.ts @@ -1,9 +1,9 @@ +import { BoilerplateConfig as GenomicBoilerplateConfig,TemplateScaffolder } from 'genomic'; import os from 'os'; import path from 'path'; -import { TemplateScaffolder, BoilerplateConfig as GenomicBoilerplateConfig } from 'genomic'; export type { BoilerplateSkill } from 'genomic'; +export type { SkillInstallFailure,SkillInstallOptions, SkillInstallResult } from 'genomic'; export { SkillInstaller } from 'genomic'; -export type { SkillInstallOptions, SkillInstallResult, SkillInstallFailure } from 'genomic'; import type { Inquirerer, Question } from 'inquirerer'; /** diff --git a/pgpm/core/src/extensions/compile.ts b/pgpm/core/src/extensions/compile.ts index 6b238b1a44..1bec58c760 100644 --- a/pgpm/core/src/extensions/compile.ts +++ b/pgpm/core/src/extensions/compile.ts @@ -38,14 +38,14 @@ const routeRole = (role: string, roleMap?: Record): string => { const grantObjectClause = (on: ExtensionGrantTarget, schema: string): string => { const s = quoteIdent(schema); switch (on) { - case 'schema': - return `SCHEMA ${s}`; - case 'all-tables': - return `ALL TABLES IN SCHEMA ${s}`; - case 'all-sequences': - return `ALL SEQUENCES IN SCHEMA ${s}`; - case 'all-functions': - return `ALL FUNCTIONS IN SCHEMA ${s}`; + case 'schema': + return `SCHEMA ${s}`; + case 'all-tables': + return `ALL TABLES IN SCHEMA ${s}`; + case 'all-sequences': + return `ALL SEQUENCES IN SCHEMA ${s}`; + case 'all-functions': + return `ALL FUNCTIONS IN SCHEMA ${s}`; } }; diff --git a/pgpm/core/src/extensions/resolve-install.ts b/pgpm/core/src/extensions/resolve-install.ts index aaa3ea9337..6ef81f96e5 100644 --- a/pgpm/core/src/extensions/resolve-install.ts +++ b/pgpm/core/src/extensions/resolve-install.ts @@ -1,6 +1,6 @@ +import { RoleMapping } from '@pgpmjs/types'; import { resolve } from 'path'; -import { RoleMapping } from '@pgpmjs/types'; import { CompiledExtensionInstall, compileExtensionInstall, CompileExtensionInstallOptions } from './compile'; import { ExtensionProvide, readExtensionsManifest } from './manifest'; diff --git a/pgpm/core/src/index.ts b/pgpm/core/src/index.ts index c4209cb731..eac274acee 100644 --- a/pgpm/core/src/index.ts +++ b/pgpm/core/src/index.ts @@ -1,31 +1,26 @@ +export * from './core/boilerplate-scanner'; +export * from './core/boilerplate-types'; export * from './core/class/pgpm'; -export * from './rebundle'; +export * from './core/template-scaffold'; export * from './extensions'; export * from './modules/modules'; export * from './packaging/check'; export * from './packaging/package'; export * from './packaging/sync-versions'; export * from './packaging/transform'; +export * from './rebundle'; export * from './resolution/deps'; export * from './resolution/resolve'; +export * from './workspace/minimal'; export * from './workspace/paths'; export * from './workspace/utils'; -export * from './workspace/minimal'; -export * from './core/template-scaffold'; -export * from './core/boilerplate-types'; -export * from './core/boilerplate-scanner'; // Re-export the module AST layer (moved to the @pgpmjs/ast leaf package) -export * from '@pgpmjs/ast/files'; -export * from '@pgpmjs/ast/module'; export * from './apply'; export * from './bundle'; -export * from './refactor'; +export { PgpmInit } from './init/client'; export { cleanSql } from './migrate/clean'; export { PgpmMigrate } from './migrate/client'; -export { PgpmInit } from './init/client'; -export * from './roles'; -export { parseAuthor } from '@pgpmjs/ast'; export { DeployOptions, DeployResult, @@ -38,3 +33,8 @@ export { VerifyResult} from './migrate/types'; export { hashFile, hashString } from './migrate/utils/hash'; export { executeQuery,TransactionContext, TransactionOptions, withTransaction } from './migrate/utils/transaction'; +export * from './refactor'; +export * from './roles'; +export { parseAuthor } from '@pgpmjs/ast'; +export * from '@pgpmjs/ast/files'; +export * from '@pgpmjs/ast/module'; diff --git a/pgpm/core/src/init/client.ts b/pgpm/core/src/init/client.ts index 26ca39bb0f..a8bdb466d4 100644 --- a/pgpm/core/src/init/client.ts +++ b/pgpm/core/src/init/client.ts @@ -3,11 +3,12 @@ import { RoleMapping, TestUserCredentials } from '@pgpmjs/types'; import { Pool } from 'pg'; import { getPgPool } from 'pg-cache'; import { PgConfig } from 'pg-env'; + import { generateCreateBaseRolesSQL, generateCreateClientRoleSQL, - generateCreateUserSQL, generateCreateTestUsersSQL, + generateCreateUserSQL, generateRemoveUserSQL } from '../roles'; diff --git a/pgpm/core/src/migrate/clean.ts b/pgpm/core/src/migrate/clean.ts index bbae161d7f..4ce7c37194 100644 --- a/pgpm/core/src/migrate/clean.ts +++ b/pgpm/core/src/migrate/clean.ts @@ -4,7 +4,7 @@ import { deparse,parse } from 'pgsql-parser'; const filterStatements = (stmts: RawStmt[]): { filteredStmts: RawStmt[], hasFiltered: boolean } => { const filteredStmts = stmts.filter(node => { const stmt = node.stmt; - return stmt && !stmt.hasOwnProperty('TransactionStmt'); + return stmt && !Object.prototype.hasOwnProperty.call(stmt, 'TransactionStmt'); }); const hasFiltered = filteredStmts.length !== stmts.length; diff --git a/pgpm/core/src/migrate/client.ts b/pgpm/core/src/migrate/client.ts index 2c9a482bbb..689bb1ae7e 100644 --- a/pgpm/core/src/migrate/client.ts +++ b/pgpm/core/src/migrate/client.ts @@ -1,3 +1,4 @@ +import { Change, parsePlanFile, parsePlanFileSimple, readScript } from '@pgpmjs/ast/files'; import { Logger } from '@pgpmjs/logger'; import { errors, extractPgErrorFields, formatPgError, formatPgErrorFields } from '@pgpmjs/types'; import { readFileSync } from 'fs'; @@ -6,7 +7,6 @@ import { Pool } from 'pg'; import { getPgPool } from 'pg-cache'; import { PgConfig } from 'pg-env'; -import { Change, parsePlanFile, parsePlanFileSimple, readScript } from '@pgpmjs/ast/files'; import { resolveDependencies } from '../resolution/deps'; import { resolveTagToChangeName } from '../resolution/resolve'; import { cleanSql } from './clean'; @@ -447,6 +447,7 @@ export class PgpmMigrate { } } } finally { + // no cleanup } if (failed.length > 0) { diff --git a/pgpm/core/src/packaging/check.ts b/pgpm/core/src/packaging/check.ts index c20a5ec31f..6ffe891b91 100644 --- a/pgpm/core/src/packaging/check.ts +++ b/pgpm/core/src/packaging/check.ts @@ -1,8 +1,7 @@ +import { verifyBundle } from '@pgpmjs/bundle'; import { execSync } from 'child_process'; import { isAbsolute, relative, resolve as resolvePath } from 'path'; -import { verifyBundle } from '@pgpmjs/bundle'; - import { bundleMatchesModule, readBundleArtifact, diff --git a/pgpm/core/src/packaging/package.ts b/pgpm/core/src/packaging/package.ts index cf1c06cdba..4f78511705 100644 --- a/pgpm/core/src/packaging/package.ts +++ b/pgpm/core/src/packaging/package.ts @@ -1,3 +1,4 @@ +import { getExtensionName } from '@pgpmjs/ast/files'; import { Logger } from '@pgpmjs/logger'; import { RawStmt } from '@pgsql/types'; import { mkdirSync, readFileSync, rmSync,writeFileSync } from 'fs'; @@ -5,7 +6,6 @@ import { relative } from 'path'; import { deparse } from 'pgsql-deparser'; import { parse } from 'pgsql-parser'; -import { getExtensionName } from '@pgpmjs/ast/files'; import { writeBundleArtifact } from '../bundle/artifact'; import { resolve, resolveWithPlan } from '../resolution/resolve'; import { transformProps } from './transform'; @@ -45,8 +45,10 @@ const filterStatements = (stmts: RawStmt[], stripTransactions: boolean): RawStmt if (!stripTransactions) return stmts; return stmts.filter(node => { const stmt = node.stmt; - return !stmt.hasOwnProperty('TransactionStmt') && - !stmt.hasOwnProperty('CreateExtensionStmt'); + return ( + !Object.prototype.hasOwnProperty.call(stmt, 'TransactionStmt') && + !Object.prototype.hasOwnProperty.call(stmt, 'CreateExtensionStmt') + ); }); }; @@ -163,7 +165,7 @@ export const writePackage = async ({ writeFileSync( controlPath, control.replace( - /default_version = '[0-9\.]+'/, + /default_version = '[0-9.]+'/, `default_version = '${version}'` ) ); diff --git a/pgpm/core/src/packaging/sync-versions.ts b/pgpm/core/src/packaging/sync-versions.ts index cc1dab1b13..fa6e2e3809 100644 --- a/pgpm/core/src/packaging/sync-versions.ts +++ b/pgpm/core/src/packaging/sync-versions.ts @@ -1,8 +1,8 @@ +import { getExtensionInfo, parseControlContent } from '@pgpmjs/ast/files'; import { Logger } from '@pgpmjs/logger'; import { existsSync, readFileSync } from 'fs'; import { join } from 'path'; -import { getExtensionInfo, parseControlContent } from '@pgpmjs/ast/files'; import { writePackage } from './package'; const log = new Logger('sync-versions'); diff --git a/pgpm/core/src/packaging/transform.ts b/pgpm/core/src/packaging/transform.ts index d77c6df207..e006ea5305 100644 --- a/pgpm/core/src/packaging/transform.ts +++ b/pgpm/core/src/packaging/transform.ts @@ -39,14 +39,14 @@ export const transformProps = (obj: any, props: TransformProps): any => { copy = {}; for (const attr in obj) { if (Object.prototype.hasOwnProperty.call(obj, attr)) { - if (props.hasOwnProperty(attr)) { + if (Object.prototype.hasOwnProperty.call(props, attr)) { const propRule = props[attr]; if (typeof propRule === 'function') { // Apply function transformation copy[attr] = propRule(obj[attr]); } else if (typeof propRule === 'object' && propRule !== null) { // Apply value-based transformation - if (propRule.hasOwnProperty(obj[attr])) { + if (Object.prototype.hasOwnProperty.call(propRule, obj[attr])) { copy[attr] = propRule[obj[attr]]; } else { copy[attr] = transformProps(obj[attr], props); diff --git a/pgpm/core/src/projects/deploy.ts b/pgpm/core/src/projects/deploy.ts index 3399dd150c..0726af1af5 100644 --- a/pgpm/core/src/projects/deploy.ts +++ b/pgpm/core/src/projects/deploy.ts @@ -6,8 +6,8 @@ import * as path from 'path'; import { getPgPool } from 'pg-cache'; import {PgConfig } from 'pg-env'; -import { resolveEffectiveModulePath } from '../apply/materialize'; import { hasApplySpec } from '../apply/apply-spec'; +import { resolveEffectiveModulePath } from '../apply/materialize'; import { deployModuleFast, isBundledDeployResult } from '../bundle/deploy-bundled'; import { PgpmPackage } from '../core/class/pgpm'; import { findExtensionInstall, roleMapFromRoles } from '../extensions'; diff --git a/pgpm/core/src/projects/revert.ts b/pgpm/core/src/projects/revert.ts index a00cbd2b4f..a7f7c69d53 100644 --- a/pgpm/core/src/projects/revert.ts +++ b/pgpm/core/src/projects/revert.ts @@ -5,8 +5,8 @@ import * as path from 'path'; import { getPgPool } from 'pg-cache'; import {PgConfig } from 'pg-env'; -import { resolveEffectiveModulePath } from '../apply/materialize'; import { hasApplySpec } from '../apply/apply-spec'; +import { resolveEffectiveModulePath } from '../apply/materialize'; import { PgpmPackage } from '../core/class/pgpm'; import { PgpmMigrate } from '../migrate/client'; import { resolveExtensionDependencies } from '../resolution/deps'; diff --git a/pgpm/core/src/projects/verify.ts b/pgpm/core/src/projects/verify.ts index f07a9c088f..2fcc4f2ef4 100644 --- a/pgpm/core/src/projects/verify.ts +++ b/pgpm/core/src/projects/verify.ts @@ -5,8 +5,8 @@ import * as path from 'path'; import { getPgPool } from 'pg-cache'; import {PgConfig } from 'pg-env'; -import { resolveEffectiveModulePath } from '../apply/materialize'; import { hasApplySpec } from '../apply/apply-spec'; +import { resolveEffectiveModulePath } from '../apply/materialize'; import { PgpmPackage } from '../core/class/pgpm'; import { PgpmMigrate } from '../migrate/client'; import { resolveExtensionDependencies } from '../resolution/deps'; diff --git a/pgpm/core/src/rebundle/index.ts b/pgpm/core/src/rebundle/index.ts index b6e0f08a6f..79cb491ebb 100644 --- a/pgpm/core/src/rebundle/index.ts +++ b/pgpm/core/src/rebundle/index.ts @@ -1,4 +1,4 @@ -export * from './types'; -export * from './rebundle'; export * from './module'; +export * from './rebundle'; +export * from './types'; export * from './workspace'; diff --git a/pgpm/core/src/rebundle/module.ts b/pgpm/core/src/rebundle/module.ts index 1184d4a134..2561727460 100644 --- a/pgpm/core/src/rebundle/module.ts +++ b/pgpm/core/src/rebundle/module.ts @@ -1,10 +1,10 @@ +import { parsePlanFile } from '@pgpmjs/ast/files/plan/parser'; +import { Change, Tag } from '@pgpmjs/ast/files/types'; +import { generatePlanContent } from '@pgpmjs/slice'; import { copyFileSync, existsSync, mkdirSync, readdirSync, writeFileSync } from 'fs'; import { join } from 'path'; -import { Change, Tag } from '@pgpmjs/ast/files/types'; -import { parsePlanFile } from '@pgpmjs/ast/files/plan/parser'; import { mergeSqlStatements, packageModule } from '../packaging/package'; -import { generatePlanContent } from '@pgpmjs/slice'; import { assembleChunkSql, rebundlePlan } from './rebundle'; import { Chunk, RebundleModuleOptions, RebundleModuleResult } from './types'; diff --git a/pgpm/core/src/rebundle/rebundle.ts b/pgpm/core/src/rebundle/rebundle.ts index 8424c6a81a..31b3a3cb7f 100644 --- a/pgpm/core/src/rebundle/rebundle.ts +++ b/pgpm/core/src/rebundle/rebundle.ts @@ -1,8 +1,4 @@ -import { readFileSync } from 'fs'; -import { join } from 'path'; - import { getChanges } from '@pgpmjs/ast/files/plan/parser'; -import { resolveWithPlan } from '../resolution/resolve'; import { parsePlanFile } from '@pgpmjs/ast/files/plan/parser'; import { buildDependencyGraph, @@ -13,6 +9,10 @@ import { extractPackageFromPath, SliceWarning, } from '@pgpmjs/slice'; +import { readFileSync } from 'fs'; +import { join } from 'path'; + +import { resolveWithPlan } from '../resolution/resolve'; import { Chunk, RebundleResult, RebundleStrategy } from './types'; /** diff --git a/pgpm/core/src/rebundle/workspace.ts b/pgpm/core/src/rebundle/workspace.ts index 78d918f140..149f52e9df 100644 --- a/pgpm/core/src/rebundle/workspace.ts +++ b/pgpm/core/src/rebundle/workspace.ts @@ -1,9 +1,9 @@ +import { parsePlanFile } from '@pgpmjs/ast/files/plan/parser'; +import { Change, Tag } from '@pgpmjs/ast/files/types'; import { existsSync, readdirSync, readFileSync } from 'fs'; import { basename, join } from 'path'; import { DEFAULT_TEMPLATE_REPO, scaffoldTemplate } from '../core/template-scaffold'; -import { Change, Tag } from '@pgpmjs/ast/files/types'; -import { parsePlanFile } from '@pgpmjs/ast/files/plan/parser'; import { mergeSqlStatements } from '../packaging/package'; import { resolveWithPlan } from '../resolution/resolve'; import { writeMinimalModule, writeMinimalWorkspace } from '../workspace/minimal'; diff --git a/pgpm/core/src/refactor/rename.ts b/pgpm/core/src/refactor/rename.ts index ecedebde9a..f7815bc8cd 100644 --- a/pgpm/core/src/refactor/rename.ts +++ b/pgpm/core/src/refactor/rename.ts @@ -1,9 +1,8 @@ -import { existsSync, mkdirSync, readdirSync, readFileSync, renameSync, rmdirSync, statSync, writeFileSync } from 'fs'; -import { dirname, join, relative, sep } from 'path'; - import { parsePlanFileSimple } from '@pgpmjs/ast/files/plan/parser'; import { parsePgpmHeader, renameInHeader, writePgpmScript } from '@pgpmjs/ast/files/sql/header'; import { renameInPlanContent } from '@pgpmjs/ast/plan-rename'; +import { existsSync, mkdirSync, readdirSync, readFileSync, renameSync, rmdirSync, statSync, writeFileSync } from 'fs'; +import { dirname, join, relative, sep } from 'path'; // Re-exported from @pgpmjs/ast so existing `@pgpmjs/core` consumers keep importing it here. export { renameInPlanContent }; diff --git a/pgpm/core/src/resolution/deps.ts b/pgpm/core/src/resolution/deps.ts index 8e0604c2df..9c5f13069a 100644 --- a/pgpm/core/src/resolution/deps.ts +++ b/pgpm/core/src/resolution/deps.ts @@ -1,13 +1,13 @@ +import { parsePlanFile } from '@pgpmjs/ast/files/plan/parser'; +import { scanDeployScript } from '@pgpmjs/ast/files/sql/header'; +import { ExtendedPlanFile } from '@pgpmjs/ast/files/types'; +import { errors } from '@pgpmjs/types'; import { readFileSync } from 'fs'; import { sync as glob } from 'glob'; import { join,relative } from 'path'; import { PgpmPackage } from '../core/class/pgpm'; import { globPattern, toPosixPath } from '../utils/glob'; -import { parsePlanFile } from '@pgpmjs/ast/files/plan/parser'; -import { scanDeployScript } from '@pgpmjs/ast/files/sql/header'; -import { ExtendedPlanFile } from '@pgpmjs/ast/files/types'; -import { errors } from '@pgpmjs/types'; /** * Represents a dependency graph where keys are module identifiers @@ -312,12 +312,12 @@ export const resolveDependencies = ( return null; }; -// Plan-mode branch: use plan.changes order directly; build graph from plan deps (no topo or resort). -// - Loads the current package plan and throws if missing. -// - For each change in plan, adds a node; edges come from change.dependencies. -// - Tag handling per tagResolution: 'preserve' keeps tokens, 'internal' maps for traversal, 'resolve' replaces with change names. -// - Cross-package refs "pkg:change" are recorded in external and kept as graph nodes for coordination by callers. -// - Internal refs like "extname:change" are normalized to "change". + // Plan-mode branch: use plan.changes order directly; build graph from plan deps (no topo or resort). + // - Loads the current package plan and throws if missing. + // - For each change in plan, adds a node; edges come from change.dependencies. + // - Tag handling per tagResolution: 'preserve' keeps tokens, 'internal' maps for traversal, 'resolve' replaces with change names. + // - Cross-package refs "pkg:change" are recorded in external and kept as graph nodes for coordination by callers. + // - Internal refs like "extname:change" are normalized to "change". const resolveTagToChange = (projectName: string, tagName: string): string | null => { const plan = loadPlanFile(projectName); if (!plan) return null; @@ -650,4 +650,4 @@ export const resolveDependencies = ( resolved = [...extensions, ...normalSql]; return { external, resolved, deps, resolvedTags: tagMappings }; -} +}; diff --git a/pgpm/core/src/resolution/resolve.ts b/pgpm/core/src/resolution/resolve.ts index c2156647f0..cad2bed0d1 100644 --- a/pgpm/core/src/resolution/resolve.ts +++ b/pgpm/core/src/resolution/resolve.ts @@ -1,9 +1,9 @@ -import { readFileSync } from 'fs'; - import { getChanges, getExtensionName } from '@pgpmjs/ast/files'; import { parsePlanFile } from '@pgpmjs/ast/files/plan/parser'; -import { resolveDependencies } from './deps'; import { errors } from '@pgpmjs/types'; +import { readFileSync } from 'fs'; + +import { resolveDependencies } from './deps'; /** * Resolves SQL scripts for deployment or reversion. diff --git a/pgpm/core/src/workspace/minimal.ts b/pgpm/core/src/workspace/minimal.ts index c9815bf1cb..ec427826fa 100644 --- a/pgpm/core/src/workspace/minimal.ts +++ b/pgpm/core/src/workspace/minimal.ts @@ -1,8 +1,7 @@ -import fs from 'fs'; -import path from 'path'; - import { Change, Tag } from '@pgpmjs/ast/files/types'; import { generatePlanContent } from '@pgpmjs/slice'; +import fs from 'fs'; +import path from 'path'; const SCRIPT_DIRS = ['deploy', 'revert', 'verify'] as const; export type MinimalScriptDir = (typeof SCRIPT_DIRS)[number]; diff --git a/pgpm/core/src/workspace/utils.ts b/pgpm/core/src/workspace/utils.ts index f0bda19c0f..74d4bdc1ed 100644 --- a/pgpm/core/src/workspace/utils.ts +++ b/pgpm/core/src/workspace/utils.ts @@ -1,6 +1,6 @@ +import { errors } from '@pgpmjs/types'; import { existsSync } from 'fs'; import { dirname, resolve } from 'path'; -import { errors } from '@pgpmjs/types'; /** * Recursively walks up directories to find a specific file (sync version). @@ -31,6 +31,6 @@ export const sluggify = (text: string): string => { return text.toString().toLowerCase().trim() .replace(/\s+/g, '-') // Replace spaces with - .replace(/&/g, '-and-') // Replace & with 'and' - .replace(/[^\w\-]+/g, '') // Remove all non-word chars - .replace(/\-\-+/g, '-'); // Replace multiple - with single - + .replace(/[^\w-]+/g, '') // Remove all non-word chars + .replace(/--+/g, '-'); // Replace multiple - with single - }; diff --git a/pgpm/core/test-utils/MigrateTestFixture.ts b/pgpm/core/test-utils/MigrateTestFixture.ts index c878560ad9..3af06dfb7f 100644 --- a/pgpm/core/test-utils/MigrateTestFixture.ts +++ b/pgpm/core/test-utils/MigrateTestFixture.ts @@ -61,6 +61,7 @@ export class MigrateTestFixture { const pool = getPgPool(pgConfig); this.pools.push(pool); + // eslint-disable-next-line @typescript-eslint/no-this-alias const fixture = this; const db: TestDatabase = { name: dbName, diff --git a/pgpm/env/src/config.ts b/pgpm/env/src/config.ts index e414e257f6..e7fb230a17 100644 --- a/pgpm/env/src/config.ts +++ b/pgpm/env/src/config.ts @@ -1,6 +1,7 @@ +import { PgpmOptions } from '@pgpmjs/types'; import * as fs from 'fs'; import * as path from 'path'; -import { PgpmOptions } from '@pgpmjs/types'; + import { walkUp } from './utils'; /** @@ -11,16 +12,16 @@ export const loadConfigFileSync = (configPath: string): PgpmOptions => { const ext = path.extname(configPath); switch (ext) { - case '.json': - return JSON.parse(fs.readFileSync(configPath, 'utf8')); + case '.json': + return JSON.parse(fs.readFileSync(configPath, 'utf8')); - case '.js': - // delete require.cache[require.resolve(configPath)]; - const configModule = require(configPath); - return configModule.default || configModule; + case '.js': + // delete require.cache[require.resolve(configPath)]; + const configModule = require(configPath); + return configModule.default || configModule; - default: - throw new Error(`Unsupported config file type: ${ext}`); + default: + throw new Error(`Unsupported config file type: ${ext}`); } }; @@ -56,6 +57,7 @@ export const loadConfigSync = (cwd: string = process.cwd()): PgpmOptions => { const configDir = walkUp(cwd, filename); return loadConfigSyncFromDir(configDir); } catch { + // ignore } } @@ -73,6 +75,7 @@ export const resolvePgpmPath = (cwd: string = process.cwd()): string | undefined try { return walkUp(cwd, filename); } catch { + // ignore } } @@ -135,15 +138,15 @@ export const resolveWorkspaceByType = ( workspaceType: WorkspaceType ): string | undefined => { switch (workspaceType) { - case 'pgpm': - return resolvePgpmPath(cwd); - case 'pnpm': - return resolvePnpmWorkspace(cwd); - case 'lerna': - return resolveLernaWorkspace(cwd); - case 'npm': - return resolveNpmWorkspace(cwd); - default: - return undefined; + case 'pgpm': + return resolvePgpmPath(cwd); + case 'pnpm': + return resolvePnpmWorkspace(cwd); + case 'lerna': + return resolveLernaWorkspace(cwd); + case 'npm': + return resolveNpmWorkspace(cwd); + default: + return undefined; } }; diff --git a/pgpm/env/src/env.ts b/pgpm/env/src/env.ts index f510cf03fe..340216e6f6 100644 --- a/pgpm/env/src/env.ts +++ b/pgpm/env/src/env.ts @@ -1,5 +1,5 @@ +import { BucketProvider,PgpmOptions } from '@pgpmjs/types'; import { parseEnvBoolean, parseEnvList, parseEnvNumber } from '12factor-env'; -import { PgpmOptions, BucketProvider } from '@pgpmjs/types'; export { parseEnvBoolean, parseEnvList, parseEnvNumber }; @@ -10,24 +10,24 @@ export { parseEnvBoolean, parseEnvList, parseEnvNumber }; * @param env - Environment object to read from (defaults to process.env for backwards compatibility) */ export const getEnvVars = (env: NodeJS.ProcessEnv = process.env): PgpmOptions => { - const { - PGROOTDATABASE, - PGTEMPLATE, - DB_PREFIX, - DB_EXTENSIONS, - DB_CWD, - PGPM_EXTENSIONS_DIR, - PGPM_ENGINE, - DB_CONNECTION_USER, - DB_CONNECTION_PASSWORD, - DB_CONNECTION_ROLE, - // New connections.app and connections.admin env vars - DB_CONNECTIONS_APP_USER, - DB_CONNECTIONS_APP_PASSWORD, - DB_CONNECTIONS_ADMIN_USER, - DB_CONNECTIONS_ADMIN_PASSWORD, + const { + PGROOTDATABASE, + PGTEMPLATE, + DB_PREFIX, + DB_EXTENSIONS, + DB_CWD, + PGPM_EXTENSIONS_DIR, + PGPM_ENGINE, + DB_CONNECTION_USER, + DB_CONNECTION_PASSWORD, + DB_CONNECTION_ROLE, + // New connections.app and connections.admin env vars + DB_CONNECTIONS_APP_USER, + DB_CONNECTIONS_APP_PASSWORD, + DB_CONNECTIONS_ADMIN_USER, + DB_CONNECTIONS_ADMIN_PASSWORD, - PORT, + PORT, SERVER_HOST, SERVER_TRUST_PROXY, SERVER_ORIGIN, @@ -90,30 +90,30 @@ export const getEnvVars = (env: NodeJS.ProcessEnv = process.env): PgpmOptions => ...(DB_PREFIX && { prefix: DB_PREFIX }), ...(DB_EXTENSIONS && { extensions: DB_EXTENSIONS.split(',').map(ext => ext.trim()) }), ...(DB_CWD && { cwd: DB_CWD }), - ...((DB_CONNECTION_USER || DB_CONNECTION_PASSWORD || DB_CONNECTION_ROLE) && { - connection: { - ...(DB_CONNECTION_USER && { user: DB_CONNECTION_USER }), - ...(DB_CONNECTION_PASSWORD && { password: DB_CONNECTION_PASSWORD }), - ...(DB_CONNECTION_ROLE && { role: DB_CONNECTION_ROLE }), + ...((DB_CONNECTION_USER || DB_CONNECTION_PASSWORD || DB_CONNECTION_ROLE) && { + connection: { + ...(DB_CONNECTION_USER && { user: DB_CONNECTION_USER }), + ...(DB_CONNECTION_PASSWORD && { password: DB_CONNECTION_PASSWORD }), + ...(DB_CONNECTION_ROLE && { role: DB_CONNECTION_ROLE }), + } + }), + ...((DB_CONNECTIONS_APP_USER || DB_CONNECTIONS_APP_PASSWORD || DB_CONNECTIONS_ADMIN_USER || DB_CONNECTIONS_ADMIN_PASSWORD) && { + connections: { + ...((DB_CONNECTIONS_APP_USER || DB_CONNECTIONS_APP_PASSWORD) && { + app: { + ...(DB_CONNECTIONS_APP_USER && { user: DB_CONNECTIONS_APP_USER }), + ...(DB_CONNECTIONS_APP_PASSWORD && { password: DB_CONNECTIONS_APP_PASSWORD }), } }), - ...((DB_CONNECTIONS_APP_USER || DB_CONNECTIONS_APP_PASSWORD || DB_CONNECTIONS_ADMIN_USER || DB_CONNECTIONS_ADMIN_PASSWORD) && { - connections: { - ...((DB_CONNECTIONS_APP_USER || DB_CONNECTIONS_APP_PASSWORD) && { - app: { - ...(DB_CONNECTIONS_APP_USER && { user: DB_CONNECTIONS_APP_USER }), - ...(DB_CONNECTIONS_APP_PASSWORD && { password: DB_CONNECTIONS_APP_PASSWORD }), - } - }), - ...((DB_CONNECTIONS_ADMIN_USER || DB_CONNECTIONS_ADMIN_PASSWORD) && { - admin: { - ...(DB_CONNECTIONS_ADMIN_USER && { user: DB_CONNECTIONS_ADMIN_USER }), - ...(DB_CONNECTIONS_ADMIN_PASSWORD && { password: DB_CONNECTIONS_ADMIN_PASSWORD }), - } - }), + ...((DB_CONNECTIONS_ADMIN_USER || DB_CONNECTIONS_ADMIN_PASSWORD) && { + admin: { + ...(DB_CONNECTIONS_ADMIN_USER && { user: DB_CONNECTIONS_ADMIN_USER }), + ...(DB_CONNECTIONS_ADMIN_PASSWORD && { password: DB_CONNECTIONS_ADMIN_PASSWORD }), } }), - }, + } + }), + }, server: { ...(PORT && { port: parseEnvNumber(PORT) }), ...(SERVER_HOST && { host: SERVER_HOST }), diff --git a/pgpm/export/__tests__/cross-flow-parity.test.ts b/pgpm/export/__tests__/cross-flow-parity.test.ts index b7df557d10..f15757cc33 100644 --- a/pgpm/export/__tests__/cross-flow-parity.test.ts +++ b/pgpm/export/__tests__/cross-flow-parity.test.ts @@ -12,15 +12,15 @@ * - A running PostgreSQL instance accessible via standard PG* env vars */ -import { getConnections, seed } from 'pgsql-test'; -import type { PgTestClient } from 'pgsql-test'; -import type { PgConfig } from 'pg-env'; import { toCamelCase } from 'inflekt'; +import type { PgConfig } from 'pg-env'; +import type { PgTestClient } from 'pgsql-test'; +import { getConnections, seed } from 'pgsql-test'; -import { exportMeta } from '../src/export-meta'; import { exportGraphQLMeta } from '../src/export-graphql-meta'; -import { GraphQLClient } from '../src/graphql-client'; +import { exportMeta } from '../src/export-meta'; import { META_TABLE_CONFIG } from '../src/export-utils'; +import { GraphQLClient } from '../src/graphql-client'; import { getGraphQLQueryName, getGraphQLTypeName, GraphQLTypeInfo } from '../src/graphql-naming'; import { lookupByPgUdt } from '../src/type-map'; diff --git a/pgpm/export/__tests__/dynamic-fields.test.ts b/pgpm/export/__tests__/dynamic-fields.test.ts index 37e1bf951c..d6426d09d4 100644 --- a/pgpm/export/__tests__/dynamic-fields.test.ts +++ b/pgpm/export/__tests__/dynamic-fields.test.ts @@ -13,16 +13,14 @@ import { toCamelCase, toSnakeCase } from 'inflekt'; import { - META_TABLE_CONFIG, + FieldType, mapPgTypeToFieldType, - FieldType -} from '../src/export-utils'; + META_TABLE_CONFIG} from '../src/export-utils'; import { - mapGraphQLTypeToFieldType, - unwrapGraphQLType, + getGraphQLQueryName, getGraphQLTypeName, - getGraphQLQueryName -} from '../src/graphql-naming'; + mapGraphQLTypeToFieldType, + unwrapGraphQLType} from '../src/graphql-naming'; import { PG_TYPE_MAP } from '../src/type-map'; // ============================================================================= diff --git a/pgpm/export/src/export-graphql-meta.ts b/pgpm/export/src/export-graphql-meta.ts index 083c539ff6..9423569d9e 100644 --- a/pgpm/export/src/export-graphql-meta.ts +++ b/pgpm/export/src/export-graphql-meta.ts @@ -8,6 +8,7 @@ */ import { Parser } from 'csv-to-pg'; import { toSnakeCase } from 'inflekt'; + import { FieldType, getTimestampDefaultColumnsForTable, META_TABLE_CONFIG, META_TABLE_ORDER, TableConfig } from './export-utils'; import { GraphQLClient } from './graphql-client'; import { diff --git a/pgpm/export/src/export-graphql.ts b/pgpm/export/src/export-graphql.ts index ebff118329..0963d3ddb0 100644 --- a/pgpm/export/src/export-graphql.ts +++ b/pgpm/export/src/export-graphql.ts @@ -7,28 +7,27 @@ * Per Dan's guidance: "I would NOT do branching in those existing files. * I would make the GraphQL flow its entire own flow at first." */ -import { Inquirerer } from 'inquirerer'; - import { PgpmPackage, PgpmRow, SqlWriteOptions, writePgpmFiles, writePgpmPlan } from '@pgpmjs/core'; import { createClient } from '@pgpmjs/migrate-client'; -import { GraphQLClient } from './graphql-client'; +import { Inquirerer } from 'inquirerer'; + import { exportGraphQLMeta } from './export-graphql-meta'; -import { graphqlRowToPostgresRow } from './graphql-naming'; -import { PartitionConfig, partitionExportRows } from './partition'; -import { ExportGranularity, restructureExportRows } from './restructure'; import { DB_REQUIRED_EXTENSIONS, - SERVICE_REQUIRED_EXTENSIONS, - META_COMMON_HEADER, - META_COMMON_FOOTER, - META_TABLE_ORDER, - Schema, detectMissingModules, installMissingModules, makeReplacer, + META_COMMON_FOOTER, + META_COMMON_HEADER, + META_TABLE_ORDER, + normalizeOutdir, preparePackage, - normalizeOutdir -} from './export-utils'; + Schema, + SERVICE_REQUIRED_EXTENSIONS} from './export-utils'; +import { GraphQLClient } from './graphql-client'; +import { graphqlRowToPostgresRow } from './graphql-naming'; +import { PartitionConfig, partitionExportRows } from './partition'; +import { ExportGranularity, restructureExportRows } from './restructure'; // ============================================================================= // Public API diff --git a/pgpm/export/src/export-migrations.ts b/pgpm/export/src/export-migrations.ts index 98306eb128..07ce473bc5 100644 --- a/pgpm/export/src/export-migrations.ts +++ b/pgpm/export/src/export-migrations.ts @@ -1,23 +1,22 @@ +import { PgpmPackage, PgpmRow, SqlWriteOptions, writePgpmFiles, writePgpmPlan } from '@pgpmjs/core'; import { PgpmOptions } from '@pgpmjs/types'; import { Inquirerer } from 'inquirerer'; import { getPgPool } from 'pg-cache'; -import { PgpmPackage, PgpmRow, SqlWriteOptions, writePgpmFiles, writePgpmPlan } from '@pgpmjs/core'; import { exportMeta } from './export-meta'; -import { PartitionConfig, partitionExportRows } from './partition'; -import { ExportGranularity, restructureExportRows } from './restructure'; import { DB_REQUIRED_EXTENSIONS, - SERVICE_REQUIRED_EXTENSIONS, - META_COMMON_HEADER, - META_COMMON_FOOTER, - META_TABLE_ORDER, detectMissingModules, installMissingModules, makeReplacer, + META_COMMON_FOOTER, + META_COMMON_HEADER, + META_TABLE_ORDER, + normalizeOutdir, preparePackage, - normalizeOutdir -} from './export-utils'; + SERVICE_REQUIRED_EXTENSIONS} from './export-utils'; +import { PartitionConfig, partitionExportRows } from './partition'; +import { ExportGranularity, restructureExportRows } from './restructure'; interface ExportMigrationsToDiskOptions { project: PgpmPackage; @@ -191,16 +190,16 @@ const exportMigrationsToDisk = async ({ // it was set on and therefore cannot be relied upon across connections. const results = excludeCategories && excludeCategories.length > 0 ? await pgPool.query( - `select * from db_migrate.sql_actions + `select * from db_migrate.sql_actions where database_id = $1 and (category is null or category != ALL($2::text[])) order by id`, - [databaseId, excludeCategories] - ) + [databaseId, excludeCategories] + ) : await pgPool.query( - `select * from db_migrate.sql_actions where database_id = $1 order by id`, - [databaseId] - ); + `select * from db_migrate.sql_actions where database_id = $1 order by id`, + [databaseId] + ); // Registry fixtures — meta_registration actions that insert into // metaschema_public.* (e.g. pg_partman partition registration) — FK-reference @@ -333,10 +332,10 @@ const exportMigrationsToDisk = async ({ const metaReplacer = makeReplacer({ schemas: metaSchemasForReplacement, name: metaExtensionName, - // Use extensionName for schema prefix — the services metadata references - // schemas owned by the application package (e.g. agent_db_auth_public), - // not the services package (agent_db_services_auth_public) - schemaPrefix: name + // Use extensionName for schema prefix — the services metadata references + // schemas owned by the application package (e.g. agent_db_auth_public), + // not the services package (agent_db_services_auth_public) + schemaPrefix: name }); // Create separate files for each table type diff --git a/pgpm/export/src/graphql-naming.ts b/pgpm/export/src/graphql-naming.ts index 29e76b7042..809e94047b 100644 --- a/pgpm/export/src/graphql-naming.ts +++ b/pgpm/export/src/graphql-naming.ts @@ -15,7 +15,7 @@ * db_migrate.sql_actions -> sqlActions * column database_id -> databaseId */ -import { toCamelCase, toPascalCase, toSnakeCase, distinctPluralize, singularizeLast } from 'inflekt'; +import { distinctPluralize, singularizeLast,toCamelCase, toPascalCase, toSnakeCase } from 'inflekt'; import { FieldType } from './export-utils'; import { lookupByGqlType } from './type-map'; @@ -122,10 +122,10 @@ export const mapGraphQLTypeToFieldType = (gqlTypeName: string, isList = false): const inner = mapGraphQLTypeToFieldType(gqlTypeName, false); // Only these array types exist in FieldType: uuid[], text[], jsonb[] switch (inner) { - case 'uuid': return 'uuid[]'; - case 'text': return 'text[]'; - case 'jsonb': return 'jsonb[]'; - default: return 'text'; // safe fallback for unsupported array types + case 'uuid': return 'uuid[]'; + case 'text': return 'text[]'; + case 'jsonb': return 'jsonb[]'; + default: return 'text'; // safe fallback for unsupported array types } } diff --git a/pgpm/export/src/index.ts b/pgpm/export/src/index.ts index 45775ca031..3c12a1a428 100644 --- a/pgpm/export/src/index.ts +++ b/pgpm/export/src/index.ts @@ -1,42 +1,40 @@ +export type { CatalogQueryable, CatalogSnapshot } from './catalog-check'; +export { diffCatalogSnapshots, snapshotCatalog } from './catalog-check'; export * from './export-data'; -export * from './export-meta'; -export * from './export-migrations'; export * from './export-graphql'; export * from './export-graphql-meta'; -export { EXPORT_GRANULARITIES, isExportGranularity, restructureExportRows } from './restructure'; -export type { ExportGranularity, RestructureExportRowsOptions, RestructureExportRowsResult } from './restructure'; -export { loadModuleSource, stripTransactionWrapper } from './module-source'; -export type { ModuleSource, ModuleSourceChange } from './module-source'; -export { parsePartitionConfig, partitionExportRows } from './partition'; -export type { PartitionConfig, PartitionedPackageRows, PartitionExportRowsResult } from './partition'; -export { diffCatalogSnapshots, snapshotCatalog } from './catalog-check'; -export type { CatalogQueryable, CatalogSnapshot } from './catalog-check'; -export { GraphQLClient } from './graphql-client'; -export { getGraphQLQueryName, getGraphQLTypeName, graphqlRowToPostgresRow, buildFieldsFragment, mapGraphQLTypeToFieldType, unwrapGraphQLType, GraphQLTypeInfo } from './graphql-naming'; +export * from './export-meta'; +export * from './export-migrations'; +export type { + FieldType, + MakeReplacerOptions, + MetaExportTableEntry, + MissingModulesResult, + PreparePackageOptions, + ReplacerResult, + Schema, + TableConfig} from './export-utils'; export { DB_REQUIRED_EXTENSIONS, - SERVICE_REQUIRED_EXTENSIONS, - META_COMMON_HEADER, + detectMissingModules, + installMissingModules, + makeReplacer, + mapPgTypeToFieldType, META_COMMON_FOOTER, - META_TABLE_ORDER, + META_COMMON_HEADER, META_TABLE_CONFIG, + META_TABLE_ORDER, META_TABLE_OVERRIDES, - mapPgTypeToFieldType, - makeReplacer, - preparePackage, normalizeOutdir, - detectMissingModules, - installMissingModules -} from './export-utils'; -export type { - FieldType, - TableConfig, - MetaExportTableEntry, - Schema, - MakeReplacerOptions, - ReplacerResult, - PreparePackageOptions, - MissingModulesResult -} from './export-utils'; -export { PG_TYPE_MAP, TypeMapEntry, lookupByPgUdt, lookupByGqlType } from './type-map'; + preparePackage, + SERVICE_REQUIRED_EXTENSIONS} from './export-utils'; +export { GraphQLClient } from './graphql-client'; +export { buildFieldsFragment, getGraphQLQueryName, getGraphQLTypeName, graphqlRowToPostgresRow, GraphQLTypeInfo,mapGraphQLTypeToFieldType, unwrapGraphQLType } from './graphql-naming'; export { intervalToPostgres, parsePgInterval, PgInterval } from './interval-utils'; +export type { ModuleSource, ModuleSourceChange } from './module-source'; +export { loadModuleSource, stripTransactionWrapper } from './module-source'; +export type { PartitionConfig, PartitionedPackageRows, PartitionExportRowsResult } from './partition'; +export { parsePartitionConfig, partitionExportRows } from './partition'; +export type { ExportGranularity, RestructureExportRowsOptions, RestructureExportRowsResult } from './restructure'; +export { EXPORT_GRANULARITIES, isExportGranularity, restructureExportRows } from './restructure'; +export { lookupByGqlType,lookupByPgUdt, PG_TYPE_MAP, TypeMapEntry } from './type-map'; diff --git a/pgpm/logger/src/index.ts b/pgpm/logger/src/index.ts index 7819f85040..50444a3aef 100644 --- a/pgpm/logger/src/index.ts +++ b/pgpm/logger/src/index.ts @@ -1,2 +1,2 @@ -export { Logger, createLogger, setLogLevel, setShowTimestamp, setLogFormat, setLogScopes } from './logger'; -export type { LogLevel, LogFormat } from './logger'; \ No newline at end of file +export type { LogFormat,LogLevel } from './logger'; +export { createLogger, Logger, setLogFormat, setLogLevel, setLogScopes,setShowTimestamp } from './logger'; \ No newline at end of file diff --git a/pgpm/portability/__tests__/seed-apply.test.ts b/pgpm/portability/__tests__/seed-apply.test.ts index aa03637464..af3b334277 100644 --- a/pgpm/portability/__tests__/seed-apply.test.ts +++ b/pgpm/portability/__tests__/seed-apply.test.ts @@ -1,7 +1,6 @@ import { cpSync, mkdtempSync, rmSync } from 'fs'; import { tmpdir } from 'os'; import { join, resolve } from 'path'; - import { getConnections, PgTestClient, SeedAdapter } from 'pgsql-test'; import { seed } from '../src'; diff --git a/pgpm/portability/src/shapes.ts b/pgpm/portability/src/shapes.ts index ed26fec6aa..893fb83016 100644 --- a/pgpm/portability/src/shapes.ts +++ b/pgpm/portability/src/shapes.ts @@ -93,19 +93,19 @@ function routesFor(shape: VendorShape, provider: ProviderBinding, invert: boolea routes.push( invert ? { - fromSchema: provider.schema!, - kind: shape.users.kind, - name: provider.users, - toSchema: shape.users.schema, - ...(provider.users !== shape.users.name ? { toName: shape.users.name } : {}) - } + fromSchema: provider.schema!, + kind: shape.users.kind, + name: provider.users, + toSchema: shape.users.schema, + ...(provider.users !== shape.users.name ? { toName: shape.users.name } : {}) + } : { - fromSchema: shape.users.schema, - kind: shape.users.kind, - name: shape.users.name, - toSchema: provider.schema, - ...(provider.users !== shape.users.name ? { toName: provider.users } : {}) - } + fromSchema: shape.users.schema, + kind: shape.users.kind, + name: shape.users.name, + toSchema: provider.schema, + ...(provider.users !== shape.users.name ? { toName: provider.users } : {}) + } ); } @@ -115,19 +115,19 @@ function routesFor(shape: VendorShape, provider: ProviderBinding, invert: boolea routes.push( invert ? { - fromSchema: provider.schema!, - kind: accessor.kind, - name: target, - toSchema: accessor.schema, - ...(target !== accessor.name ? { toName: accessor.name } : {}) - } + fromSchema: provider.schema!, + kind: accessor.kind, + name: target, + toSchema: accessor.schema, + ...(target !== accessor.name ? { toName: accessor.name } : {}) + } : { - fromSchema: accessor.schema, - kind: accessor.kind, - name: accessor.name, - toSchema: provider.schema, - ...(target !== accessor.name ? { toName: target } : {}) - } + fromSchema: accessor.schema, + kind: accessor.kind, + name: accessor.name, + toSchema: provider.schema, + ...(target !== accessor.name ? { toName: target } : {}) + } ); } diff --git a/pgpm/slice/__tests__/partition.test.ts b/pgpm/slice/__tests__/partition.test.ts index 8bcfa95072..f847962519 100644 --- a/pgpm/slice/__tests__/partition.test.ts +++ b/pgpm/slice/__tests__/partition.test.ts @@ -1,3 +1,4 @@ +import { parsePlanFile } from '@pgpmjs/ast/files/plan/parser'; import { mkdirSync, rmSync, writeFileSync } from 'fs'; import { tmpdir } from 'os'; import { dirname, join } from 'path'; @@ -10,7 +11,6 @@ import { partitionChanges, partitionModule } from '../src'; -import { parsePlanFile } from '@pgpmjs/ast/files/plan/parser'; beforeAll(async () => { await loadModule(); diff --git a/pgpm/slice/__tests__/slice.test.ts b/pgpm/slice/__tests__/slice.test.ts index bc7bdab8cb..ad186921ef 100644 --- a/pgpm/slice/__tests__/slice.test.ts +++ b/pgpm/slice/__tests__/slice.test.ts @@ -1,20 +1,19 @@ +import { ExtendedPlanFile } from '@pgpmjs/ast/files/types'; import { mkdirSync, rmSync, writeFileSync } from 'fs'; import { join } from 'path'; import { - buildDependencyGraph, - validateDAG, - extractPackageFromPath, - findMatchingPattern, assignChangesToPackages, + buildDependencyGraph, buildPackageDependencies, - detectPackageCycle, computeDeployOrder, - topologicalSortWithinPackage, + detectPackageCycle, + extractPackageFromPath, + findMatchingPattern, + PatternStrategy, slicePlan, - PatternStrategy -} from '../src'; -import { ExtendedPlanFile } from '@pgpmjs/ast/files/types'; + topologicalSortWithinPackage, + validateDAG} from '../src'; describe('Slice Module', () => { const testDir = join(__dirname, 'test-slice'); @@ -190,9 +189,9 @@ describe('Slice Module', () => { const assignments = assignChangesToPackages(graph, { type: 'explicit', mapping: { - 'change_a': 'pkg1', - 'change_b': 'pkg1', - 'change_c': 'pkg2' + change_a: 'pkg1', + change_b: 'pkg1', + change_c: 'pkg2' } }); diff --git a/pgpm/slice/src/index.ts b/pgpm/slice/src/index.ts index 9a84da45f7..31ed3b3d28 100644 --- a/pgpm/slice/src/index.ts +++ b/pgpm/slice/src/index.ts @@ -1,8 +1,8 @@ -export * from './types'; -export * from './slice'; -export * from './output'; -export * from './refs'; export * from './closure'; -export * from './partition'; export * from './exclude'; export * from './object-graph'; +export * from './output'; +export * from './partition'; +export * from './refs'; +export * from './slice'; +export * from './types'; diff --git a/pgpm/slice/src/output.ts b/pgpm/slice/src/output.ts index 008b1004de..cd298ee7b2 100644 --- a/pgpm/slice/src/output.ts +++ b/pgpm/slice/src/output.ts @@ -1,7 +1,7 @@ import fs from 'fs'; import path from 'path'; -import { SliceResult, PackageOutput } from './types'; +import { PackageOutput,SliceResult } from './types'; /** * Options for writing sliced packages to disk diff --git a/pgpm/slice/src/partition.ts b/pgpm/slice/src/partition.ts index 40f9f75241..add2312646 100644 --- a/pgpm/slice/src/partition.ts +++ b/pgpm/slice/src/partition.ts @@ -1,8 +1,7 @@ +import { parsePlanFile } from '@pgpmjs/ast/files/plan/parser'; import { existsSync, readFileSync } from 'fs'; import { join } from 'path'; -import { parsePlanFile } from '@pgpmjs/ast/files/plan/parser'; - import { AstEdges, buildAstEdges } from './closure'; import { objectKey } from './object-graph'; import { extractSqlFacts, SqlObjectRef } from './refs'; diff --git a/pgpm/slice/src/slice.ts b/pgpm/slice/src/slice.ts index 26925b8a4c..baea10748f 100644 --- a/pgpm/slice/src/slice.ts +++ b/pgpm/slice/src/slice.ts @@ -1,21 +1,19 @@ -import { Change, Tag, ExtendedPlanFile } from '@pgpmjs/ast/files/types'; import { parsePlanFile } from '@pgpmjs/ast/files/plan/parser'; import { generateChangeLineContent, generateTagLineContent } from '@pgpmjs/ast/files/plan/writer'; +import { Change, ExtendedPlanFile,Tag } from '@pgpmjs/ast/files/types'; +import { minimatch } from 'minimatch'; + import { buildAstEdges, expandClosures } from './closure'; import { ClosureReport, - SliceConfig, - SliceResult, + CrossPackageDepMode, DependencyGraph, - PackageOutput, - WorkspaceManifest, - SliceWarning, - SliceStats, GroupingStrategy, + PackageOutput, PatternStrategy, - CrossPackageDepMode -} from './types'; -import { minimatch } from 'minimatch'; + SliceConfig, + SliceResult, + SliceWarning} from './types'; /** * Build a dependency graph from a parsed plan file @@ -150,23 +148,23 @@ export function assignChangesToPackages( let packageName: string; switch (strategy.type) { - case 'folder': { - const depth = strategy.depth ?? 1; - const prefix = strategy.prefixToStrip ?? 'schemas'; - packageName = extractPackageFromPath(changeName, depth, prefix); - break; - } - case 'pattern': { - const matched = findMatchingPattern(changeName, strategy); - packageName = matched || defaultPackage; - break; - } - case 'explicit': { - packageName = strategy.mapping[changeName] || defaultPackage; - break; - } - default: - packageName = defaultPackage; + case 'folder': { + const depth = strategy.depth ?? 1; + const prefix = strategy.prefixToStrip ?? 'schemas'; + packageName = extractPackageFromPath(changeName, depth, prefix); + break; + } + case 'pattern': { + const matched = findMatchingPattern(changeName, strategy); + packageName = matched || defaultPackage; + break; + } + case 'explicit': { + packageName = strategy.mapping[changeName] || defaultPackage; + break; + } + default: + packageName = defaultPackage; } // Fallback to default package diff --git a/pgpm/slice/src/types.ts b/pgpm/slice/src/types.ts index 300d90da81..c45903f23a 100644 --- a/pgpm/slice/src/types.ts +++ b/pgpm/slice/src/types.ts @@ -1,4 +1,4 @@ -import { Change, Tag, ExtendedPlanFile } from '@pgpmjs/ast/files/types'; +import { Change, ExtendedPlanFile,Tag } from '@pgpmjs/ast/files/types'; /** * Configuration for slicing a plan into multiple packages diff --git a/pgpm/transform/__tests__/bundle-driver.test.ts b/pgpm/transform/__tests__/bundle-driver.test.ts index 4d9a3f01b6..c713413599 100644 --- a/pgpm/transform/__tests__/bundle-driver.test.ts +++ b/pgpm/transform/__tests__/bundle-driver.test.ts @@ -116,7 +116,7 @@ describe('makeSchemaTranspiler', () => { extensions: { toSchema: 'extensions' } }); const out = t.transformScript( - "CREATE TABLE auth.t (id uuid DEFAULT gen_random_bytes(16));", + 'CREATE TABLE auth.t (id uuid DEFAULT gen_random_bytes(16));', CTX ); expect(out).toContain('tenant_auth.t'); diff --git a/pgpm/transform/__tests__/semantic-diff-driver.test.ts b/pgpm/transform/__tests__/semantic-diff-driver.test.ts index 5d538c3fba..57fd7bdbc6 100644 --- a/pgpm/transform/__tests__/semantic-diff-driver.test.ts +++ b/pgpm/transform/__tests__/semantic-diff-driver.test.ts @@ -1,6 +1,6 @@ import { loadModule } from 'plpgsql-parser'; -import { DiffInputChange, diffChangeSets, diffSchemas } from '../src/semantic-diff-driver'; +import { diffChangeSets, DiffInputChange, diffSchemas } from '../src/semantic-diff-driver'; beforeAll(async () => { await loadModule(); diff --git a/pgpm/transform/src/bundle-driver.ts b/pgpm/transform/src/bundle-driver.ts index 8b10e95749..5c25b43fbd 100644 --- a/pgpm/transform/src/bundle-driver.ts +++ b/pgpm/transform/src/bundle-driver.ts @@ -13,11 +13,11 @@ import { createExtensionResult, createRoleResult, ExtensionDefinition, - ExtensionRouteSpec, ExtensionRouter, + ExtensionRouteSpec, ExtensionTransformResult, - RoleRouteSpec, RoleRouter, + RoleRouteSpec, RoleTransformResult, RouteSpec, SchemaRouter, @@ -180,9 +180,9 @@ export function buildSchemaRouter(options: SchemaTranspilerOptions): SchemaRoute route.toName === undefined && typeof route.toSchema === 'string' ? route.toSchema : { - ...(route.toSchema !== undefined ? { schema: route.toSchema } : {}), - ...(route.toName !== undefined ? { name: route.toName } : {}) - }; + ...(route.toSchema !== undefined ? { schema: route.toSchema } : {}), + ...(route.toName !== undefined ? { name: route.toName } : {}) + }; } return new SchemaRouter(spec); } diff --git a/pgpm/transform/src/fixture-closure.ts b/pgpm/transform/src/fixture-closure.ts index 542c4136ba..0ededc7ad7 100644 --- a/pgpm/transform/src/fixture-closure.ts +++ b/pgpm/transform/src/fixture-closure.ts @@ -1,9 +1,10 @@ +import { classifyStatements, QualifiedName, StatementFacts } from '@pgsql/transform'; + import { CategoryProfile, ChangeCategory, TIER_PROFILE } from './categorize'; -import { classifyStatements, QualifiedName, StatementFacts } from '@pgsql/transform'; /** * A change plus its deploy SQL. Optional plan `dependencies` (from `pgpm.plan`) diff --git a/pgpm/transform/src/index.ts b/pgpm/transform/src/index.ts index 4284221c77..7e58ee6f79 100644 --- a/pgpm/transform/src/index.ts +++ b/pgpm/transform/src/index.ts @@ -1,5 +1,3 @@ -export * from '@pgsql/transform'; -export { loadModule } from 'plpgsql-parser'; export type { BundleScriptContext, ExtensionRoutingInput, @@ -14,6 +12,23 @@ export { makeNamespaceValidator, makeSchemaTranspiler, } from './bundle-driver'; +export type { + CategoryProfile, + ChangeCategory, +} from './categorize'; +export { + buildCategoryOf, + categorizeChange, + TIER_PROFILE, +} from './categorize'; +export type { + ClosureChange, + ClosureInputChange, + ClosureReason, + FixtureClosure, + ResolveFixtureClosureOptions, +} from './fixture-closure'; +export { resolveFixtureClosure } from './fixture-closure'; export type { GranularityChange, RestructuredChange, @@ -24,18 +39,6 @@ export { defaultChangeName, restructureChanges, } from './granularity-driver'; -export type { - DiffInputChange, - ObjectDelta, - SemanticDeltaChange, - SemanticDiffOptions, - SemanticDiffResult, - SemanticObjectDiff, -} from './semantic-diff-driver'; -export { - diffChangeSets, - diffSchemas, -} from './semantic-diff-driver'; export type { PartitionConfig, PartitionedChange, @@ -52,22 +55,11 @@ export { RESIDUAL_UNIT_PATH, } from './partition-driver'; export type { - CategoryProfile, - ChangeCategory, -} from './categorize'; -export { - buildCategoryOf, - categorizeChange, - TIER_PROFILE, -} from './categorize'; -export type { - ClosureChange, - ClosureInputChange, - ClosureReason, - FixtureClosure, - ResolveFixtureClosureOptions, -} from './fixture-closure'; -export { resolveFixtureClosure } from './fixture-closure'; + SqlProgram, + SqlStatementAst, + SqlStatementSpan, +} from './program'; +export { emitSqlProgram, parseSqlProgram } from './program'; export type { GeneratedScript, RegeneratedScripts, @@ -78,8 +70,16 @@ export { regenerateScripts, } from './regen'; export type { - SqlProgram, - SqlStatementAst, - SqlStatementSpan, -} from './program'; -export { emitSqlProgram, parseSqlProgram } from './program'; + DiffInputChange, + ObjectDelta, + SemanticDeltaChange, + SemanticDiffOptions, + SemanticDiffResult, + SemanticObjectDiff, +} from './semantic-diff-driver'; +export { + diffChangeSets, + diffSchemas, +} from './semantic-diff-driver'; +export * from '@pgsql/transform'; +export { loadModule } from 'plpgsql-parser'; diff --git a/pgpm/types/src/driver.ts b/pgpm/types/src/driver.ts index 1e659681cb..cc3a1f73fc 100644 --- a/pgpm/types/src/driver.ts +++ b/pgpm/types/src/driver.ts @@ -87,6 +87,6 @@ export const DEFAULT_ENGINE = 'pg'; * named directly with `--driver `. */ export const BUILTIN_ENGINES: Record = { - [DEFAULT_ENGINE]: {}, - pglite: { plugin: '@pgpmjs/pglite-adapter' } + [DEFAULT_ENGINE]: {}, + pglite: { plugin: '@pgpmjs/pglite-adapter' } }; diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 9dbe931f08..0df9faf1e0 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -14,6 +14,9 @@ packageExtensionsChecksum: sha256-x8B4zkJ4KLRX+yspUWxuggXWlz6zrBLSIh72pNhpPiE= importers: .: devDependencies: + '@constructive-io/eslint-config': + specifier: ^0.2.0 + version: 0.2.0(eslint@9.39.2(jiti@2.7.0))(typescript@5.9.3) '@jest/test-sequencer': specifier: ^30.4.1 version: 30.4.1 @@ -4517,6 +4520,14 @@ packages: integrity: sha512-0hYQ8SB4Db5zvZB4axdMHGwEaQjkZzFjQiN9LVYvIFB2nSUHW9tYpxWriPrWDASIxiaXax83REcLxuSdnGPZtw==, } + '@constructive-io/eslint-config@0.2.0': + resolution: + { + integrity: sha512-BaIBn/3Oi+DcyzNqMyUQmelSD7z7MMnFQtlKr4vVrgAv8PXVkYXaY2IlfZH4MeqYactf3mDunS11+7ndOf9oVw==, + } + peerDependencies: + eslint: ^9 + '@constructive-io/fetch@1.1.1': resolution: { @@ -10588,6 +10599,13 @@ packages: } engines: { node: '>=18' } + globals@17.8.0: + resolution: + { + integrity: sha512-Zz/LMDZScFmkakeL2cTHzf+PbWKdpU3uclqkZT7TjDG58j5WPt0PpA+n9uPI24fZtlw07q0OtEi84K+umsRzqQ==, + } + engines: { node: '>=18' } + google-auth-library@10.9.1: resolution: { @@ -16206,6 +16224,20 @@ snapshots: '@bcoe/v8-coverage@0.2.3': {} + '@constructive-io/eslint-config@0.2.0(eslint@9.39.2(jiti@2.7.0))(typescript@5.9.3)': + dependencies: + '@eslint/js': 9.39.2 + '@typescript-eslint/eslint-plugin': 8.59.4(@typescript-eslint/parser@8.59.4(eslint@9.39.2(jiti@2.7.0))(typescript@5.9.3))(eslint@9.39.2(jiti@2.7.0))(typescript@5.9.3) + '@typescript-eslint/parser': 8.59.4(eslint@9.39.2(jiti@2.7.0))(typescript@5.9.3) + eslint: 9.39.2(jiti@2.7.0) + eslint-config-prettier: 10.1.8(eslint@9.39.2(jiti@2.7.0)) + eslint-plugin-simple-import-sort: 12.1.1(eslint@9.39.2(jiti@2.7.0)) + eslint-plugin-unused-imports: 4.4.1(@typescript-eslint/eslint-plugin@8.59.4(@typescript-eslint/parser@8.59.4(eslint@9.39.2(jiti@2.7.0))(typescript@5.9.3))(eslint@9.39.2(jiti@2.7.0))(typescript@5.9.3))(eslint@9.39.2(jiti@2.7.0)) + globals: 17.8.0 + transitivePeerDependencies: + - supports-color + - typescript + '@constructive-io/fetch@1.1.1': {} '@constructive-io/noble-hashes@0.2.1': {} @@ -20277,6 +20309,8 @@ snapshots: globals@14.0.0: {} + globals@17.8.0: {} + google-auth-library@10.9.1: dependencies: base64-js: 1.5.1 diff --git a/postgres/constructive-test/src/connect.ts b/postgres/constructive-test/src/connect.ts index 12dd5f67ce..5123b2d166 100644 --- a/postgres/constructive-test/src/connect.ts +++ b/postgres/constructive-test/src/connect.ts @@ -1,8 +1,7 @@ import { - getConnections as getPgConnections, type GetConnectionOpts, - type GetConnectionResult -} from 'pgsql-test'; + type GetConnectionResult, + getConnections as getPgConnections} from 'pgsql-test'; /** * Get connections with Constructive platform behavior. diff --git a/postgres/constructive-test/src/index.ts b/postgres/constructive-test/src/index.ts index ca08b4d5bb..6132a78095 100644 --- a/postgres/constructive-test/src/index.ts +++ b/postgres/constructive-test/src/index.ts @@ -2,8 +2,8 @@ export * from 'pgsql-test'; // Export Constructive-specific getConnections with defaults baked in -export { getConnections } from './connect'; export type { GetConnectionOpts, GetConnectionResult } from './connect'; +export { getConnections } from './connect'; // Re-export snapshot utility export { snapshot } from 'pgsql-test'; diff --git a/postgres/drizzle-orm-test/__tests__/drizzle-seed.test.ts b/postgres/drizzle-orm-test/__tests__/drizzle-seed.test.ts index 2c448e66ed..5427b5e296 100644 --- a/postgres/drizzle-orm-test/__tests__/drizzle-seed.test.ts +++ b/postgres/drizzle-orm-test/__tests__/drizzle-seed.test.ts @@ -1,11 +1,12 @@ process.env.LOG_SCOPE = 'drizzle-orm-test'; -import { writeFileSync, mkdirSync } from 'fs'; -import { join } from 'path'; -import { tmpdir } from 'os'; -import { drizzle } from 'drizzle-orm/node-postgres'; -import { pgTable, pgSchema, uuid, text, serial, integer } from 'drizzle-orm/pg-core'; import { eq } from 'drizzle-orm'; +import { drizzle } from 'drizzle-orm/node-postgres'; +import {pgSchema, serial, text, uuid } from 'drizzle-orm/pg-core'; +import { mkdirSync,writeFileSync } from 'fs'; +import { tmpdir } from 'os'; +import { join } from 'path'; import { seed } from 'pgsql-test'; + import { getConnections, PgTestClient } from '../src'; let pg: PgTestClient; diff --git a/postgres/insforge-test/src/connect.ts b/postgres/insforge-test/src/connect.ts index 7ac51d870a..5cf5e3eea2 100644 --- a/postgres/insforge-test/src/connect.ts +++ b/postgres/insforge-test/src/connect.ts @@ -1,11 +1,10 @@ +import type { PgTestConnectionOptions } from '@pgpmjs/types'; import deepmerge from 'deepmerge'; import { getPgEnvVars, PgConfig } from 'pg-env'; import { - getConnections as getPgConnections, type GetConnectionOpts, - type GetConnectionResult -} from 'pgsql-test'; -import type { PgTestConnectionOptions } from '@pgpmjs/types'; + type GetConnectionResult, + getConnections as getPgConnections} from 'pgsql-test'; /** * InsForge default connection options diff --git a/postgres/insforge-test/src/helpers.ts b/postgres/insforge-test/src/helpers.ts index 35461987aa..82c1b0c8fb 100644 --- a/postgres/insforge-test/src/helpers.ts +++ b/postgres/insforge-test/src/helpers.ts @@ -8,23 +8,23 @@ import { PgTestClient } from 'pgsql-test'; * @returns The inserted user object with id and email */ export async function insertUser( - client: PgTestClient, - email: string, - id?: string - ): Promise<{ id: string; email: string }> { - if (id) { - return await client.one( - `INSERT INTO auth.users (id, email) + client: PgTestClient, + email: string, + id?: string +): Promise<{ id: string; email: string }> { + if (id) { + return await client.one( + `INSERT INTO auth.users (id, email) VALUES ($1, $2) RETURNING id, email`, - [id, email] - ); - } else { - return await client.one( - `INSERT INTO auth.users (id, email) + [id, email] + ); + } else { + return await client.one( + `INSERT INTO auth.users (id, email) VALUES (gen_random_uuid(), $1) RETURNING id, email`, - [email] - ); - } + [email] + ); } +} diff --git a/postgres/insforge-test/src/index.ts b/postgres/insforge-test/src/index.ts index b7a2cee112..618606fec4 100644 --- a/postgres/insforge-test/src/index.ts +++ b/postgres/insforge-test/src/index.ts @@ -5,8 +5,8 @@ export * from 'pgsql-test'; export * from './helpers'; // Export InsForge-specific getConnections with defaults baked in -export { getConnections } from './connect'; export type { GetConnectionOpts, GetConnectionResult } from './connect'; +export { getConnections } from './connect'; // Re-export snapshot utility export { snapshot } from 'pgsql-test'; diff --git a/postgres/introspectron/src/gql.ts b/postgres/introspectron/src/gql.ts index d5e571cda0..a653641387 100644 --- a/postgres/introspectron/src/gql.ts +++ b/postgres/introspectron/src/gql.ts @@ -102,13 +102,13 @@ export const parseGraphQuery = (introQuery: IntrospectionQueryResult) => { return getInputForQueries(input.ofType!, context); } - if (input.kind === 'INPUT_OBJECT' && input.name && HASH.hasOwnProperty(input.name)) { + if (input.kind === 'INPUT_OBJECT' && input.name && Object.prototype.hasOwnProperty.call(HASH, input.name)) { const schema = HASH[input.name]; context.properties = schema.inputFields!.map((field) => ({ name: field.name, type: field.type })).reduce((m3, v) => { m3[v.name] = v; return m3; }, {} as Record); - } else if (input.kind === 'OBJECT' && input.name && HASH.hasOwnProperty(input.name)) { + } else if (input.kind === 'OBJECT' && input.name && Object.prototype.hasOwnProperty.call(HASH, input.name)) { const schema = HASH[input.name]; context.properties = schema.fields!.map((field) => ({ name: field.name, type: field.type })).reduce((m3, v) => { m3[v.name] = v; @@ -141,13 +141,13 @@ export const parseGraphQuery = (introQuery: IntrospectionQueryResult) => { return getInputForMutations(input.ofType!, context); } - if (input.kind === 'INPUT_OBJECT' && input.name && HASH.hasOwnProperty(input.name)) { + if (input.kind === 'INPUT_OBJECT' && input.name && Object.prototype.hasOwnProperty.call(HASH, input.name)) { const schema = HASH[input.name]; context.properties = schema.inputFields!.map((field) => getInputForMutations(field.type, { name: field.name })).reduce((m3, v) => { m3[v.name!] = v; return m3; }, {} as Record); - } else if (input.kind === 'OBJECT' && input.name && HASH.hasOwnProperty(input.name)) { + } else if (input.kind === 'OBJECT' && input.name && Object.prototype.hasOwnProperty.call(HASH, input.name)) { const schema = HASH[input.name]; context.properties = schema.fields!.map((field) => ({ name: field.name, type: field.type })).reduce((m3, v) => { m3[v.name] = v; @@ -169,7 +169,7 @@ export const parseGraphQuery = (introQuery: IntrospectionQueryResult) => { const props = mutation.args.reduce((m2, arg) => { const type = arg.type?.ofType?.name; const isNotNull = arg.type?.kind === 'NON_NULL'; - if (type && HASH.hasOwnProperty(type)) { + if (type && Object.prototype.hasOwnProperty.call(HASH, type)) { const schema = HASH[type]; const fields = schema.inputFields!.filter((a) => a.name !== 'clientMutationId'); const properties = fields.map((a) => getInputForMutations(a.type, { name: a.name })).reduce((m3, v) => { diff --git a/postgres/introspectron/src/introspectGql.ts b/postgres/introspectron/src/introspectGql.ts index 9a087bd3f0..56e000dafc 100644 --- a/postgres/introspectron/src/introspectGql.ts +++ b/postgres/introspectron/src/introspectGql.ts @@ -1,5 +1,5 @@ -import gql from 'graphql-tag'; import { DocumentNode } from 'graphql'; +import gql from 'graphql-tag'; export const IntrospectionQuery: DocumentNode = gql` query IntrospectionQuery { diff --git a/postgres/pg-cache/src/__tests__/lru.test.ts b/postgres/pg-cache/src/__tests__/lru.test.ts index cca6db9634..a68afa616f 100644 --- a/postgres/pg-cache/src/__tests__/lru.test.ts +++ b/postgres/pg-cache/src/__tests__/lru.test.ts @@ -8,6 +8,7 @@ // close() calls are idempotent. See pg-cache-close-leak.md for full details. import pg from 'pg'; + import { PgPoolCacheManager } from '../lru'; // Minimal mock — we only need pool.end() and pool.ended diff --git a/postgres/pg-cache/src/lru.ts b/postgres/pg-cache/src/lru.ts index 98612a862b..633dc6388e 100644 --- a/postgres/pg-cache/src/lru.ts +++ b/postgres/pg-cache/src/lru.ts @@ -1,5 +1,5 @@ -import { parseEnvNumber } from '12factor-env'; import { Logger } from '@pgpmjs/logger'; +import { parseEnvNumber } from '12factor-env'; import { LRUCache } from 'lru-cache'; import pg from 'pg'; diff --git a/postgres/pg-cache/src/pg.ts b/postgres/pg-cache/src/pg.ts index ffb88babcc..08920e924d 100644 --- a/postgres/pg-cache/src/pg.ts +++ b/postgres/pg-cache/src/pg.ts @@ -1,7 +1,7 @@ +import { Logger } from '@pgpmjs/logger'; import { parseEnvNumber } from '12factor-env'; import pg from 'pg'; import { getPgEnvOptions, PgConfig, PgPoolConfig } from 'pg-env'; -import { Logger } from '@pgpmjs/logger'; import { getActivePgPoolFactory, PgPoolFactory } from './driver'; import { pgCache } from './lru'; diff --git a/postgres/pglite-test/__tests__/roles.test.ts b/postgres/pglite-test/__tests__/roles.test.ts index 8e6bbb41cc..52a1fda8d6 100644 --- a/postgres/pglite-test/__tests__/roles.test.ts +++ b/postgres/pglite-test/__tests__/roles.test.ts @@ -22,7 +22,7 @@ describe('pglite-test: default role bootstrap', () => { it('creates the standard app roles with no manual CREATE ROLE', async () => { const { rows } = await pg.query<{ rolname: string }>( - "SELECT rolname FROM pg_roles WHERE rolname = ANY($1) ORDER BY rolname", + 'SELECT rolname FROM pg_roles WHERE rolname = ANY($1) ORDER BY rolname', [['administrator', 'anonymous', 'authenticated', 'authenticated_client']] ); expect(rows.map((r) => r.rolname)).toEqual([ @@ -39,7 +39,7 @@ describe('pglite-test: default role bootstrap', () => { rolbypassrls: boolean; rolcanlogin: boolean; }>( - "SELECT rolname, rolbypassrls, rolcanlogin FROM pg_roles WHERE rolname = ANY($1) ORDER BY rolname", + 'SELECT rolname, rolbypassrls, rolcanlogin FROM pg_roles WHERE rolname = ANY($1) ORDER BY rolname', [['administrator', 'authenticated']] ); const admin = rows.find((r) => r.rolname === 'administrator'); @@ -72,7 +72,7 @@ describe('pglite-test: role bootstrap escape hatch', () => { it('does not create app roles when roles: false', async () => { const { rows } = await pg.query<{ n: number }>( - "SELECT count(*)::int AS n FROM pg_roles WHERE rolname = ANY($1)", + 'SELECT count(*)::int AS n FROM pg_roles WHERE rolname = ANY($1)', [['anonymous', 'authenticated', 'administrator', 'authenticated_client']] ); expect(rows[0].n).toBe(0); diff --git a/postgres/pglite-test/src/index.ts b/postgres/pglite-test/src/index.ts index fc3b2c09a4..327d993d57 100644 --- a/postgres/pglite-test/src/index.ts +++ b/postgres/pglite-test/src/index.ts @@ -102,9 +102,9 @@ export const getConnections = async ( const roleMapping = getRoleMapping({ roles: cn.db?.roles }); const roleSql = bootstrapRoles ? [ - generateCreateBaseRolesSQL(roleMapping), - generateCreateClientRoleSQL(roleMapping) - ] + generateCreateBaseRolesSQL(roleMapping), + generateCreateClientRoleSQL(roleMapping) + ] : []; const handle = await registerPglite({ diff --git a/postgres/pgsql-client/src/client.ts b/postgres/pgsql-client/src/client.ts index 3057233e1e..87d1cdb2a5 100644 --- a/postgres/pgsql-client/src/client.ts +++ b/postgres/pgsql-client/src/client.ts @@ -35,7 +35,9 @@ export class PgClient { if (this.connectPromise) { try { await this.connectPromise; - } catch {} + } catch { + // ignore + } } } diff --git a/postgres/pgsql-seed/src/index.ts b/postgres/pgsql-seed/src/index.ts index e18586eaf3..562eee8ae2 100644 --- a/postgres/pgsql-seed/src/index.ts +++ b/postgres/pgsql-seed/src/index.ts @@ -1,21 +1,21 @@ // Re-export everything from pg-seed (core seeding utilities) export { + // Types + type ClientInput, + type CopyableClient, + type CsvSeedMap, + // SQL utilities + execSql, // CSV utilities exportCsv, - loadCsv, - loadCsvMap, // JSON utilities insertJson, insertJsonMap, - // SQL utilities - execSql, + type JsonSeedMap, + loadCsv, + loadCsvMap, loadSql, loadSqlFiles, - // Types - type ClientInput, - type CopyableClient, - type CsvSeedMap, - type JsonSeedMap, type QueryableClient, // Utility unwrapClient diff --git a/postgres/pgsql-test/__tests__/postgres-test.pgpm-migration-errors.test.ts b/postgres/pgsql-test/__tests__/postgres-test.pgpm-migration-errors.test.ts index bd43d16498..1c103d9f26 100644 --- a/postgres/pgsql-test/__tests__/postgres-test.pgpm-migration-errors.test.ts +++ b/postgres/pgsql-test/__tests__/postgres-test.pgpm-migration-errors.test.ts @@ -1,11 +1,10 @@ process.env.LOG_SCOPE = 'pgsql-test'; +import { PgpmMigrate } from '@pgpmjs/core'; import { mkdirSync, mkdtempSync, rmSync, writeFileSync } from 'fs'; import { tmpdir } from 'os'; import { join } from 'path'; -import { PgpmMigrate } from '@pgpmjs/core'; - import { getConnections } from '../src/connect'; import { PgTestClient } from '../src/test-client'; diff --git a/postgres/pgsql-test/__tests__/postgres-test.seed-methods.test.ts b/postgres/pgsql-test/__tests__/postgres-test.seed-methods.test.ts index 550e86e624..5623b7b699 100644 --- a/postgres/pgsql-test/__tests__/postgres-test.seed-methods.test.ts +++ b/postgres/pgsql-test/__tests__/postgres-test.seed-methods.test.ts @@ -1,7 +1,8 @@ process.env.LOG_SCOPE = 'pgsql-test'; -import { writeFileSync, mkdirSync } from 'fs'; -import { join } from 'path'; +import { mkdirSync,writeFileSync } from 'fs'; import { tmpdir } from 'os'; +import { join } from 'path'; + import { seed } from '../src'; import { getConnections } from '../src/connect'; import { PgTestClient } from '../src/test-client'; diff --git a/postgres/pgsql-test/__tests__/utils.test.ts b/postgres/pgsql-test/__tests__/utils.test.ts index 9f75dda8ce..6652f0adf0 100644 --- a/postgres/pgsql-test/__tests__/utils.test.ts +++ b/postgres/pgsql-test/__tests__/utils.test.ts @@ -1,13 +1,12 @@ import { - snapshot, + IdHash, prune, pruneDates, - pruneIds, + pruneHashes, pruneIdArrays, + pruneIds, pruneUUIDs, - pruneHashes, - IdHash -} from '../src/utils'; + snapshot} from '../src/utils'; describe('snapshot utilities', () => { describe('pruneDates', () => { @@ -196,7 +195,7 @@ describe('snapshot utilities', () => { }); it('prune applies IdHash mapping when provided', () => { - const idHash: IdHash = { '1': 1, '2': 2 }; + const idHash: IdHash = { 1: 1, 2: 2 }; const row = { id: 1, user_id: 2, name: 'Alice' }; expect(prune(row, idHash)).toEqual({ id: '[ID-1]', diff --git a/postgres/pgsql-test/src/admin.ts b/postgres/pgsql-test/src/admin.ts index dcca2d60c3..6dc2e9979a 100644 --- a/postgres/pgsql-test/src/admin.ts +++ b/postgres/pgsql-test/src/admin.ts @@ -1,6 +1,7 @@ -import { DbAdmin as BaseDbAdmin } from 'pgsql-client'; import { PgTestConnectionOptions } from '@pgpmjs/types'; import { PgConfig } from 'pg-env'; +import { DbAdmin as BaseDbAdmin } from 'pgsql-client'; + import { SeedAdapter } from './seed/types'; // Extend DbAdmin from pgsql-client with test-specific methods diff --git a/postgres/pgsql-test/src/connect.ts b/postgres/pgsql-test/src/connect.ts index 06aa359093..518ff3cada 100644 --- a/postgres/pgsql-test/src/connect.ts +++ b/postgres/pgsql-test/src/connect.ts @@ -2,12 +2,10 @@ import { getConnEnvOptions } from '@pgpmjs/env'; import { PgTestConnectionOptions } from '@pgpmjs/types'; import { randomUUID } from 'crypto'; import { teardownPgPools } from 'pg-cache'; - import { getPgEnvOptions, PgConfig, } from 'pg-env'; - import { getDefaultRole } from 'pgsql-client'; import { DbAdmin } from './admin'; diff --git a/postgres/pgsql-test/src/index.ts b/postgres/pgsql-test/src/index.ts index 461eb95fbe..81c7303474 100644 --- a/postgres/pgsql-test/src/index.ts +++ b/postgres/pgsql-test/src/index.ts @@ -3,4 +3,4 @@ export * from './connect'; export * from './manager'; export * from './seed'; export * from './test-client'; -export { snapshot, getErrorCode } from './utils'; +export { getErrorCode,snapshot } from './utils'; diff --git a/postgres/pgsql-test/src/seed/csv.ts b/postgres/pgsql-test/src/seed/csv.ts index 381dd3264d..df0bebf303 100644 --- a/postgres/pgsql-test/src/seed/csv.ts +++ b/postgres/pgsql-test/src/seed/csv.ts @@ -1,4 +1,4 @@ -import { loadCsv, type CsvSeedMap } from 'pgsql-seed'; +import { type CsvSeedMap,loadCsv } from 'pgsql-seed'; import { SeedAdapter, SeedContext } from './types'; diff --git a/postgres/pgsql-test/src/test-client.ts b/postgres/pgsql-test/src/test-client.ts index c990b539c6..fd91867072 100644 --- a/postgres/pgsql-test/src/test-client.ts +++ b/postgres/pgsql-test/src/test-client.ts @@ -1,10 +1,11 @@ +import { QueryResult } from 'pg'; import { PgConfig } from 'pg-env'; import { PgClient, PgClientOpts } from 'pgsql-client'; import { insertJsonMap, type JsonSeedMap } from 'pgsql-seed'; -import { loadCsvMap, type CsvSeedMap } from 'pgsql-seed'; +import { type CsvSeedMap,loadCsvMap } from 'pgsql-seed'; import { loadSqlFiles } from 'pgsql-seed'; import { deployPgpm } from 'pgsql-seed'; -import { QueryResult } from 'pg'; + import { formatPgError } from './utils'; export type PgTestClientOpts = PgClientOpts & { diff --git a/postgres/pgsql-test/src/utils.ts b/postgres/pgsql-test/src/utils.ts index b277068be5..d5930e342c 100644 --- a/postgres/pgsql-test/src/utils.ts +++ b/postgres/pgsql-test/src/utils.ts @@ -1,19 +1,17 @@ import { extractPgErrorFields, - formatPgErrorFields, formatPgError, - type PgErrorFields, - type PgErrorContext -} from '@pgpmjs/types'; + formatPgErrorFields, + type PgErrorContext, + type PgErrorFields} from '@pgpmjs/types'; // Re-export PostgreSQL error formatting utilities export { extractPgErrorFields, - formatPgErrorFields, formatPgError, - type PgErrorFields, - type PgErrorContext -}; + formatPgErrorFields, + type PgErrorContext, + type PgErrorFields}; /** * Extract the error code from an error message. diff --git a/postgres/query-builder/src/index.ts b/postgres/query-builder/src/index.ts index 4e7f7c455b..b3a0634823 100644 --- a/postgres/query-builder/src/index.ts +++ b/postgres/query-builder/src/index.ts @@ -1,3 +1,16 @@ +export type { + Expr, + FieldFilter, + Filter, + FnArg, + FnArgs, + Operand, + ParamAllocator, + QueryOutput, + SelectExpr, + SelectItem, + SqlValue, +} from './query-builder'; export { add, and, @@ -21,16 +34,3 @@ export { QueryBuilder, sub } from './query-builder'; -export type { - Expr, - FieldFilter, - Filter, - FnArg, - FnArgs, - Operand, - ParamAllocator, - QueryOutput, - SelectExpr, - SelectItem, - SqlValue, -} from './query-builder'; diff --git a/postgres/query-builder/src/query-builder.ts b/postgres/query-builder/src/query-builder.ts index 4a3232aff1..f69c950cf5 100644 --- a/postgres/query-builder/src/query-builder.ts +++ b/postgres/query-builder/src/query-builder.ts @@ -311,7 +311,7 @@ const TYPE_NAME_ALIASES: Record = { 'time with time zone': 'timetz', 'time without time zone': 'time', 'character varying': 'varchar', - 'character': 'bpchar', + character: 'bpchar', 'double precision': 'float8', 'bit varying': 'varbit' }; diff --git a/postgres/supabase-test/src/connect.ts b/postgres/supabase-test/src/connect.ts index cefd524253..9c96894df8 100644 --- a/postgres/supabase-test/src/connect.ts +++ b/postgres/supabase-test/src/connect.ts @@ -1,11 +1,10 @@ +import type { PgTestConnectionOptions } from '@pgpmjs/types'; import deepmerge from 'deepmerge'; import { getPgEnvVars, PgConfig } from 'pg-env'; import { - getConnections as getPgConnections, type GetConnectionOpts, - type GetConnectionResult -} from 'pgsql-test'; -import type { PgTestConnectionOptions } from '@pgpmjs/types'; + type GetConnectionResult, + getConnections as getPgConnections} from 'pgsql-test'; /** * Supabase default connection options diff --git a/postgres/supabase-test/src/helpers.ts b/postgres/supabase-test/src/helpers.ts index 1b5015ffb7..0bc2abaa89 100644 --- a/postgres/supabase-test/src/helpers.ts +++ b/postgres/supabase-test/src/helpers.ts @@ -8,23 +8,23 @@ import { PgTestClient } from 'pgsql-test'; * @returns The inserted user object with id and email */ export async function insertUser( - client: PgTestClient, - email: string, - id?: string - ): Promise<{ id: string; email: string }> { - if (id) { - return await client.one( - `INSERT INTO auth.users (id, email) + client: PgTestClient, + email: string, + id?: string +): Promise<{ id: string; email: string }> { + if (id) { + return await client.one( + `INSERT INTO auth.users (id, email) VALUES ($1, $2) RETURNING id, email`, - [id, email] - ); - } else { - return await client.one( - `INSERT INTO auth.users (id, email) + [id, email] + ); + } else { + return await client.one( + `INSERT INTO auth.users (id, email) VALUES (gen_random_uuid(), $1) RETURNING id, email`, - [email] - ); - } - } \ No newline at end of file + [email] + ); + } +} \ No newline at end of file diff --git a/postgres/supabase-test/src/index.ts b/postgres/supabase-test/src/index.ts index 6dd9ae3700..00faf9b587 100644 --- a/postgres/supabase-test/src/index.ts +++ b/postgres/supabase-test/src/index.ts @@ -5,8 +5,8 @@ export * from 'pgsql-test'; export * from './helpers'; // Export Supabase-specific getConnections with defaults baked in -export { getConnections } from './connect'; export type { GetConnectionOpts, GetConnectionResult } from './connect'; +export { getConnections } from './connect'; // Re-export snapshot utility export { snapshot } from 'pgsql-test'; diff --git a/sdk/constructive-cli/scripts/generate-sdk.ts b/sdk/constructive-cli/scripts/generate-sdk.ts index 981cff1fce..adcb6902b0 100644 --- a/sdk/constructive-cli/scripts/generate-sdk.ts +++ b/sdk/constructive-cli/scripts/generate-sdk.ts @@ -1,8 +1,8 @@ +import type { GraphQLSDKConfigTarget } from '@constructive-io/graphql-codegen'; import { - generateMulti, expandSchemaDirToMultiTarget, + generateMulti, } from '@constructive-io/graphql-codegen'; -import type { GraphQLSDKConfigTarget } from '@constructive-io/graphql-codegen'; const SCHEMA_DIR = '../constructive-sdk/schemas'; diff --git a/sdk/constructive-react/scripts/generate-react.ts b/sdk/constructive-react/scripts/generate-react.ts index 511b7bae8a..dde526ab8f 100644 --- a/sdk/constructive-react/scripts/generate-react.ts +++ b/sdk/constructive-react/scripts/generate-react.ts @@ -1,8 +1,8 @@ +import type { GraphQLSDKConfigTarget } from '@constructive-io/graphql-codegen'; import { - generateMulti, expandSchemaDirToMultiTarget, + generateMulti, } from '@constructive-io/graphql-codegen'; -import type { GraphQLSDKConfigTarget } from '@constructive-io/graphql-codegen'; const SCHEMA_DIR = '../constructive-sdk/schemas'; diff --git a/sdk/constructive-sdk/scripts/generate-migrate-client.ts b/sdk/constructive-sdk/scripts/generate-migrate-client.ts index 32fb8f6124..bb87e03a34 100644 --- a/sdk/constructive-sdk/scripts/generate-migrate-client.ts +++ b/sdk/constructive-sdk/scripts/generate-migrate-client.ts @@ -8,9 +8,10 @@ */ import * as fs from 'node:fs'; import * as path from 'node:path'; + import { - generateMulti, expandSchemaDirToMultiTarget, + generateMulti, } from '@constructive-io/graphql-codegen'; const SCHEMA_DIR = '../migrate-client/schemas'; diff --git a/sdk/constructive-sdk/scripts/generate-sdk.ts b/sdk/constructive-sdk/scripts/generate-sdk.ts index eb35d1ec13..19a4ae1a0f 100644 --- a/sdk/constructive-sdk/scripts/generate-sdk.ts +++ b/sdk/constructive-sdk/scripts/generate-sdk.ts @@ -1,8 +1,8 @@ +import type { GraphQLSDKConfigTarget } from '@constructive-io/graphql-codegen'; import { - generateMulti, expandSchemaDirToMultiTarget, + generateMulti, } from '@constructive-io/graphql-codegen'; -import type { GraphQLSDKConfigTarget } from '@constructive-io/graphql-codegen'; const SCHEMA_DIR = '../constructive-sdk/schemas'; diff --git a/uploads/s3-streamer/__tests__/uploads.test.ts b/uploads/s3-streamer/__tests__/uploads.test.ts index bce7520ac1..7e8fd84d36 100644 --- a/uploads/s3-streamer/__tests__/uploads.test.ts +++ b/uploads/s3-streamer/__tests__/uploads.test.ts @@ -1,6 +1,6 @@ import { S3Client } from '@aws-sdk/client-s3'; -import { getEnvOptions } from '@pgpmjs/env'; import { createS3Bucket } from '@constructive-io/s3-utils'; +import { getEnvOptions } from '@pgpmjs/env'; import { createReadStream } from 'fs'; import { sync as glob } from 'glob'; import { basename } from 'path'; diff --git a/uploads/s3-streamer/src/s3.ts b/uploads/s3-streamer/src/s3.ts index 8948d886aa..7ec443d77e 100644 --- a/uploads/s3-streamer/src/s3.ts +++ b/uploads/s3-streamer/src/s3.ts @@ -1,6 +1,6 @@ -import { createS3Client } from '@constructive-io/s3-utils'; -import type { StorageProvider } from '@constructive-io/s3-utils'; import type { S3Client } from '@aws-sdk/client-s3'; +import type { StorageProvider } from '@constructive-io/s3-utils'; +import { createS3Client } from '@constructive-io/s3-utils'; import type { BucketProvider } from '@pgpmjs/types'; interface S3Options { diff --git a/uploads/s3-utils/__tests__/client.test.ts b/uploads/s3-utils/__tests__/client.test.ts index 3849ef11ec..8985df4126 100644 --- a/uploads/s3-utils/__tests__/client.test.ts +++ b/uploads/s3-utils/__tests__/client.test.ts @@ -2,8 +2,8 @@ * Tests for the unified S3 client factory. */ -import { createS3Client, S3ConfigError } from '../src/client'; import type { StorageConnectionConfig } from '../src/client'; +import { createS3Client, S3ConfigError } from '../src/client'; describe('createS3Client', () => { const baseConfig: StorageConnectionConfig = { diff --git a/uploads/s3-utils/__tests__/presigned.test.ts b/uploads/s3-utils/__tests__/presigned.test.ts index 44595e75a1..db9e0612a5 100644 --- a/uploads/s3-utils/__tests__/presigned.test.ts +++ b/uploads/s3-utils/__tests__/presigned.test.ts @@ -6,7 +6,8 @@ */ import { getSignedUrl } from '@aws-sdk/s3-request-presigner'; -import { presignPutUrl, presignGetUrl, headObject } from '../src/presigned'; + +import { headObject,presignGetUrl, presignPutUrl } from '../src/presigned'; // Mock the AWS SDK modules jest.mock('@aws-sdk/s3-request-presigner', () => ({ diff --git a/uploads/s3-utils/src/presigned.ts b/uploads/s3-utils/src/presigned.ts index be15cd77fe..3985aa664b 100644 --- a/uploads/s3-utils/src/presigned.ts +++ b/uploads/s3-utils/src/presigned.ts @@ -25,12 +25,12 @@ * ``` */ +import type { S3Client } from '@aws-sdk/client-s3'; import { - PutObjectCommand, GetObjectCommand, HeadObjectCommand, + PutObjectCommand, } from '@aws-sdk/client-s3'; -import type { S3Client } from '@aws-sdk/client-s3'; import { getSignedUrl } from '@aws-sdk/s3-request-presigner'; // --- Types --- diff --git a/uploads/s3-utils/src/utils.ts b/uploads/s3-utils/src/utils.ts index 434a9ac1bb..cab6103847 100644 --- a/uploads/s3-utils/src/utils.ts +++ b/uploads/s3-utils/src/utils.ts @@ -36,6 +36,7 @@ export const download = async ({ bucket, key, }: FileOperationArgs & { writeStream: NodeJS.WritableStream }): Promise => { + // eslint-disable-next-line no-async-promise-executor return new Promise(async (resolve, reject) => { try { const errors: Error[] = []; diff --git a/uploads/upload-names/src/index.ts b/uploads/upload-names/src/index.ts index 244b2b75a2..5949151972 100644 --- a/uploads/upload-names/src/index.ts +++ b/uploads/upload-names/src/index.ts @@ -1,4 +1,5 @@ import { basename, extname } from 'path'; + import slugify from './slugify'; interface Options {