@lakeql/datasource 0.0.0-stage → 1.0.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/LICENSE ADDED
@@ -0,0 +1,201 @@
1
+ Apache License
2
+ Version 2.0, January 2004
3
+ http://www.apache.org/licenses/
4
+
5
+ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
6
+
7
+ 1. Definitions.
8
+
9
+ "License" shall mean the terms and conditions for use, reproduction,
10
+ and distribution as defined by Sections 1 through 9 of this document.
11
+
12
+ "Licensor" shall mean the copyright owner or entity authorized by
13
+ the copyright owner that is granting the License.
14
+
15
+ "Legal Entity" shall mean the union of the acting entity and all
16
+ other entities that control, are controlled by, or are under common
17
+ control with that entity. For the purposes of this definition,
18
+ "control" means (i) the power, direct or indirect, to cause the
19
+ direction or management of such entity, whether by contract or
20
+ otherwise, or (ii) ownership of fifty percent (50%) or more of the
21
+ outstanding shares, or (iii) beneficial ownership of such entity.
22
+
23
+ "You" (or "Your") shall mean an individual or Legal Entity
24
+ exercising permissions granted by this License.
25
+
26
+ "Source" form shall mean the preferred form for making modifications,
27
+ including but not limited to software source code, documentation
28
+ source, and configuration files.
29
+
30
+ "Object" form shall mean any form resulting from mechanical
31
+ transformation or translation of a Source form, including but
32
+ not limited to compiled object code, generated documentation,
33
+ and conversions to other media types.
34
+
35
+ "Work" shall mean the work of authorship, whether in Source or
36
+ Object form, made available under the License, as indicated by a
37
+ copyright notice that is included in or attached to the work
38
+ (an example is provided in the Appendix below).
39
+
40
+ "Derivative Works" shall mean any work, whether in Source or Object
41
+ form, that is based on (or derived from) the Work and for which the
42
+ editorial revisions, annotations, elaborations, or other modifications
43
+ represent, as a whole, an original work of authorship. For the purposes
44
+ of this License, Derivative Works shall not include works that remain
45
+ separable from, or merely link (or bind by name) to the interfaces of,
46
+ the Work and Derivative Works thereof.
47
+
48
+ "Contribution" shall mean any work of authorship, including
49
+ the original version of the Work and any modifications or additions
50
+ to that Work or Derivative Works thereof, that is intentionally
51
+ submitted to Licensor for inclusion in the Work by the copyright owner
52
+ or by an individual or Legal Entity authorized to submit on behalf of
53
+ the copyright owner. For the purposes of this definition, "submitted"
54
+ means any form of electronic, verbal, or written communication sent
55
+ to the Licensor or its representatives, including but not limited to
56
+ communication on electronic mailing lists, source code control systems,
57
+ and issue tracking systems that are managed by, or on behalf of, the
58
+ Licensor for the purpose of discussing and improving the Work, but
59
+ excluding communication that is conspicuously marked or otherwise
60
+ designated in writing by the copyright owner as "Not a Contribution."
61
+
62
+ "Contributor" shall mean Licensor and any individual or Legal Entity
63
+ on behalf of whom a Contribution has been received by Licensor and
64
+ subsequently incorporated within the Work.
65
+
66
+ 2. Grant of Copyright License. Subject to the terms and conditions of
67
+ this License, each Contributor hereby grants to You a perpetual,
68
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
69
+ copyright license to reproduce, prepare Derivative Works of,
70
+ publicly display, publicly perform, sublicense, and distribute the
71
+ Work and such Derivative Works in Source or Object form.
72
+
73
+ 3. Grant of Patent License. Subject to the terms and conditions of
74
+ this License, each Contributor hereby grants to You a perpetual,
75
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
76
+ (except as stated in this section) patent license to make, have made,
77
+ use, offer to sell, sell, import, and otherwise transfer the Work,
78
+ where such license applies only to those patent claims licensable
79
+ by such Contributor that are necessarily infringed by their
80
+ Contribution(s) alone or by combination of their Contribution(s)
81
+ with the Work to which such Contribution(s) was submitted. If You
82
+ institute patent litigation against any entity (including a
83
+ cross-claim or counterclaim in a lawsuit) alleging that the Work
84
+ or a Contribution incorporated within the Work constitutes direct
85
+ or contributory patent infringement, then any patent licenses
86
+ granted to You under this License for that Work shall terminate
87
+ as of the date such litigation is filed.
88
+
89
+ 4. Redistribution. You may reproduce and distribute copies of the
90
+ Work or Derivative Works thereof in any medium, with or without
91
+ modifications, and in Source or Object form, provided that You
92
+ meet the following conditions:
93
+
94
+ (a) You must give any other recipients of the Work or
95
+ Derivative Works a copy of this License; and
96
+
97
+ (b) You must cause any modified files to carry prominent notices
98
+ stating that You changed the files; and
99
+
100
+ (c) You must retain, in the Source form of any Derivative Works
101
+ that You distribute, all copyright, patent, trademark, and
102
+ attribution notices from the Source form of the Work,
103
+ excluding those notices that do not pertain to any part of
104
+ the Derivative Works; and
105
+
106
+ (d) If the Work includes a "NOTICE" text file as part of its
107
+ distribution, then any Derivative Works that You distribute must
108
+ include a readable copy of the attribution notices contained
109
+ within such NOTICE file, excluding those notices that do not
110
+ pertain to any part of the Derivative Works, in at least one
111
+ of the following places: within a NOTICE text file distributed
112
+ as part of the Derivative Works; within the Source form or
113
+ documentation, if provided along with the Derivative Works; or,
114
+ within a display generated by the Derivative Works, if and
115
+ wherever such third-party notices normally appear. The contents
116
+ of the NOTICE file are for informational purposes only and
117
+ do not modify the License. You may add Your own attribution
118
+ notices within Derivative Works that You distribute, alongside
119
+ or as an addendum to the NOTICE text from the Work, provided
120
+ that such additional attribution notices cannot be construed
121
+ as modifying the License.
122
+
123
+ You may add Your own copyright statement to Your modifications and
124
+ may provide additional or different license terms and conditions
125
+ for use, reproduction, or distribution of Your modifications, or
126
+ for any such Derivative Works as a whole, provided Your use,
127
+ reproduction, and distribution of the Work otherwise complies with
128
+ the conditions stated in this License.
129
+
130
+ 5. Submission of Contributions. Unless You explicitly state otherwise,
131
+ any Contribution intentionally submitted for inclusion in the Work
132
+ by You to the Licensor shall be under the terms and conditions of
133
+ this License, without any additional terms or conditions.
134
+ Notwithstanding the above, nothing herein shall supersede or modify
135
+ the terms of any separate license agreement you may have executed
136
+ with Licensor regarding such Contributions.
137
+
138
+ 6. Trademarks. This License does not grant permission to use the trade
139
+ names, trademarks, service marks, or product names of the Licensor,
140
+ except as required for reasonable and customary use in describing the
141
+ origin of the Work and reproducing the content of the NOTICE file.
142
+
143
+ 7. Disclaimer of Warranty. Unless required by applicable law or
144
+ agreed to in writing, Licensor provides the Work (and each
145
+ Contributor provides its Contributions) on an "AS IS" BASIS,
146
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
147
+ implied, including, without limitation, any warranties or conditions
148
+ of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
149
+ PARTICULAR PURPOSE. You are solely responsible for determining the
150
+ appropriateness of using or redistributing the Work and assume any
151
+ risks associated with Your exercise of permissions under this License.
152
+
153
+ 8. Limitation of Liability. In no event and under no legal theory,
154
+ whether in tort (including negligence), contract, or otherwise,
155
+ unless required by applicable law (such as deliberate and grossly
156
+ negligent acts) or agreed to in writing, shall any Contributor be
157
+ liable to You for damages, including any direct, indirect, special,
158
+ incidental, or consequential damages of any character arising as a
159
+ result of this License or out of the use or inability to use the
160
+ Work (including but not limited to damages for loss of goodwill,
161
+ work stoppage, computer failure or malfunction, or any and all
162
+ other commercial damages or losses), even if such Contributor
163
+ has been advised of the possibility of such damages.
164
+
165
+ 9. Accepting Warranty or Additional Liability. While redistributing
166
+ the Work or Derivative Works thereof, You may choose to offer,
167
+ and charge a fee for, acceptance of support, warranty, indemnity,
168
+ or other liability obligations and/or rights consistent with this
169
+ License. However, in accepting such obligations, You may act only
170
+ on Your own behalf and on Your sole responsibility, not on behalf
171
+ of any other Contributor, and only if You agree to indemnify,
172
+ defend, and hold each Contributor harmless for any liability
173
+ incurred by, or claims asserted against, such Contributor by reason
174
+ of your accepting any such warranty or additional liability.
175
+
176
+ END OF TERMS AND CONDITIONS
177
+
178
+ APPENDIX: How to apply the Apache License to your work.
179
+
180
+ To apply the Apache License to your work, attach the following
181
+ boilerplate notice, with the fields enclosed by brackets "[]"
182
+ replaced with your own identifying information. (Don't include
183
+ the brackets!) The text should be enclosed in the appropriate
184
+ comment syntax for the file format. We also recommend that a
185
+ file or class name and description of purpose be included on the
186
+ same "printed page" as the copyright notice for easier
187
+ identification within third-party archives.
188
+
189
+ Copyright [yyyy] [name of copyright owner]
190
+
191
+ Licensed under the Apache License, Version 2.0 (the "License");
192
+ you may not use this file except in compliance with the License.
193
+ You may obtain a copy of the License at
194
+
195
+ http://www.apache.org/licenses/LICENSE-2.0
196
+
197
+ Unless required by applicable law or agreed to in writing, software
198
+ distributed under the License is distributed on an "AS IS" BASIS,
199
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
200
+ See the License for the specific language governing permissions and
201
+ limitations under the License.
@@ -0,0 +1,375 @@
1
+ import { a as AdapterName, o as SourceConfig, r as DataSourceWriteStrategy } from "./write-a_2WwSyG.mjs";
2
+ import { n as TypeMapper } from "./type-mapper-B7AlDDrp.mjs";
3
+ /**
4
+ * Neutral authentication types for data source access.
5
+ *
6
+ * These types live in `@lakeql/datasource` (design decision 4) because
7
+ * they are required by the adapter factory and read strategy contracts.
8
+ */
9
+ /**
10
+ * Discriminated union of authentication credentials that can be
11
+ * transported through the core without adapter-specific knowledge.
12
+ *
13
+ * The set of variants may be extended by a future auth design, but
14
+ * the core must carry request auth without interpreting adapter-level
15
+ * credential details.
16
+ */
17
+ type DataSourceAuth = {
18
+ /** Username and password credentials. */
19
+ type: "basic";
20
+ /** Username sent to the data source. */
21
+ username: string;
22
+ /** Password sent to the data source. */
23
+ password: string;
24
+ } | {
25
+ /** Static bearer token credentials. */
26
+ type: "bearer";
27
+ /** Token sent in the authorization header. */
28
+ token: string;
29
+ } | {
30
+ /** OAuth 2.0 access-token credentials. */
31
+ type: "oauth2";
32
+ /** Current OAuth 2.0 access token. */
33
+ accessToken: string;
34
+ };
35
+ /**
36
+ * Auth resolution function injected into read strategies and adapter
37
+ * factories. Given a data source name and an opaque request context,
38
+ * it returns optional credentials and adapter-level options.
39
+ *
40
+ * @param dataSourceName - Configured runtime name of the data source.
41
+ * @param context - Opaque request context from which credentials can be resolved.
42
+ * @returns Credentials and adapter-owned options for the request, when available.
43
+ */
44
+ type ResolveAuth = (dataSourceName: string, context: unknown) => Promise<{
45
+ /** Credentials to attach to the data-source request. */
46
+ requestAuth?: DataSourceAuth;
47
+ /** Adapter-owned request options. */
48
+ options?: Record<string, unknown>;
49
+ }>;
50
+ /**
51
+ * Describes actual support for operations, metadata discovery, write
52
+ * modes, and DDL provided by a data source.
53
+ *
54
+ * Adapters populate this at construction time so that the runtime can
55
+ * avoid selecting unsupported operations.
56
+ */
57
+ interface DataSourceCapabilities {
58
+ /** Whether the data source supports query execution. */
59
+ query: boolean;
60
+ /** Whether the data source supports streaming results. */
61
+ stream: boolean;
62
+ /** Metadata discovery support per catalog object type. */
63
+ metadata: {
64
+ /** Whether catalog discovery is supported. */
65
+ catalogs: boolean;
66
+ /** Whether schema discovery is supported. */
67
+ schemas: boolean;
68
+ /** Whether table discovery is supported. */
69
+ tables: boolean;
70
+ /** Whether view discovery is supported. */
71
+ views: boolean;
72
+ /** Whether column discovery is supported. */
73
+ columns: boolean;
74
+ };
75
+ /** Write support and available write modes. */
76
+ write: {
77
+ supported: boolean;
78
+ /**
79
+ * Available write modes — an open string array so that future
80
+ * adapters can provide modes not known to the core.
81
+ */
82
+ modes: string[];
83
+ };
84
+ /** DDL support. */
85
+ ddl: {
86
+ /** Whether creating tables is supported. */
87
+ createTable: boolean;
88
+ /** Whether dropping tables is supported. */
89
+ dropTable: boolean;
90
+ };
91
+ }
92
+ /**
93
+ * Parameters for executing a SQL query against a data source.
94
+ */
95
+ interface QueryProps {
96
+ /** SQL statement to execute. */
97
+ sql: string;
98
+ /** Optional cancellation signal for the query. */
99
+ signal?: AbortSignal;
100
+ /** Credentials resolved for this request. */
101
+ requestAuth?: DataSourceAuth;
102
+ /** Adapter-specific query options. */
103
+ options?: Record<string, unknown>;
104
+ }
105
+ /**
106
+ * Metadata describing a single column in a table.
107
+ */
108
+ interface ColumnInfo {
109
+ /** Column name as exposed by the data source. */
110
+ name: string;
111
+ /** Native or normalized data type name. */
112
+ type: string;
113
+ /** Additional adapter-provided metadata, such as precision or nullability. */
114
+ extra?: string;
115
+ /** Optional human-readable column description. */
116
+ description?: string;
117
+ }
118
+ /**
119
+ * Definition for creating a new table.
120
+ */
121
+ interface TableDefinition {
122
+ /** Catalog in which to create the table. */
123
+ catalog: string;
124
+ /** Schema in which to create the table. */
125
+ schema: string;
126
+ /** Name of the table to create. */
127
+ table: string;
128
+ /** Ordered column definitions for the new table. */
129
+ columns: {
130
+ name: string;
131
+ type: string;
132
+ }[];
133
+ }
134
+ /**
135
+ * Adapter-neutral data source contract.
136
+ *
137
+ * Every adapter package implements this interface to provide query
138
+ * execution, streaming, metadata discovery, DDL, and lifecycle
139
+ * management without coupling the core to adapter-specific details.
140
+ */
141
+ interface DataSource {
142
+ /** Open adapter identifier for this data source instance. */
143
+ readonly adapter: AdapterName;
144
+ /** Capabilities supported by this data source. */
145
+ readonly capabilities: DataSourceCapabilities;
146
+ /** Maps between this adapter's engine types and LakeQL primitive types. */
147
+ readonly typeMapper: TypeMapper;
148
+ /**
149
+ * Executes a SQL query and returns all matching rows.
150
+ *
151
+ * @template TRow - Shape of each row returned by the data source.
152
+ * @param props - SQL text, optional cancellation signal, request auth, and adapter options.
153
+ * @returns All rows produced by the query.
154
+ */
155
+ query: <TRow>(props: QueryProps) => Promise<TRow[]>;
156
+ /**
157
+ * Executes a SQL query and returns its rows as an asynchronous generator.
158
+ *
159
+ * @template TRow - Shape of each row yielded by the data source.
160
+ * @param props - SQL text, optional cancellation signal, request auth, and adapter options.
161
+ * @returns A generator that yields rows in source order.
162
+ */
163
+ stream: <TRow>(props: QueryProps) => Promise<AsyncGenerator<TRow>>;
164
+ /**
165
+ * Lists catalogs available to the current data source.
166
+ *
167
+ * @returns Catalog names visible to the configured connection.
168
+ */
169
+ catalogs: () => Promise<string[]>;
170
+ /**
171
+ * Lists schemas within a catalog.
172
+ *
173
+ * @param catalog - Catalog whose schemas should be listed.
174
+ * @returns Schema names in the catalog.
175
+ */
176
+ schemas: (catalog: string) => Promise<string[]>;
177
+ /**
178
+ * Lists tables within a catalog and schema.
179
+ *
180
+ * @param catalog - Catalog containing the schema.
181
+ * @param schema - Schema whose tables should be listed.
182
+ * @returns Table names in the schema.
183
+ */
184
+ tables: (catalog: string, schema: string) => Promise<string[]>;
185
+ /**
186
+ * Lists views within a catalog and schema.
187
+ *
188
+ * @param catalog - Catalog containing the schema.
189
+ * @param schema - Schema whose views should be listed.
190
+ * @returns View names in the schema.
191
+ */
192
+ views: (catalog: string, schema: string) => Promise<string[]>;
193
+ /**
194
+ * Lists column metadata for a table.
195
+ *
196
+ * @param catalog - Catalog containing the table.
197
+ * @param schema - Schema containing the table.
198
+ * @param table - Table whose columns should be listed.
199
+ * @returns Metadata for the table's columns.
200
+ */
201
+ columns: (catalog: string, schema: string, table: string) => Promise<ColumnInfo[]>;
202
+ /**
203
+ * Creates a table from a neutral definition.
204
+ *
205
+ * @param definition - Target coordinates and ordered column definitions.
206
+ */
207
+ createTable: (definition: TableDefinition) => Promise<void>;
208
+ /**
209
+ * Drops a table.
210
+ *
211
+ * @param catalog - Catalog containing the table.
212
+ * @param schema - Schema containing the table.
213
+ * @param table - Table to drop.
214
+ */
215
+ dropTable: (catalog: string, schema: string, table: string) => Promise<void>;
216
+ /**
217
+ * Builds an adapter-specific fully qualified table name.
218
+ *
219
+ * @param config - Source coordinates to qualify.
220
+ * @returns The data-source-specific qualified table name.
221
+ */
222
+ qualifiedTableName: (config: SourceConfig) => string;
223
+ /** Releases all resources held by this data source. */
224
+ close: () => Promise<void>;
225
+ }
226
+ /**
227
+ * Resolved per-data-source paging limits.
228
+ *
229
+ * Owned by `@lakeql/datasource` so resolved config values flow to the
230
+ * adapter factory and read strategies with compile-time assignability.
231
+ */
232
+ interface ReadStrategyPaging {
233
+ /** Page size used when a request omits `perPage`. */
234
+ defaultPerPage: number;
235
+ /** Upper bound a request's `perPage` may not exceed. */
236
+ maxRecordsPerPage: number;
237
+ }
238
+ /**
239
+ * Shared read input that types common values while leaving
240
+ * filter, schema, and context generic for adapter- or API-specific
241
+ * extensibility.
242
+ *
243
+ * @template TFilter - Filter expression understood by the read implementation.
244
+ * @template TSchema - Schema or selection metadata understood by the read implementation.
245
+ * @template TContext - Request-scoped context passed through to the read implementation.
246
+ */
247
+ interface DataSourceReadInput<TFilter = unknown, TSchema = unknown, TContext = unknown> {
248
+ /** Table and adapter coordinates for the requested source. */
249
+ sourceConfig: SourceConfig;
250
+ /** Source fields to include in the result. */
251
+ selectFields: readonly string[];
252
+ /** Adapter- or API-specific filter expression. */
253
+ filter: TFilter;
254
+ /**
255
+ * One-based page number and the requested page size. `perPage` is
256
+ * optional; the strategy substitutes the resolved default when omitted.
257
+ */
258
+ paging: {
259
+ page: number;
260
+ perPage?: number | null;
261
+ };
262
+ /** Adapter- or API-specific sort definitions. */
263
+ sorting: readonly unknown[];
264
+ /** Mapping from source field names to their result aliases. */
265
+ transformFields: Readonly<Record<string, string>>;
266
+ /** Fields that require date-specific handling by the adapter. */
267
+ dateFields: readonly string[];
268
+ /** Schema or selection metadata required by the read implementation. */
269
+ schema: TSchema;
270
+ /** Request-scoped context passed through without core interpretation. */
271
+ context: TContext;
272
+ }
273
+ /**
274
+ * Neutral read result exposing total count, page information,
275
+ * and typed result nodes.
276
+ *
277
+ * @template T - Shape of each record in the result page.
278
+ */
279
+ interface DataSourceReadResult<T> {
280
+ /** Total number of matching records across all pages. */
281
+ totalCount: number;
282
+ /** Paging metadata for the returned result page. */
283
+ pageInfo: {
284
+ /** Total number of available pages, or zero when no records match. */
285
+ maxPages: number;
286
+ /** Whether another page is available after this one. */
287
+ hasNext: boolean;
288
+ /** Whether a page is available before this one. */
289
+ hasPrevious: boolean;
290
+ /** One-based number of the returned page. */
291
+ currentPage: number;
292
+ /** One-based number of the next page, or `null` when on the last page. */
293
+ nextPage: number | null;
294
+ /** One-based number of the previous page, or `null` when on the first page. */
295
+ previousPage: number | null;
296
+ };
297
+ /** Typed records returned for the requested page. */
298
+ nodes: T[];
299
+ }
300
+ /**
301
+ * Strategy contract for reading data from a data source.
302
+ * Adapter-specific read implementations conform to this interface.
303
+ */
304
+ interface DataSourceReadStrategy {
305
+ /**
306
+ * Reads a page of records. Implementations must validate paging before
307
+ * building or executing their query.
308
+ *
309
+ * @template T - Shape of each record returned by the read strategy.
310
+ * @param input - Source coordinates, selection, filtering, paging, and request context.
311
+ * @returns A typed page of matching records and its paging metadata.
312
+ */
313
+ read: <T>(input: DataSourceReadInput) => Promise<DataSourceReadResult<T>>;
314
+ }
315
+ /**
316
+ * Adapter factory contract.
317
+ *
318
+ * Every adapter package exposes a single factory that the runtime
319
+ * uses to construct a data source, read strategy, and write strategy
320
+ * without adapter-specific switch statements.
321
+ *
322
+ * Config parameters use `unknown` to keep the core free of
323
+ * adapter-specific type imports. Adapter factories own validation
324
+ * and narrowing of their configuration objects.
325
+ *
326
+ * Environment-based connection configuration is NOT part of this
327
+ * contract. If an adapter needs environment parsing, it provides
328
+ * a separate config-layer provider that feeds the central config
329
+ * loader.
330
+ */
331
+ interface AdapterFactory {
332
+ /** Unique adapter identifier (e.g. `"trino"`, `"fabric"`). */
333
+ readonly adapterName: AdapterName;
334
+ /**
335
+ * Constructs an adapter-owned data source from validated adapter-specific
336
+ * configuration and its configured runtime name.
337
+ *
338
+ * @param config - Adapter-specific configuration to validate and consume.
339
+ * @param name - Configured runtime name for the new data source.
340
+ * @returns A data source owned by this adapter.
341
+ */
342
+ createDataSource: (config: unknown, name: string) => DataSource;
343
+ /**
344
+ * Constructs a read strategy with its data source and auth resolver.
345
+ *
346
+ * @param args - The data source and request-auth resolver required by the strategy.
347
+ * @returns A read strategy owned by this adapter.
348
+ */
349
+ createReadStrategy: (args: {
350
+ /** Data source used to execute reads. */
351
+ dataSource: DataSource;
352
+ /** Resolves credentials from the request context. */
353
+ resolveAuth: ResolveAuth;
354
+ /**
355
+ * Resolved per-data-source paging limits from config. Optional so
356
+ * existing/third-party implementers and test stubs stay valid.
357
+ */
358
+ paging?: ReadStrategyPaging;
359
+ }) => DataSourceReadStrategy;
360
+ /**
361
+ * Constructs a write strategy from adapter-owned configuration.
362
+ *
363
+ * @param args - The data source, its configured name, and write configuration.
364
+ * @returns A write strategy owned by this adapter.
365
+ */
366
+ createWriteStrategy: (args: {
367
+ /** Data source used to execute writes. */
368
+ dataSource: DataSource;
369
+ /** Configured runtime name of the data source. */
370
+ dataSourceName: string;
371
+ /** Validated adapter-specific write configuration. */
372
+ writeConfig: unknown;
373
+ }) => DataSourceWriteStrategy;
374
+ }
375
+ export { ReadStrategyPaging as a, QueryProps as c, DataSourceAuth as d, ResolveAuth as f, DataSourceReadStrategy as i, TableDefinition as l, DataSourceReadInput as n, DataSource as o, DataSourceReadResult as r, ColumnInfo as s, AdapterFactory as t, DataSourceCapabilities as u };
@@ -0,0 +1,282 @@
1
+ /**
2
+ * Adapter-neutral contracts for LakeQL data sources, read strategies,
3
+ * write strategies, and adapter factories.
4
+ *
5
+ * Package: lakeql/datasource
6
+ */
7
+ import { a as AdapterName, i as LoadStrategy, n as DataSourceWriteInput, o as SourceConfig, r as DataSourceWriteStrategy, t as DataSourceWriteConfig } from "./write-a_2WwSyG.mjs";
8
+ import { a as ReadStrategyPaging, c as QueryProps, d as DataSourceAuth, f as ResolveAuth, i as DataSourceReadStrategy, l as TableDefinition, n as DataSourceReadInput, o as DataSource, r as DataSourceReadResult, s as ColumnInfo, t as AdapterFactory, u as DataSourceCapabilities } from "./adapter-factory-BzuS1VyB.mjs";
9
+ import { n as TypeMapper, t as PrimitiveType } from "./type-mapper-B7AlDDrp.mjs";
10
+ import { UnsupportedWriteStrategy } from "./unsupported-write-strategy.mjs";
11
+ import { TypeMapperTables, createTypeMapper } from "./type-mapper-factory.mjs";
12
+ /**
13
+ * Category strings that classify operational datasource errors.
14
+ *
15
+ * Each category maps to a specific {@link DataSourceError} subclass,
16
+ * allowing consumers to branch on the category without `instanceof`
17
+ * checks or message parsing.
18
+ */
19
+ type DataSourceErrorCategory = "auth" | "query" | "network" | "timeout" | "cancelled" | "unsupported";
20
+ /**
21
+ * Base operational error for datasource failures.
22
+ *
23
+ * Every instance carries a fixed {@link category}, the
24
+ * {@link adapter} name and {@link dataSource} identifier that
25
+ * produced the failure, and optionally the lower-level
26
+ * {@link Error.cause | cause}.
27
+ *
28
+ * Adapter-owned configuration and connection errors remain the
29
+ * adapter's responsibility — they should extend their own error
30
+ * types, not this one.
31
+ */
32
+ export declare class DataSourceError extends Error {
33
+ /** Open identifier of the adapter that produced this error. */
34
+ readonly adapter: AdapterName;
35
+ /** Runtime name of the data source that produced this error. */
36
+ readonly dataSource: string;
37
+ /** Fixed category classifying this operational error. */
38
+ readonly category: DataSourceErrorCategory;
39
+ /**
40
+ * @param message - Human-readable explanation of the failure. Must not contain credentials.
41
+ * @param adapter - Open identifier of the adapter that produced this error.
42
+ * @param dataSource - Runtime name of the data source that produced this error.
43
+ * @param category - Fixed category for this error class.
44
+ * @param options - Optional lower-level cause to preserve.
45
+ */
46
+ constructor(message: string, adapter: AdapterName, dataSource: string, category: DataSourceErrorCategory, options?: {
47
+ cause?: unknown;
48
+ });
49
+ }
50
+ /**
51
+ * Operational error for authentication or authorization failures.
52
+ *
53
+ * Fixes {@link DataSourceError.category | category} to `"auth"`.
54
+ */
55
+ export declare class AuthenticationError extends DataSourceError {
56
+ /**
57
+ * @param message - Human-readable explanation of the auth failure. Must not contain credentials.
58
+ * @param adapter - Open identifier of the adapter that produced this error.
59
+ * @param dataSource - Runtime name of the data source that produced this error.
60
+ * @param options - Optional lower-level cause to preserve.
61
+ */
62
+ constructor(message: string, adapter: AdapterName, dataSource: string, options?: {
63
+ cause?: unknown;
64
+ });
65
+ }
66
+ /**
67
+ * Operational error for explicitly cancelled operations.
68
+ *
69
+ * Fixes {@link DataSourceError.category | category} to `"cancelled"`.
70
+ */
71
+ export declare class CancellationError extends DataSourceError {
72
+ /**
73
+ * @param message - Human-readable explanation of the cancellation. Must not contain credentials.
74
+ * @param adapter - Open identifier of the adapter that produced this error.
75
+ * @param dataSource - Runtime name of the data source that produced this error.
76
+ * @param options - Optional lower-level cause to preserve.
77
+ */
78
+ constructor(message: string, adapter: AdapterName, dataSource: string, options?: {
79
+ cause?: unknown;
80
+ });
81
+ }
82
+ /**
83
+ * Validation error for core contract values.
84
+ *
85
+ * Identifies the invalid field and value when the validation logic can
86
+ * reasonably determine them. Field identification is optional.
87
+ */
88
+ export declare class DataSourceValidationError extends Error {
89
+ /** Name of the invalid field, when validation can identify one. */
90
+ readonly field?: string;
91
+ /** Invalid value, when validation can safely expose it. */
92
+ readonly value?: unknown;
93
+ /**
94
+ * @param message - Human-readable explanation of the invalid value.
95
+ * @param options - Optional field, value, and lower-level cause metadata.
96
+ */
97
+ constructor(message: string, options?: {
98
+ field?: string;
99
+ value?: unknown;
100
+ cause?: unknown;
101
+ });
102
+ }
103
+ /**
104
+ * Operational error for network-level failures (connection refused,
105
+ * DNS resolution, TLS handshake, etc.).
106
+ *
107
+ * Fixes {@link DataSourceError.category | category} to `"network"`.
108
+ */
109
+ export declare class NetworkError extends DataSourceError {
110
+ /**
111
+ * @param message - Human-readable explanation of the network failure. Must not contain credentials.
112
+ * @param adapter - Open identifier of the adapter that produced this error.
113
+ * @param dataSource - Runtime name of the data source that produced this error.
114
+ * @param options - Optional lower-level cause to preserve.
115
+ */
116
+ constructor(message: string, adapter: AdapterName, dataSource: string, options?: {
117
+ cause?: unknown;
118
+ });
119
+ }
120
+ /**
121
+ * Operational error for query execution failures.
122
+ *
123
+ * Fixes {@link DataSourceError.category | category} to `"query"`.
124
+ */
125
+ export declare class QueryExecutionError extends DataSourceError {
126
+ /**
127
+ * @param message - Human-readable explanation of the query failure. Must not contain credentials.
128
+ * @param adapter - Open identifier of the adapter that produced this error.
129
+ * @param dataSource - Runtime name of the data source that produced this error.
130
+ * @param options - Optional lower-level cause to preserve.
131
+ */
132
+ constructor(message: string, adapter: AdapterName, dataSource: string, options?: {
133
+ cause?: unknown;
134
+ });
135
+ }
136
+ /**
137
+ * Operational error for operations that exceeded a time limit.
138
+ *
139
+ * Fixes {@link DataSourceError.category | category} to `"timeout"`.
140
+ */
141
+ export declare class TimeoutError extends DataSourceError {
142
+ /**
143
+ * @param message - Human-readable explanation of the timeout. Must not contain credentials.
144
+ * @param adapter - Open identifier of the adapter that produced this error.
145
+ * @param dataSource - Runtime name of the data source that produced this error.
146
+ * @param options - Optional lower-level cause to preserve.
147
+ */
148
+ constructor(message: string, adapter: AdapterName, dataSource: string, options?: {
149
+ cause?: unknown;
150
+ });
151
+ }
152
+ /**
153
+ * Operational error for operations that an adapter does not support.
154
+ *
155
+ * Fixes {@link DataSourceError.category | category} to `"unsupported"`
156
+ * and exposes the rejected {@link operation} name.
157
+ */
158
+ export declare class UnsupportedOperationError extends DataSourceError {
159
+ /** Name of the unsupported operation (e.g. `"write"`). */
160
+ readonly operation: string;
161
+ /**
162
+ * @param message - Human-readable explanation. Must not contain credentials.
163
+ * @param adapter - Open identifier of the adapter that produced this error.
164
+ * @param dataSource - Runtime name of the data source that produced this error.
165
+ * @param operation - Name of the unsupported operation.
166
+ * @param options - Optional lower-level cause to preserve.
167
+ */
168
+ constructor(message: string, adapter: AdapterName, dataSource: string, operation: string, options?: {
169
+ cause?: unknown;
170
+ });
171
+ }
172
+ /**
173
+ * Default upper bound for `perPage` when no {@link ReadValidationConfig}
174
+ * override is supplied.
175
+ */
176
+ export declare const DEFAULT_MAX_PER_PAGE = 10000;
177
+ /**
178
+ * Configuration for read-input validation.
179
+ */
180
+ interface ReadValidationConfig {
181
+ /**
182
+ * Maximum allowed `perPage` value.
183
+ *
184
+ * @default 10000
185
+ */
186
+ maxPerPage?: number;
187
+ }
188
+ /**
189
+ * Validates paging (and optional sorting) parameters before query building.
190
+ *
191
+ * Read-strategy implementations MUST call this before building or executing
192
+ * any query. Invalid input throws a {@link DataSourceValidationError} to block
193
+ * query construction.
194
+ *
195
+ * Rules:
196
+ * - `page`: finite integer ≥ 1.
197
+ * - `perPage`: finite integer between 1 and `config.maxPerPage`
198
+ * (default {@link DEFAULT_MAX_PER_PAGE}).
199
+ * - `sorting` (when present): must be an array.
200
+ *
201
+ * @param paging - One-based page number, page size, and optional sorting.
202
+ * @param config - Optional validation limits (e.g. `maxPerPage`).
203
+ * @throws {DataSourceValidationError} When any value is out of range or of the
204
+ * wrong shape.
205
+ */
206
+ export declare function validatePaging(paging: {
207
+ page: number;
208
+ perPage: number;
209
+ sorting?: readonly unknown[];
210
+ }, config?: ReadValidationConfig): void;
211
+ /**
212
+ * Adapter-neutral SQL rendering primitives shared across LakeQL adapters.
213
+ *
214
+ * These helpers own the escaping and validation semantics that every adapter
215
+ * must apply identically: control-character rejection, single-quote literal
216
+ * escaping, qualified-identifier joining, and strict plain-object detection.
217
+ * Dialect-specific identifier quoting (double-quote vs bracket doubling) stays
218
+ * per-adapter and is injected into {@link quoteQualified}.
219
+ *
220
+ * @module
221
+ */
222
+ /**
223
+ * Throws if `value` contains any C0 (U+0000–U+001F) or C1 (U+007F–U+009F)
224
+ * control character.
225
+ *
226
+ * @param value - The raw string to validate.
227
+ * @param context - Human-readable label used in the thrown error message.
228
+ * @throws {Error} If `value` contains a C0 or C1 control character.
229
+ */
230
+ export declare function rejectControlChars(value: string, context: string): void;
231
+ /**
232
+ * Escape a value as a SQL string literal.
233
+ *
234
+ * The input is treated as a string literal value. Embedded single-quote
235
+ * characters are escaped by doubling them (`'` → `''`), and the result is
236
+ * wrapped in single quotes. The escaping is identical across the Trino and
237
+ * Fabric dialects.
238
+ *
239
+ * @param value - The raw string value to escape.
240
+ * @returns The safely single-quoted literal string.
241
+ * @throws {Error} If `value` contains C0/C1 control characters.
242
+ *
243
+ * @example
244
+ * ```ts
245
+ * escapeLiteral("hello") // => "'hello'"
246
+ * escapeLiteral("it's") // => "'it''s'"
247
+ * escapeLiteral("schema'name") // => "'schema''name'"
248
+ * ```
249
+ */
250
+ export declare function escapeLiteral(value: string): string;
251
+ /**
252
+ * Quote a fully-qualified identifier composed of one or more segments.
253
+ *
254
+ * Applies the dialect-specific `quoteFn` independently to each segment and
255
+ * joins them with literal dots. Requires at least one segment. The per-segment
256
+ * quoting semantics are owned by the caller's `quoteFn`.
257
+ *
258
+ * @param quoteFn - Dialect-specific single-segment quoter (e.g. double-quote or bracket).
259
+ * @param segments - One or more raw identifier segments (e.g. catalog, schema, table).
260
+ * @returns The safely quoted qualified identifier string.
261
+ * @throws {Error} If no segments are provided, or if any segment is invalid per `quoteFn`.
262
+ *
263
+ * @example
264
+ * ```ts
265
+ * quoteQualified(quoteIdentifier, "iceberg", "public", "orders")
266
+ * // => '"iceberg"."public"."orders"' (with a double-quote quoteFn)
267
+ * ```
268
+ */
269
+ export declare function quoteQualified(quoteFn: (segment: string) => string, ...segments: string[]): string;
270
+ /**
271
+ * Returns `true` if `value` is a non-null plain object: its prototype is
272
+ * `Object.prototype` or `null`, and it is not an array.
273
+ *
274
+ * This is the strict variant shared across all adapter modules. It rejects
275
+ * class instances, Date, RegExp, and other exotic objects, and it is safe for
276
+ * prototype-less objects created via `Object.create(null)`.
277
+ *
278
+ * @param value - The value to test.
279
+ * @returns `true` if `value` is a plain object, otherwise `false`.
280
+ */
281
+ export declare function isPlainObject(value: unknown): value is Record<string, unknown>;
282
+ export { type AdapterFactory, type AdapterName, type ColumnInfo, type DataSource, type DataSourceAuth, type DataSourceCapabilities, type DataSourceErrorCategory, type DataSourceReadInput, type DataSourceReadResult, type DataSourceReadStrategy, type DataSourceWriteConfig, type DataSourceWriteInput, type DataSourceWriteStrategy, type LoadStrategy, type PrimitiveType, type QueryProps, type ReadStrategyPaging, type ReadValidationConfig, type ResolveAuth, type SourceConfig, type TableDefinition, type TypeMapper, type TypeMapperTables, UnsupportedWriteStrategy, createTypeMapper };
package/dist/index.mjs ADDED
@@ -0,0 +1 @@
1
+ import{n as e,r as t,t as n}from"./unsupported-write-strategy-MBzQRkBF.mjs";import{createTypeMapper as r}from"./type-mapper-factory.mjs";var i=class extends t{constructor(e,t,n,r){super(e,t,n,`auth`,r),this.name=`AuthenticationError`}},a=class extends t{constructor(e,t,n,r){super(e,t,n,`cancelled`,r),this.name=`CancellationError`}},o=class extends Error{field;value;constructor(e,t){super(e,{cause:t?.cause}),this.name=`DataSourceValidationError`,this.field=t?.field,this.value=t?.value}},s=class extends t{constructor(e,t,n,r){super(e,t,n,`network`,r),this.name=`NetworkError`}},c=class extends t{constructor(e,t,n,r){super(e,t,n,`query`,r),this.name=`QueryExecutionError`}},l=class extends t{constructor(e,t,n,r){super(e,t,n,`timeout`,r),this.name=`TimeoutError`}};const u=1e4;function d(e,t){let n=t?.maxPerPage??1e4;if(!Number.isInteger(e.page)||e.page<1)throw new o(`Invalid page value: ${e.page}. Must be a positive integer.`,{field:`page`,value:e.page});if(!Number.isInteger(e.perPage)||e.perPage<1)throw new o(`Invalid perPage value: ${e.perPage}. Must be a positive integer.`,{field:`perPage`,value:e.perPage});if(e.perPage>n)throw new o(`Invalid perPage value: ${e.perPage}. Must not exceed ${n}.`,{field:`perPage`,value:e.perPage});if(e.sorting!==void 0&&!Array.isArray(e.sorting))throw new o(`Invalid sorting value: expected an array.`,{field:`sorting`,value:e.sorting})}const f=/[\u0000-\u001F\u007F-\u009F]/u;function p(e,t){if(f.test(e))throw Error(`${t} must not contain control characters (C0 U+0000–U+001F or C1 U+007F–U+009F)`)}function m(e){return p(e,`String literal`),`'${e.replaceAll(`'`,`''`)}'`}function h(e,...t){if(t.length===0)throw Error(`quoteQualified requires at least one segment`);return t.map(e).join(`.`)}function g(e){if(typeof e!=`object`||!e||Array.isArray(e))return!1;let t=Object.getPrototypeOf(e);return t===Object.prototype||t===null}export{i as AuthenticationError,a as CancellationError,u as DEFAULT_MAX_PER_PAGE,t as DataSourceError,o as DataSourceValidationError,s as NetworkError,c as QueryExecutionError,l as TimeoutError,e as UnsupportedOperationError,n as UnsupportedWriteStrategy,r as createTypeMapper,m as escapeLiteral,g as isPlainObject,h as quoteQualified,p as rejectControlChars,d as validatePaging};
@@ -0,0 +1,65 @@
1
+ import { a as AdapterName, n as DataSourceWriteInput, o as SourceConfig, r as DataSourceWriteStrategy } from "../write-a_2WwSyG.mjs";
2
+ import { a as ReadStrategyPaging, c as QueryProps, f as ResolveAuth, i as DataSourceReadStrategy, l as TableDefinition, n as DataSourceReadInput, o as DataSource, r as DataSourceReadResult, s as ColumnInfo, t as AdapterFactory, u as DataSourceCapabilities } from "../adapter-factory-BzuS1VyB.mjs";
3
+ import { n as TypeMapper } from "../type-mapper-B7AlDDrp.mjs";
4
+ /**
5
+ * Minimal fake `DataSource` implementation for testing.
6
+ *
7
+ * All methods return no-op stubs. Does not import `@lakeql/config`
8
+ * or any concrete adapter package.
9
+ */
10
+ export declare class FakeDataSource implements DataSource {
11
+ readonly adapter: AdapterName;
12
+ readonly capabilities: DataSourceCapabilities;
13
+ readonly typeMapper: TypeMapper;
14
+ query<TRow>(_props: QueryProps): Promise<TRow[]>;
15
+ _streamGenerator<TRow>(): AsyncGenerator<TRow>;
16
+ stream<TRow>(_props: QueryProps): Promise<AsyncGenerator<TRow>>;
17
+ catalogs(): Promise<string[]>;
18
+ schemas(_catalog: string): Promise<string[]>;
19
+ tables(_catalog: string, _schema: string): Promise<string[]>;
20
+ views(_catalog: string, _schema: string): Promise<string[]>;
21
+ columns(_catalog: string, _schema: string, _table: string): Promise<ColumnInfo[]>;
22
+ createTable(_definition: TableDefinition): Promise<void>;
23
+ dropTable(_catalog: string, _schema: string, _table: string): Promise<void>;
24
+ qualifiedTableName(config: SourceConfig): string;
25
+ close(): Promise<void>;
26
+ }
27
+ /**
28
+ * Minimal fake `AdapterFactory` for testing.
29
+ *
30
+ * Proves that a third-party adapter can implement the factory contract
31
+ * without importing `@lakeql/config` or any concrete adapter package.
32
+ */
33
+ export declare class FakeAdapterFactory implements AdapterFactory {
34
+ readonly adapterName = "fake";
35
+ createDataSource(_config: unknown, _name: string): DataSource;
36
+ createReadStrategy(_args: {
37
+ dataSource: DataSource;
38
+ resolveAuth: ResolveAuth;
39
+ paging?: ReadStrategyPaging;
40
+ }): DataSourceReadStrategy;
41
+ createWriteStrategy(_args: {
42
+ dataSource: DataSource;
43
+ dataSourceName: string;
44
+ writeConfig: unknown;
45
+ }): DataSourceWriteStrategy;
46
+ }
47
+ /**
48
+ * Minimal fake `DataSourceReadStrategy` for testing.
49
+ *
50
+ * Returns empty results with valid page info. Does not import
51
+ * `@lakeql/config` or any concrete adapter package.
52
+ */
53
+ export declare class FakeReadStrategy implements DataSourceReadStrategy {
54
+ read: <T>(_input: DataSourceReadInput) => Promise<DataSourceReadResult<T>>;
55
+ }
56
+ /**
57
+ * Minimal fake write strategy for testing.
58
+ * Simulates a direct-insert write without importing `@lakeql/storage`.
59
+ */
60
+ export declare class FakeWriteStrategy implements DataSourceWriteStrategy {
61
+ /** Record batches received through {@link write}, in call order. */
62
+ readonly writtenRecords: Record<string, unknown>[][];
63
+ /** Records the input batch without writing it to an external system. */
64
+ write: (input: DataSourceWriteInput) => Promise<void>;
65
+ }
@@ -0,0 +1 @@
1
+ var e=class{adapter=`fake`;capabilities={query:!0,stream:!0,metadata:{catalogs:!0,schemas:!0,tables:!0,views:!0,columns:!0},write:{supported:!0,modes:[`full_load`,`append`]},ddl:{createTable:!0,dropTable:!0}};typeMapper={toPrimitiveType:e=>`String`,toEngineType:e=>e};query(e){return Promise.resolve([])}async*_streamGenerator(){}stream(e){return Promise.resolve(this._streamGenerator())}catalogs(){return Promise.resolve([])}schemas(e){return Promise.resolve([])}tables(e,t){return Promise.resolve([])}views(e,t){return Promise.resolve([])}columns(e,t,n){return Promise.resolve([])}createTable(e){return Promise.resolve()}dropTable(e,t,n){return Promise.resolve()}qualifiedTableName(e){return`${e.catalog}.${e.schema}.${e.tableName}`}close(){return Promise.resolve()}},t=class{adapterName=`fake`;createDataSource(t,n){return new e}createReadStrategy(e){return{read:async e=>({totalCount:0,pageInfo:{maxPages:0,hasNext:!1,hasPrevious:!1,currentPage:1,nextPage:null,previousPage:null},nodes:[]})}}createWriteStrategy(e){return{write:async e=>{}}}},n=class{read=async e=>({totalCount:0,pageInfo:{maxPages:0,hasNext:!1,hasPrevious:!1,currentPage:1,nextPage:null,previousPage:null},nodes:[]})},r=class{writtenRecords=[];write=async e=>{this.writtenRecords.push(e.records)}};export{t as FakeAdapterFactory,e as FakeDataSource,n as FakeReadStrategy,r as FakeWriteStrategy};
@@ -0,0 +1,43 @@
1
+ /**
2
+ * Adapter-neutral type mapping between engine-specific data types and the
3
+ * canonical LakeQL primitive type system.
4
+ *
5
+ * @module
6
+ */
7
+ /**
8
+ * The canonical LakeQL primitive types used across codegen and metadata.
9
+ *
10
+ * This union mirrors `PrimitiveType` in `@lakeql/schema-generator`
11
+ * (the source of truth). It is duplicated here on purpose: this contract
12
+ * package must not depend on an implementation package. Keep the two in sync.
13
+ */
14
+ type PrimitiveType = "String" | "Integer" | "Float" | "Boolean" | "Date" | "DateTime";
15
+ /**
16
+ * Maps between an adapter's engine-specific data types and LakeQL
17
+ * {@link PrimitiveType}s.
18
+ *
19
+ * Each adapter provides its own implementation that understands its engine's
20
+ * native type system (Trino, T-SQL, etc.).
21
+ */
22
+ interface TypeMapper {
23
+ /**
24
+ * Converts an engine-specific type string to a LakeQL {@link PrimitiveType}.
25
+ *
26
+ * Implementations SHALL normalize the input (case, type parameters) and
27
+ * fall back to `"String"` when the engine type has no known mapping.
28
+ *
29
+ * @param engineType - The engine-specific type string (e.g. `"varchar(255)"`,
30
+ * `"nvarchar"`, `"bigint"`).
31
+ * @returns The corresponding LakeQL primitive type.
32
+ */
33
+ toPrimitiveType: (engineType: string) => PrimitiveType;
34
+ /**
35
+ * Converts a LakeQL {@link PrimitiveType} to the engine's native type string.
36
+ *
37
+ * @param primitiveType - The LakeQL primitive type to convert.
38
+ * @returns The corresponding engine-specific type string (e.g. `"VARCHAR"`,
39
+ * `"BIGINT"`).
40
+ */
41
+ toEngineType: (primitiveType: PrimitiveType) => string;
42
+ }
43
+ export { TypeMapper as n, PrimitiveType as t };
@@ -0,0 +1,29 @@
1
+ /**
2
+ * Shared factory for building a {@link TypeMapper} from two lookup records.
3
+ *
4
+ * @module
5
+ */
6
+ import { n as TypeMapper, t as PrimitiveType } from "./type-mapper-B7AlDDrp.mjs";
7
+ /**
8
+ * Lookup tables that define an adapter's type mapping in both directions.
9
+ */
10
+ export interface TypeMapperTables {
11
+ /**
12
+ * Maps a normalized engine type (lowercased, without parameters) to a LakeQL
13
+ * {@link PrimitiveType}. Unknown engine types fall back to `"String"`.
14
+ */
15
+ toPrimitive: Record<string, PrimitiveType>;
16
+ /** Maps each LakeQL {@link PrimitiveType} to the engine's native type string. */
17
+ toEngine: Record<PrimitiveType, string>;
18
+ }
19
+ /**
20
+ * Builds a {@link TypeMapper} from an adapter's engine↔primitive lookup tables.
21
+ *
22
+ * The returned `toPrimitiveType` normalizes its input before the lookup and
23
+ * falls back to `"String"` for unknown engine types. `toEngineType` reads the
24
+ * mapping for the closed {@link PrimitiveType} union.
25
+ *
26
+ * @param tables - The adapter's bidirectional type-mapping tables.
27
+ * @returns A {@link TypeMapper} backed by the supplied tables.
28
+ */
29
+ export declare function createTypeMapper(tables: TypeMapperTables): TypeMapper;
@@ -0,0 +1 @@
1
+ function e(e){return e.toLowerCase().replaceAll(/\(.*\)/gu,``).trim()}function t(t){let{toPrimitive:n,toEngine:r}=t;return{toPrimitiveType(t){return n[e(t)]??`String`},toEngineType(e){return r[e]}}}export{t as createTypeMapper};
@@ -0,0 +1 @@
1
+ var e=class extends Error{adapter;dataSource;category;constructor(e,t,n,r,i){super(e,{cause:i?.cause}),this.name=`DataSourceError`,this.adapter=t,this.dataSource=n,this.category=r}},t=class extends e{operation;constructor(e,t,n,r,i){super(e,t,n,`unsupported`,i),this.name=`UnsupportedOperationError`,this.operation=r}},n=class{#e;#t;constructor(e){this.#e=e.adapter,this.#t=e.dataSource}write(e){return Promise.reject(new t(`Adapter "${this.#e}" does not support write operations`,this.#e,this.#t,`write`))}};export{t as n,e as r,n as t};
@@ -0,0 +1,31 @@
1
+ import { a as AdapterName, n as DataSourceWriteInput, r as DataSourceWriteStrategy } from "./write-a_2WwSyG.mjs";
2
+ /**
3
+ * A write strategy that rejects every write with an
4
+ * {@link UnsupportedOperationError}.
5
+ *
6
+ * Adapter factories use this to satisfy the {@link DataSourceWriteStrategy}
7
+ * contract when the adapter does not yet provide a real write path.
8
+ */
9
+ export declare class UnsupportedWriteStrategy implements DataSourceWriteStrategy {
10
+ #private;
11
+ /**
12
+ * @param options - Adapter and data-source identifiers attached to the
13
+ * rejection error.
14
+ * @param options.adapter - Open identifier of the adapter.
15
+ * @param options.dataSource - Runtime name of the data source.
16
+ */
17
+ constructor(options: {
18
+ adapter: AdapterName;
19
+ dataSource: string;
20
+ });
21
+ /**
22
+ * Always rejects with an {@link UnsupportedOperationError}.
23
+ *
24
+ * The input is intentionally ignored — the strategy does not inspect,
25
+ * destructure, validate, log, mutate, forward, or otherwise access it.
26
+ *
27
+ * @param _input - Write input (unused).
28
+ * @returns A promise that rejects with an `UnsupportedOperationError`.
29
+ */
30
+ write(_input: DataSourceWriteInput): Promise<void>;
31
+ }
@@ -0,0 +1 @@
1
+ export{t as UnsupportedWriteStrategy}from"./unsupported-write-strategy-MBzQRkBF.mjs";
@@ -0,0 +1,89 @@
1
+ /**
2
+ * Open adapter name type.
3
+ *
4
+ * Adapter identifiers are plain strings so that third-party adapters
5
+ * do not require changes to a central union type.
6
+ */
7
+ type AdapterName = string;
8
+ /**
9
+ * Shared source configuration that identifies a table within a
10
+ * data source without coupling to adapter-specific connection details.
11
+ */
12
+ interface SourceConfig {
13
+ /** Runtime name of the configured data source. */
14
+ dataSource: string;
15
+ /** Open identifier of the adapter that owns this source. */
16
+ adapter: AdapterName;
17
+ /** Source catalog containing the target table. */
18
+ catalog: string;
19
+ /** Source schema containing the target table. */
20
+ schema: string;
21
+ /** Name of the target table. */
22
+ tableName: string;
23
+ }
24
+ /**
25
+ * Supported load strategies for write operations.
26
+ *
27
+ * - `full_load` — replace the target table completely
28
+ * - `full_load_append` — replace existing partitions; append new ones
29
+ * - `append` — add records without removing existing data
30
+ */
31
+ type LoadStrategy = "full_load" | "full_load_append" | "append";
32
+ /**
33
+ * Shared write configuration containing table coordinates and
34
+ * optional common write settings. Storage-backed strategies may
35
+ * require `basePath`; direct-insert strategies omit it.
36
+ */
37
+ interface DataSourceWriteConfig {
38
+ /** Catalog, schema, and table name of the write target. */
39
+ table: {
40
+ catalog: string;
41
+ schema: string;
42
+ tableName: string;
43
+ };
44
+ /** Behavior to apply when records reach an existing target. */
45
+ loadStrategy?: LoadStrategy;
46
+ /** Storage base path required by storage-backed write strategies. */
47
+ basePath?: string;
48
+ /**
49
+ * When `true`, instructs strategies that manage shadow tables
50
+ * to retain them after the write completes. Useful for debugging
51
+ * or auditing intermediate state.
52
+ */
53
+ keepShadowTables?: boolean;
54
+ /**
55
+ * Reserved for future idempotency support. Accepting this value
56
+ * now ensures forward-compatible configuration, but it has no
57
+ * current behavioral effect.
58
+ */
59
+ writeId?: string;
60
+ /** Adapter-owned partitioning configuration. */
61
+ partitioning?: unknown;
62
+ /** Adapter-owned format for partition values. */
63
+ partitioningFormat?: string;
64
+ }
65
+ /**
66
+ * Schema-library-agnostic write input containing records, a generic
67
+ * schema value, and write configuration.
68
+ */
69
+ interface DataSourceWriteInput {
70
+ /** Records to write to the configured target. */
71
+ records: Record<string, unknown>[];
72
+ /** Schema understood by the adapter-owned write implementation. */
73
+ schema: unknown;
74
+ /** Common and adapter-owned settings for this write. */
75
+ config: DataSourceWriteConfig;
76
+ }
77
+ /**
78
+ * Strategy contract for writing data to a data source.
79
+ * Adapter-specific write implementations conform to this interface.
80
+ */
81
+ interface DataSourceWriteStrategy {
82
+ /**
83
+ * Writes the supplied records and completes when the write has finished.
84
+ *
85
+ * @param input - Records, schema, and configuration for the write operation.
86
+ */
87
+ write: (input: DataSourceWriteInput) => Promise<void>;
88
+ }
89
+ export { AdapterName as a, LoadStrategy as i, DataSourceWriteInput as n, SourceConfig as o, DataSourceWriteStrategy as r, DataSourceWriteConfig as t };
package/package.json CHANGED
@@ -1,6 +1,64 @@
1
1
  {
2
2
  "name": "@lakeql/datasource",
3
- "version": "0.0.0-stage",
4
- "stub": true,
5
- "description": "Temporary package placeholder for staged publishing"
3
+ "version": "1.0.0",
4
+ "description": "Adapter-neutral contracts for LakeQL data sources, read strategies, write strategies, and adapter factories",
5
+ "keywords": [
6
+ "contracts",
7
+ "datasource",
8
+ "lakeql",
9
+ "types"
10
+ ],
11
+ "homepage": "https://lakeql.dev",
12
+ "license": "Apache-2.0",
13
+ "author": {
14
+ "name": "Marcus Reinhardt",
15
+ "url": "https://github.com/noxify"
16
+ },
17
+ "contributors": [
18
+ {
19
+ "name": "Marcus Reinhardt",
20
+ "url": "https://github.com/noxify"
21
+ }
22
+ ],
23
+ "repository": {
24
+ "type": "git",
25
+ "url": "https://github.com/noxify/lakeql",
26
+ "directory": "packages/datasource"
27
+ },
28
+ "files": [
29
+ "dist"
30
+ ],
31
+ "type": "module",
32
+ "sideEffects": false,
33
+ "exports": {
34
+ ".": {
35
+ "types": "./dist/index.d.mts",
36
+ "import": "./dist/index.mjs"
37
+ },
38
+ "./testing": {
39
+ "types": "./dist/testing/index.d.mts",
40
+ "import": "./dist/testing/index.mjs"
41
+ }
42
+ },
43
+ "publishConfig": {
44
+ "access": "public"
45
+ },
46
+ "devDependencies": {
47
+ "@lakeql/tsconfig": "0.1.0",
48
+ "@lakeql/vitest-config": "0.1.0",
49
+ "@types/node": "24.19.2",
50
+ "fast-check": "4.10.2",
51
+ "tsdown": "0.23.7",
52
+ "typescript": "6.0.3",
53
+ "vitest": "5.1.0"
54
+ },
55
+ "scripts": {
56
+ "build": "tsdown",
57
+ "clean": "git clean -xdf .cache .turbo dist node_modules dist",
58
+ "clean:cache": "git clean -xdf .cache .turbo",
59
+ "clean:dist": "git clean -xdf dist",
60
+ "dev": "tsdown --watch",
61
+ "test": "vitest run",
62
+ "typecheck": "tsc --noEmit"
63
+ }
6
64
  }
package/README.md DELETED
@@ -1,3 +0,0 @@
1
- # Temporary Holding Version
2
-
3
- This version is a temporary placeholder for this package. An operational version to replace this has been submitted for review and is awaiting a staged release.