( options: SqliteClientConfig )
| 115 | readonly backup: (destination: string) => Effect.Effect<BackupMetadata, SqlError> |
| 116 | readonly loadExtension: (path: string) => Effect.Effect<void, SqlError> |
| 117 | } |
| 118 | |
| 119 | /** |
| 120 | * Creates a scoped node SQLite client from the supplied configuration, using a single serialized connection with WAL and a 5-second busy timeout enabled by default. Explicit transactions on writable connections take the write lock for their duration, even when they only read; clients opened with `readonly: true` are unaffected. |
| 121 | * |
| 122 | * @category constructors |
| 123 | * @since 4.0.0 |
| 124 | */ |
| 125 | export const make = ( |
| 126 | options: SqliteClientConfig |
| 127 | ): Effect.Effect<SqliteClient, never, Scope.Scope | Reactivity.Reactivity> => |
| 128 | Effect.gen(function*() { |
| 129 | const compiler = Statement.makeCompilerSqlite(options.transformQueryNames) |
| 130 | const transformRows = options.transformResultNames ? |
| 131 | Statement.defaultTransforms( |
| 132 | options.transformResultNames |
| 133 | ).array : |
| 134 | undefined |
| 135 | |
| 136 | const makeConnection = Effect.gen(function*() { |
| 137 | const scope = yield* Effect.scope |
| 138 | const db = new DatabaseSync(options.filename, { |
| 139 | readOnly: options.readonly ?? false, |
| 140 | allowExtension: true |
| 141 | }) |
| 142 | yield* Scope.addFinalizer(scope, Effect.sync(() => db.close())) |
| 143 | db.enableLoadExtension(false) |
| 144 | const busyTimeout = Math.min( |
| 145 | MAX_BUSY_TIMEOUT, |
| 146 | Math.max(0, Math.round(Duration.toMillis(options.busyTimeout ?? Duration.seconds(5)))) |
| 147 | ) |
| 148 | db.exec(`PRAGMA busy_timeout = ${busyTimeout}`) |
| 149 | |
| 150 | if (options.disableWAL !== true) { |
| 151 | db.exec("PRAGMA journal_mode = WAL") |
| 152 | } |
| 153 | |
| 154 | const prepareCache = yield* Cache.make({ |
| 155 | capacity: options.prepareCacheSize ?? 200, |
| 156 | timeToLive: options.prepareCacheTTL ?? Duration.minutes(10), |
| 157 | lookup: (sql: string) => |
| 158 | Effect.try({ |
| 159 | try: () => db.prepare(sql), |
| 160 | catch: (cause) => new SqlError({ reason: classifyError(cause, "Failed to prepare statement", "prepare") }) |
| 161 | }) |
| 162 | }) |
| 163 | |
| 164 | const runStatement = ( |
| 165 | statement: StatementSync, |
| 166 | params: ReadonlyArray<unknown>, |
| 167 | raw: boolean |
| 168 | ) => |
| 169 | Effect.withFiber<ReadonlyArray<any>, SqlError>((fiber) => { |
| 170 | const useSafeIntegers = Context.get(fiber.context, Client.SafeIntegers) |
| 171 | return Effect.try({ |
| 172 | try: () => { |
| 173 | statement.setReadBigInts(useSafeIntegers) |
| 174 | if (statement.columns().length > 0) { |
no test coverage detected
searching dependent graphs…