@proteinjs/db-driver-spanner 1.17.0 → 1.19.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.
@@ -12,7 +12,7 @@ import '@proteinjs/util';
12
12
  /** Generate Source Graph */
13
13
 
14
14
  const sourceGraph =
15
- '{"options":{"directed":true,"multigraph":false,"compound":false},"nodes":[{"v":"@proteinjs/db-driver-spanner/TestDbDriverFactory","value":{"packageName":"@proteinjs/db-driver-spanner","name":"TestDbDriverFactory","filePath":"/home/runner/work/db/db/packages/drivers/spanner/test/config/TestDbDriverFactory.ts","qualifiedName":"@proteinjs/db-driver-spanner/TestDbDriverFactory","isAbstract":false,"isStatic":false,"visibility":"public","properties":[],"methods":[{"name":"getDbDriver","returnType":{"packageName":"@proteinjs/db","name":"DbDriver","filePath":null,"qualifiedName":"@proteinjs/db/DbDriver","typeParameters":null,"directParents":null},"isAsync":false,"isOptional":false,"isAbstract":false,"isStatic":false,"visibility":"public","parameters":[]}],"typeParameters":[],"directParentInterfaces":[{"packageName":"@proteinjs/db","name":"DefaultDbDriverFactory","filePath":null,"qualifiedName":"@proteinjs/db/DefaultDbDriverFactory","properties":[],"methods":[],"typeParameters":[],"directParents":[]}],"directParentClasses":[],"sourceType":2}},{"v":"@proteinjs/db/DefaultDbDriverFactory"},{"v":"@proteinjs/db-driver-spanner/ServiceVerbsDoc","value":{"packageName":"@proteinjs/db-driver-spanner","name":"ServiceVerbsDoc","filePath":"/home/runner/work/db/db/packages/drivers/spanner/test/util/serviceUpdateVerbsTestTables.ts","qualifiedName":"@proteinjs/db-driver-spanner/ServiceVerbsDoc","properties":[{"name":"title","type":{"packageName":"","name":"string","filePath":null,"qualifiedName":"/string","typeParameters":null,"directParents":null},"isOptional":false,"isAbstract":false,"isStatic":false,"visibility":"public"},{"name":"scope","type":{"packageName":"","name":"string","filePath":null,"qualifiedName":"/string","typeParameters":null,"directParents":null},"isOptional":true,"isAbstract":false,"isStatic":false,"visibility":"public"},{"name":"members","type":{"packageName":"","name":"ReferenceArray<ServiceVerbsDoc>","filePath":null,"qualifiedName":"/ReferenceArray<ServiceVerbsDoc>","typeParameters":null,"directParents":null},"isOptional":true,"isAbstract":false,"isStatic":false,"visibility":"public"},{"name":"body","type":{"packageName":"@proteinjs/db-driver-spanner","name":"ServiceVerbsDocBody","filePath":null,"qualifiedName":"@proteinjs/db-driver-spanner/ServiceVerbsDocBody","typeParameters":null,"directParents":null},"isOptional":true,"isAbstract":false,"isStatic":false,"visibility":"public"}],"methods":[],"typeParameters":[],"directParents":[{"packageName":"@proteinjs/db","name":"Record","filePath":null,"qualifiedName":"@proteinjs/db/Record","properties":[],"methods":[],"typeParameters":[],"directParents":[]}],"sourceType":3}},{"v":"@proteinjs/db/Record"},{"v":"@proteinjs/db-driver-spanner/ServiceVerbsDocTable","value":{"packageName":"@proteinjs/db-driver-spanner","name":"ServiceVerbsDocTable","filePath":"/home/runner/work/db/db/packages/drivers/spanner/test/util/serviceUpdateVerbsTestTables.ts","qualifiedName":"@proteinjs/db-driver-spanner/ServiceVerbsDocTable","isAbstract":false,"isStatic":false,"visibility":"public","properties":[{"name":"name","type":null,"isOptional":false,"isAbstract":false,"isStatic":false,"visibility":"public"},{"name":"columns","type":null,"isOptional":false,"isAbstract":false,"isStatic":false,"visibility":"public"}],"methods":[],"typeParameters":[],"directParentInterfaces":[],"directParentClasses":[{"packageName":"@proteinjs/db","name":"Table","filePath":null,"qualifiedName":"@proteinjs/db/Table","isAbstract":false,"isStatic":false,"visibility":"public","properties":[],"methods":[],"typeParameters":["@proteinjs/db-driver-spanner/ServiceVerbsDoc"],"directParentInterfaces":[],"directParentClasses":[]}],"sourceType":2}},{"v":"@proteinjs/db/Table"},{"v":"@proteinjs/db-driver-spanner/SpannerDriver","value":{"packageName":"@proteinjs/db-driver-spanner","name":"SpannerDriver","filePath":"/home/runner/work/db/db/packages/drivers/spanner/src/SpannerDriver.ts","qualifiedName":"@proteinjs/db-driver-spanner/SpannerDriver","isAbstract":false,"isStatic":false,"visibility":"public","properties":[{"name":"SPANNER","type":{"packageName":"@google-cloud/spanner","name":"Spanner","filePath":null,"qualifiedName":"@google-cloud/spanner/Spanner","typeParameters":null,"directParents":null},"isOptional":true,"isAbstract":false,"isStatic":true,"visibility":"private"},{"name":"SPANNER_INSTANCE","type":{"packageName":"@google-cloud/spanner","name":"Instance","filePath":null,"qualifiedName":"@google-cloud/spanner/Instance","typeParameters":null,"directParents":null},"isOptional":true,"isAbstract":false,"isStatic":true,"visibility":"private"},{"name":"SPANNER_DB","type":{"packageName":"@google-cloud/spanner","name":"Database","filePath":null,"qualifiedName":"@google-cloud/spanner/Database","typeParameters":null,"directParents":null},"isOptional":true,"isAbstract":false,"isStatic":true,"visibility":"private"},{"name":"LIVENESS_MONITOR","type":{"packageName":"@proteinjs/db-driver-spanner","name":"SpannerLivenessMonitor","filePath":null,"qualifiedName":"@proteinjs/db-driver-spanner/SpannerLivenessMonitor","typeParameters":null,"directParents":null},"isOptional":false,"isAbstract":false,"isStatic":true,"visibility":"private"},{"name":"CLIENT_GENERATION","type":null,"isOptional":false,"isAbstract":false,"isStatic":true,"visibility":"private"},{"name":"CONSECUTIVE_DEADLINE_FAILURES","type":null,"isOptional":false,"isAbstract":false,"isStatic":true,"visibility":"private"},{"name":"logger","type":null,"isOptional":false,"isAbstract":false,"isStatic":false,"visibility":"private"},{"name":"config","type":{"packageName":"@proteinjs/db-driver-spanner","name":"SpannerConfig","filePath":null,"qualifiedName":"@proteinjs/db-driver-spanner/SpannerConfig","typeParameters":null,"directParents":null},"isOptional":false,"isAbstract":false,"isStatic":false,"visibility":"private"},{"name":"getTable","type":{"packageName":"","name":"((name: string) => Table<any>) | undefined","filePath":null,"qualifiedName":"/((name: string) => Table<any>) | undefined","typeParameters":null,"directParents":null},"isOptional":false,"isAbstract":false,"isStatic":false,"visibility":"public"}],"methods":[{"name":"getSpanner","returnType":{"packageName":"@google-cloud/spanner","name":"Spanner","filePath":null,"qualifiedName":"@google-cloud/spanner/Spanner","typeParameters":null,"directParents":null},"isAsync":false,"isOptional":false,"isAbstract":false,"isStatic":false,"visibility":"private","parameters":[]},{"name":"getSpannerInstance","returnType":{"packageName":"@google-cloud/spanner","name":"Instance","filePath":null,"qualifiedName":"@google-cloud/spanner/Instance","typeParameters":null,"directParents":null},"isAsync":false,"isOptional":false,"isAbstract":false,"isStatic":false,"visibility":"private","parameters":[]},{"name":"getSpannerDb","returnType":{"packageName":"@google-cloud/spanner","name":"Database","filePath":null,"qualifiedName":"@google-cloud/spanner/Database","typeParameters":null,"directParents":null},"isAsync":false,"isOptional":false,"isAbstract":false,"isStatic":false,"visibility":"private","parameters":[]},{"name":"getDbName","returnType":null,"isAsync":false,"isOptional":false,"isAbstract":false,"isStatic":false,"visibility":"public","parameters":[]},{"name":"getTableManager","returnType":{"packageName":"@proteinjs/db","name":"TableManager","filePath":null,"qualifiedName":"@proteinjs/db/TableManager","typeParameters":null,"directParents":null},"isAsync":false,"isOptional":false,"isAbstract":false,"isStatic":false,"visibility":"public","parameters":[]},{"name":"getColumnType","returnType":{"packageName":"","name":"string","filePath":null,"qualifiedName":"/string","typeParameters":null,"directParents":null},"isAsync":false,"isOptional":false,"isAbstract":false,"isStatic":false,"visibility":"public","parameters":[{"name":"tableName","type":{"packageName":"","name":"string","filePath":null,"qualifiedName":"/string","typeParameters":null,"directParents":null}},{"name":"columnName","type":{"packageName":"","name":"string","filePath":null,"qualifiedName":"/string","typeParameters":null,"directParents":null}}]},{"name":"handleCaseSensitivity","returnType":{"packageName":"","name":"string","filePath":null,"qualifiedName":"/string","typeParameters":null,"directParents":null},"isAsync":false,"isOptional":false,"isAbstract":false,"isStatic":false,"visibility":"public","parameters":[{"name":"tableName","type":{"packageName":"","name":"string","filePath":null,"qualifiedName":"/string","typeParameters":null,"directParents":null}},{"name":"columnName","type":{"packageName":"","name":"string","filePath":null,"qualifiedName":"/string","typeParameters":null,"directParents":null}},{"name":"caseSensitive","type":{"packageName":"","name":"boolean","filePath":null,"qualifiedName":"/boolean","typeParameters":null,"directParents":null}}]},{"name":"createDbIfNotExists","returnType":{"packageName":"","name":"Promise<void>","filePath":null,"qualifiedName":"/Promise<void>","typeParameters":null,"directParents":null},"isAsync":true,"isOptional":false,"isAbstract":false,"isStatic":false,"visibility":"public","parameters":[]},{"name":"dbExists","returnType":{"packageName":"","name":"Promise<boolean>","filePath":null,"qualifiedName":"/Promise<boolean>","typeParameters":null,"directParents":null},"isAsync":true,"isOptional":false,"isAbstract":false,"isStatic":false,"visibility":"private","parameters":[{"name":"databaseName","type":{"packageName":"","name":"string","filePath":null,"qualifiedName":"/string","typeParameters":null,"directParents":null}}]},{"name":"runQuery","returnType":{"packageName":"","name":"Promise<any[]>","filePath":null,"qualifiedName":"/Promise<any[]>","typeParameters":null,"directParents":null},"isAsync":true,"isOptional":false,"isAbstract":false,"isStatic":false,"visibility":"public","parameters":[{"name":"generateStatement","type":{"packageName":"","name":"(config: DbDriverQueryStatementConfig) => Statement","filePath":null,"qualifiedName":"/(config: DbDriverQueryStatementConfig) => Statement","typeParameters":null,"directParents":null}},{"name":"transaction","type":{"packageName":"@google-cloud/spanner","name":"Transaction","filePath":null,"qualifiedName":"@google-cloud/spanner/Transaction","typeParameters":null,"directParents":null}}]},{"name":"executeQuery","returnType":{"packageName":"","name":"Promise<any[]>","filePath":null,"qualifiedName":"/Promise<any[]>","typeParameters":null,"directParents":null},"isAsync":true,"isOptional":false,"isAbstract":false,"isStatic":false,"visibility":"private","parameters":[{"name":"generateStatement","type":{"packageName":"","name":"(config: DbDriverQueryStatementConfig) => Statement","filePath":null,"qualifiedName":"/(config: DbDriverQueryStatementConfig) => Statement","typeParameters":null,"directParents":null}},{"name":"runner","type":{"packageName":"","name":"Database | Transaction","filePath":null,"qualifiedName":"/Database | Transaction","typeParameters":null,"directParents":null}}]},{"name":"runDml","returnType":{"packageName":"","name":"Promise<number>","filePath":null,"qualifiedName":"/Promise<number>","typeParameters":null,"directParents":null},"isAsync":true,"isOptional":false,"isAbstract":false,"isStatic":false,"visibility":"public","parameters":[{"name":"generateStatement","type":{"packageName":"","name":"(config: DbDriverDmlStatementConfig) => Statement","filePath":null,"qualifiedName":"/(config: DbDriverDmlStatementConfig) => Statement","typeParameters":null,"directParents":null}},{"name":"transaction","type":{"packageName":"@google-cloud/spanner","name":"Transaction","filePath":null,"qualifiedName":"@google-cloud/spanner/Transaction","typeParameters":null,"directParents":null}}]},{"name":"executeDml","returnType":{"packageName":"","name":"Promise<number>","filePath":null,"qualifiedName":"/Promise<number>","typeParameters":null,"directParents":null},"isAsync":true,"isOptional":false,"isAbstract":false,"isStatic":false,"visibility":"private","parameters":[{"name":"generateStatement","type":{"packageName":"","name":"(config: DbDriverDmlStatementConfig) => Statement","filePath":null,"qualifiedName":"/(config: DbDriverDmlStatementConfig) => Statement","typeParameters":null,"directParents":null}},{"name":"runner","type":{"packageName":"@google-cloud/spanner","name":"Transaction","filePath":null,"qualifiedName":"@google-cloud/spanner/Transaction","typeParameters":null,"directParents":null}}]},{"name":"runTransaction","returnType":{"packageName":"","name":"Promise<T>","filePath":null,"qualifiedName":"/Promise<T>","typeParameters":null,"directParents":null},"isAsync":true,"isOptional":false,"isAbstract":false,"isStatic":false,"visibility":"public","parameters":[{"name":"fn","type":{"packageName":"","name":"(transaction: Transaction) => Promise<T>","filePath":null,"qualifiedName":"/(transaction: Transaction) => Promise<T>","typeParameters":null,"directParents":null}}]},{"name":"commit","returnType":{"packageName":"","name":"Promise<void>","filePath":null,"qualifiedName":"/Promise<void>","typeParameters":null,"directParents":null},"isAsync":true,"isOptional":false,"isAbstract":false,"isStatic":false,"visibility":"private","parameters":[{"name":"transaction","type":{"packageName":"@google-cloud/spanner","name":"Transaction","filePath":null,"qualifiedName":"@google-cloud/spanner/Transaction","typeParameters":null,"directParents":null}}]},{"name":"rollbackQuietly","returnType":{"packageName":"","name":"Promise<void>","filePath":null,"qualifiedName":"/Promise<void>","typeParameters":null,"directParents":null},"isAsync":true,"isOptional":false,"isAbstract":false,"isStatic":false,"visibility":"private","parameters":[{"name":"transaction","type":{"packageName":"@google-cloud/spanner","name":"Transaction","filePath":null,"qualifiedName":"@google-cloud/spanner/Transaction","typeParameters":null,"directParents":null}}]},{"name":"withDeadline","returnType":{"packageName":"","name":"Promise<T>","filePath":null,"qualifiedName":"/Promise<T>","typeParameters":null,"directParents":null},"isAsync":false,"isOptional":false,"isAbstract":false,"isStatic":false,"visibility":"private","parameters":[{"name":"op","type":{"packageName":"","name":"string","filePath":null,"qualifiedName":"/string","typeParameters":null,"directParents":null}},{"name":"sql","type":{"packageName":"","name":"string","filePath":null,"qualifiedName":"/string","typeParameters":null,"directParents":null}},{"name":"promise","type":{"packageName":"","name":"PromiseLike<T>","filePath":null,"qualifiedName":"/PromiseLike<T>","typeParameters":null,"directParents":null}}]},{"name":"recordOpSuccess","returnType":{"packageName":"","name":"void","filePath":null,"qualifiedName":"/void","typeParameters":null,"directParents":null},"isAsync":false,"isOptional":false,"isAbstract":false,"isStatic":false,"visibility":"private","parameters":[{"name":"generation","type":{"packageName":"","name":"number","filePath":null,"qualifiedName":"/number","typeParameters":null,"directParents":null}}]},{"name":"recordDeadlineFailure","returnType":{"packageName":"","name":"void","filePath":null,"qualifiedName":"/void","typeParameters":null,"directParents":null},"isAsync":false,"isOptional":false,"isAbstract":false,"isStatic":false,"visibility":"private","parameters":[{"name":"generation","type":{"packageName":"","name":"number","filePath":null,"qualifiedName":"/number","typeParameters":null,"directParents":null}}]},{"name":"recycleClient","returnType":{"packageName":"","name":"void","filePath":null,"qualifiedName":"/void","typeParameters":null,"directParents":null},"isAsync":false,"isOptional":false,"isAbstract":false,"isStatic":false,"visibility":"private","parameters":[]},{"name":"operationDeadlineMs","returnType":{"packageName":"","name":"number","filePath":null,"qualifiedName":"/number","typeParameters":null,"directParents":null},"isAsync":false,"isOptional":false,"isAbstract":false,"isStatic":false,"visibility":"private","parameters":[]},{"name":"deadlineFailuresBeforeRecycle","returnType":{"packageName":"","name":"number","filePath":null,"qualifiedName":"/number","typeParameters":null,"directParents":null},"isAsync":false,"isOptional":false,"isAbstract":false,"isStatic":false,"visibility":"private","parameters":[]},{"name":"runUpdateSchema","returnType":{"packageName":"","name":"Promise<void>","filePath":null,"qualifiedName":"/Promise<void>","typeParameters":null,"directParents":null},"isAsync":true,"isOptional":false,"isAbstract":false,"isStatic":false,"visibility":"public","parameters":[{"name":"sql","type":{"packageName":"","name":"string","filePath":null,"qualifiedName":"/string","typeParameters":null,"directParents":null}}]}],"typeParameters":[],"directParentInterfaces":[{"packageName":"@proteinjs/db","name":"DbDriver","filePath":null,"qualifiedName":"@proteinjs/db/DbDriver","properties":[],"methods":[],"typeParameters":[],"directParents":[]}],"directParentClasses":[],"sourceType":2}},{"v":"@proteinjs/db/DbDriver"},{"v":"@proteinjs/db-driver-spanner/SpannerSchemaMetadata","value":{"packageName":"@proteinjs/db-driver-spanner","name":"SpannerSchemaMetadata","filePath":"/home/runner/work/db/db/packages/drivers/spanner/src/SpannerSchemaMetadata.ts","qualifiedName":"@proteinjs/db-driver-spanner/SpannerSchemaMetadata","isAbstract":false,"isStatic":false,"visibility":"public","properties":[],"methods":[{"name":"tableExists","returnType":{"packageName":"","name":"Promise<boolean>","filePath":null,"qualifiedName":"/Promise<boolean>","typeParameters":null,"directParents":null},"isAsync":true,"isOptional":false,"isAbstract":false,"isStatic":false,"visibility":"public","parameters":[{"name":"table","type":{"packageName":"","name":"Table<any>","filePath":null,"qualifiedName":"/Table<any>","typeParameters":null,"directParents":null}}]},{"name":"getColumnMetadata","returnType":{"packageName":"","name":"Promise<{ [columnName: string]: { type: string; isNullable: boolean } }>","filePath":null,"qualifiedName":"/Promise<{ [columnName: string]: { type: string; isNullable: boolean } }>","typeParameters":null,"directParents":null},"isAsync":true,"isOptional":false,"isAbstract":false,"isStatic":false,"visibility":"public","parameters":[{"name":"table","type":{"packageName":"","name":"Table<any>","filePath":null,"qualifiedName":"/Table<any>","typeParameters":null,"directParents":null}}]},{"name":"getPrimaryKey","returnType":{"packageName":"","name":"Promise<string[]>","filePath":null,"qualifiedName":"/Promise<string[]>","typeParameters":null,"directParents":null},"isAsync":true,"isOptional":false,"isAbstract":false,"isStatic":false,"visibility":"public","parameters":[{"name":"table","type":{"packageName":"","name":"Table<any>","filePath":null,"qualifiedName":"/Table<any>","typeParameters":null,"directParents":null}}]},{"name":"getForeignKeys","returnType":{"packageName":"","name":"Promise<{ [columnName: string]: { referencedTableName: string; referencedColumnName: string } }>","filePath":null,"qualifiedName":"/Promise<{ [columnName: string]: { referencedTableName: string; referencedColumnName: string } }>","typeParameters":null,"directParents":null},"isAsync":true,"isOptional":false,"isAbstract":false,"isStatic":false,"visibility":"public","parameters":[{"name":"table","type":{"packageName":"","name":"Table<any>","filePath":null,"qualifiedName":"/Table<any>","typeParameters":null,"directParents":null}}]},{"name":"getUniqueColumns","returnType":{"packageName":"","name":"Promise<string[]>","filePath":null,"qualifiedName":"/Promise<string[]>","typeParameters":null,"directParents":null},"isAsync":true,"isOptional":false,"isAbstract":false,"isStatic":false,"visibility":"public","parameters":[{"name":"table","type":{"packageName":"","name":"Table<any>","filePath":null,"qualifiedName":"/Table<any>","typeParameters":null,"directParents":null}}]},{"name":"getIndexes","returnType":{"packageName":"","name":"Promise<{ [keyName: string]: string[] }>","filePath":null,"qualifiedName":"/Promise<{ [keyName: string]: string[] }>","typeParameters":null,"directParents":null},"isAsync":true,"isOptional":false,"isAbstract":false,"isStatic":false,"visibility":"public","parameters":[{"name":"table","type":{"packageName":"","name":"Table<any>","filePath":null,"qualifiedName":"/Table<any>","typeParameters":null,"directParents":null}}]}],"typeParameters":[],"directParentInterfaces":[],"directParentClasses":[{"packageName":"@proteinjs/db","name":"SchemaMetadata","filePath":null,"qualifiedName":"@proteinjs/db/SchemaMetadata","isAbstract":false,"isStatic":false,"visibility":"public","properties":[],"methods":[],"typeParameters":[],"directParentInterfaces":[],"directParentClasses":[]}],"sourceType":2}},{"v":"@proteinjs/db/SchemaMetadata"},{"v":"@proteinjs/db-driver-spanner/SpannerSchemaOperations","value":{"packageName":"@proteinjs/db-driver-spanner","name":"SpannerSchemaOperations","filePath":"/home/runner/work/db/db/packages/drivers/spanner/src/SpannerSchemaOperations.ts","qualifiedName":"@proteinjs/db-driver-spanner/SpannerSchemaOperations","isAbstract":false,"isStatic":false,"visibility":"public","properties":[{"name":"logger","type":null,"isOptional":false,"isAbstract":false,"isStatic":false,"visibility":"private"},{"name":"spannerDriver","type":{"packageName":"@proteinjs/db-driver-spanner","name":"SpannerDriver","filePath":null,"qualifiedName":"@proteinjs/db-driver-spanner/SpannerDriver","typeParameters":null,"directParents":null},"isOptional":false,"isAbstract":false,"isStatic":false,"visibility":"private"}],"methods":[{"name":"createTable","returnType":null,"isAsync":true,"isOptional":false,"isAbstract":false,"isStatic":false,"visibility":"public","parameters":[{"name":"table","type":{"packageName":"","name":"Table<any>","filePath":null,"qualifiedName":"/Table<any>","typeParameters":null,"directParents":null}}]},{"name":"alterTable","returnType":null,"isAsync":true,"isOptional":false,"isAbstract":false,"isStatic":false,"visibility":"public","parameters":[{"name":"table","type":{"packageName":"","name":"Table<any>","filePath":null,"qualifiedName":"/Table<any>","typeParameters":null,"directParents":null}},{"name":"tableChanges","type":{"packageName":"@proteinjs/db","name":"TableChanges","filePath":null,"qualifiedName":"@proteinjs/db/TableChanges","typeParameters":null,"directParents":null}}]},{"name":"stringWideningStatement","returnType":{"packageName":"","name":"string | null","filePath":null,"qualifiedName":"/string | null","typeParameters":null,"directParents":null},"isAsync":false,"isOptional":false,"isAbstract":false,"isStatic":false,"visibility":"private","parameters":[{"name":"table","type":{"packageName":"","name":"Table<any>","filePath":null,"qualifiedName":"/Table<any>","typeParameters":null,"directParents":null}},{"name":"change","type":{"packageName":"@proteinjs/db-driver-spanner","name":"{ name: string; newType: string; oldType: string }","filePath":null,"qualifiedName":"@proteinjs/db-driver-spanner/{ name: string; newType: string; oldType: string }","typeParameters":null,"directParents":null}}]}],"typeParameters":[],"directParentInterfaces":[{"packageName":"@proteinjs/db","name":"SchemaOperations","filePath":null,"qualifiedName":"@proteinjs/db/SchemaOperations","properties":[],"methods":[],"typeParameters":[],"directParents":[]}],"directParentClasses":[],"sourceType":2}},{"v":"@proteinjs/db/SchemaOperations"}],"edges":[{"v":"@proteinjs/db-driver-spanner/TestDbDriverFactory","w":"@proteinjs/db/DefaultDbDriverFactory","value":"implements interface"},{"v":"@proteinjs/db-driver-spanner/ServiceVerbsDoc","w":"@proteinjs/db/Record","value":"extends interface"},{"v":"@proteinjs/db-driver-spanner/ServiceVerbsDocTable","w":"@proteinjs/db/Table","value":"extends class"},{"v":"@proteinjs/db-driver-spanner/SpannerDriver","w":"@proteinjs/db/DbDriver","value":"implements interface"},{"v":"@proteinjs/db-driver-spanner/SpannerSchemaMetadata","w":"@proteinjs/db/SchemaMetadata","value":"extends class"},{"v":"@proteinjs/db-driver-spanner/SpannerSchemaOperations","w":"@proteinjs/db/SchemaOperations","value":"implements interface"}]}';
15
+ '{"options":{"directed":true,"multigraph":false,"compound":false},"nodes":[{"v":"@proteinjs/db-driver-spanner/TestDbDriverFactory","value":{"packageName":"@proteinjs/db-driver-spanner","name":"TestDbDriverFactory","filePath":"/home/runner/work/db/db/packages/drivers/spanner/test/config/TestDbDriverFactory.ts","qualifiedName":"@proteinjs/db-driver-spanner/TestDbDriverFactory","isAbstract":false,"isStatic":false,"visibility":"public","properties":[],"methods":[{"name":"getDbDriver","returnType":{"packageName":"@proteinjs/db","name":"DbDriver","filePath":null,"qualifiedName":"@proteinjs/db/DbDriver","typeParameters":null,"directParents":null},"isAsync":false,"isOptional":false,"isAbstract":false,"isStatic":false,"visibility":"public","parameters":[]}],"typeParameters":[],"directParentInterfaces":[{"packageName":"@proteinjs/db","name":"DefaultDbDriverFactory","filePath":null,"qualifiedName":"@proteinjs/db/DefaultDbDriverFactory","properties":[],"methods":[],"typeParameters":[],"directParents":[]}],"directParentClasses":[],"sourceType":2}},{"v":"@proteinjs/db/DefaultDbDriverFactory"},{"v":"@proteinjs/db-driver-spanner/ServiceVerbsDoc","value":{"packageName":"@proteinjs/db-driver-spanner","name":"ServiceVerbsDoc","filePath":"/home/runner/work/db/db/packages/drivers/spanner/test/util/serviceUpdateVerbsTestTables.ts","qualifiedName":"@proteinjs/db-driver-spanner/ServiceVerbsDoc","properties":[{"name":"title","type":{"packageName":"","name":"string","filePath":null,"qualifiedName":"/string","typeParameters":null,"directParents":null},"isOptional":false,"isAbstract":false,"isStatic":false,"visibility":"public"},{"name":"scope","type":{"packageName":"","name":"string","filePath":null,"qualifiedName":"/string","typeParameters":null,"directParents":null},"isOptional":true,"isAbstract":false,"isStatic":false,"visibility":"public"},{"name":"members","type":{"packageName":"","name":"ReferenceArray<ServiceVerbsDoc>","filePath":null,"qualifiedName":"/ReferenceArray<ServiceVerbsDoc>","typeParameters":null,"directParents":null},"isOptional":true,"isAbstract":false,"isStatic":false,"visibility":"public"},{"name":"body","type":{"packageName":"@proteinjs/db-driver-spanner","name":"ServiceVerbsDocBody","filePath":null,"qualifiedName":"@proteinjs/db-driver-spanner/ServiceVerbsDocBody","typeParameters":null,"directParents":null},"isOptional":true,"isAbstract":false,"isStatic":false,"visibility":"public"}],"methods":[],"typeParameters":[],"directParents":[{"packageName":"@proteinjs/db","name":"Record","filePath":null,"qualifiedName":"@proteinjs/db/Record","properties":[],"methods":[],"typeParameters":[],"directParents":[]}],"sourceType":3}},{"v":"@proteinjs/db/Record"},{"v":"@proteinjs/db-driver-spanner/ServiceVerbsDocTable","value":{"packageName":"@proteinjs/db-driver-spanner","name":"ServiceVerbsDocTable","filePath":"/home/runner/work/db/db/packages/drivers/spanner/test/util/serviceUpdateVerbsTestTables.ts","qualifiedName":"@proteinjs/db-driver-spanner/ServiceVerbsDocTable","isAbstract":false,"isStatic":false,"visibility":"public","properties":[{"name":"name","type":null,"isOptional":false,"isAbstract":false,"isStatic":false,"visibility":"public"},{"name":"columns","type":null,"isOptional":false,"isAbstract":false,"isStatic":false,"visibility":"public"}],"methods":[],"typeParameters":[],"directParentInterfaces":[],"directParentClasses":[{"packageName":"@proteinjs/db","name":"Table","filePath":null,"qualifiedName":"@proteinjs/db/Table","isAbstract":false,"isStatic":false,"visibility":"public","properties":[],"methods":[],"typeParameters":["@proteinjs/db-driver-spanner/ServiceVerbsDoc"],"directParentInterfaces":[],"directParentClasses":[]}],"sourceType":2}},{"v":"@proteinjs/db/Table"},{"v":"@proteinjs/db-driver-spanner/SpannerDriver","value":{"packageName":"@proteinjs/db-driver-spanner","name":"SpannerDriver","filePath":"/home/runner/work/db/db/packages/drivers/spanner/src/SpannerDriver.ts","qualifiedName":"@proteinjs/db-driver-spanner/SpannerDriver","isAbstract":false,"isStatic":false,"visibility":"public","properties":[{"name":"SPANNER","type":{"packageName":"@google-cloud/spanner","name":"Spanner","filePath":null,"qualifiedName":"@google-cloud/spanner/Spanner","typeParameters":null,"directParents":null},"isOptional":true,"isAbstract":false,"isStatic":true,"visibility":"private"},{"name":"SPANNER_INSTANCE","type":{"packageName":"@google-cloud/spanner","name":"Instance","filePath":null,"qualifiedName":"@google-cloud/spanner/Instance","typeParameters":null,"directParents":null},"isOptional":true,"isAbstract":false,"isStatic":true,"visibility":"private"},{"name":"SPANNER_DB","type":{"packageName":"@google-cloud/spanner","name":"Database","filePath":null,"qualifiedName":"@google-cloud/spanner/Database","typeParameters":null,"directParents":null},"isOptional":true,"isAbstract":false,"isStatic":true,"visibility":"private"},{"name":"LIVENESS_MONITOR","type":{"packageName":"@proteinjs/db-driver-spanner","name":"SpannerLivenessMonitor","filePath":null,"qualifiedName":"@proteinjs/db-driver-spanner/SpannerLivenessMonitor","typeParameters":null,"directParents":null},"isOptional":false,"isAbstract":false,"isStatic":true,"visibility":"private"},{"name":"CLIENT_GENERATION","type":null,"isOptional":false,"isAbstract":false,"isStatic":true,"visibility":"private"},{"name":"CONSECUTIVE_DEADLINE_FAILURES","type":null,"isOptional":false,"isAbstract":false,"isStatic":true,"visibility":"private"},{"name":"logger","type":null,"isOptional":false,"isAbstract":false,"isStatic":false,"visibility":"private"},{"name":"config","type":{"packageName":"@proteinjs/db-driver-spanner","name":"SpannerConfig","filePath":null,"qualifiedName":"@proteinjs/db-driver-spanner/SpannerConfig","typeParameters":null,"directParents":null},"isOptional":false,"isAbstract":false,"isStatic":false,"visibility":"private"},{"name":"getTable","type":{"packageName":"","name":"((name: string) => Table<any>) | undefined","filePath":null,"qualifiedName":"/((name: string) => Table<any>) | undefined","typeParameters":null,"directParents":null},"isOptional":false,"isAbstract":false,"isStatic":false,"visibility":"public"}],"methods":[{"name":"getSessionPoolStats","returnType":{"packageName":"","name":"SpannerSessionPoolStats | undefined","filePath":null,"qualifiedName":"/SpannerSessionPoolStats | undefined","typeParameters":null,"directParents":null},"isAsync":false,"isOptional":false,"isAbstract":false,"isStatic":true,"visibility":"public","parameters":[]},{"name":"getSpanner","returnType":{"packageName":"@google-cloud/spanner","name":"Spanner","filePath":null,"qualifiedName":"@google-cloud/spanner/Spanner","typeParameters":null,"directParents":null},"isAsync":false,"isOptional":false,"isAbstract":false,"isStatic":false,"visibility":"private","parameters":[]},{"name":"getSpannerInstance","returnType":{"packageName":"@google-cloud/spanner","name":"Instance","filePath":null,"qualifiedName":"@google-cloud/spanner/Instance","typeParameters":null,"directParents":null},"isAsync":false,"isOptional":false,"isAbstract":false,"isStatic":false,"visibility":"private","parameters":[]},{"name":"getSpannerDb","returnType":{"packageName":"@google-cloud/spanner","name":"Database","filePath":null,"qualifiedName":"@google-cloud/spanner/Database","typeParameters":null,"directParents":null},"isAsync":false,"isOptional":false,"isAbstract":false,"isStatic":false,"visibility":"private","parameters":[]},{"name":"getDbName","returnType":null,"isAsync":false,"isOptional":false,"isAbstract":false,"isStatic":false,"visibility":"public","parameters":[]},{"name":"getTableManager","returnType":{"packageName":"@proteinjs/db","name":"TableManager","filePath":null,"qualifiedName":"@proteinjs/db/TableManager","typeParameters":null,"directParents":null},"isAsync":false,"isOptional":false,"isAbstract":false,"isStatic":false,"visibility":"public","parameters":[]},{"name":"getColumnType","returnType":{"packageName":"","name":"string","filePath":null,"qualifiedName":"/string","typeParameters":null,"directParents":null},"isAsync":false,"isOptional":false,"isAbstract":false,"isStatic":false,"visibility":"public","parameters":[{"name":"tableName","type":{"packageName":"","name":"string","filePath":null,"qualifiedName":"/string","typeParameters":null,"directParents":null}},{"name":"columnName","type":{"packageName":"","name":"string","filePath":null,"qualifiedName":"/string","typeParameters":null,"directParents":null}}]},{"name":"handleCaseSensitivity","returnType":{"packageName":"","name":"string","filePath":null,"qualifiedName":"/string","typeParameters":null,"directParents":null},"isAsync":false,"isOptional":false,"isAbstract":false,"isStatic":false,"visibility":"public","parameters":[{"name":"tableName","type":{"packageName":"","name":"string","filePath":null,"qualifiedName":"/string","typeParameters":null,"directParents":null}},{"name":"columnName","type":{"packageName":"","name":"string","filePath":null,"qualifiedName":"/string","typeParameters":null,"directParents":null}},{"name":"caseSensitive","type":{"packageName":"","name":"boolean","filePath":null,"qualifiedName":"/boolean","typeParameters":null,"directParents":null}}]},{"name":"createDbIfNotExists","returnType":{"packageName":"","name":"Promise<void>","filePath":null,"qualifiedName":"/Promise<void>","typeParameters":null,"directParents":null},"isAsync":true,"isOptional":false,"isAbstract":false,"isStatic":false,"visibility":"public","parameters":[]},{"name":"dbExists","returnType":{"packageName":"","name":"Promise<boolean>","filePath":null,"qualifiedName":"/Promise<boolean>","typeParameters":null,"directParents":null},"isAsync":true,"isOptional":false,"isAbstract":false,"isStatic":false,"visibility":"private","parameters":[{"name":"databaseName","type":{"packageName":"","name":"string","filePath":null,"qualifiedName":"/string","typeParameters":null,"directParents":null}}]},{"name":"runQuery","returnType":{"packageName":"","name":"Promise<any[]>","filePath":null,"qualifiedName":"/Promise<any[]>","typeParameters":null,"directParents":null},"isAsync":true,"isOptional":false,"isAbstract":false,"isStatic":false,"visibility":"public","parameters":[{"name":"generateStatement","type":{"packageName":"","name":"(config: DbDriverQueryStatementConfig) => Statement","filePath":null,"qualifiedName":"/(config: DbDriverQueryStatementConfig) => Statement","typeParameters":null,"directParents":null}},{"name":"transaction","type":{"packageName":"@google-cloud/spanner","name":"Transaction","filePath":null,"qualifiedName":"@google-cloud/spanner/Transaction","typeParameters":null,"directParents":null}}]},{"name":"executeQuery","returnType":{"packageName":"","name":"Promise<any[]>","filePath":null,"qualifiedName":"/Promise<any[]>","typeParameters":null,"directParents":null},"isAsync":true,"isOptional":false,"isAbstract":false,"isStatic":false,"visibility":"private","parameters":[{"name":"generateStatement","type":{"packageName":"","name":"(config: DbDriverQueryStatementConfig) => Statement","filePath":null,"qualifiedName":"/(config: DbDriverQueryStatementConfig) => Statement","typeParameters":null,"directParents":null}},{"name":"runner","type":{"packageName":"","name":"Database | Transaction","filePath":null,"qualifiedName":"/Database | Transaction","typeParameters":null,"directParents":null}}]},{"name":"runDml","returnType":{"packageName":"","name":"Promise<number>","filePath":null,"qualifiedName":"/Promise<number>","typeParameters":null,"directParents":null},"isAsync":true,"isOptional":false,"isAbstract":false,"isStatic":false,"visibility":"public","parameters":[{"name":"generateStatement","type":{"packageName":"","name":"(config: DbDriverDmlStatementConfig) => Statement","filePath":null,"qualifiedName":"/(config: DbDriverDmlStatementConfig) => Statement","typeParameters":null,"directParents":null}},{"name":"transaction","type":{"packageName":"@google-cloud/spanner","name":"Transaction","filePath":null,"qualifiedName":"@google-cloud/spanner/Transaction","typeParameters":null,"directParents":null}}]},{"name":"executeDml","returnType":{"packageName":"","name":"Promise<number>","filePath":null,"qualifiedName":"/Promise<number>","typeParameters":null,"directParents":null},"isAsync":true,"isOptional":false,"isAbstract":false,"isStatic":false,"visibility":"private","parameters":[{"name":"generateStatement","type":{"packageName":"","name":"(config: DbDriverDmlStatementConfig) => Statement","filePath":null,"qualifiedName":"/(config: DbDriverDmlStatementConfig) => Statement","typeParameters":null,"directParents":null}},{"name":"runner","type":{"packageName":"@google-cloud/spanner","name":"Transaction","filePath":null,"qualifiedName":"@google-cloud/spanner/Transaction","typeParameters":null,"directParents":null}}]},{"name":"runTransaction","returnType":{"packageName":"","name":"Promise<T>","filePath":null,"qualifiedName":"/Promise<T>","typeParameters":null,"directParents":null},"isAsync":true,"isOptional":false,"isAbstract":false,"isStatic":false,"visibility":"public","parameters":[{"name":"fn","type":{"packageName":"","name":"(transaction: Transaction) => Promise<T>","filePath":null,"qualifiedName":"/(transaction: Transaction) => Promise<T>","typeParameters":null,"directParents":null}}]},{"name":"commit","returnType":{"packageName":"","name":"Promise<void>","filePath":null,"qualifiedName":"/Promise<void>","typeParameters":null,"directParents":null},"isAsync":true,"isOptional":false,"isAbstract":false,"isStatic":false,"visibility":"private","parameters":[{"name":"transaction","type":{"packageName":"@google-cloud/spanner","name":"Transaction","filePath":null,"qualifiedName":"@google-cloud/spanner/Transaction","typeParameters":null,"directParents":null}}]},{"name":"rollbackQuietly","returnType":{"packageName":"","name":"Promise<void>","filePath":null,"qualifiedName":"/Promise<void>","typeParameters":null,"directParents":null},"isAsync":true,"isOptional":false,"isAbstract":false,"isStatic":false,"visibility":"private","parameters":[{"name":"transaction","type":{"packageName":"@google-cloud/spanner","name":"Transaction","filePath":null,"qualifiedName":"@google-cloud/spanner/Transaction","typeParameters":null,"directParents":null}}]},{"name":"withDeadline","returnType":{"packageName":"","name":"Promise<T>","filePath":null,"qualifiedName":"/Promise<T>","typeParameters":null,"directParents":null},"isAsync":false,"isOptional":false,"isAbstract":false,"isStatic":false,"visibility":"private","parameters":[{"name":"op","type":{"packageName":"","name":"string","filePath":null,"qualifiedName":"/string","typeParameters":null,"directParents":null}},{"name":"sql","type":{"packageName":"","name":"string","filePath":null,"qualifiedName":"/string","typeParameters":null,"directParents":null}},{"name":"promise","type":{"packageName":"","name":"PromiseLike<T>","filePath":null,"qualifiedName":"/PromiseLike<T>","typeParameters":null,"directParents":null}}]},{"name":"recordOpSuccess","returnType":{"packageName":"","name":"void","filePath":null,"qualifiedName":"/void","typeParameters":null,"directParents":null},"isAsync":false,"isOptional":false,"isAbstract":false,"isStatic":false,"visibility":"private","parameters":[{"name":"generation","type":{"packageName":"","name":"number","filePath":null,"qualifiedName":"/number","typeParameters":null,"directParents":null}}]},{"name":"recordDeadlineFailure","returnType":{"packageName":"","name":"void","filePath":null,"qualifiedName":"/void","typeParameters":null,"directParents":null},"isAsync":false,"isOptional":false,"isAbstract":false,"isStatic":false,"visibility":"private","parameters":[{"name":"generation","type":{"packageName":"","name":"number","filePath":null,"qualifiedName":"/number","typeParameters":null,"directParents":null}}]},{"name":"recycleClient","returnType":{"packageName":"","name":"void","filePath":null,"qualifiedName":"/void","typeParameters":null,"directParents":null},"isAsync":false,"isOptional":false,"isAbstract":false,"isStatic":false,"visibility":"private","parameters":[]},{"name":"dmlGaxOptions","returnType":{"packageName":"@proteinjs/db-driver-spanner","name":"{ timeout: number; retry?: null }","filePath":null,"qualifiedName":"@proteinjs/db-driver-spanner/{ timeout: number; retry?: null }","typeParameters":null,"directParents":null},"isAsync":false,"isOptional":false,"isAbstract":false,"isStatic":false,"visibility":"private","parameters":[]},{"name":"operationDeadlineMs","returnType":{"packageName":"","name":"number","filePath":null,"qualifiedName":"/number","typeParameters":null,"directParents":null},"isAsync":false,"isOptional":false,"isAbstract":false,"isStatic":false,"visibility":"private","parameters":[]},{"name":"deadlineFailuresBeforeRecycle","returnType":{"packageName":"","name":"number","filePath":null,"qualifiedName":"/number","typeParameters":null,"directParents":null},"isAsync":false,"isOptional":false,"isAbstract":false,"isStatic":false,"visibility":"private","parameters":[]},{"name":"runUpdateSchema","returnType":{"packageName":"","name":"Promise<void>","filePath":null,"qualifiedName":"/Promise<void>","typeParameters":null,"directParents":null},"isAsync":true,"isOptional":false,"isAbstract":false,"isStatic":false,"visibility":"public","parameters":[{"name":"sql","type":{"packageName":"","name":"string","filePath":null,"qualifiedName":"/string","typeParameters":null,"directParents":null}}]}],"typeParameters":[],"directParentInterfaces":[{"packageName":"@proteinjs/db","name":"DbDriver","filePath":null,"qualifiedName":"@proteinjs/db/DbDriver","properties":[],"methods":[],"typeParameters":[],"directParents":[]}],"directParentClasses":[],"sourceType":2}},{"v":"@proteinjs/db/DbDriver"},{"v":"@proteinjs/db-driver-spanner/SpannerSchemaMetadata","value":{"packageName":"@proteinjs/db-driver-spanner","name":"SpannerSchemaMetadata","filePath":"/home/runner/work/db/db/packages/drivers/spanner/src/SpannerSchemaMetadata.ts","qualifiedName":"@proteinjs/db-driver-spanner/SpannerSchemaMetadata","isAbstract":false,"isStatic":false,"visibility":"public","properties":[],"methods":[{"name":"tableExists","returnType":{"packageName":"","name":"Promise<boolean>","filePath":null,"qualifiedName":"/Promise<boolean>","typeParameters":null,"directParents":null},"isAsync":true,"isOptional":false,"isAbstract":false,"isStatic":false,"visibility":"public","parameters":[{"name":"table","type":{"packageName":"","name":"Table<any>","filePath":null,"qualifiedName":"/Table<any>","typeParameters":null,"directParents":null}}]},{"name":"getColumnMetadata","returnType":{"packageName":"","name":"Promise<{ [columnName: string]: { type: string; isNullable: boolean } }>","filePath":null,"qualifiedName":"/Promise<{ [columnName: string]: { type: string; isNullable: boolean } }>","typeParameters":null,"directParents":null},"isAsync":true,"isOptional":false,"isAbstract":false,"isStatic":false,"visibility":"public","parameters":[{"name":"table","type":{"packageName":"","name":"Table<any>","filePath":null,"qualifiedName":"/Table<any>","typeParameters":null,"directParents":null}}]},{"name":"getPrimaryKey","returnType":{"packageName":"","name":"Promise<string[]>","filePath":null,"qualifiedName":"/Promise<string[]>","typeParameters":null,"directParents":null},"isAsync":true,"isOptional":false,"isAbstract":false,"isStatic":false,"visibility":"public","parameters":[{"name":"table","type":{"packageName":"","name":"Table<any>","filePath":null,"qualifiedName":"/Table<any>","typeParameters":null,"directParents":null}}]},{"name":"getForeignKeys","returnType":{"packageName":"","name":"Promise<{ [columnName: string]: { referencedTableName: string; referencedColumnName: string } }>","filePath":null,"qualifiedName":"/Promise<{ [columnName: string]: { referencedTableName: string; referencedColumnName: string } }>","typeParameters":null,"directParents":null},"isAsync":true,"isOptional":false,"isAbstract":false,"isStatic":false,"visibility":"public","parameters":[{"name":"table","type":{"packageName":"","name":"Table<any>","filePath":null,"qualifiedName":"/Table<any>","typeParameters":null,"directParents":null}}]},{"name":"getUniqueColumns","returnType":{"packageName":"","name":"Promise<string[]>","filePath":null,"qualifiedName":"/Promise<string[]>","typeParameters":null,"directParents":null},"isAsync":true,"isOptional":false,"isAbstract":false,"isStatic":false,"visibility":"public","parameters":[{"name":"table","type":{"packageName":"","name":"Table<any>","filePath":null,"qualifiedName":"/Table<any>","typeParameters":null,"directParents":null}}]},{"name":"getIndexes","returnType":{"packageName":"","name":"Promise<{ [keyName: string]: string[] }>","filePath":null,"qualifiedName":"/Promise<{ [keyName: string]: string[] }>","typeParameters":null,"directParents":null},"isAsync":true,"isOptional":false,"isAbstract":false,"isStatic":false,"visibility":"public","parameters":[{"name":"table","type":{"packageName":"","name":"Table<any>","filePath":null,"qualifiedName":"/Table<any>","typeParameters":null,"directParents":null}}]}],"typeParameters":[],"directParentInterfaces":[],"directParentClasses":[{"packageName":"@proteinjs/db","name":"SchemaMetadata","filePath":null,"qualifiedName":"@proteinjs/db/SchemaMetadata","isAbstract":false,"isStatic":false,"visibility":"public","properties":[],"methods":[],"typeParameters":[],"directParentInterfaces":[],"directParentClasses":[]}],"sourceType":2}},{"v":"@proteinjs/db/SchemaMetadata"},{"v":"@proteinjs/db-driver-spanner/SpannerSchemaOperations","value":{"packageName":"@proteinjs/db-driver-spanner","name":"SpannerSchemaOperations","filePath":"/home/runner/work/db/db/packages/drivers/spanner/src/SpannerSchemaOperations.ts","qualifiedName":"@proteinjs/db-driver-spanner/SpannerSchemaOperations","isAbstract":false,"isStatic":false,"visibility":"public","properties":[{"name":"logger","type":null,"isOptional":false,"isAbstract":false,"isStatic":false,"visibility":"private"},{"name":"spannerDriver","type":{"packageName":"@proteinjs/db-driver-spanner","name":"SpannerDriver","filePath":null,"qualifiedName":"@proteinjs/db-driver-spanner/SpannerDriver","typeParameters":null,"directParents":null},"isOptional":false,"isAbstract":false,"isStatic":false,"visibility":"private"}],"methods":[{"name":"createTable","returnType":null,"isAsync":true,"isOptional":false,"isAbstract":false,"isStatic":false,"visibility":"public","parameters":[{"name":"table","type":{"packageName":"","name":"Table<any>","filePath":null,"qualifiedName":"/Table<any>","typeParameters":null,"directParents":null}}]},{"name":"alterTable","returnType":null,"isAsync":true,"isOptional":false,"isAbstract":false,"isStatic":false,"visibility":"public","parameters":[{"name":"table","type":{"packageName":"","name":"Table<any>","filePath":null,"qualifiedName":"/Table<any>","typeParameters":null,"directParents":null}},{"name":"tableChanges","type":{"packageName":"@proteinjs/db","name":"TableChanges","filePath":null,"qualifiedName":"@proteinjs/db/TableChanges","typeParameters":null,"directParents":null}}]},{"name":"stringWideningStatement","returnType":{"packageName":"","name":"string | null","filePath":null,"qualifiedName":"/string | null","typeParameters":null,"directParents":null},"isAsync":false,"isOptional":false,"isAbstract":false,"isStatic":false,"visibility":"private","parameters":[{"name":"table","type":{"packageName":"","name":"Table<any>","filePath":null,"qualifiedName":"/Table<any>","typeParameters":null,"directParents":null}},{"name":"change","type":{"packageName":"@proteinjs/db-driver-spanner","name":"{ name: string; newType: string; oldType: string }","filePath":null,"qualifiedName":"@proteinjs/db-driver-spanner/{ name: string; newType: string; oldType: string }","typeParameters":null,"directParents":null}}]}],"typeParameters":[],"directParentInterfaces":[{"packageName":"@proteinjs/db","name":"SchemaOperations","filePath":null,"qualifiedName":"@proteinjs/db/SchemaOperations","properties":[],"methods":[],"typeParameters":[],"directParents":[]}],"directParentClasses":[],"sourceType":2}},{"v":"@proteinjs/db/SchemaOperations"}],"edges":[{"v":"@proteinjs/db-driver-spanner/TestDbDriverFactory","w":"@proteinjs/db/DefaultDbDriverFactory","value":"implements interface"},{"v":"@proteinjs/db-driver-spanner/ServiceVerbsDoc","w":"@proteinjs/db/Record","value":"extends interface"},{"v":"@proteinjs/db-driver-spanner/ServiceVerbsDocTable","w":"@proteinjs/db/Table","value":"extends class"},{"v":"@proteinjs/db-driver-spanner/SpannerDriver","w":"@proteinjs/db/DbDriver","value":"implements interface"},{"v":"@proteinjs/db-driver-spanner/SpannerSchemaMetadata","w":"@proteinjs/db/SchemaMetadata","value":"extends class"},{"v":"@proteinjs/db-driver-spanner/SpannerSchemaOperations","w":"@proteinjs/db/SchemaOperations","value":"implements interface"}]}';
16
16
 
