jsonstat-io 0.1.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.
Files changed (99) hide show
  1. package/LICENSE +201 -0
  2. package/README.md +200 -0
  3. package/dist/arrow/index.cjs +60 -0
  4. package/dist/arrow/index.cjs.map +1 -0
  5. package/dist/arrow/index.d.cts +125 -0
  6. package/dist/arrow/index.d.ts +125 -0
  7. package/dist/arrow/index.js +3 -0
  8. package/dist/arrow/index.js.map +1 -0
  9. package/dist/arrowToCube-BdRWZ5oG.d.cts +29 -0
  10. package/dist/arrowToCube-Mjr79ZHM.d.ts +29 -0
  11. package/dist/chunk-2HY7NRKX.js +259 -0
  12. package/dist/chunk-2HY7NRKX.js.map +1 -0
  13. package/dist/chunk-62NIY7ML.js +191 -0
  14. package/dist/chunk-62NIY7ML.js.map +1 -0
  15. package/dist/chunk-AXUZF6O5.cjs +352 -0
  16. package/dist/chunk-AXUZF6O5.cjs.map +1 -0
  17. package/dist/chunk-EFRDFQOT.js +335 -0
  18. package/dist/chunk-EFRDFQOT.js.map +1 -0
  19. package/dist/chunk-GDKDYLZ4.cjs +263 -0
  20. package/dist/chunk-GDKDYLZ4.cjs.map +1 -0
  21. package/dist/chunk-IDTQZG4B.js +432 -0
  22. package/dist/chunk-IDTQZG4B.js.map +1 -0
  23. package/dist/chunk-KFIKGBIJ.cjs +200 -0
  24. package/dist/chunk-KFIKGBIJ.cjs.map +1 -0
  25. package/dist/chunk-L65CRXTV.js +64 -0
  26. package/dist/chunk-L65CRXTV.js.map +1 -0
  27. package/dist/chunk-PHLCWTHB.cjs +446 -0
  28. package/dist/chunk-PHLCWTHB.cjs.map +1 -0
  29. package/dist/chunk-VQCS4LVD.cjs +166 -0
  30. package/dist/chunk-VQCS4LVD.cjs.map +1 -0
  31. package/dist/chunk-VYS7DPB3.js +162 -0
  32. package/dist/chunk-VYS7DPB3.js.map +1 -0
  33. package/dist/chunk-ZEDTWRDN.cjs +70 -0
  34. package/dist/chunk-ZEDTWRDN.cjs.map +1 -0
  35. package/dist/cli/index.cjs +337 -0
  36. package/dist/cli/index.cjs.map +1 -0
  37. package/dist/cli/index.d.cts +90 -0
  38. package/dist/cli/index.d.ts +90 -0
  39. package/dist/cli/index.js +333 -0
  40. package/dist/cli/index.js.map +1 -0
  41. package/dist/cubeBuilder-BEGA4C5Y.js +4 -0
  42. package/dist/cubeBuilder-BEGA4C5Y.js.map +1 -0
  43. package/dist/cubeBuilder-ZU76VVEX.cjs +25 -0
  44. package/dist/cubeBuilder-ZU76VVEX.cjs.map +1 -0
  45. package/dist/cubeReader-7QVUF3TI.js +4 -0
  46. package/dist/cubeReader-7QVUF3TI.js.map +1 -0
  47. package/dist/cubeReader-UN2BHQWK.cjs +21 -0
  48. package/dist/cubeReader-UN2BHQWK.cjs.map +1 -0
  49. package/dist/index.cjs +172 -0
  50. package/dist/index.cjs.map +1 -0
  51. package/dist/index.d.cts +445 -0
  52. package/dist/index.d.ts +445 -0
  53. package/dist/index.js +7 -0
  54. package/dist/index.js.map +1 -0
  55. package/dist/ir-BArfNxo-.d.cts +143 -0
  56. package/dist/ir-Jae2ymov.d.ts +143 -0
  57. package/dist/jsonstat-BX4mBLci.d.cts +179 -0
  58. package/dist/jsonstat-BX4mBLci.d.ts +179 -0
  59. package/dist/sources/csv.cjs +40 -0
  60. package/dist/sources/csv.cjs.map +1 -0
  61. package/dist/sources/csv.d.cts +112 -0
  62. package/dist/sources/csv.d.ts +112 -0
  63. package/dist/sources/csv.js +3 -0
  64. package/dist/sources/csv.js.map +1 -0
  65. package/dist/sources/csvw.cjs +236 -0
  66. package/dist/sources/csvw.cjs.map +1 -0
  67. package/dist/sources/csvw.d.cts +143 -0
  68. package/dist/sources/csvw.d.ts +143 -0
  69. package/dist/sources/csvw.js +230 -0
  70. package/dist/sources/csvw.js.map +1 -0
  71. package/dist/sources/duckdb.cjs +121 -0
  72. package/dist/sources/duckdb.cjs.map +1 -0
  73. package/dist/sources/duckdb.d.cts +111 -0
  74. package/dist/sources/duckdb.d.ts +111 -0
  75. package/dist/sources/duckdb.js +115 -0
  76. package/dist/sources/duckdb.js.map +1 -0
  77. package/dist/sources/parquet.cjs +117 -0
  78. package/dist/sources/parquet.cjs.map +1 -0
  79. package/dist/sources/parquet.d.cts +83 -0
  80. package/dist/sources/parquet.d.ts +83 -0
  81. package/dist/sources/parquet.js +111 -0
  82. package/dist/sources/parquet.js.map +1 -0
  83. package/dist/sources/polars.cjs +94 -0
  84. package/dist/sources/polars.cjs.map +1 -0
  85. package/dist/sources/polars.d.cts +91 -0
  86. package/dist/sources/polars.d.ts +91 -0
  87. package/dist/sources/polars.js +87 -0
  88. package/dist/sources/polars.js.map +1 -0
  89. package/docs/api.md +322 -0
  90. package/docs/architecture.md +140 -0
  91. package/docs/cli.md +159 -0
  92. package/docs/formats/arrow.md +111 -0
  93. package/docs/formats/csv.md +115 -0
  94. package/docs/formats/csvw.md +152 -0
  95. package/docs/formats/duckdb.md +151 -0
  96. package/docs/formats/parquet.md +132 -0
  97. package/docs/formats/polars.md +111 -0
  98. package/docs/mapping.md +136 -0
  99. package/package.json +119 -0
