@dbsp/core 1.8.0 → 1.10.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.d.ts CHANGED
@@ -1693,13 +1693,14 @@ declare class UnsupportedStrategyError extends Error {
1693
1693
  */
1694
1694
  declare class ModelIRImpl implements ModelIR {
1695
1695
  readonly tables: ReadonlyMap<string, TableIR>;
1696
+ readonly externalTables: ReadonlySet<string>;
1696
1697
  readonly relations: ReadonlyMap<string, RelationIR>;
1697
1698
  readonly enums?: ReadonlyMap<string, EnumIR>;
1698
1699
  readonly extensions?: readonly string[];
1699
1700
  readonly sequences?: ReadonlyMap<string, SequenceIR>;
1700
1701
  private readonly relationsBySource;
1701
1702
  private readonly relationsByTarget;
1702
- constructor(tables: Map<string, TableIR>, relations: Map<string, RelationIR>, enums?: Map<string, EnumIR>, extensions?: readonly string[], sequences?: Map<string, SequenceIR>);
1703
+ constructor(tables: Map<string, TableIR>, relations: Map<string, RelationIR>, enums?: Map<string, EnumIR>, extensions?: readonly string[], sequences?: Map<string, SequenceIR>, externalTables?: Iterable<string>);
1703
1704
  /**
1704
1705
  * Get table by name
1705
1706
  */
@@ -4074,8 +4075,14 @@ interface QueryBuilder<TResult = unknown> {
4074
4075
  * Check whether any matching rows exist.
4075
4076
  *
4076
4077
  * Compiles to `SELECT EXISTS(SELECT 1 FROM ... WHERE ...)`.
4077
- * Strips `orderBy` and `include` (irrelevant for existence checks).
4078
- * Preserves `groupBy`, `having`, and `offset` (they affect the result set).
4078
+ * Strips `orderBy`; every include is kept and compiled exactly as for the
4079
+ * full query nothing is pruned. The `SELECT 1` wrap then discards the
4080
+ * target list, so target-list hydration (the default `json_agg`) vanishes
4081
+ * for free while FROM joins (`inner`/`left`/`lateral`/`cte`, incl. recursive)
4082
+ * ride along and filter/multiply the root rows just as they would in the full
4083
+ * query. `groupBy`, `having`, and `offset` are preserved (they affect the
4084
+ * result). A recursive include therefore builds its CTE here (and throws on a
4085
+ * dialect without `supportsRecursiveCTE`) rather than a cheaper shortcut.
4079
4086
  *
4080
4087
  * Requires `db` to be configured in createOrm() options.
4081
4088
  *
@@ -4461,7 +4468,10 @@ declare class QueryBuilderImpl<TResult = unknown> implements QueryBuilder<TResul
4461
4468
  private executeWithHooksInner;
4462
4469
  /**
4463
4470
  * Build an existence-check intent from current state.
4464
- * Strips orderBy and include (irrelevant), preserves groupBy/having/offset.
4471
+ * Strips orderBy (irrelevant once wrapped in EXISTS), sets existsWrap and
4472
+ * limit: 1, and keeps every include unchanged; the compiler decides which
4473
+ * include contributions still need to be emitted (see exists-intent.ts
4474
+ * and shouldEmitInclude() in the pgsql compiler) (#230).
4465
4475
  */
4466
4476
  private buildExistsIntent;
4467
4477
  /**
@@ -7455,6 +7465,19 @@ declare function defineModel<DB = Record<string, unknown>>(options: DefineModelO
7455
7465
  * - Custom logging frameworks (pino, winston, etc.)
7456
7466
  * - Structured logging
7457
7467
  */
7468
+ /**
7469
+ * Category of a DX warning, used internally by {@link emitWarning} to decide
7470
+ * env/per-instance suppression (#159). The category is NEVER passed to the
7471
+ * logger sink (see {@link Logger.warn}) — it only drives the suppression
7472
+ * decision inside `emitWarning`.
7473
+ *
7474
+ * - `'dx'`: developer-experience warnings (e.g. reserved word column access).
7475
+ * Suppressible via `DBSP_SUPPRESS_DX_WARNINGS` and per-instance `suppressDxWarnings`.
7476
+ * - `'runtime'`: operational warnings (e.g. raw SQL usage). Suppressible via
7477
+ * its own gate (e.g. `NODE_ENV`) plus the global logger, but NOT via
7478
+ * `DBSP_SUPPRESS_DX_WARNINGS` or per-instance `suppressDxWarnings`.
7479
+ */
7480
+ type WarningCategory = 'dx' | 'runtime';
7458
7481
  /**
7459
7482
  * Logger interface for dbsp library code.
7460
7483
  *
@@ -7465,6 +7488,13 @@ interface Logger {
7465
7488
  /**
7466
7489
  * Log a warning message.
7467
7490
  * Used for: reserved word usage, raw SQL warnings, deprecation notices.
7491
+ *
7492
+ * @param message - The warning message text (stable across versions —
7493
+ * downstream consumers may parse it). This is the ONLY argument the
7494
+ * sink ever receives — {@link WarningCategory} is internal to
7495
+ * {@link emitWarning}'s suppression decision and is never forwarded
7496
+ * here, so a `{ warn: console.warn }` or rest-arg/pino-style wrapper
7497
+ * never sees an unexpected extra token.
7468
7498
  */
7469
7499
  warn(message: string): void;
7470
7500
  }
@@ -7504,8 +7534,49 @@ declare function setLogger(logger: Logger): void;
7504
7534
  declare function getLogger(): Logger;
7505
7535
  /**
7506
7536
  * Reset logger to default (for testing).
7537
+ *
7538
+ * Also clears the module-level reserved-word warning dedup (#159) so tests
7539
+ * that install a spy logger and assert on warn call counts stay isolated
7540
+ * from each other.
7507
7541
  */
7508
7542
  declare function resetLogger(): void;
7543
+ /**
7544
+ * Options for {@link emitWarning}.
7545
+ */
7546
+ interface EmitWarningOptions {
7547
+ /**
7548
+ * Categories to suppress for this call site — e.g. an ORM instance's
7549
+ * `suppressDxWarnings` option (passing `['dx']`). Union'd with the env gate: a warning is
7550
+ * suppressed if EITHER applies.
7551
+ */
7552
+ readonly suppress?: readonly WarningCategory[];
7553
+ }
7554
+ /**
7555
+ * Central warning emission helper (#159).
7556
+ *
7557
+ * Suppression precedence (a warning is suppressed if ANY of the following hold):
7558
+ * 1. `category === 'dx'` AND `DBSP_SUPPRESS_DX_WARNINGS` is enabled per
7559
+ * {@link isEnvFlagEnabled} (read per-call, matching this repo's `NODE_ENV`
7560
+ * gate convention; `'0'`/`'false'` do NOT enable it).
7561
+ * 2. `options.suppress` includes `category`.
7562
+ * 3. The global logger is the exported `silentLogger` singleton (an explicit
7563
+ * global silence — checked by reference, not behavior, so a custom no-op
7564
+ * logger does NOT trigger this branch).
7565
+ *
7566
+ * Default (no env var, no `suppress` option, non-silent logger) → nothing is
7567
+ * suppressed; the message reaches `getLogger().warn(...)`.
7568
+ *
7569
+ * The category is used ONLY for this suppression decision — it is NEVER
7570
+ * passed to `getLogger().warn(...)`, which receives just the message (see
7571
+ * {@link Logger.warn}).
7572
+ *
7573
+ * @returns `true` when the warning was actually emitted, `false` when
7574
+ * suppressed. Callers that dedup (e.g. the reserved-word warning) MUST
7575
+ * only record the dedup key when this returns `true` — recording it
7576
+ * unconditionally would let a suppressed call permanently "poison" the
7577
+ * dedup slot for every later, non-suppressed caller in the same process.
7578
+ */
7579
+ declare function emitWarning(message: string, category: WarningCategory, options?: EmitWarningOptions): boolean;
7509
7580
 
7510
7581
  /** Error thrown when behavior = 'error' and unsupported feature detected */
7511
7582
  declare class UnsupportedFeatureError extends Error {
@@ -7628,6 +7699,24 @@ interface SimplifiedOrmOptions<T extends SchemaDefinition = SchemaDefinition> {
7628
7699
  * Pass FeatureBehaviorConfig for per-feature overrides.
7629
7700
  */
7630
7701
  readonly unsupportedFeatures?: UnsupportedFeatureBehavior | FeatureBehaviorConfig;
7702
+ /**
7703
+ * Suppress `'dx'` warnings (e.g. reserved-word column access) for this
7704
+ * ORM instance (#159). Union'd with the `DBSP_SUPPRESS_DX_WARNINGS` env
7705
+ * gate — a warning is suppressed if EITHER applies.
7706
+ *
7707
+ * Deliberately DX-only (not `WarningCategory[]`): `'runtime'` warnings
7708
+ * (raw-SQL usage) are emitted by the adapter's compiler, which has no
7709
+ * per-ORM-instance context, so a `'runtime'` entry here would silently
7710
+ * do nothing. `'runtime'` warnings are controlled only by the adapter's
7711
+ * `NODE_ENV` gate and the global logger (e.g. `silentLogger`) — not by
7712
+ * `DBSP_SUPPRESS_DX_WARNINGS` or this option.
7713
+ *
7714
+ * @example
7715
+ * ```typescript
7716
+ * const orm = createOrm({ schema, adapter, suppressDxWarnings: true });
7717
+ * ```
7718
+ */
7719
+ readonly suppressDxWarnings?: boolean;
7631
7720
  }
7632
7721
  /**
7633
7722
  * Create an ORM instance with the specified configuration.
@@ -8255,4 +8344,4 @@ declare const assertIntentHasOrderBy: (result: AssertionQueryResult, expected: b
8255
8344
  */
8256
8345
  declare function runAssertions(blocks: AssertionBlock[], results: AssertionQueryResult[], queries: string[], hasDb?: boolean): AssertionSummary;
8257
8346
 
8258
- export { ASSERTION_TYPES, AdapterRequiredError, type AdjacencyOptions, type AfterMutationHook, type AfterQueryHook, type AggregateOptions, type AliasedColumn, type AliasedExprColumn, type AllColumns, AmbiguousPlanError, AmbiguousRelationError, type Assertion, type AssertionBlock, type AssertionOutcome, type AssertionQueryResult, type AssertionSummary, type AssertionType, BRAND, type BatchValuesOptions, type BatchValuesRef, type BeforeMutationHook, type BeforeQueryHook, type BrandKey, COLUMN_META, type CardinalityShorthand, CaseBuilder, type CaseValue, type ColumnDef, type ColumnMetaKey, ColumnNotFoundError, type ColumnRef, type ColumnSpec, type ColumnTypeToTS, CteBuilder, type CteDump, CteQueryBuilder, type CursorPaginateOptions, type CursorPaginatedResult, DEFAULT_CONVENTIONS, DEFAULT_FEATURE_CHECKERS, DUCKDB_CAPABILITIES, type DefaultFilters, type DefineModelOptions, DeleteBuilder, type DistinctField, type DumpMetaInput, type EdgeTableOptions, ErrorCode, type ErrorHookContext, Errors, ExecutionError, type ExprInput, ExpressionRef, type ExpressionSpec, type FeatureChecker, type FeatureUsage, type FilterOperators, type FilterValue, type FullTextSearchField, type FullTextSearchOptions, type GeneratedBelongsTo, type GeneratedColumn, type GeneratedColumnType, type GeneratedConventions, type GeneratedHasMany, type GeneratedHint, type GeneratedManyToMany, type GeneratedRelation, type GeneratedRelationKind, type GeneratedSchema, type GeneratedTable, type GetSchemaFromDbOptions, type HierarchyOptions, type HookErrorHandler, type HookManager, type HookPriority, type HydrateOptions, IRREGULAR_PLURALS, type IncludeOptions, type IncludeOptionsWithRecursive, type InferColumn, type InferColumnType, type InferColumnTypes, type InferDB, type InferDBFromSchema, type InferRefColumn, type InferRow, type InferRowType, type InferSchemaDB, type InferTableRow, type InferTables, type InferredRangeValue, InsertBuilder, IntentBuilder, type IntentBuilderState, type IntentSummary, InvalidOperationError, InvalidRelationDefinitionError, type JoinOptions, type JsonValue, type LightweightRelationsDef, type ListHierarchyOptions, type ListIndexOptions, type Logger, MSSQL_CAPABILITIES, MYSQL_CAPABILITIES, ModelIRImpl, type MutationDump, type MutationHookContext, type MutationOperation, NamingConventionMismatchError, type NegotiationResult, type NestedInclude, type SchemaColumnType$1 as NewSchemaColumnType, NotFoundError, type NqlBuilder, type NqlRawFragment, type NqlTag, type OnErrorHook, type OrderByInput, type OrderByRecord, type OrderBySpec, type OrmInstance, type OrmOf, type OrmOptions, type OrmOptionsWithAdapter, type OrmOptionsWithModel, type OrmOptionsWithSchema, POSTGRESQL_CAPABILITIES, type PaginateOptions, type PaginatedResult, type ParseError, type ParseResult, type ParsedRelationDef, type ParsedRelationKey, type PathOptions, type PrioritizedHook, type QueryAssertionResult, type QueryBuilder, type QueryHookContext, type QueryResultType, RELATION_META, type RangeType, RawCteQueryBuilder, type RecursiveDump, type RecursiveIncludeConfig, type RecursiveOptions, RecursiveShapeMismatchError, type RefDefinition, type RefOptions, type RelationHints, type RelationKey, type RelationMetaKey, RelationNotFoundError, type RelationObjectDef, type RelationPathIncludeNode, type RelationPathUsage, type RelationRef, type RelationShorthand, type RelationTupleDef, type ResolvedSchema, ResolvedSchemaValidation, ResultHydrator, SQLITE_CAPABILITIES, SQL_RAW_MARKER, type Schema, type SchemaBelongsToRelation, type SchemaCardinality, type SchemaColumnDefinition, type SchemaColumnType, type SchemaConfigInput, type SchemaConstraints, type SchemaConventionsDefinition, type SchemaConversionResult, type SchemaDefinition, type SchemaDefinitionInput, SchemaValidationError$1 as SchemaError, type SchemaExtras, type SchemaFilterStrategy, type SchemaForeignKeyReference, type SchemaHasManyRelation, type SchemaHintDefinition, type SchemaHintsDefinition, type SchemaIndexDefinition, type SchemaIndexOptions, type SchemaIndexesDefinition, type SchemaManyToManyRelation, type SchemaOnDeleteAction, type SchemaOptions, type SchemaRelationDefinition, type SchemaRelationKind, type SchemaRelationsDefinition, type SchemaTableDefinition, type SchemaTableOptions, type SchemaTablesDefinition, SchemaValidationError, type SelectField, type SelfRefRoles, type SetOperationBuilder, type SimplifiedOrmOptions, type SqlRawExpression, type StreamOptions, SubqueryBuilder, SubqueryExpression, TABLE_META, type TableAssertionData, type TableDDL, type TableDef, type TableIndexes, type TableMetaKey, TableNotFoundError, type TableRef, type TraversalDirection, UnhandledTypeInDialect, UnknownDialectError, UnsafeOperationError, UnsupportedCapabilityError, UnsupportedFeatureError, UnsupportedStrategyError, UpdateBuilder, UpsertBuilder, type ValidatedResolvedSchema, type WhereFilter, WindowBuilder, aggOrderBy, and, any, array, arrayAgg, assertCapability, assertContains, assertDbColumnExists, assertDbOutput, assertDbRowsEquals, assertDbRowsMax, assertDbRowsMin, assertDbValueEquals, assertEquals, assertIntentHasGroupBy, assertIntentHasOrderBy, assertIntentHasWhere, assertIntentTable, assertIntentType, assertIntentWith, assertMatches, assertParamsEquals, assertParamsLength, assertParamsType, assertParamsValue, assertResolvedSchemaToGeneratedSchema, assertSQLColumn, assertSQLEquals, assertSQLJoin, assertSQLTable, assertSuccess, assertTypeSupported, batchValues, buildModelFromResolvedSchema, buildModelFromSchema, capitalize, caseWhen, cast, coalesce, col, composeAfterMutationHooks, composeAfterQueryHooks, composeBeforeMutationHooks, composeBeforeQueryHooks, composeOnErrorHooks, countDistinctRelationPathsByName, createDialectCapabilities, createHookManager, createNqlTag, createOrm, createPseudoColumnMetadata, createRawCteBuilder, createRecursiveMetadata, decapitalize, defaultLogger, defineModel, defineSchema, denseRank, deriveRelationPathFromIntentPath, detectForeignKeys, detectManyToMany, distinct, eq, every, exists, ref as exprRef, extendDialect, extractPseudoColumnKeywords, findClosestMatch, fn, fullTextSearch, getAvailableDialects, getDialectCapabilities, getLogger, getRelationKind, getSchemaFromDb, gt, gte, inArray, inSubquery, inferForeignKey, inferRelationsFromSchema, isAliasedColumn, isAllColumns, isBatchValuesRef, isBelongsTo, isCardinalityShorthand, isColumnRef, isDistinctField, isDistinctFrom, isExpressionSpec, isGeneratedSchema, isHasMany, isKnownDialect, isManyToMany, isNotNull, isNull, isOverallSuccess, isRecursiveIncludeOptions, isRecursiveRelation, isRef, isRelationObjectDef, isRelationRef, isRelationTupleDef, isResolvedSchema, isSelfReferential, isSqlRaw, isSubqueryExpression, isTableRef, isWhereIntent, lag, lead, like, literal, lt, lte, namedArg, negotiateFeatures, neq, none, normalizeSQL, normalizeSchema, not, notExists, nqlRaw, objectToWhereIntent, op, or, outerRef, param, parseAssertionFile, parseRelationDef, parseRelationKey, pipeAfterMutationHooks, pipeAfterQueryHooks, pipeBeforeMutationHooks, pipeBeforeQueryHooks, pipeOnErrorHooks, plan, planRecursive, pluralize, rangeContainedBy, rangeContains, rangeOverlaps, rank, raw, rawExists, rawNotExists, ref$1 as ref, registerDialect, relationColumn, requiresDatabase, resetLogger, resolveQueryIndex, resolvedSchemaToGeneratedSchema, rowNumber, runAssertions, schema, schemaToModelIR, setLogger, silentLogger, singularize, some, sortByPriority, sql, star, stringAgg, subquery, supportsDDLGeneration, supportsExecution, supportsIntrospection, supportsRawSql, supportsStreaming, supportsTransactions, textScore, unary, validateAssertionBlocks, validateRecursiveInclude, validateRecursiveShape, validateTypeName, wAvg, wCount, wMax, wMin, wSum, withPriority };
8347
+ export { ASSERTION_TYPES, AdapterRequiredError, type AdjacencyOptions, type AfterMutationHook, type AfterQueryHook, type AggregateOptions, type AliasedColumn, type AliasedExprColumn, type AllColumns, AmbiguousPlanError, AmbiguousRelationError, type Assertion, type AssertionBlock, type AssertionOutcome, type AssertionQueryResult, type AssertionSummary, type AssertionType, BRAND, type BatchValuesOptions, type BatchValuesRef, type BeforeMutationHook, type BeforeQueryHook, type BrandKey, COLUMN_META, type CardinalityShorthand, CaseBuilder, type CaseValue, type ColumnDef, type ColumnMetaKey, ColumnNotFoundError, type ColumnRef, type ColumnSpec, type ColumnTypeToTS, CteBuilder, type CteDump, CteQueryBuilder, type CursorPaginateOptions, type CursorPaginatedResult, DEFAULT_CONVENTIONS, DEFAULT_FEATURE_CHECKERS, DUCKDB_CAPABILITIES, type DefaultFilters, type DefineModelOptions, DeleteBuilder, type DistinctField, type DumpMetaInput, type EdgeTableOptions, type EmitWarningOptions, ErrorCode, type ErrorHookContext, Errors, ExecutionError, type ExprInput, ExpressionRef, type ExpressionSpec, type FeatureChecker, type FeatureUsage, type FilterOperators, type FilterValue, type FullTextSearchField, type FullTextSearchOptions, type GeneratedBelongsTo, type GeneratedColumn, type GeneratedColumnType, type GeneratedConventions, type GeneratedHasMany, type GeneratedHint, type GeneratedManyToMany, type GeneratedRelation, type GeneratedRelationKind, type GeneratedSchema, type GeneratedTable, type GetSchemaFromDbOptions, type HierarchyOptions, type HookErrorHandler, type HookManager, type HookPriority, type HydrateOptions, IRREGULAR_PLURALS, type IncludeOptions, type IncludeOptionsWithRecursive, type InferColumn, type InferColumnType, type InferColumnTypes, type InferDB, type InferDBFromSchema, type InferRefColumn, type InferRow, type InferRowType, type InferSchemaDB, type InferTableRow, type InferTables, type InferredRangeValue, InsertBuilder, IntentBuilder, type IntentBuilderState, type IntentSummary, InvalidOperationError, InvalidRelationDefinitionError, type JoinOptions, type JsonValue, type LightweightRelationsDef, type ListHierarchyOptions, type ListIndexOptions, type Logger, MSSQL_CAPABILITIES, MYSQL_CAPABILITIES, ModelIRImpl, type MutationDump, type MutationHookContext, type MutationOperation, NamingConventionMismatchError, type NegotiationResult, type NestedInclude, type SchemaColumnType$1 as NewSchemaColumnType, NotFoundError, type NqlBuilder, type NqlRawFragment, type NqlTag, type OnErrorHook, type OrderByInput, type OrderByRecord, type OrderBySpec, type OrmInstance, type OrmOf, type OrmOptions, type OrmOptionsWithAdapter, type OrmOptionsWithModel, type OrmOptionsWithSchema, POSTGRESQL_CAPABILITIES, type PaginateOptions, type PaginatedResult, type ParseError, type ParseResult, type ParsedRelationDef, type ParsedRelationKey, type PathOptions, type PrioritizedHook, type QueryAssertionResult, type QueryBuilder, type QueryHookContext, type QueryResultType, RELATION_META, type RangeType, RawCteQueryBuilder, type RecursiveDump, type RecursiveIncludeConfig, type RecursiveOptions, RecursiveShapeMismatchError, type RefDefinition, type RefOptions, type RelationHints, type RelationKey, type RelationMetaKey, RelationNotFoundError, type RelationObjectDef, type RelationPathIncludeNode, type RelationPathUsage, type RelationRef, type RelationShorthand, type RelationTupleDef, type ResolvedSchema, ResolvedSchemaValidation, ResultHydrator, SQLITE_CAPABILITIES, SQL_RAW_MARKER, type Schema, type SchemaBelongsToRelation, type SchemaCardinality, type SchemaColumnDefinition, type SchemaColumnType, type SchemaConfigInput, type SchemaConstraints, type SchemaConventionsDefinition, type SchemaConversionResult, type SchemaDefinition, type SchemaDefinitionInput, SchemaValidationError$1 as SchemaError, type SchemaExtras, type SchemaFilterStrategy, type SchemaForeignKeyReference, type SchemaHasManyRelation, type SchemaHintDefinition, type SchemaHintsDefinition, type SchemaIndexDefinition, type SchemaIndexOptions, type SchemaIndexesDefinition, type SchemaManyToManyRelation, type SchemaOnDeleteAction, type SchemaOptions, type SchemaRelationDefinition, type SchemaRelationKind, type SchemaRelationsDefinition, type SchemaTableDefinition, type SchemaTableOptions, type SchemaTablesDefinition, SchemaValidationError, type SelectField, type SelfRefRoles, type SetOperationBuilder, type SimplifiedOrmOptions, type SqlRawExpression, type StreamOptions, SubqueryBuilder, SubqueryExpression, TABLE_META, type TableAssertionData, type TableDDL, type TableDef, type TableIndexes, type TableMetaKey, TableNotFoundError, type TableRef, type TraversalDirection, UnhandledTypeInDialect, UnknownDialectError, UnsafeOperationError, UnsupportedCapabilityError, UnsupportedFeatureError, UnsupportedStrategyError, UpdateBuilder, UpsertBuilder, type ValidatedResolvedSchema, type WarningCategory, type WhereFilter, WindowBuilder, aggOrderBy, and, any, array, arrayAgg, assertCapability, assertContains, assertDbColumnExists, assertDbOutput, assertDbRowsEquals, assertDbRowsMax, assertDbRowsMin, assertDbValueEquals, assertEquals, assertIntentHasGroupBy, assertIntentHasOrderBy, assertIntentHasWhere, assertIntentTable, assertIntentType, assertIntentWith, assertMatches, assertParamsEquals, assertParamsLength, assertParamsType, assertParamsValue, assertResolvedSchemaToGeneratedSchema, assertSQLColumn, assertSQLEquals, assertSQLJoin, assertSQLTable, assertSuccess, assertTypeSupported, batchValues, buildModelFromResolvedSchema, buildModelFromSchema, capitalize, caseWhen, cast, coalesce, col, composeAfterMutationHooks, composeAfterQueryHooks, composeBeforeMutationHooks, composeBeforeQueryHooks, composeOnErrorHooks, countDistinctRelationPathsByName, createDialectCapabilities, createHookManager, createNqlTag, createOrm, createPseudoColumnMetadata, createRawCteBuilder, createRecursiveMetadata, decapitalize, defaultLogger, defineModel, defineSchema, denseRank, deriveRelationPathFromIntentPath, detectForeignKeys, detectManyToMany, distinct, emitWarning, eq, every, exists, ref as exprRef, extendDialect, extractPseudoColumnKeywords, findClosestMatch, fn, fullTextSearch, getAvailableDialects, getDialectCapabilities, getLogger, getRelationKind, getSchemaFromDb, gt, gte, inArray, inSubquery, inferForeignKey, inferRelationsFromSchema, isAliasedColumn, isAllColumns, isBatchValuesRef, isBelongsTo, isCardinalityShorthand, isColumnRef, isDistinctField, isDistinctFrom, isExpressionSpec, isGeneratedSchema, isHasMany, isKnownDialect, isManyToMany, isNotNull, isNull, isOverallSuccess, isRecursiveIncludeOptions, isRecursiveRelation, isRef, isRelationObjectDef, isRelationRef, isRelationTupleDef, isResolvedSchema, isSelfReferential, isSqlRaw, isSubqueryExpression, isTableRef, isWhereIntent, lag, lead, like, literal, lt, lte, namedArg, negotiateFeatures, neq, none, normalizeSQL, normalizeSchema, not, notExists, nqlRaw, objectToWhereIntent, op, or, outerRef, param, parseAssertionFile, parseRelationDef, parseRelationKey, pipeAfterMutationHooks, pipeAfterQueryHooks, pipeBeforeMutationHooks, pipeBeforeQueryHooks, pipeOnErrorHooks, plan, planRecursive, pluralize, rangeContainedBy, rangeContains, rangeOverlaps, rank, raw, rawExists, rawNotExists, ref$1 as ref, registerDialect, relationColumn, requiresDatabase, resetLogger, resolveQueryIndex, resolvedSchemaToGeneratedSchema, rowNumber, runAssertions, schema, schemaToModelIR, setLogger, silentLogger, singularize, some, sortByPriority, sql, star, stringAgg, subquery, supportsDDLGeneration, supportsExecution, supportsIntrospection, supportsRawSql, supportsStreaming, supportsTransactions, textScore, unary, validateAssertionBlocks, validateRecursiveInclude, validateRecursiveShape, validateTypeName, wAvg, wCount, wMax, wMin, wSum, withPriority };
package/dist/index.js CHANGED
@@ -60,6 +60,7 @@ import * as types_star from "@dbsp/types";
60
60
  // src/model-impl.ts
61
61
  var ModelIRImpl = class {
62
62
  tables;
63
+ externalTables;
63
64
  relations;
64
65
  enums;
65
66
  extensions;
@@ -67,8 +68,11 @@ var ModelIRImpl = class {
67
68
  // Pre-computed indexes for efficient lookups
68
69
  relationsBySource;
69
70
  relationsByTarget;
70
- constructor(tables, relations, enums, extensions, sequences) {
71
+ constructor(tables, relations, enums, extensions, sequences, externalTables) {
71
72
  this.tables = Object.freeze(new Map(tables));
73
+ this.externalTables = Object.freeze(
74
+ new Set(externalTables)
75
+ );
72
76
  this.relations = Object.freeze(new Map(relations));
73
77
  if (enums) {
74
78
  this.enums = Object.freeze(new Map(enums));
@@ -156,6 +160,11 @@ var ModelIRImpl = class {
156
160
  validate() {
157
161
  const errors = [];
158
162
  for (const table of this.tables.values()) {
163
+ if (this.externalTables.has(table.name)) {
164
+ errors.push(
165
+ `Table "${table.name}" cannot be both managed and external`
166
+ );
167
+ }
159
168
  if (table.primaryKey) {
160
169
  const pkCols = Array.isArray(table.primaryKey) ? table.primaryKey : [table.primaryKey];
161
170
  for (const pk of pkCols) {
@@ -169,7 +178,7 @@ var ModelIRImpl = class {
169
178
  }
170
179
  for (const table of this.tables.values()) {
171
180
  for (const fk of table.foreignKeys) {
172
- if (!this.tables.has(fk.references.table)) {
181
+ if (!this.tables.has(fk.references.table) && !this.externalTables.has(fk.references.table)) {
173
182
  errors.push(
174
183
  `Table "${table.name}" has FK referencing non-existent table "${fk.references.table}"`
175
184
  );
@@ -247,6 +256,28 @@ function getLogger() {
247
256
  }
248
257
  function resetLogger() {
249
258
  globalLogger = defaultLogger;
259
+ resetWarnedReservedWords();
260
+ }
261
+ function isEnvFlagEnabled(value) {
262
+ if (value === void 0) {
263
+ return false;
264
+ }
265
+ const normalized = value.trim().toLowerCase();
266
+ return normalized !== "" && normalized !== "0" && normalized !== "false";
267
+ }
268
+ function emitWarning(message, category, options) {
269
+ if (category === "dx" && isEnvFlagEnabled(process.env.DBSP_SUPPRESS_DX_WARNINGS)) {
270
+ return false;
271
+ }
272
+ if (options?.suppress?.includes(category)) {
273
+ return false;
274
+ }
275
+ const logger = getLogger();
276
+ if (logger === silentLogger) {
277
+ return false;
278
+ }
279
+ logger.warn(message);
280
+ return true;
250
281
  }
251
282
 
252
283
  // src/dx/symbols.ts
@@ -306,10 +337,23 @@ var JS_RESERVED_WORDS = /* @__PURE__ */ new Set([
306
337
  "throw",
307
338
  "typeof"
308
339
  ]);
309
- function warnReservedWord(tableName, columnName) {
310
- getLogger().warn(
311
- `[dbsp] Warning: Column "${columnName}" in table "${tableName}" is a JavaScript reserved word. Access it via bracket notation: table['${columnName}']`
340
+ var warnedReservedWords = /* @__PURE__ */ new Set();
341
+ function resetWarnedReservedWords() {
342
+ warnedReservedWords.clear();
343
+ }
344
+ function warnReservedWord(tableName, columnName, suppress) {
345
+ const dedupKey = `${tableName}.${columnName}`;
346
+ if (warnedReservedWords.has(dedupKey)) {
347
+ return;
348
+ }
349
+ const emitted = emitWarning(
350
+ `[dbsp] Warning: Column "${columnName}" in table "${tableName}" is a JavaScript reserved word. Access it via bracket notation: table['${columnName}']`,
351
+ "dx",
352
+ suppress ? { suppress } : void 0
312
353
  );
354
+ if (emitted) {
355
+ warnedReservedWords.add(dedupKey);
356
+ }
313
357
  }
314
358
  function createColumnRef(tableName, columnName, relationPath) {
315
359
  const columnRef = {
@@ -439,7 +483,7 @@ function createRelationRef(targetTable, relationType, model, relationName, paren
439
483
  }
440
484
  });
441
485
  }
442
- function createTableRef(tableName, model) {
486
+ function createTableRef(tableName, model, suppress) {
443
487
  const tableIR = model.getTable(tableName);
444
488
  if (!tableIR) {
445
489
  throw new Error(`Table "${tableName}" not found in model`);
@@ -463,7 +507,6 @@ function createTableRef(tableName, model) {
463
507
  relations.set(inverseName, { target: relation.source, type: "hasMany" });
464
508
  }
465
509
  }
466
- const warnedReservedWords = /* @__PURE__ */ new Set();
467
510
  return new Proxy(base, {
468
511
  get(target, prop, receiver) {
469
512
  if (typeof prop === "symbol") {
@@ -478,10 +521,7 @@ function createTableRef(tableName, model) {
478
521
  const propStr = prop;
479
522
  if (JS_RESERVED_WORDS.has(propStr)) {
480
523
  if (hasColumn(tableIR.columns, propStr)) {
481
- if (!warnedReservedWords.has(propStr)) {
482
- warnReservedWord(tableName, propStr);
483
- warnedReservedWords.add(propStr);
484
- }
524
+ warnReservedWord(tableName, propStr, suppress);
485
525
  return createColumnRef(tableName, propStr);
486
526
  }
487
527
  }
@@ -532,9 +572,10 @@ function createTableRef(tableName, model) {
532
572
  }
533
573
  });
534
574
  }
535
- function createTablesProxy(model, tableNames) {
575
+ function createTablesProxy(model, tableNames, options) {
536
576
  const tableSet = new Set(tableNames);
537
577
  const cache = /* @__PURE__ */ new Map();
578
+ const suppress = options?.suppressWarnings;
538
579
  return new Proxy(
539
580
  {},
540
581
  {
@@ -547,7 +588,7 @@ function createTablesProxy(model, tableNames) {
547
588
  return cache.get(propStr);
548
589
  }
549
590
  if (tableSet.has(propStr)) {
550
- const tableRef = createTableRef(propStr, model);
591
+ const tableRef = createTableRef(propStr, model, suppress);
551
592
  cache.set(propStr, tableRef);
552
593
  return tableRef;
553
594
  }
@@ -566,7 +607,7 @@ function createTablesProxy(model, tableNames) {
566
607
  if (typeof prop === "string" && tableSet.has(prop)) {
567
608
  let tableRef = cache.get(prop);
568
609
  if (!tableRef) {
569
- tableRef = createTableRef(prop, model);
610
+ tableRef = createTableRef(prop, model, suppress);
570
611
  cache.set(prop, tableRef);
571
612
  }
572
613
  return {
@@ -1234,6 +1275,7 @@ function addCompositeConstraintRelations(relations, tableNames, constraints) {
1234
1275
  const foreignKey = [...columns];
1235
1276
  const referencedKey = [...references];
1236
1277
  const belongsToName = deriveCompositeConstraintRelationName(
1278
+ // biome-ignore lint/style/noNonNullAssertion: foreignKey copies columns whose length is guaranteed >= 1 by the "if (!columns?.length) continue;" guard above
1237
1279
  foreignKey[0],
1238
1280
  fkRef.options
1239
1281
  );
@@ -7735,6 +7777,13 @@ function findSelfRefRelation(model, table, direction) {
7735
7777
  return null;
7736
7778
  }
7737
7779
 
7780
+ // src/dx/exists-intent.ts
7781
+ function buildExistsIntent(baseIntent) {
7782
+ const { orderBy: _orderBy, ...rest } = baseIntent;
7783
+ const existsLimit = baseIntent.limit === 0 ? 0 : 1;
7784
+ return { ...rest, existsWrap: true, limit: existsLimit };
7785
+ }
7786
+
7738
7787
  // src/dx/pagination-impl.ts
7739
7788
  function resolveCursorKey(orderBy) {
7740
7789
  if (typeof orderBy === "string") return orderBy;
@@ -9765,36 +9814,20 @@ var QueryBuilderImpl = class _QueryBuilderImpl {
9765
9814
  }
9766
9815
  /**
9767
9816
  * Build an existence-check intent from current state.
9768
- * Strips orderBy and include (irrelevant), preserves groupBy/having/offset.
9817
+ * Strips orderBy (irrelevant once wrapped in EXISTS), sets existsWrap and
9818
+ * limit: 1, and keeps every include unchanged; the compiler decides which
9819
+ * include contributions still need to be emitted (see exists-intent.ts
9820
+ * and shouldEmitInclude() in the pgsql compiler) (#230).
9769
9821
  */
9770
9822
  buildExistsIntent() {
9771
- const baseIntent = this.buildIntent();
9772
- const {
9773
- orderBy: _orderBy,
9774
- include: _include,
9775
- ...rest
9776
- } = baseIntent;
9777
- return {
9778
- ...rest,
9779
- existsWrap: true,
9780
- limit: 1
9781
- };
9823
+ return buildExistsIntent(this.buildIntent());
9782
9824
  }
9783
9825
  /**
9784
9826
  * Build exists-wrapped intent from a pre-built intent (E17b: for hook-aware path).
9785
9827
  * @internal
9786
9828
  */
9787
9829
  buildExistsIntentFromIntent(baseIntent) {
9788
- const {
9789
- orderBy: _orderBy,
9790
- include: _include,
9791
- ...rest
9792
- } = baseIntent;
9793
- return {
9794
- ...rest,
9795
- existsWrap: true,
9796
- limit: 1
9797
- };
9830
+ return buildExistsIntent(baseIntent);
9798
9831
  }
9799
9832
  /**
9800
9833
  * Handle ambiguity based on strict mode setting.
@@ -10216,6 +10249,9 @@ function generateCreateIndexSQL(tableName, schemaName, opts) {
10216
10249
  `INCLUDE (${opts.include.map((c) => quoteIdent(c)).join(", ")})`
10217
10250
  );
10218
10251
  }
10252
+ if (opts.unique && opts.nullsNotDistinct) {
10253
+ parts.push("NULLS NOT DISTINCT");
10254
+ }
10219
10255
  if (opts.with && Object.keys(opts.with).length > 0) {
10220
10256
  const withClauses = Object.entries(opts.with).map(([k, v2]) => `${k} = ${v2}`).join(", ");
10221
10257
  parts.push(`WITH (${withClauses})`);
@@ -10780,8 +10816,10 @@ function createOrm(options) {
10780
10816
  planOptions: globalPlanOptions,
10781
10817
  hooks: hookManager,
10782
10818
  onHookError,
10783
- unsupportedFeatures
10819
+ unsupportedFeatures,
10820
+ suppressDxWarnings
10784
10821
  } = options;
10822
+ const suppressWarnings = suppressDxWarnings ? ["dx"] : void 0;
10785
10823
  let model;
10786
10824
  let schemaDefinition;
10787
10825
  let defaultFilters;
@@ -10815,7 +10853,11 @@ function createOrm(options) {
10815
10853
  }
10816
10854
  }
10817
10855
  const frozenHookStore = hookManager ? getHookStore(hookManager.freeze()) : void 0;
10818
- const tablesProxy = schemaObj && "tables" in schemaObj ? schemaObj.tables : createTablesProxy(model, model.tables ? [...model.tables.keys()] : []);
10856
+ const tablesProxy = schemaObj && "tables" in schemaObj && !suppressWarnings ? schemaObj.tables : createTablesProxy(
10857
+ model,
10858
+ model.tables ? [...model.tables.keys()] : [],
10859
+ suppressWarnings ? { suppressWarnings } : void 0
10860
+ );
10819
10861
  return createOrmInstance(
10820
10862
  model,
10821
10863
  strictMode,
@@ -13071,6 +13113,7 @@ export {
13071
13113
  detectForeignKeys,
13072
13114
  detectManyToMany,
13073
13115
  distinct,
13116
+ emitWarning,
13074
13117
  eq,
13075
13118
  every,
13076
13119
  exists,