17
17
  /** Generate Source Links */
18
18
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@proteinjs/db-driver-spanner",
3
- "version": "1.17.0",
3
+ "version": "1.19.0",
4
4
  "main": "./dist/generated/index.js",
5
5
  "types": "./dist/generated/index.d.ts",
6
6
  "exports": {
@@ -42,10 +42,10 @@
42
42
  },
43
43
  "dependencies": {
44
44
  "@google-cloud/spanner": "7.5.0",
45
- "@proteinjs/db": "^1.30.0",
46
- "@proteinjs/db-query": "^1.6.3",
47
- "@proteinjs/db-spanner-common": "^1.3.6",
48
- "@proteinjs/db-transaction-context": "^0.5.6",
45
+ "@proteinjs/db": "^1.31.0",
46
+ "@proteinjs/db-query": "^1.7.0",
47
+ "@proteinjs/db-spanner-common": "^1.3.7",
48
+ "@proteinjs/db-transaction-context": "^0.5.7",
49
49
  "@proteinjs/logger": "^1.0.21",
50
50
  "@proteinjs/reflection": "^1.1.12",
51
51
  "@proteinjs/util": "^1.6.1"
@@ -63,5 +63,5 @@
63
63
  "ts-jest": "29.1.1",
64
64
  "typescript": "5.2.2"
65
65
  },