@@ -0,0 +1,83 @@
1
+ import { O as Observations } from '../ir-Jae2ymov.js';
2
+ import { J as JsonStatDataset } from '../jsonstat-BX4mBLci.js';
3
+ import { A as ArrowToCubeOptions } from '../arrowToCube-Mjr79ZHM.js';
4
+ import { Table } from 'apache-arrow';
5
+
6
+ /**
7
+ * Parquet adapter — `jsonstat-io/parquet`.
8
+ *
9
+ * **Import:** reads a Parquet file (bytes) into an Arrow [`Table`] via
10
+ * `parquet-wasm`, then funnels through the Arrow hub
11
+ * ([`arrowToCube`](../arrow/arrowToCube.ts)).
12
+ *
13
+ * **Export:** [`cubeToParquet`] writes the [`Observations`] IR to a Parquet
14
+ * file via `cubeToArrow` → `parquet-wasm` `writeParquet`.
15
+ *
16
+ * `parquet-wasm` is an **optional peer dependency** — it is imported lazily so
17
+ * that consumers who never touch Parquet pay no bundle cost. If it is not
18
+ * installed, calling [`parquetToCube`] / [`cubeToParquet`] throws a helpful
19
+ * error.
20
+ */
21
+
22
+ declare class ParquetSourceError extends Error {
23
+ constructor(message: string);
24
+ }
25
+ interface ParquetToCubeOptions extends ArrowToCubeOptions {
26
+ /**
27
+ * Async initializer for parquet-wasm (e.g. to set the WASM base URL in the
28
+ * browser). If provided, it is awaited before reading. Defaults to a no-op.
29
+ */
30
+ init?: () => Promise<void>;
31
+ }
32
+ /**
33
+ * Read a Parquet file (as `Uint8Array` / `ArrayBuffer`) into the
34
+ * [`Observations`] IR.
35
+ *
36
+ * @throws [`ParquetSourceError`] if parquet-wasm is missing or the file is invalid.
37
+ */
38
+ declare function parquetToCube(bytes: Uint8Array | ArrayBuffer, options?: ParquetToCubeOptions): Promise<Observations>;
39
+ /** Convenience: Parquet bytes → JSON-stat [`Dataset`]. */
40
+ declare function parquetToDataset(bytes: Uint8Array | ArrayBuffer, options?: ParquetToCubeOptions): Promise<JsonStatDataset>;
41
+ interface CubeToParquetOptions {
42
+ /**
43
+ * Async initializer for parquet-wasm (e.g. to set the WASM base URL in the
44
+ * browser). If provided, it is awaited before writing. Defaults to a no-op.
45
+ */
46
+ init?: () => Promise<void>;
47
+ /**
48
+ * Compression codec. Falls back to parquet-wasm's default (Snappy) when
49
+ * undefined. Friendly names (case-insensitive) accepted: `"uncompressed"`,
50
+ * `"snappy"`, `"gzip"`, `"brotli"`, `"lz4"`, `"lz4_raw"`, `"zstd"`, `"lzo"`.
51
+ * Codec availability depends on the parquet-wasm build flavor (e.g. Brotli
52
+ * may be absent in slim builds); an unavailable codec surfaces as a
53
+ * [`ParquetSourceError`].
54
+ */
55
+ compression?: string;
56
+ }
57
+ /**
58
+ * Serialize an Arrow [`Table`] to Parquet bytes using `parquet-wasm`. Extracted
59
+ * so [`cubeToParquet`] and the round-trip tests share one path.
60
+ *
61
+ * @internal
62
+ */
63
+ declare function arrowToParquet(table: Table, options?: CubeToParquetOptions): Promise<Uint8Array>;
64
+ /**
65
+ * Write the [`Observations`](../model/ir.ts) IR to a Parquet file (bytes).
66
+ *
67
+ * The IR is first converted to an Arrow [`Table`] via [`cubeToArrow`], then
68
+ * serialized to Parquet via `parquet-wasm`'s `writeParquet`. All `jsonstat.*`
69
+ * schema/field metadata is preserved, so the result round-trips through
70
+ * [`parquetToCube`].
71
+ *
72
+ * @returns A `Uint8Array` of the Parquet file.
73
+ * @throws [`ParquetSourceError`] if parquet-wasm is missing or the write fails.
74
+ *
75
+ * @example
76
+ * ```ts
77
+ * import { cubeToParquet } from "jsonstat-io/parquet";
78
+ * const bytes = await cubeToParquet(observations);
79
+ * ```
80
+ */
81
+ declare function cubeToParquet(obs: Observations, options?: CubeToParquetOptions): Promise<Uint8Array>;
82
+
83
+ export { type CubeToParquetOptions, ParquetSourceError, type ParquetToCubeOptions, arrowToParquet, cubeToParquet, parquetToCube, parquetToDataset };
@@ -0,0 +1,111 @@
1
+ import { arrowToCube, cubeToArrow } from '../chunk-IDTQZG4B.js';
2
+ import { tableFromIPC, tableToIPC } from 'apache-arrow';
3
+
4
+ var ParquetSourceError = class extends Error {
5
+ constructor(message) {
6
+ super(message);
7
+ this.name = "ParquetSourceError";
8
+ }
9
+ };
10
+ async function ensureParquetWasmInit(mod) {
11
+ const initialize = typeof mod.default === "function" ? mod.default : typeof mod.init === "function" ? mod.init : void 0;
12
+ if (initialize) await initialize();
13
+ }
14
+ async function loadParquetWasm() {
15
+ try {
16
+ const mod = await import('parquet-wasm');
17
+ await ensureParquetWasmInit(mod);
18
+ if (mod.default && typeof mod.default.readParquet === "function") return mod.default;
19
+ return mod;
20
+ } catch (e) {
21
+ throw new ParquetSourceError(
22
+ "parquet-wasm is not installed. Install it with `npm i parquet-wasm` to read Parquet files."
23
+ );
24
+ }
25
+ }
26
+ async function parquetToCube(bytes, options = {}) {
27
+ if (options.init) await options.init();
28
+ const wasm = await loadParquetWasm();
29
+ let wasmTable;
30
+ try {
31
+ wasmTable = wasm.readParquet(bytes);
32
+ } catch (e) {
33
+ throw new ParquetSourceError(`Failed to read Parquet: ${e?.message ?? e}`);
34
+ }
35
+ if (!wasmTable) throw new ParquetSourceError("parquet-wasm returned no table");
36
+ const ipc = wasmTable.intoIPCStream();
37
+ const table = tableFromIPC(ipc);
38
+ return arrowToCube(table, options);
39
+ }
40
+ async function parquetToDataset(bytes, options) {
41
+ const { toDataset } = await import('../cubeBuilder-BEGA4C5Y.js');
42
+ return toDataset(await parquetToCube(bytes, options));
43
+ }
44
+ var COMPRESSION_CODEC_KEYS = [
45
+ "uncompressed",
46
+ "snappy",
47
+ "gzip",
48
+ "brotli",
49
+ "lz4",
50
+ "lz4_raw",
51
+ "zstd",
52
+ "lzo"
53
+ ];
54
+ var COMPRESSION_CODEC_SET = new Set(COMPRESSION_CODEC_KEYS);
55
+ function buildWriterProperties(wasm, codec) {
56
+ if (!codec) return void 0;
57
+ const key = codec.toLowerCase();
58
+ if (!COMPRESSION_CODEC_SET.has(key)) {
59
+ throw new ParquetSourceError(
60
+ `Unknown compression codec "${codec}". Valid (case-insensitive): ${[...COMPRESSION_CODEC_KEYS].join(", ")}.`
61
+ );
62
+ }
63
+ const Compression = wasm.Compression;
64
+ const WriterPropertiesBuilder = wasm.WriterPropertiesBuilder;
65
+ if (!Compression || !WriterPropertiesBuilder) {
66
+ throw new ParquetSourceError(
67
+ `Cannot apply compression "${codec}": this parquet-wasm build does not export WriterPropertiesBuilder/Compression. Omit the \`compression\` option to use the default codec.`
68
+ );
69
+ }
70
+ const enumKey = key.toUpperCase();
71
+ if (!(enumKey in Compression)) {
72
+ throw new ParquetSourceError(
73
+ `Compression codec "${codec}" is not available in this parquet-wasm build. Omit the \`compression\` option to use the default codec.`
74
+ );
75
+ }
76
+ return new WriterPropertiesBuilder().setCompression(Compression[enumKey]).build();
77
+ }
78
+ async function loadParquetWriter() {
79
+ try {
80
+ const mod = await import('parquet-wasm');
81
+ await ensureParquetWasmInit(mod);
82
+ if (mod.default && typeof mod.default.writeParquet === "function") return mod.default;
83
+ return mod;
84
+ } catch {
85
+ throw new ParquetSourceError(
86
+ "parquet-wasm is not installed. Install it with `npm i parquet-wasm` to write Parquet files."
87
+ );
88
+ }
89
+ }
90
+ async function arrowToParquet(table, options = {}) {
91
+ if (options.init) await options.init();
92
+ const wasm = await loadParquetWriter();
93
+ try {
94
+ const writerProps = buildWriterProperties(wasm, options.compression);
95
+ const ipc = tableToIPC(table, "stream");
96
+ const wasmTable = wasm.Table.fromIPCStream(ipc);
97
+ const bytes = wasm.writeParquet(wasmTable, writerProps);
98
+ if (bytes instanceof Uint8Array) return bytes;
99
+ return new Uint8Array(bytes);
100
+ } catch (e) {
101
+ throw new ParquetSourceError(`Failed to write Parquet: ${e?.message ?? e}`);
102
+ }
103
+ }
104
+ async function cubeToParquet(obs, options = {}) {
105
+ const table = cubeToArrow(obs);
106
+ return arrowToParquet(table, options);
107
+ }
108
+
109
+ export { ParquetSourceError, arrowToParquet, cubeToParquet, parquetToCube, parquetToDataset };
110
+ //# sourceMappingURL=parquet.js.map
111
+ //# sourceMappingURL=parquet.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/sources/parquet.ts"],"names":[],"mappings":"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","file":"parquet.js","sourcesContent":["/**\n * Parquet adapter — `jsonstat-io/parquet`.\n *\n * **Import:** reads a Parquet file (bytes) into an Arrow [`Table`] via\n * `parquet-wasm`, then funnels through the Arrow hub\n * ([`arrowToCube`](../arrow/arrowToCube.ts)).\n *\n * **Export:** [`cubeToParquet`] writes the [`Observations`] IR to a Parquet\n * file via `cubeToArrow` → `parquet-wasm` `writeParquet`.\n *\n * `parquet-wasm` is an **optional peer dependency** — it is imported lazily so\n * that consumers who never touch Parquet pay no bundle cost. If it is not\n * installed, calling [`parquetToCube`] / [`cubeToParquet`] throws a helpful\n * error.\n */\n\nimport type { Observations } from \"../model/ir\";\nimport type { JsonStatDataset } from \"../model/jsonstat\";\nimport { arrowToCube, type ArrowToCubeOptions } from \"../arrow/arrowToCube\";\nimport { cubeToArrow } from \"../arrow/arrowFromCube\";\nimport type { Table } from \"apache-arrow\";\nimport { tableToIPC, tableFromIPC } from \"apache-arrow\";\n\n// ---------------------------------------------------------------------------\n// Errors\n// ---------------------------------------------------------------------------\n\nexport class ParquetSourceError extends Error {\n constructor(message: string) {\n super(message);\n this.name = \"ParquetSourceError\";\n }\n}\n\n// ---------------------------------------------------------------------------\n// Options\n// ---------------------------------------------------------------------------\n\nexport interface ParquetToCubeOptions extends ArrowToCubeOptions {\n /**\n * Async initializer for parquet-wasm (e.g. to set the WASM base URL in the\n * browser). If provided, it is awaited before reading. Defaults to a no-op.\n */\n init?: () => Promise<void>;\n}\n\n// ---------------------------------------------------------------------------\n// Internal: lazy parquet-wasm loader\n// ---------------------------------------------------------------------------\n\n/**\n * Dynamically import parquet-wasm and ensure its WASM binary is instantiated.\n * Kept in a function so the import is only evaluated when a Parquet read is\n * actually requested.\n *\n * parquet-wasm's ESM build exports the WASM initializer (`__wbg_init`) as the\n * module's **default** export. Calling it with no argument makes it fetch and\n * instantiate `parquet_wasm_bg.wasm` relative to the module URL. It is\n * idempotent (early-returns once `wasm` is set), so calling it again on a build\n * that already initialized — e.g. the Node/CJS build, which may auto-init — is\n * safe. Without this call, `readParquet`/`writeParquet` throw because the\n * wasm-bindgen internals (e.g. `__wbindgen_add_to_stack_pointer`) are not yet\n * wired up.\n */\nasync function ensureParquetWasmInit(mod: any): Promise<void> {\n const initialize =\n typeof mod.default === \"function\"\n ? mod.default // ESM build: default export = __wbg_init\n : typeof mod.init === \"function\"\n ? mod.init // some bundles expose a named init()\n : undefined;\n if (initialize) await initialize();\n}\n\n/**\n * Dynamically import parquet-wasm, ensure the WASM binary is ready, and return\n * the object exposing `readParquet`.\n */\nasync function loadParquetWasm(): Promise<any> {\n try {\n const mod: any = await import(\"parquet-wasm\");\n await ensureParquetWasmInit(mod);\n // After init, the named exports (readParquet, Table, ...) are ready.\n if (mod.default && typeof mod.default.readParquet === \"function\") return mod.default;\n return mod;\n } catch (e) {\n throw new ParquetSourceError(\n \"parquet-wasm is not installed. Install it with `npm i parquet-wasm` to read Parquet files.\",\n );\n }\n}\n\n// ---------------------------------------------------------------------------\n// Public API\n// ---------------------------------------------------------------------------\n\n/**\n * Read a Parquet file (as `Uint8Array` / `ArrayBuffer`) into the\n * [`Observations`] IR.\n *\n * @throws [`ParquetSourceError`] if parquet-wasm is missing or the file is invalid.\n */\nexport async function parquetToCube(\n bytes: Uint8Array | ArrayBuffer,\n options: ParquetToCubeOptions = {},\n): Promise<Observations> {\n if (options.init) await options.init();\n const wasm = await loadParquetWasm();\n let wasmTable: any;\n try {\n // parquet-wasm's readParquet returns its own Arrow Table (apache-arrow\n // interop via IPC), not the caller's apache-arrow Table.\n wasmTable = wasm.readParquet(bytes);\n } catch (e: any) {\n throw new ParquetSourceError(`Failed to read Parquet: ${e?.message ?? e}`);\n }\n if (!wasmTable) throw new ParquetSourceError(\"parquet-wasm returned no table\");\n\n // Bridge the dual-Arrow hazard: serialize via IPC (a format both copies\n // understand) and reconstruct with our apache-arrow `tableFromIPC`, exactly\n // as documented in the parquet-wasm README:\n // const arrowTable = tableFromIPC(wasmTable.intoIPCStream());\n const ipc = wasmTable.intoIPCStream();\n const table = tableFromIPC(ipc);\n return arrowToCube(table, options);\n}\n\n/** Convenience: Parquet bytes → JSON-stat [`Dataset`]. */\nexport async function parquetToDataset(\n bytes: Uint8Array | ArrayBuffer,\n options?: ParquetToCubeOptions,\n): Promise<JsonStatDataset> {\n const { toDataset } = await import(\"../core/cubeBuilder\");\n return toDataset(await parquetToCube(bytes, options));\n}\n\n// ---------------------------------------------------------------------------\n// Export: Observations IR → Parquet bytes\n// ---------------------------------------------------------------------------\n\nexport interface CubeToParquetOptions {\n /**\n * Async initializer for parquet-wasm (e.g. to set the WASM base URL in the\n * browser). If provided, it is awaited before writing. Defaults to a no-op.\n */\n init?: () => Promise<void>;\n /**\n * Compression codec. Falls back to parquet-wasm's default (Snappy) when\n * undefined. Friendly names (case-insensitive) accepted: `\"uncompressed\"`,\n * `\"snappy\"`, `\"gzip\"`, `\"brotli\"`, `\"lz4\"`, `\"lz4_raw\"`, `\"zstd\"`, `\"lzo\"`.\n * Codec availability depends on the parquet-wasm build flavor (e.g. Brotli\n * may be absent in slim builds); an unavailable codec surfaces as a\n * [`ParquetSourceError`].\n */\n compression?: string;\n}\n\n/**\n * Friendly codec name (lowercase) → parquet-wasm `Compression` enum key.\n *\n * The enum's *numeric* values are read off the loaded wasm module at runtime\n * (see [`buildWriterProperties`]) rather than hardcoded here, so the adapter\n * tracks upstream renumbering automatically. We only map names → enum keys.\n */\nconst COMPRESSION_CODEC_KEYS = [\n \"uncompressed\",\n \"snappy\",\n \"gzip\",\n \"brotli\",\n \"lz4\",\n \"lz4_raw\",\n \"zstd\",\n \"lzo\",\n] as const;\n\n/** Set of accepted codec names, for fast lowercase lookup + error messages. */\nconst COMPRESSION_CODEC_SET = new Set<string>(COMPRESSION_CODEC_KEYS);\n\n/**\n * Build a parquet-wasm `WriterProperties` for the requested codec, or return\n * `undefined` to let `writeParquet` use its default (Snappy).\n *\n * Reads the real `Compression` enum off the loaded wasm module — so we never\n * hardcode numeric values that could drift across parquet-wasm versions.\n *\n * @throws [`ParquetSourceError`] if the codec name is unknown, or if the wasm\n * build does not export `WriterPropertiesBuilder` / `Compression` / the\n * requested codec key.\n */\nfunction buildWriterProperties(wasm: any, codec: string | undefined): any {\n if (!codec) return undefined;\n const key = codec.toLowerCase();\n if (!COMPRESSION_CODEC_SET.has(key)) {\n throw new ParquetSourceError(\n `Unknown compression codec \"${codec}\". ` +\n `Valid (case-insensitive): ${[...COMPRESSION_CODEC_KEYS].join(\", \")}.`,\n );\n }\n const Compression: any = wasm.Compression;\n const WriterPropertiesBuilder: any = wasm.WriterPropertiesBuilder;\n if (!Compression || !WriterPropertiesBuilder) {\n throw new ParquetSourceError(\n `Cannot apply compression \"${codec}\": this parquet-wasm build does not ` +\n \"export WriterPropertiesBuilder/Compression. \" +\n \"Omit the `compression` option to use the default codec.\",\n );\n }\n const enumKey = key.toUpperCase();\n if (!(enumKey in Compression)) {\n throw new ParquetSourceError(\n `Compression codec \"${codec}\" is not available in this parquet-wasm ` +\n \"build. Omit the `compression` option to use the default codec.\",\n );\n }\n return new WriterPropertiesBuilder().setCompression(Compression[enumKey]).build();\n}\n\n/**\n * Resolve the parquet-wasm `writeParquet` entrypoint. Mirrors\n * [`loadParquetWasm`], but documented separately because the two bindings can\n * diverge across parquet-wasm versions.\n */\nasync function loadParquetWriter(): Promise<any> {\n try {\n const mod: any = await import(\"parquet-wasm\");\n await ensureParquetWasmInit(mod);\n if (mod.default && typeof mod.default.writeParquet === \"function\") return mod.default;\n return mod;\n } catch {\n throw new ParquetSourceError(\n \"parquet-wasm is not installed. Install it with `npm i parquet-wasm` to write Parquet files.\",\n );\n }\n}\n\n/**\n * Serialize an Arrow [`Table`] to Parquet bytes using `parquet-wasm`. Extracted\n * so [`cubeToParquet`] and the round-trip tests share one path.\n *\n * @internal\n */\nexport async function arrowToParquet(\n table: Table,\n options: CubeToParquetOptions = {},\n): Promise<Uint8Array> {\n if (options.init) await options.init();\n const wasm = await loadParquetWriter();\n try {\n // Resolve the codec to a real parquet-wasm WriterProperties instance.\n // parquet-wasm@0.6.x's writeParquet expects a WriterProperties built via\n // WriterPropertiesBuilder (NOT a plain {compression} options bag); passing\n // a plain object throws \"expected instance of WriterProperties\". When\n // `compression` is omitted we pass `undefined` so writeParquet falls back\n // to its own default (Snappy). See .idea/jsonstat-io-parquet-compression-plan.md.\n const writerProps = buildWriterProperties(wasm, options.compression);\n\n // Bridge the dual-Arrow hazard: parquet-wasm bundles its own copy of\n // apache-arrow, so an `instanceof` check against its internal `Table` fails\n // for our caller's `Table`. We serialize via IPC (a format both copies\n // understand) and reconstruct inside parquet-wasm's `Table`, exactly as\n // documented in the parquet-wasm README:\n // Table.fromIPCStream(tableToIPC(table, \"stream\"))\n const ipc = tableToIPC(table, \"stream\");\n const wasmTable = wasm.Table.fromIPCStream(ipc);\n const bytes = wasm.writeParquet(wasmTable, writerProps);\n\n // parquet-wasm returns a Uint8Array (node) or a WebAssembly.Memory-backed\n // view; normalize to Uint8Array in both runtimes.\n if (bytes instanceof Uint8Array) return bytes;\n return new Uint8Array(bytes);\n } catch (e: any) {\n throw new ParquetSourceError(`Failed to write Parquet: ${e?.message ?? e}`);\n }\n}\n\n/**\n * Write the [`Observations`](../model/ir.ts) IR to a Parquet file (bytes).\n *\n * The IR is first converted to an Arrow [`Table`] via [`cubeToArrow`], then\n * serialized to Parquet via `parquet-wasm`'s `writeParquet`. All `jsonstat.*`\n * schema/field metadata is preserved, so the result round-trips through\n * [`parquetToCube`].\n *\n * @returns A `Uint8Array` of the Parquet file.\n * @throws [`ParquetSourceError`] if parquet-wasm is missing or the write fails.\n *\n * @example\n * ```ts\n * import { cubeToParquet } from \"jsonstat-io/parquet\";\n * const bytes = await cubeToParquet(observations);\n * ```\n */\nexport async function cubeToParquet(\n obs: Observations,\n options: CubeToParquetOptions = {},\n): Promise<Uint8Array> {\n const table = cubeToArrow(obs);\n return arrowToParquet(table, options);\n}\n"]}
@@ -0,0 +1,94 @@
1
+ 'use strict';
2
+
3
+ var chunkPHLCWTHB_cjs = require('../chunk-PHLCWTHB.cjs');
4
+
5
+ // src/sources/polars.ts
6
+ var PolarsSourceError = class extends Error {
7
+ constructor(message) {
8
+ super(message);
9
+ this.name = "PolarsSourceError";
10
+ }
11
+ };
12
+ async function polarsToArrow(df, method) {
13
+ const tried = [];
14
+ const tryMethod = async (name) => {
15
+ if (typeof df[name] !== "function") {
16
+ tried.push(name);
17
+ return void 0;
18
+ }
19
+ const result = await df[name]();
20
+ return result;
21
+ };
22
+ if (method === "toArrow" || method === "auto" || method === void 0) {
23
+ const t = await tryMethod("toArrow");
24
+ if (t) return t;
25
+ }
26
+ if (method === "toIPC" || method === "auto" || method === void 0) {
27
+ const ipc = await tryMethod("toIPC");
28
+ if (ipc) {
29
+ const { tableFromIPC } = await import('apache-arrow');
30
+ return tableFromIPC(ipc);
31
+ }
32
+ }
33
+ throw new PolarsSourceError(
34
+ `Could not obtain an Arrow Table from the Polars DataFrame (tried: ${tried.join(", ")}). Ensure nodejs-polars is installed and the DataFrame supports toArrow()/toIPC().`
35
+ );
36
+ }
37
+ async function polarsToCube(df, options = {}) {
38
+ const table = await polarsToArrow(df, options.arrowMethod ?? "auto");
39
+ if (!table) throw new PolarsSourceError("Polars DataFrame yielded no Arrow table");
40
+ return chunkPHLCWTHB_cjs.arrowToCube(table, options);
41
+ }
42
+ async function polarsToDataset(df, options) {
43
+ const { toDataset } = await import('../cubeBuilder-ZU76VVEX.cjs');
44
+ return toDataset(await polarsToCube(df, options));
45
+ }
46
+ async function loadPolars() {
47
+ try {
48
+ return await import('nodejs-polars');
49
+ } catch {
50
+ throw new PolarsSourceError(
51
+ "nodejs-polars is not installed. Install it with `npm i nodejs-polars` (Node only)."
52
+ );
53
+ }
54
+ }
55
+ async function arrowToPolars(table, method = "auto") {
56
+ const pl = await loadPolars();
57
+ const tried = [];
58
+ if (method === "fromArrow" || method === "auto") {
59
+ tried.push("pl.fromArrow");
60
+ if (typeof pl.fromArrow === "function") {
61
+ try {
62
+ return pl.fromArrow(table);
63
+ } catch {
64
+ }
65
+ }
66
+ }
67
+ if (method === "ipc" || method === "auto") {
68
+ tried.push("pl.readIPC");
69
+ const { tableToIPC } = await import('apache-arrow');
70
+ const buf = tableToIPC(table, "stream");
71
+ if (typeof pl.readIPC === "function") {
72
+ try {
73
+ return pl.readIPC(buf);
74
+ } catch {
75
+ }
76
+ }
77
+ }
78
+ throw new PolarsSourceError(
79
+ `Could not build a Polars DataFrame from the Arrow Table (tried: ${tried.join(", ")}). Ensure nodejs-polars is installed and supports fromArrow()/readIPC().`
80
+ );
81
+ }
82
+ async function cubeToPolars(obs, options = {}) {
83
+ const table = chunkPHLCWTHB_cjs.cubeToArrow(obs);
84
+ return arrowToPolars(table, options.method);
85
+ }
86
+
87
+ exports.PolarsSourceError = PolarsSourceError;
88
+ exports.arrowToPolars = arrowToPolars;
89
+ exports.cubeToPolars = cubeToPolars;
90
+ exports.loadPolars = loadPolars;
91
+ exports.polarsToCube = polarsToCube;
92
+ exports.polarsToDataset = polarsToDataset;
93
+ //# sourceMappingURL=polars.cjs.map
94
+ //# sourceMappingURL=polars.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/sources/polars.ts"],"names":["arrowToCube","cubeToArrow"],"mappings":";;;;;AA6BO,IAAM,iBAAA,GAAN,cAAgC,KAAA,CAAM;AAAA,EAC3C,YAAY,OAAA,EAAiB;AAC3B,IAAA,KAAA,CAAM,OAAO,CAAA;AACb,IAAA,IAAA,CAAK,IAAA,GAAO,mBAAA;AAAA,EACd;AACF;AAwBA,eAAe,aAAA,CAAc,IAAS,MAAA,EAA0D;AAC9F,EAAA,MAAM,QAAkB,EAAC;AACzB,EAAA,MAAM,SAAA,GAAY,OAAO,IAAA,KAA+B;AACtD,IAAA,IAAI,OAAO,EAAA,CAAG,IAAI,CAAA,KAAM,UAAA,EAAY;AAClC,MAAA,KAAA,CAAM,KAAK,IAAI,CAAA;AACf,MAAA,OAAO,MAAA;AAAA,IACT;AACA,IAAA,MAAM,MAAA,GAAS,MAAM,EAAA,CAAG,IAAI,CAAA,EAAE;AAC9B,IAAA,OAAO,MAAA;AAAA,EACT,CAAA;AAEA,EAAA,IAAI,MAAA,KAAW,SAAA,IAAa,MAAA,KAAW,MAAA,IAAU,WAAW,MAAA,EAAW;AACrE,IAAA,MAAM,CAAA,GAAI,MAAM,SAAA,CAAU,SAAS,CAAA;AACnC,IAAA,IAAI,GAAG,OAAO,CAAA;AAAA,EAChB;AACA,EAAA,IAAI,MAAA,KAAW,OAAA,IAAW,MAAA,KAAW,MAAA,IAAU,WAAW,MAAA,EAAW;AACnE,IAAA,MAAM,GAAA,GAAM,MAAM,SAAA,CAAU,OAAO,CAAA;AACnC,IAAA,IAAI,GAAA,EAAK;AAEP,MAAA,MAAM,EAAE,YAAA,EAAa,GAAI,MAAM,OAAO,cAAc,CAAA;AACpD,MAAA,OAAO,aAAa,GAAG,CAAA;AAAA,IACzB;AAAA,EACF;AAEA,EAAA,MAAM,IAAI,iBAAA;AAAA,IACR,CAAA,kEAAA,EAAqE,KAAA,CAAM,IAAA,CAAK,IAAI,CAAC,CAAA,kFAAA;AAAA,GAEvF;AACF;AAaA,eAAsB,YAAA,CACpB,EAAA,EACA,OAAA,GAA+B,EAAC,EACT;AACvB,EAAA,MAAM,QAAQ,MAAM,aAAA,CAAc,EAAA,EAAI,OAAA,CAAQ,eAAe,MAAM,CAAA;AACnE,EAAA,IAAI,CAAC,KAAA,EAAO,MAAM,IAAI,kBAAkB,yCAAyC,CAAA;AACjF,EAAA,OAAOA,6BAAA,CAAY,OAAO,OAAO,CAAA;AACnC;AAGA,eAAsB,eAAA,CACpB,IACA,OAAA,EAC0B;AAC1B,EAAA,MAAM,EAAE,SAAA,EAAU,GAAI,MAAM,OAAO,6BAAqB,CAAA;AACxD,EAAA,OAAO,SAAA,CAAU,MAAM,YAAA,CAAa,EAAA,EAAI,OAAO,CAAC,CAAA;AAClD;AAMA,eAAsB,UAAA,GAA2B;AAC/C,EAAA,IAAI;AACF,IAAA,OAAO,MAAM,OAAO,eAAe,CAAA;AAAA,EACrC,CAAA,CAAA,MAAQ;AACN,IAAA,MAAM,IAAI,iBAAA;AAAA,MACR;AAAA,KACF;AAAA,EACF;AACF;AAuBA,eAAsB,aAAA,CACpB,KAAA,EACA,MAAA,GAAwC,MAAA,EAC1B;AACd,EAAA,MAAM,EAAA,GAAK,MAAM,UAAA,EAAW;AAC5B,EAAA,MAAM,QAAkB,EAAC;AAEzB,EAAA,IAAI,MAAA,KAAW,WAAA,IAAe,MAAA,KAAW,MAAA,EAAQ;AAC/C,IAAA,KAAA,CAAM,KAAK,cAAc,CAAA;AACzB,IAAA,IAAI,OAAO,EAAA,CAAG,SAAA,KAAc,UAAA,EAAY;AACtC,MAAA,IAAI;AACF,QAAA,OAAO,EAAA,CAAG,UAAU,KAAK,CAAA;AAAA,MAC3B,CAAA,CAAA,MAAQ;AAAA,MAER;AAAA,IACF;AAAA,EACF;AAEA,EAAA,IAAI,MAAA,KAAW,KAAA,IAAS,MAAA,KAAW,MAAA,EAAQ;AACzC,IAAA,KAAA,CAAM,KAAK,YAAY,CAAA;AAEvB,IAAA,MAAM,EAAE,UAAA,EAAW,GAAI,MAAM,OAAO,cAAc,CAAA;AAClD,IAAA,MAAM,GAAA,GAAM,UAAA,CAAW,KAAA,EAAO,QAAQ,CAAA;AACtC,IAAA,IAAI,OAAO,EAAA,CAAG,OAAA,KAAY,UAAA,EAAY;AACpC,MAAA,IAAI;AACF,QAAA,OAAO,EAAA,CAAG,QAAQ,GAAG,CAAA;AAAA,MACvB,CAAA,CAAA,MAAQ;AAAA,MAER;AAAA,IACF;AAAA,EACF;AAEA,EAAA,MAAM,IAAI,iBAAA;AAAA,IACR,CAAA,gEAAA,EAAmE,KAAA,CAAM,IAAA,CAAK,IAAI,CAAC,CAAA,wEAAA;AAAA,GAErF;AACF;AAuBA,eAAsB,YAAA,CACpB,GAAA,EACA,OAAA,GAA+B,EAAC,EAClB;AACd,EAAA,MAAM,KAAA,GAAQC,8BAAY,GAAG,CAAA;AAC7B,EAAA,OAAO,aAAA,CAAc,KAAA,EAAO,OAAA,CAAQ,MAAM,CAAA;AAC5C","file":"polars.cjs","sourcesContent":["/**\n * Polars adapter — `jsonstat-io/polars`.\n *\n * **Import:** accepts a Polars `DataFrame` (from `nodejs-polars`) and funnels\n * its Arrow representation through the Arrow hub\n * ([`arrowToCube`](../arrow/arrowToCube.ts)).\n *\n * **Export:** [`cubeToPolars`] builds an Arrow [`Table`] from the\n * [`Observations`] IR and converts it back to a Polars `DataFrame`.\n *\n * ## Node-only\n *\n * `nodejs-polars` is a native Node module — it cannot run in the browser. For\n * browser Polars data, convert to Arrow IPC first and use\n * `jsonstat-io/arrow` directly. This adapter is therefore documented as\n * **Node-only**; importing it in a browser bundle will fail at runtime (the\n * `nodejs-polars` import is lazy, so the failure only happens on use).\n */\n\nimport type { Observations } from \"../model/ir\";\nimport type { JsonStatDataset } from \"../model/jsonstat\";\nimport { arrowToCube, type ArrowToCubeOptions } from \"../arrow/arrowToCube\";\nimport { cubeToArrow } from \"../arrow/arrowFromCube\";\nimport type { Table } from \"apache-arrow\";\n\n// ---------------------------------------------------------------------------\n// Errors\n// ---------------------------------------------------------------------------\n\nexport class PolarsSourceError extends Error {\n constructor(message: string) {\n super(message);\n this.name = \"PolarsSourceError\";\n }\n}\n\n// ---------------------------------------------------------------------------\n// Options\n// ---------------------------------------------------------------------------\n\nexport interface PolarsToCubeOptions extends ArrowToCubeOptions {\n /**\n * Polars frames expose different Arrow conversion methods across versions\n * (`toArrow()`, `toRecords()`, etc.). The adapter tries them in order; this\n * option forces a specific one. Usually unnecessary.\n */\n arrowMethod?: \"toArrow\" | \"toIPC\" | \"auto\";\n}\n\n// ---------------------------------------------------------------------------\n// Internal: lazy nodejs-polars-free Arrow extraction\n// ---------------------------------------------------------------------------\n\n/**\n * Extract an Arrow Table from a Polars DataFrame. Tries the common conversion\n * methods. We do NOT statically import `nodejs-polars` — the caller passes a\n * DataFrame object, keeping this module free of a hard dependency.\n */\nasync function polarsToArrow(df: any, method: PolarsToCubeOptions[\"arrowMethod\"]): Promise<any> {\n const tried: string[] = [];\n const tryMethod = async (name: string): Promise<any> => {\n if (typeof df[name] !== \"function\") {\n tried.push(name);\n return undefined;\n }\n const result = await df[name]();\n return result;\n };\n\n if (method === \"toArrow\" || method === \"auto\" || method === undefined) {\n const t = await tryMethod(\"toArrow\");\n if (t) return t;\n }\n if (method === \"toIPC\" || method === \"auto\" || method === undefined) {\n const ipc = await tryMethod(\"toIPC\");\n if (ipc) {\n // IPC bytes → Arrow Table via apache-arrow's readIPC (lazy import).\n const { tableFromIPC } = await import(\"apache-arrow\");\n return tableFromIPC(ipc);\n }\n }\n\n throw new PolarsSourceError(\n `Could not obtain an Arrow Table from the Polars DataFrame (tried: ${tried.join(\", \")}). ` +\n \"Ensure nodejs-polars is installed and the DataFrame supports toArrow()/toIPC().\",\n );\n}\n\n// ---------------------------------------------------------------------------\n// Public API\n// ---------------------------------------------------------------------------\n\n/**\n * Convert a Polars `DataFrame` to the [`Observations`] IR via the Arrow hub.\n *\n * @param df A Polars DataFrame (`nodejs-polars`). Not statically typed to avoid\n * a hard dependency; pass any object exposing `toArrow()`/`toIPC()`.\n * @throws [`PolarsSourceError`] if Arrow extraction fails.\n */\nexport async function polarsToCube(\n df: any,\n options: PolarsToCubeOptions = {},\n): Promise<Observations> {\n const table = await polarsToArrow(df, options.arrowMethod ?? \"auto\");\n if (!table) throw new PolarsSourceError(\"Polars DataFrame yielded no Arrow table\");\n return arrowToCube(table, options);\n}\n\n/** Convenience: Polars DataFrame → JSON-stat [`Dataset`]. */\nexport async function polarsToDataset(\n df: any,\n options?: PolarsToCubeOptions,\n): Promise<JsonStatDataset> {\n const { toDataset } = await import(\"../core/cubeBuilder\");\n return toDataset(await polarsToCube(df, options));\n}\n\n/**\n * Lazily load `nodejs-polars`. Exposed so callers can `readCSV`/`readParquet`\n * via Polars without a direct import in their own code.\n */\nexport async function loadPolars(): Promise<any> {\n try {\n return await import(\"nodejs-polars\");\n } catch {\n throw new PolarsSourceError(\n \"nodejs-polars is not installed. Install it with `npm i nodejs-polars` (Node only).\",\n );\n }\n}\n\n// ---------------------------------------------------------------------------\n// Export: Observations IR → Polars DataFrame\n// ---------------------------------------------------------------------------\n\nexport interface CubeToPolarsOptions {\n /**\n * Conversion path from Arrow to Polars. `\"fromArrow\"` (default) uses\n * `pl.fromArrow(table)`; `\"ipc\"` serializes the table to Arrow IPC and reads\n * it via `pl.readIPC(buf)`. Usually unnecessary; `\"auto\"` tries `\"fromArrow\"`\n * first, then `\"ipc\"`.\n */\n method?: \"fromArrow\" | \"ipc\" | \"auto\";\n}\n\n/**\n * Convert an Arrow [`Table`] to a Polars `DataFrame`. Tries the common\n * nodejs-polars constructors in order. Extracted so [`cubeToPolars`] and the\n * round-trip tests share one path.\n *\n * @internal\n */\nexport async function arrowToPolars(\n table: Table,\n method: CubeToPolarsOptions[\"method\"] = \"auto\",\n): Promise<any> {\n const pl = await loadPolars();\n const tried: string[] = [];\n\n if (method === \"fromArrow\" || method === \"auto\") {\n tried.push(\"pl.fromArrow\");\n if (typeof pl.fromArrow === \"function\") {\n try {\n return pl.fromArrow(table);\n } catch {\n // fall through to ipc\n }\n }\n }\n\n if (method === \"ipc\" || method === \"auto\") {\n tried.push(\"pl.readIPC\");\n // Serialize the Arrow Table to IPC stream bytes, then read via Polars.\n const { tableToIPC } = await import(\"apache-arrow\");\n const buf = tableToIPC(table, \"stream\");\n if (typeof pl.readIPC === \"function\") {\n try {\n return pl.readIPC(buf);\n } catch {\n // fall through\n }\n }\n }\n\n throw new PolarsSourceError(\n `Could not build a Polars DataFrame from the Arrow Table (tried: ${tried.join(\", \")}). ` +\n \"Ensure nodejs-polars is installed and supports fromArrow()/readIPC().\",\n );\n}\n\n/**\n * Write the [`Observations`](../model/ir.ts) IR to a Polars `DataFrame`.\n *\n * The IR is first converted to an Arrow [`Table`] via [`cubeToArrow`], then\n * handed to `nodejs-polars` (`pl.fromArrow`). All `jsonstat.*` schema/field\n * metadata travels on the Arrow schema; Polars preserves it through the Arrow\n * IPC pathway, so a subsequent `df.toArrow()` → [`arrowToCube`] round-trips.\n *\n * Node-only: this function dynamically imports `nodejs-polars` and will throw\n * [`PolarsSourceError`] in the browser.\n *\n * @returns A Polars `DataFrame` (`nodejs-polars`).\n * @throws [`PolarsSourceError`] if nodejs-polars is missing or the conversion fails.\n *\n * @example\n * ```ts\n * import { cubeToPolars } from \"jsonstat-io/polars\";\n * const df = await cubeToPolars(observations);\n * console.log(df.shape);\n * ```\n */\nexport async function cubeToPolars(\n obs: Observations,\n options: CubeToPolarsOptions = {},\n): Promise<any> {\n const table = cubeToArrow(obs);\n return arrowToPolars(table, options.method);\n}\n"]}
@@ -0,0 +1,91 @@
1
+ import { O as Observations } from '../ir-BArfNxo-.cjs';
2
+ import { J as JsonStatDataset } from '../jsonstat-BX4mBLci.cjs';
3
+ import { A as ArrowToCubeOptions } from '../arrowToCube-BdRWZ5oG.cjs';
4
+ import { Table } from 'apache-arrow';
5
+
6
+ /**
7
+ * Polars adapter — `jsonstat-io/polars`.
8
+ *
9
+ * **Import:** accepts a Polars `DataFrame` (from `nodejs-polars`) and funnels
10
+ * its Arrow representation through the Arrow hub
11
+ * ([`arrowToCube`](../arrow/arrowToCube.ts)).
12
+ *
13
+ * **Export:** [`cubeToPolars`] builds an Arrow [`Table`] from the
14
+ * [`Observations`] IR and converts it back to a Polars `DataFrame`.
15
+ *
16
+ * ## Node-only
17
+ *
18
+ * `nodejs-polars` is a native Node module — it cannot run in the browser. For
19
+ * browser Polars data, convert to Arrow IPC first and use
20
+ * `jsonstat-io/arrow` directly. This adapter is therefore documented as
21
+ * **Node-only**; importing it in a browser bundle will fail at runtime (the
22
+ * `nodejs-polars` import is lazy, so the failure only happens on use).
23
+ */
24
+
25
+ declare class PolarsSourceError extends Error {
26
+ constructor(message: string);
27
+ }
28
+ interface PolarsToCubeOptions extends ArrowToCubeOptions {
29
+ /**
30
+ * Polars frames expose different Arrow conversion methods across versions
31
+ * (`toArrow()`, `toRecords()`, etc.). The adapter tries them in order; this
32
+ * option forces a specific one. Usually unnecessary.
33
+ */
34
+ arrowMethod?: "toArrow" | "toIPC" | "auto";
35
+ }
36
+ /**
37
+ * Convert a Polars `DataFrame` to the [`Observations`] IR via the Arrow hub.
38
+ *
39
+ * @param df A Polars DataFrame (`nodejs-polars`). Not statically typed to avoid
40
+ * a hard dependency; pass any object exposing `toArrow()`/`toIPC()`.
41
+ * @throws [`PolarsSourceError`] if Arrow extraction fails.
42
+ */
43
+ declare function polarsToCube(df: any, options?: PolarsToCubeOptions): Promise<Observations>;
44
+ /** Convenience: Polars DataFrame → JSON-stat [`Dataset`]. */
45
+ declare function polarsToDataset(df: any, options?: PolarsToCubeOptions): Promise<JsonStatDataset>;
46
+ /**
47
+ * Lazily load `nodejs-polars`. Exposed so callers can `readCSV`/`readParquet`
48
+ * via Polars without a direct import in their own code.
49
+ */
50
+ declare function loadPolars(): Promise<any>;
51
+ interface CubeToPolarsOptions {
52
+ /**
53
+ * Conversion path from Arrow to Polars. `"fromArrow"` (default) uses
54
+ * `pl.fromArrow(table)`; `"ipc"` serializes the table to Arrow IPC and reads
55
+ * it via `pl.readIPC(buf)`. Usually unnecessary; `"auto"` tries `"fromArrow"`
56
+ * first, then `"ipc"`.
57
+ */
58
+ method?: "fromArrow" | "ipc" | "auto";
59
+ }
60
+ /**
61
+ * Convert an Arrow [`Table`] to a Polars `DataFrame`. Tries the common
62
+ * nodejs-polars constructors in order. Extracted so [`cubeToPolars`] and the
63
+ * round-trip tests share one path.
64
+ *
65
+ * @internal
66
+ */
67
+ declare function arrowToPolars(table: Table, method?: CubeToPolarsOptions["method"]): Promise<any>;
68
+ /**
69
+ * Write the [`Observations`](../model/ir.ts) IR to a Polars `DataFrame`.
70
+ *
71
+ * The IR is first converted to an Arrow [`Table`] via [`cubeToArrow`], then
72
+ * handed to `nodejs-polars` (`pl.fromArrow`). All `jsonstat.*` schema/field
73
+ * metadata travels on the Arrow schema; Polars preserves it through the Arrow
74
+ * IPC pathway, so a subsequent `df.toArrow()` → [`arrowToCube`] round-trips.
75
+ *
76
+ * Node-only: this function dynamically imports `nodejs-polars` and will throw
77
+ * [`PolarsSourceError`] in the browser.
78
+ *
79
+ * @returns A Polars `DataFrame` (`nodejs-polars`).
80
+ * @throws [`PolarsSourceError`] if nodejs-polars is missing or the conversion fails.
81
+ *
82
+ * @example
83
+ * ```ts
84
+ * import { cubeToPolars } from "jsonstat-io/polars";
85
+ * const df = await cubeToPolars(observations);
86
+ * console.log(df.shape);
87
+ * ```
88
+ */
89
+ declare function cubeToPolars(obs: Observations, options?: CubeToPolarsOptions): Promise<any>;
90
+
91
+ export { type CubeToPolarsOptions, PolarsSourceError, type PolarsToCubeOptions, arrowToPolars, cubeToPolars, loadPolars, polarsToCube, polarsToDataset };
@@ -0,0 +1,91 @@
1
+ import { O as Observations } from '../ir-Jae2ymov.js';
2
+ import { J as JsonStatDataset } from '../jsonstat-BX4mBLci.js';
3
+ import { A as ArrowToCubeOptions } from '../arrowToCube-Mjr79ZHM.js';
4
+ import { Table } from 'apache-arrow';
5
+
6
+ /**
7
+ * Polars adapter — `jsonstat-io/polars`.
8
+ *
9
+ * **Import:** accepts a Polars `DataFrame` (from `nodejs-polars`) and funnels
10
+ * its Arrow representation through the Arrow hub
11
+ * ([`arrowToCube`](../arrow/arrowToCube.ts)).
12
+ *
13
+ * **Export:** [`cubeToPolars`] builds an Arrow [`Table`] from the
14
+ * [`Observations`] IR and converts it back to a Polars `DataFrame`.
15
+ *
16
+ * ## Node-only
17
+ *
18
+ * `nodejs-polars` is a native Node module — it cannot run in the browser. For
19
+ * browser Polars data, convert to Arrow IPC first and use
20
+ * `jsonstat-io/arrow` directly. This adapter is therefore documented as
21
+ * **Node-only**; importing it in a browser bundle will fail at runtime (the
22
+ * `nodejs-polars` import is lazy, so the failure only happens on use).
23
+ */
24
+
25
+ declare class PolarsSourceError extends Error {
26
+ constructor(message: string);
27
+ }
28
+ interface PolarsToCubeOptions extends ArrowToCubeOptions {
29
+ /**
30
+ * Polars frames expose different Arrow conversion methods across versions
31
+ * (`toArrow()`, `toRecords()`, etc.). The adapter tries them in order; this
32
+ * option forces a specific one. Usually unnecessary.
33
+ */
34
+ arrowMethod?: "toArrow" | "toIPC" | "auto";
35
+ }
36
+ /**
37
+ * Convert a Polars `DataFrame` to the [`Observations`] IR via the Arrow hub.
38
+ *
39
+ * @param df A Polars DataFrame (`nodejs-polars`). Not statically typed to avoid
40
+ * a hard dependency; pass any object exposing `toArrow()`/`toIPC()`.
41
+ * @throws [`PolarsSourceError`] if Arrow extraction fails.
42
+ */
43
+ declare function polarsToCube(df: any, options?: PolarsToCubeOptions): Promise<Observations>;
44
+ /** Convenience: Polars DataFrame → JSON-stat [`Dataset`]. */
45
+ declare function polarsToDataset(df: any, options?: PolarsToCubeOptions): Promise<JsonStatDataset>;
46
+ /**
47
+ * Lazily load `nodejs-polars`. Exposed so callers can `readCSV`/`readParquet`
48
+ * via Polars without a direct import in their own code.
49
+ */
50
+ declare function loadPolars(): Promise<any>;
51
+ interface CubeToPolarsOptions {
52
+ /**
53
+ * Conversion path from Arrow to Polars. `"fromArrow"` (default) uses
54
+ * `pl.fromArrow(table)`; `"ipc"` serializes the table to Arrow IPC and reads
55
+ * it via `pl.readIPC(buf)`. Usually unnecessary; `"auto"` tries `"fromArrow"`
56
+ * first, then `"ipc"`.
57
+ */
58
+ method?: "fromArrow" | "ipc" | "auto";
59
+ }
60
+ /**
61
+ * Convert an Arrow [`Table`] to a Polars `DataFrame`. Tries the common
62
+ * nodejs-polars constructors in order. Extracted so [`cubeToPolars`] and the
63
+ * round-trip tests share one path.
64
+ *
65
+ * @internal
66
+ */
67
+ declare function arrowToPolars(table: Table, method?: CubeToPolarsOptions["method"]): Promise<any>;
68
+ /**
69
+ * Write the [`Observations`](../model/ir.ts) IR to a Polars `DataFrame`.
70
+ *
71
+ * The IR is first converted to an Arrow [`Table`] via [`cubeToArrow`], then
72
+ * handed to `nodejs-polars` (`pl.fromArrow`). All `jsonstat.*` schema/field
73
+ * metadata travels on the Arrow schema; Polars preserves it through the Arrow
74
+ * IPC pathway, so a subsequent `df.toArrow()` → [`arrowToCube`] round-trips.
75
+ *
76
+ * Node-only: this function dynamically imports `nodejs-polars` and will throw
77
+ * [`PolarsSourceError`] in the browser.
78
+ *
79
+ * @returns A Polars `DataFrame` (`nodejs-polars`).
80
+ * @throws [`PolarsSourceError`] if nodejs-polars is missing or the conversion fails.
81
+ *
82
+ * @example
83
+ * ```ts
84
+ * import { cubeToPolars } from "jsonstat-io/polars";
85
+ * const df = await cubeToPolars(observations);
86
+ * console.log(df.shape);
87
+ * ```
88
+ */
89
+ declare function cubeToPolars(obs: Observations, options?: CubeToPolarsOptions): Promise<any>;
90
+
91
+ export { type CubeToPolarsOptions, PolarsSourceError, type PolarsToCubeOptions, arrowToPolars, cubeToPolars, loadPolars, polarsToCube, polarsToDataset };
@@ -0,0 +1,87 @@
1
+ import { arrowToCube, cubeToArrow } from '../chunk-IDTQZG4B.js';
2
+
3
+ // src/sources/polars.ts
4
+ var PolarsSourceError = class extends Error {
5
+ constructor(message) {
6
+ super(message);
7
+ this.name = "PolarsSourceError";
8
+ }
9
+ };
10
+ async function polarsToArrow(df, method) {
11
+ const tried = [];
12
+ const tryMethod = async (name) => {
13
+ if (typeof df[name] !== "function") {
14
+ tried.push(name);
15
+ return void 0;
16
+ }
17
+ const result = await df[name]();
18
+ return result;
19
+ };
20
+ if (method === "toArrow" || method === "auto" || method === void 0) {
21
+ const t = await tryMethod("toArrow");
22
+ if (t) return t;
23
+ }
24
+ if (method === "toIPC" || method === "auto" || method === void 0) {
25
+ const ipc = await tryMethod("toIPC");
26
+ if (ipc) {
27
+ const { tableFromIPC } = await import('apache-arrow');
28
+ return tableFromIPC(ipc);
29
+ }
30
+ }
31
+ throw new PolarsSourceError(
32
+ `Could not obtain an Arrow Table from the Polars DataFrame (tried: ${tried.join(", ")}). Ensure nodejs-polars is installed and the DataFrame supports toArrow()/toIPC().`
33
+ );
34
+ }
35
+ async function polarsToCube(df, options = {}) {
36
+ const table = await polarsToArrow(df, options.arrowMethod ?? "auto");
37
+ if (!table) throw new PolarsSourceError("Polars DataFrame yielded no Arrow table");
38
+ return arrowToCube(table, options);
39
+ }
40
+ async function polarsToDataset(df, options) {
41
+ const { toDataset } = await import('../cubeBuilder-BEGA4C5Y.js');
42
+ return toDataset(await polarsToCube(df, options));
43
+ }
44
+ async function loadPolars() {
45
+ try {
46
+ return await import('nodejs-polars');
47
+ } catch {
48
+ throw new PolarsSourceError(
49
+ "nodejs-polars is not installed. Install it with `npm i nodejs-polars` (Node only)."
50
+ );
51
+ }
52
+ }
53
+ async function arrowToPolars(table, method = "auto") {
54
+ const pl = await loadPolars();
55
+ const tried = [];
56
+ if (method === "fromArrow" || method === "auto") {
57
+ tried.push("pl.fromArrow");
58
+ if (typeof pl.fromArrow === "function") {
59
+ try {
60
+ return pl.fromArrow(table);
61
+ } catch {
62
+ }
63
+ }
64
+ }
65
+ if (method === "ipc" || method === "auto") {
66
+ tried.push("pl.readIPC");
67
+ const { tableToIPC } = await import('apache-arrow');
68
+ const buf = tableToIPC(table, "stream");
69
+ if (typeof pl.readIPC === "function") {
70
+ try {
71
+ return pl.readIPC(buf);
72
+ } catch {
73
+ }
74
+ }
75
+ }
76
+ throw new PolarsSourceError(
77
+ `Could not build a Polars DataFrame from the Arrow Table (tried: ${tried.join(", ")}). Ensure nodejs-polars is installed and supports fromArrow()/readIPC().`
78
+ );
79
+ }
80
+ async function cubeToPolars(obs, options = {}) {
81
+ const table = cubeToArrow(obs);
82
+ return arrowToPolars(table, options.method);
83
+ }
84
+
85
+ export { PolarsSourceError, arrowToPolars, cubeToPolars, loadPolars, polarsToCube, polarsToDataset };
86
+ //# sourceMappingURL=polars.js.map
87
+ //# sourceMappingURL=polars.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/sources/polars.ts"],"names":[],"mappings":"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","file":"polars.js","sourcesContent":["/**\n * Polars adapter — `jsonstat-io/polars`.\n *\n * **Import:** accepts a Polars `DataFrame` (from `nodejs-polars`) and funnels\n * its Arrow representation through the Arrow hub\n * ([`arrowToCube`](../arrow/arrowToCube.ts)).\n *\n * **Export:** [`cubeToPolars`] builds an Arrow [`Table`] from the\n * [`Observations`] IR and converts it back to a Polars `DataFrame`.\n *\n * ## Node-only\n *\n * `nodejs-polars` is a native Node module — it cannot run in the browser. For\n * browser Polars data, convert to Arrow IPC first and use\n * `jsonstat-io/arrow` directly. This adapter is therefore documented as\n * **Node-only**; importing it in a browser bundle will fail at runtime (the\n * `nodejs-polars` import is lazy, so the failure only happens on use).\n */\n\nimport type { Observations } from \"../model/ir\";\nimport type { JsonStatDataset } from \"../model/jsonstat\";\nimport { arrowToCube, type ArrowToCubeOptions } from \"../arrow/arrowToCube\";\nimport { cubeToArrow } from \"../arrow/arrowFromCube\";\nimport type { Table } from \"apache-arrow\";\n\n// ---------------------------------------------------------------------------\n// Errors\n// ---------------------------------------------------------------------------\n\nexport class PolarsSourceError extends Error {\n constructor(message: string) {\n super(message);\n this.name = \"PolarsSourceError\";\n }\n}\n\n// ---------------------------------------------------------------------------\n// Options\n// ---------------------------------------------------------------------------\n\nexport interface PolarsToCubeOptions extends ArrowToCubeOptions {\n /**\n * Polars frames expose different Arrow conversion methods across versions\n * (`toArrow()`, `toRecords()`, etc.). The adapter tries them in order; this\n * option forces a specific one. Usually unnecessary.\n */\n arrowMethod?: \"toArrow\" | \"toIPC\" | \"auto\";\n}\n\n// ---------------------------------------------------------------------------\n// Internal: lazy nodejs-polars-free Arrow extraction\n// ---------------------------------------------------------------------------\n\n/**\n * Extract an Arrow Table from a Polars DataFrame. Tries the common conversion\n * methods. We do NOT statically import `nodejs-polars` — the caller passes a\n * DataFrame object, keeping this module free of a hard dependency.\n */\nasync function polarsToArrow(df: any, method: PolarsToCubeOptions[\"arrowMethod\"]): Promise<any> {\n const tried: string[] = [];\n const tryMethod = async (name: string): Promise<any> => {\n if (typeof df[name] !== \"function\") {\n tried.push(name);\n return undefined;\n }\n const result = await df[name]();\n return result;\n };\n\n if (method === \"toArrow\" || method === \"auto\" || method === undefined) {\n const t = await tryMethod(\"toArrow\");\n if (t) return t;\n }\n if (method === \"toIPC\" || method === \"auto\" || method === undefined) {\n const ipc = await tryMethod(\"toIPC\");\n if (ipc) {\n // IPC bytes → Arrow Table via apache-arrow's readIPC (lazy import).\n const { tableFromIPC } = await import(\"apache-arrow\");\n return tableFromIPC(ipc);\n }\n }\n\n throw new PolarsSourceError(\n `Could not obtain an Arrow Table from the Polars DataFrame (tried: ${tried.join(\", \")}). ` +\n \"Ensure nodejs-polars is installed and the DataFrame supports toArrow()/toIPC().\",\n );\n}\n\n// ---------------------------------------------------------------------------\n// Public API\n// ---------------------------------------------------------------------------\n\n/**\n * Convert a Polars `DataFrame` to the [`Observations`] IR via the Arrow hub.\n *\n * @param df A Polars DataFrame (`nodejs-polars`). Not statically typed to avoid\n * a hard dependency; pass any object exposing `toArrow()`/`toIPC()`.\n * @throws [`PolarsSourceError`] if Arrow extraction fails.\n */\nexport async function polarsToCube(\n df: any,\n options: PolarsToCubeOptions = {},\n): Promise<Observations> {\n const table = await polarsToArrow(df, options.arrowMethod ?? \"auto\");\n if (!table) throw new PolarsSourceError(\"Polars DataFrame yielded no Arrow table\");\n return arrowToCube(table, options);\n}\n\n/** Convenience: Polars DataFrame → JSON-stat [`Dataset`]. */\nexport async function polarsToDataset(\n df: any,\n options?: PolarsToCubeOptions,\n): Promise<JsonStatDataset> {\n const { toDataset } = await import(\"../core/cubeBuilder\");\n return toDataset(await polarsToCube(df, options));\n}\n\n/**\n * Lazily load `nodejs-polars`. Exposed so callers can `readCSV`/`readParquet`\n * via Polars without a direct import in their own code.\n */\nexport async function loadPolars(): Promise<any> {\n try {\n return await import(\"nodejs-polars\");\n } catch {\n throw new PolarsSourceError(\n \"nodejs-polars is not installed. Install it with `npm i nodejs-polars` (Node only).\",\n );\n }\n}\n\n// ---------------------------------------------------------------------------\n// Export: Observations IR → Polars DataFrame\n// ---------------------------------------------------------------------------\n\nexport interface CubeToPolarsOptions {\n /**\n * Conversion path from Arrow to Polars. `\"fromArrow\"` (default) uses\n * `pl.fromArrow(table)`; `\"ipc\"` serializes the table to Arrow IPC and reads\n * it via `pl.readIPC(buf)`. Usually unnecessary; `\"auto\"` tries `\"fromArrow\"`\n * first, then `\"ipc\"`.\n */\n method?: \"fromArrow\" | \"ipc\" | \"auto\";\n}\n\n/**\n * Convert an Arrow [`Table`] to a Polars `DataFrame`. Tries the common\n * nodejs-polars constructors in order. Extracted so [`cubeToPolars`] and the\n * round-trip tests share one path.\n *\n * @internal\n */\nexport async function arrowToPolars(\n table: Table,\n method: CubeToPolarsOptions[\"method\"] = \"auto\",\n): Promise<any> {\n const pl = await loadPolars();\n const tried: string[] = [];\n\n if (method === \"fromArrow\" || method === \"auto\") {\n tried.push(\"pl.fromArrow\");\n if (typeof pl.fromArrow === \"function\") {\n try {\n return pl.fromArrow(table);\n } catch {\n // fall through to ipc\n }\n }\n }\n\n if (method === \"ipc\" || method === \"auto\") {\n tried.push(\"pl.readIPC\");\n // Serialize the Arrow Table to IPC stream bytes, then read via Polars.\n const { tableToIPC } = await import(\"apache-arrow\");\n const buf = tableToIPC(table, \"stream\");\n if (typeof pl.readIPC === \"function\") {\n try {\n return pl.readIPC(buf);\n } catch {\n // fall through\n }\n }\n }\n\n throw new PolarsSourceError(\n `Could not build a Polars DataFrame from the Arrow Table (tried: ${tried.join(\", \")}). ` +\n \"Ensure nodejs-polars is installed and supports fromArrow()/readIPC().\",\n );\n}\n\n/**\n * Write the [`Observations`](../model/ir.ts) IR to a Polars `DataFrame`.\n *\n * The IR is first converted to an Arrow [`Table`] via [`cubeToArrow`], then\n * handed to `nodejs-polars` (`pl.fromArrow`). All `jsonstat.*` schema/field\n * metadata travels on the Arrow schema; Polars preserves it through the Arrow\n * IPC pathway, so a subsequent `df.toArrow()` → [`arrowToCube`] round-trips.\n *\n * Node-only: this function dynamically imports `nodejs-polars` and will throw\n * [`PolarsSourceError`] in the browser.\n *\n * @returns A Polars `DataFrame` (`nodejs-polars`).\n * @throws [`PolarsSourceError`] if nodejs-polars is missing or the conversion fails.\n *\n * @example\n * ```ts\n * import { cubeToPolars } from \"jsonstat-io/polars\";\n * const df = await cubeToPolars(observations);\n * console.log(df.shape);\n * ```\n */\nexport async function cubeToPolars(\n obs: Observations,\n options: CubeToPolarsOptions = {},\n): Promise<any> {\n const table = cubeToArrow(obs);\n return arrowToPolars(table, options.method);\n}\n"]}