66
- "gitHead": "fd3dd48fae93c6da8c0b3decd6dd30a506a9109a"
66
+ "gitHead": "d84e548336f96b2541c1fbbe6a9ad6074df610c7"
67
67
  }
@@ -8,7 +8,7 @@ import {
8
8
  tableByName,
9
9
  } from '@proteinjs/db';
10
10
  import { SpannerConfig } from './SpannerConfig';
11
- import { SpannerLivenessMonitor } from './SpannerLivenessMonitor';
11
+ import { SpannerLivenessMonitor, type SpannerSessionPoolStats } from './SpannerLivenessMonitor';
12
12
  import { Logger } from '@proteinjs/logger';
13
13
  import { Statement } from '@proteinjs/db-query';
14
14
  import { SpannerSchemaOperations } from './SpannerSchemaOperations';
@@ -40,6 +40,18 @@ export class SpannerDriver implements DbDriver {
40
40
  this.getTable = getTable;
41
41
  }
42
42
 
43
+ /**
44
+ * The session-pool gauge (P4a), read-only — the four numbers that make pool exhaustion
45
+ * observable, for external observers (the ops monitors platform). Undefined until the process
46
+ * has connected a Database (no pool exists to gauge yet).
47
+ */
48
+ static getSessionPoolStats(): SpannerSessionPoolStats | undefined {
49
+ if (!SpannerDriver.SPANNER_DB) {
50
+ return undefined;
51
+ }
52
+ return SpannerDriver.LIVENESS_MONITOR.poolStats();
53
+ }
54
+
43
55
  private getSpanner(): Spanner {
44
56
  if (!SpannerDriver.SPANNER) {
45
57
  // gRPC channel keepalive (2026-07-11 flow-hang investigation): a call in flight on a dead
@@ -268,18 +280,25 @@ export class SpannerDriver implements DbDriver {
268
280
 
269
281
  try {
270
282
  this.logger.debug({ message: `Executing dml`, obj: { sql, params: namedParams } });
271
- const [rowCount] = await this.withDeadline(
283
+ // DML rides the unary ExecuteBatchDml RPC (`batchUpdate`), never streaming `runUpdate`
284
+ // (ExecuteStreamingSql). The client's streaming transport TRANSPARENTLY RE-SENDS a DML
285
+ // whose response was lost: gax wraps every server-streaming call in retry-request, which
286
+ // silently replays on ANY pre-response error. Seqno replay protection only covers the
287
+ // same-transaction geometry; the geometries it cannot cover are where the 2026-08-13
288
+ // splice incident lived — an inline-begin replay BEGINS A FRESH TRANSACTION per attempt
289
+ // (abandoned applied-but-uncommitted siblings churn locks and collide with rows committed
290
+ // by other paths: spurious `6 ALREADY_EXISTS` under pool pressure), and the stream-
291
+ // resumption layer re-mints a NEW seqno into the SAME transaction after inline-begin
292
+ // learned its id (unprotected even on real Spanner). The unary RPC has none of that
293
+ // machinery — see dmlGaxOptions() for the per-backend retry policy on it.
294
+ const [rowCounts] = await this.withDeadline(
272
295
  'spanner dml',
273
296
  sql,
274
- runner.runUpdate({
275
- sql,
276
- params: namedParams?.params,
277
- types: namedParams?.types,
278
- // gRPC deadline: cancels the RPC on a dead channel so the transaction's run function
279
- // settles and the library releases the session (see runDml).
280
- gaxOptions: { timeout: this.operationDeadlineMs() },
297
+ runner.batchUpdate([{ sql, params: namedParams?.params, types: namedParams?.types }], {
298
+ gaxOptions: this.dmlGaxOptions(),
281
299
  })
282
300
  );
301
+ const rowCount = rowCounts[0] ?? 0;
283
302
  const durationMs = Number(process.hrtime.bigint() - startTime) / 1_000_000;
284
303
  this.logger.debug({
285
304
  message: `Dml executed`,
@@ -500,6 +519,29 @@ export class SpannerDriver implements DbDriver {
500
519
  }
501
520
  }
502
521
 
522
+ /**
523
+ * Per-call gax options for the DML RPC (ExecuteBatchDml). The gRPC deadline (see runDml)
524
+ * applies everywhere. The transparent-retry policy differs by backend:
525
+ *
526
+ * - Real Spanner: gax's default unary policy (UNAVAILABLE only) stands. A replay re-sends the
527
+ * identical request — same seqno, deduped in the same-transaction geometry — and in the
528
+ * inline-begin geometry only the transaction the client ultimately commits applies durably,
529
+ * so the transient-blip resilience is safe there.
530
+ * - Emulator (SPANNER_EMULATOR_HOST — the same switch the client library keys on): a replayed
531
+ * inline-begin DML begins a fresh transaction per attempt, and the abandoned
532
+ * applied-but-uncommitted siblings are exactly what fed the splice incident's spurious
533
+ * failures under pool pressure. `retry: null` makes the call single-attempt: a lost response
534
+ * surfaces as the loss to the caller, deterministically, instead of invisible multi-
535
+ * transaction churn. Loopback needs no blip resilience.
536
+ */
537
+ private dmlGaxOptions(): { timeout: number; retry?: null } {
538
+ const gaxOptions: { timeout: number; retry?: null } = { timeout: this.operationDeadlineMs() };
539
+ if (process.env.SPANNER_EMULATOR_HOST) {
540
+ gaxOptions.retry = null;
541
+ }
542
+ return gaxOptions;
543
+ }
544
+
503
545
  private operationDeadlineMs(): number {
504
546
  return this.config.operationDeadlineMs ?? 60_000;
505
547
  }
@@ -0,0 +1,305 @@
1
+ import { PassThrough } from 'stream';
2
+ import { Db, Record, StringColumn, Table, tableByName, withRecordColumns } from '@proteinjs/db';
3
+ import { TransactionContext } from '@proteinjs/db-transaction-context';
4
+ import { SpannerDriver } from '@proteinjs/db-driver-spanner';
5
+ import { registerTestUser, clearTestUser } from '@proteinjs/db/test';
6
+ import { SourceRepository } from '@proteinjs/reflection';
7
+ import { getDropTestTable } from './util/getDropTestTable';
8
+ import { SpannerEmulatorProvisioner } from './util/SpannerEmulatorProvisioner';
9
+ import '../generated/test/index';
10
+
11
+ /**
12
+ * DML retry safety (the 2026-08-13 splice incident class): a DML request whose response is LOST
13
+ * in transport must NEVER be transparently re-sent by the client. On the pre-fix streaming DML
14
+ * path (`runUpdate` → ExecuteStreamingSql), gax wraps every attempt in retry-request, which
15
+ * silently replays on ANY pre-response error. Seqno replay protection only covers the
16
+ * same-transaction geometry; the replay geometries it cannot cover are where the incident lived:
17
+ * an inline-begin replay BEGINS A FRESH TRANSACTION per attempt (abandoned applied-but-
18
+ * uncommitted siblings churn locks and collide with rows committed by other paths — the
19
+ * spurious `6 ALREADY_EXISTS` under pool pressure), and the stream-resumption layer re-mints a
20
+ * NEW seqno into the SAME transaction after inline-begin learned its id (unprotected even on
21
+ * real Spanner).
22
+ *
23
+ * These tests drive the retry deterministically by injecting loss at the TRANSPORT SEAM — the
24
+ * resolved gRPC stub method, which the gapic layer looks up per attempt
25
+ * (`stub[methodName].apply`), i.e. the exact function every transparent retry re-invokes.
26
+ *
27
+ * Contract under test (the fix): DML rides the unary ExecuteBatchDml RPC, and under the emulator
28
+ * the call is single-attempt (`retry: null`) — a loss surfaces as the loss itself, after at most
29
+ * ONE wire execution.
30
+ */
31
+
32
+ interface RetryAnchor extends Record {
33
+ name: string;
34
+ }
35
+
36
+ interface RetryTarget extends Record {
37
+ name: string;
38
+ }
39
+
40
+ class RetryAnchorTestTable extends Table<RetryAnchor> {
41
+ name = 'db_test_dml_retry_anchor';
42
+ columns = withRecordColumns<RetryAnchor>({
43
+ name: new StringColumn('name'),
44
+ });
45
+ }
46
+
47
+ class RetryTargetTestTable extends Table<RetryTarget> {
48
+ name = 'db_test_dml_retry_target';
49
+ columns = withRecordColumns<RetryTarget>({
50
+ name: new StringColumn('name'),
51
+ });
52
+ }
53
+
54
+ const anchorTable: Table<RetryAnchor> = new RetryAnchorTestTable();
55
+ const targetTable: Table<RetryTarget> = new RetryTargetTestTable();
56
+ // Local tables — not in any reflection source graph, so thread getTable explicitly (the
57
+ // TransactionSafety pattern); other lookups resolve normally.
58
+ const getTable = (tableName: string) => {
59
+ if (tableName === anchorTable.name) {
60
+ return anchorTable;
61
+ }
62
+ if (tableName === targetTable.name) {
63
+ return targetTable;
64
+ }
65
+ return tableByName(tableName);
66
+ };
67
+ const spannerConfig = {
68
+ projectId: 'proteinjs-test',
69
+ instanceName: 'proteinjs-test',
70
+ databaseName: 'test',
71
+ };
72
+ const spannerDriver = new SpannerDriver(spannerConfig, getTable);
73
+
74
+ const INJECTED_LOSS = 'injected response loss';
75
+ const targetInsertSqlMarker = `INSERT INTO \`db_test_dml_retry_target\``;
76
+ const isTargetInsertSql = (sql: string) => sql.includes(targetInsertSqlMarker);
77
+
78
+ type StubPatch = { attempts: () => number; restore: () => void };
79
+ /**
80
+ * 'applied-then-lost': the first attempt reaches the emulator (the statement EXECUTES
81
+ * server-side) but its response is dropped — the incident's loss shape. 'lost-in-flight': the
82
+ * first attempt never reaches the emulator — a transparent replay makes the op silently
83
+ * SUCCEED behind a "failed" attempt (the smoking gun that a replay layer exists).
84
+ */
85
+ type LossMode = 'applied-then-lost' | 'lost-in-flight';
86
+
87
+ /** The resolved gRPC stub the gapic layer re-invokes per attempt — the transport seam. */
88
+ const getSpannerStub = async (): Promise<any> => {
89
+ const spanner = (SpannerDriver as unknown as { SPANNER?: any }).SPANNER;
90
+ if (!spanner) {
91
+ throw new Error('SpannerDriver.SPANNER not initialized — run an op first');
92
+ }
93
+ const gapicClient = spanner.clients_.get('SpannerClient');
94
+ if (!gapicClient) {
95
+ throw new Error('SpannerClient gapic client not created — run a data op first');
96
+ }
97
+ return await gapicClient.spannerStub;
98
+ };
99
+
100
+ const makeLossError = (): Error => {
101
+ const error: any = new Error(INJECTED_LOSS);
102
+ error.code = 14; // UNAVAILABLE — the shape of a dropped connection / lost response
103
+ return error;
104
+ };
105
+
106
+ /** Inject loss on the FIRST matching ExecuteStreamingSql attempt; later attempts pass through. */
107
+ const patchStreamingLoss = (stub: any, isTargetSql: (sql: string) => boolean, mode: LossMode): StubPatch => {
108
+ const original = stub.executeStreamingSql;
109
+ let attempts = 0;
110
+ stub.executeStreamingSql = function (this: any, ...args: any[]) {
111
+ const request = args[0];
112
+ if (typeof request?.sql !== 'string' || !isTargetSql(request.sql)) {
113
+ return original.apply(this, args);
114
+ }
115
+ attempts += 1;
116
+ if (attempts > 1) {
117
+ return original.apply(this, args);
118
+ }
119
+ const wrapper: any = new PassThrough({ objectMode: true });
120
+ let injected = false;
121
+ const inject = () => {
122
+ if (injected) {
123
+ return;
124
+ }
125
+ injected = true;
126
+ wrapper.emit('error', makeLossError());
127
+ };
128
+ if (mode === 'lost-in-flight') {
129
+ wrapper.cancel = () => undefined;
130
+ setImmediate(inject);
131
+ return wrapper;
132
+ }
133
+ const real = original.apply(this, args);
134
+ wrapper.cancel = () => real.cancel?.();
135
+ real.on('data', () => undefined); // drain — the response is consumed and dropped
136
+ real.on('metadata', () => undefined);
137
+ real.on('error', inject);
138
+ real.on('status', inject);
139
+ real.on('end', inject);
140
+ return wrapper;
141
+ };
142
+ return { attempts: () => attempts, restore: () => (stub.executeStreamingSql = original) };
143
+ };
144
+
145
+ /** Inject loss on the FIRST matching ExecuteBatchDml attempt; later attempts pass through. */
146
+ const patchUnaryLoss = (stub: any, isTargetSql: (sql: string) => boolean, mode: LossMode): StubPatch => {
147
+ const original = stub.executeBatchDml;
148
+ let attempts = 0;
149
+ stub.executeBatchDml = function (this: any, ...args: any[]) {
150
+ const request = args[0];
151
+ const statements: any[] = request?.statements ?? [];
152
+ if (!statements.some((statement) => typeof statement?.sql === 'string' && isTargetSql(statement.sql))) {
153
+ return original.apply(this, args);
154
+ }
155
+ attempts += 1;
156
+ if (attempts > 1) {
157
+ return original.apply(this, args);
158
+ }
159
+ const callback = args[args.length - 1];
160
+ if (typeof callback !== 'function') {
161
+ throw new Error('expected trailing callback on unary stub call');
162
+ }
163
+ if (mode === 'lost-in-flight') {
164
+ setImmediate(() => callback(makeLossError()));
165
+ return { cancel: () => undefined };
166
+ }
167
+ const lossyCallback = () => callback(makeLossError());
168
+ return original.apply(this, [...args.slice(0, -1), lossyCallback]);
169
+ };
170
+ return { attempts: () => attempts, restore: () => (stub.executeBatchDml = original) };
171
+ };
172
+
173
+ /** Pass-through counter for DML on the streaming transport — must stay ZERO post-fix. */
174
+ const patchStreamingDmlCounter = (stub: any, isTargetSql: (sql: string) => boolean): StubPatch => {
175
+ const original = stub.executeStreamingSql;
176
+ let attempts = 0;
177
+ stub.executeStreamingSql = function (this: any, ...args: any[]) {
178
+ if (typeof args[0]?.sql === 'string' && isTargetSql(args[0].sql)) {
179
+ attempts += 1;
180
+ }
181
+ return original.apply(this, args);
182
+ };
183
+ return { attempts: () => attempts, restore: () => (stub.executeStreamingSql = original) };
184
+ };
185
+
186
+ describe('DML retry safety (a lost response must never re-execute a statement)', () => {
187
+ const dropTable = getDropTestTable(spannerDriver);
188
+ const db = new Db(spannerDriver, getTable, new TransactionContext());
189
+
190
+ beforeAll(async () => {
191
+ registerTestUser();
192
+ // HERMETIC two-table world (the TransactionSafety pattern): the delete path's
193
+ // reverse-cascade scan walks getTables(); scope the registry to the local tables.
194
+ (SourceRepository.get() as unknown as { objectCache: { [key: string]: unknown[] } }).objectCache[
195
+ '@proteinjs/db/Table'
196
+ ] = [anchorTable, targetTable];
197
+ await SpannerEmulatorProvisioner.ensureProvisioned(spannerConfig);
198
+ await spannerDriver.createDbIfNotExists();
199
+ await spannerDriver.getTableManager().loadTable(anchorTable);
200
+ await spannerDriver.getTableManager().loadTable(targetTable);
201
+ // Warm the data client so the gapic SpannerClient + resolved stub exist to patch.
202
+ await db.query(targetTable, { name: 'warmup' });
203
+ }, 60000);
204
+
205
+ afterAll(async () => {
206
+ await dropTable(targetTable);
207
+ await dropTable(anchorTable);
208
+ await SpannerEmulatorProvisioner.release();
209
+ delete (SourceRepository.get() as unknown as { objectCache: { [key: string]: unknown[] } }).objectCache[
210
+ '@proteinjs/db/Table'
211
+ ];
212
+ clearTestUser();
213
+ }, 60000);
214
+
215
+ afterEach(async () => {
216
+ // Tests assert their own outcomes; this just keeps rows from leaking across tests.
217
+ for (const table of [targetTable, anchorTable]) {
218
+ const leftovers = await db.query(table as Table<any>, {});
219
+ for (const row of leftovers) {
220
+ await db.delete(table as Table<any>, { id: row.id } as any);
221
+ }
222
+ }
223
+ }, 30000);
224
+
225
+ test('in-transaction DML, response lost after the emulator applied it: the loss surfaces (no self-collision), one wire execution, nothing commits', async () => {
226
+ const stub = await getSpannerStub();
227
+ const streamingPatch = patchStreamingLoss(stub, isTargetInsertSql, 'applied-then-lost');
228
+ const unaryPatch = patchUnaryLoss(stub, isTargetInsertSql, 'applied-then-lost');
229
+ let outcome: unknown;
230
+ try {
231
+ outcome = await db
232
+ .runTransaction(async () => {
233
+ // Statement 1 establishes the transaction id; statement 2 is the target DML whose
234
+ // response is lost AFTER the emulator applied it. Pre-fix, retry-request transparently
235
+ // replayed it (2 wire attempts; the op only survived because same-txn same-seqno
236
+ // replays happen to be absorbed by backend replay protection — the inline-begin
237
+ // geometry has no such shield). The contract: ONE wire execution, the LOSS surfaces.
238
+ await db.insert(anchorTable, { name: 'RetryAnchorA' });
239
+ await db.insert(targetTable, { name: 'RetryTargetA' });
240
+ })
241
+ .then(() => 'resolved' as const)
242
+ .catch((error: Error) => error);
243
+ } finally {
244
+ streamingPatch.restore();
245
+ unaryPatch.restore();
246
+ }
247
+
248
+ // The surfaced failure is the injected loss — NOT a replay self-collision (6 ALREADY_EXISTS).
249
+ expect(outcome).toBeInstanceOf(Error);
250
+ expect(String((outcome as Error).message)).toContain(INJECTED_LOSS);
251
+ expect((outcome as any).code).not.toBe(6);
252
+ // Exactly one wire execution of the target DML across both transports.
253
+ expect(streamingPatch.attempts() + unaryPatch.attempts()).toBe(1);
254
+ // The failed transaction committed nothing.
255
+ expect(await db.query(targetTable, { name: 'RetryTargetA' })).toHaveLength(0);
256
+ expect(await db.query(anchorTable, { name: 'RetryAnchorA' })).toHaveLength(0);
257
+ }, 30000);
258
+
259
+ test('standalone DML (inline begin), request lost in flight: the loss surfaces, one wire attempt, no row materializes behind the failure', async () => {
260
+ const stub = await getSpannerStub();
261
+ const streamingPatch = patchStreamingLoss(stub, isTargetInsertSql, 'lost-in-flight');
262
+ const unaryPatch = patchUnaryLoss(stub, isTargetInsertSql, 'lost-in-flight');
263
+ let outcome: unknown;
264
+ try {
265
+ outcome = await db
266
+ .insert(targetTable, { name: 'RetryTargetB' })
267
+ .then(() => 'resolved' as const)
268
+ .catch((error: Error) => error);
269
+ } finally {
270
+ streamingPatch.restore();
271
+ unaryPatch.restore();
272
+ }
273
+
274
+ // The op fails with the injected loss — it is NOT silently healed by a transparent replay
275
+ // (a replay resolves the op and materializes a row behind a "failed" attempt).
276
+ expect(outcome).toBeInstanceOf(Error);
277
+ expect(String((outcome as Error).message)).toContain(INJECTED_LOSS);
278
+ expect(streamingPatch.attempts() + unaryPatch.attempts()).toBe(1);
279
+ expect(await db.query(targetTable, { name: 'RetryTargetB' })).toHaveLength(0);
280
+ }, 30000);
281
+
282
+ test('happy path: DML rides the unary RPC (streaming carries none), commits exactly once with faithful row counts', async () => {
283
+ const stub = await getSpannerStub();
284
+ const isTargetDmlSql = (sql: string) =>
285
+ sql.includes('`db_test_dml_retry_target`') && !sql.trim().startsWith('SELECT');
286
+ const streamingCounter = patchStreamingDmlCounter(stub, isTargetDmlSql);
287
+ try {
288
+ const inserted = await db.runTransaction(async () => {
289
+ await db.insert(anchorTable, { name: 'RetryAnchorC' });
290
+ return await db.insert(targetTable, { name: 'RetryTargetC' });
291
+ });
292
+
293
+ const committed = await db.query(targetTable, { name: 'RetryTargetC' });
294
+ expect(committed).toHaveLength(1);
295
+ // Row counts flow faithfully through the unary path.
296
+ expect(await db.update(targetTable, { name: 'RetryTargetC-updated' }, { id: inserted.id })).toBe(1);
297
+ expect(await db.delete(targetTable, { id: inserted.id })).toBe(1);
298
+ // No DML (insert/update/delete) ever touched the streaming transport, whose retry
299
+ // layers transparently replay lost responses.
300
+ expect(streamingCounter.attempts()).toBe(0);
301
+ } finally {
302
+ streamingCounter.restore();
303
+ }
304
+ }, 30000);
305
+ });
@@ -0,0 +1,16 @@
1
+ import { recordIteratorTests } from '@proteinjs/db/test';
2
+ import { SpannerDriver } from '@proteinjs/db-driver-spanner';
3
+ import { getDropTestTable } from './util/getDropTestTable';
4
+ import { TransactionContext } from '@proteinjs/db-transaction-context';
5
+ import '../generated/test/index';
6
+
7
+ const spannerDriver = new SpannerDriver({
8
+ projectId: 'proteinjs-test',
9
+ instanceName: 'proteinjs-test',
10
+ databaseName: 'test',
11
+ });
12
+
13
+ describe(
14
+ 'RecordIterator cursor-window tests',
15
+ recordIteratorTests(spannerDriver, new TransactionContext(), getDropTestTable(spannerDriver))
16
+ );