@noormdev/sdk 1.0.0-alpha.2 → 1.0.0-alpha.20

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 (46) hide show
  1. package/dist/chunk-3UDETNWW.js +943 -0
  2. package/dist/chunk-3UDETNWW.js.map +1 -0
  3. package/dist/chunk-D2XW2UOP.js +42 -0
  4. package/dist/chunk-D2XW2UOP.js.map +1 -0
  5. package/dist/chunk-TBRUDUBQ.js +1099 -0
  6. package/dist/chunk-TBRUDUBQ.js.map +1 -0
  7. package/dist/chunk-UDUDHOIB.js +3136 -0
  8. package/dist/chunk-UDUDHOIB.js.map +1 -0
  9. package/dist/chunk-UOFJT5PY.js +1499 -0
  10. package/dist/chunk-UOFJT5PY.js.map +1 -0
  11. package/dist/chunk-YJBKNUTP.js +7233 -0
  12. package/dist/chunk-YJBKNUTP.js.map +1 -0
  13. package/dist/chunk-ZKYTJJIF.js +308 -0
  14. package/dist/chunk-ZKYTJJIF.js.map +1 -0
  15. package/dist/csv-T5P3IN4K.js +7 -0
  16. package/dist/csv-T5P3IN4K.js.map +1 -0
  17. package/dist/engine-27DNMF4T.js +11 -0
  18. package/dist/{engine-B4JH5RQJ.js.map → engine-27DNMF4T.js.map} +1 -1
  19. package/dist/index.d.ts +2848 -1038
  20. package/dist/index.js +26190 -6890
  21. package/dist/index.js.map +1 -1
  22. package/dist/json5-LNT3RGJ7.js +7 -0
  23. package/dist/json5-LNT3RGJ7.js.map +1 -0
  24. package/dist/mssql-3NNVV77C.js +121 -0
  25. package/dist/mssql-3NNVV77C.js.map +1 -0
  26. package/dist/{mysql-C2DR4TF7.js → mysql-UPMQUBLE.js} +5 -3
  27. package/dist/mysql-UPMQUBLE.js.map +1 -0
  28. package/dist/{postgres-SIDJBSIT.js → postgres-CPVTCR7W.js} +5 -3
  29. package/dist/postgres-CPVTCR7W.js.map +1 -0
  30. package/dist/{sqlite-5VZTBN5J.js → sqlite-F3ZSSDUM.js} +5 -3
  31. package/dist/sqlite-F3ZSSDUM.js.map +1 -0
  32. package/dist/sqlite-bun-LMHUMGQI.js +60 -0
  33. package/dist/sqlite-bun-LMHUMGQI.js.map +1 -0
  34. package/dist/storage-TZNQBIX3.js +8 -0
  35. package/dist/storage-TZNQBIX3.js.map +1 -0
  36. package/dist/yaml-XI7RQ2D5.js +7 -0
  37. package/dist/yaml-XI7RQ2D5.js.map +1 -0
  38. package/package.json +8 -4
  39. package/dist/chunk-MERTHCAJ.js +0 -299
  40. package/dist/chunk-MERTHCAJ.js.map +0 -1
  41. package/dist/engine-B4JH5RQJ.js +0 -3
  42. package/dist/mssql-T4M7OGEC.js +0 -46
  43. package/dist/mssql-T4M7OGEC.js.map +0 -1
  44. package/dist/mysql-C2DR4TF7.js.map +0 -1
  45. package/dist/postgres-SIDJBSIT.js.map +0 -1
  46. package/dist/sqlite-5VZTBN5J.js.map +0 -1
@@ -0,0 +1,7 @@
1
+ import { createRequire } from 'module';
2
+ export { loadJson5 } from './chunk-TBRUDUBQ.js';
3
+ import './chunk-D2XW2UOP.js';
4
+
5
+ createRequire(import.meta.url);
6
+ //# sourceMappingURL=json5-LNT3RGJ7.js.map
7
+ //# sourceMappingURL=json5-LNT3RGJ7.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":[],"names":[],"mappings":"","file":"json5-LNT3RGJ7.js"}
@@ -0,0 +1,121 @@
1
+ import { createRequire } from 'module';
2
+ import './chunk-D2XW2UOP.js';
3
+ import { Kysely, MssqlDialect, sql, OperationNodeTransformer } from 'kysely';
4
+
5
+ createRequire(import.meta.url);
6
+ var LimitToTopTransformer = class extends OperationNodeTransformer {
7
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
8
+ transformSelectQuery(node) {
9
+ const transformed = super.transformSelectQuery(node);
10
+ if (!transformed.limit || transformed.top) {
11
+ return transformed;
12
+ }
13
+ const limitOp = transformed.limit.limit;
14
+ let value;
15
+ if (limitOp?.kind === "ValueNode" && (typeof limitOp.value === "number" || typeof limitOp.value === "bigint")) {
16
+ value = limitOp.value;
17
+ }
18
+ if (value === void 0) {
19
+ return transformed;
20
+ }
21
+ return {
22
+ ...transformed,
23
+ limit: void 0,
24
+ top: {
25
+ kind: "TopNode",
26
+ expression: value
27
+ }
28
+ };
29
+ }
30
+ };
31
+ var MssqlLimitPlugin = class {
32
+ #transformer = new LimitToTopTransformer();
33
+ transformQuery(args) {
34
+ return this.#transformer.transformNode(args.node);
35
+ }
36
+ async transformResult(args) {
37
+ return args.result;
38
+ }
39
+ };
40
+
41
+ // src/core/connection/dialects/mssql.ts
42
+ function buildTediousConfig(Tedious, config, database) {
43
+ return new Tedious.Connection({
44
+ server: config.host ?? "localhost",
45
+ authentication: {
46
+ type: "default",
47
+ options: {
48
+ userName: config.user,
49
+ password: config.password
50
+ }
51
+ },
52
+ options: {
53
+ port: config.port ?? 1433,
54
+ database: database ?? config.database,
55
+ trustServerCertificate: !config.ssl,
56
+ encrypt: true
57
+ }
58
+ });
59
+ }
60
+ async function verifyDatabaseExists(Tedious, Tarn, config) {
61
+ const masterDb = new Kysely({
62
+ dialect: new MssqlDialect({
63
+ tarn: {
64
+ ...Tarn,
65
+ options: {
66
+ min: 0,
67
+ max: 1,
68
+ propagateCreateError: true
69
+ }
70
+ },
71
+ tedious: {
72
+ ...Tedious,
73
+ connectionFactory: () => buildTediousConfig(Tedious, config, "master")
74
+ }
75
+ }),
76
+ plugins: [new MssqlLimitPlugin()]
77
+ });
78
+ try {
79
+ const { rows } = await sql`
80
+ SELECT name FROM sys.databases WHERE name = ${config.database}
81
+ `.execute(masterDb);
82
+ if (rows.length === 0) {
83
+ throw new Error(
84
+ `Database '${config.database}' does not exist on ${config.host ?? "localhost"}:${config.port ?? 1433}`
85
+ );
86
+ }
87
+ } finally {
88
+ await masterDb.destroy();
89
+ }
90
+ }
91
+ async function createMssqlConnection(config) {
92
+ const Tedious = await import('tedious');
93
+ const Tarn = await import('tarn');
94
+ await verifyDatabaseExists(Tedious, Tarn, config);
95
+ const db = new Kysely({
96
+ dialect: new MssqlDialect({
97
+ tarn: {
98
+ ...Tarn,
99
+ options: {
100
+ min: config.pool?.min ?? 0,
101
+ max: config.pool?.max ?? 10,
102
+ propagateCreateError: true
103
+ }
104
+ },
105
+ tedious: {
106
+ ...Tedious,
107
+ connectionFactory: () => buildTediousConfig(Tedious, config)
108
+ }
109
+ }),
110
+ plugins: [new MssqlLimitPlugin()]
111
+ });
112
+ return {
113
+ db,
114
+ dialect: "mssql",
115
+ destroy: () => db.destroy()
116
+ };
117
+ }
118
+
119
+ export { createMssqlConnection };
120
+ //# sourceMappingURL=mssql-3NNVV77C.js.map
121
+ //# sourceMappingURL=mssql-3NNVV77C.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../../src/core/connection/dialects/mssql-limit-plugin.ts","../../../src/core/connection/dialects/mssql.ts"],"names":[],"mappings":"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","file":"mssql-3NNVV77C.js","sourcesContent":["/**\n * Kysely plugin that converts LIMIT to TOP for MSSQL.\n *\n * Kysely 0.28.x's MssqlQueryCompiler does not override visitLimit(),\n * so .limit(n) generates invalid `LIMIT n` SQL instead of `TOP(n)`.\n * This plugin transforms the query AST before compilation, converting\n * LimitNode to TopNode on SELECT queries.\n *\n * WHY: MSSQL does not support the LIMIT keyword. It uses TOP(n) for\n * simple row limiting and OFFSET...FETCH for pagination.\n *\n * @example\n * ```typescript\n * import { Kysely, MssqlDialect } from 'kysely'\n * import { MssqlLimitPlugin } from './mssql-limit-plugin'\n *\n * const db = new Kysely({\n * dialect: new MssqlDialect({...}),\n * plugins: [new MssqlLimitPlugin()],\n * })\n *\n * // .limit() now works correctly on MSSQL\n * await db.selectFrom('users').selectAll().limit(10).execute()\n * // SQL: SELECT TOP(10) * FROM \"users\"\n * ```\n */\nimport {\n OperationNodeTransformer,\n type KyselyPlugin,\n type PluginTransformQueryArgs,\n type PluginTransformResultArgs,\n type QueryResult,\n type UnknownRow,\n} from 'kysely';\n\nimport type { RootOperationNode } from 'kysely';\n\n/**\n * AST transformer that rewrites LimitNode → TopNode on SELECT queries.\n *\n * Only transforms when:\n * - The SELECT has a limit but no top already set\n * - The limit value is a ValueNode containing a number\n */\nclass LimitToTopTransformer extends OperationNodeTransformer {\n\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n protected override transformSelectQuery(node: any): any {\n\n // Let parent transform children first (handles subqueries)\n const transformed = super.transformSelectQuery(node);\n\n // Only convert if there's a limit and no top already\n if (!transformed.limit || transformed.top) {\n\n return transformed;\n\n }\n\n // Extract the numeric value from the LimitNode\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n const limitOp = transformed.limit.limit as any;\n let value: number | bigint | undefined;\n\n if (limitOp?.kind === 'ValueNode' && (typeof limitOp.value === 'number' || typeof limitOp.value === 'bigint')) {\n\n value = limitOp.value;\n\n }\n\n // Can't convert non-literal limits\n if (value === undefined) {\n\n return transformed;\n\n }\n\n // Replace limit with top\n return {\n ...transformed,\n limit: undefined,\n top: {\n kind: 'TopNode',\n expression: value,\n },\n };\n\n }\n\n}\n\n/**\n * Kysely plugin that patches .limit() for MSSQL compatibility.\n *\n * Add to the Kysely instance via the plugins option:\n *\n * @example\n * ```typescript\n * new Kysely({ dialect, plugins: [new MssqlLimitPlugin()] })\n * ```\n */\nexport class MssqlLimitPlugin implements KyselyPlugin {\n\n readonly #transformer = new LimitToTopTransformer();\n\n transformQuery(args: PluginTransformQueryArgs): RootOperationNode {\n\n return this.#transformer.transformNode(args.node) as RootOperationNode;\n\n }\n\n async transformResult(args: PluginTransformResultArgs): Promise<QueryResult<UnknownRow>> {\n\n return args.result;\n\n }\n\n}\n","/**\n * SQL Server (MSSQL) dialect adapter.\n *\n * Uses 'tedious' and 'tarn' packages for MSSQL connections.\n * Install with: npm install tedious tarn\n *\n * Verifies database existence via sys.databases before connecting\n * to the target database, avoiding cryptic ECONNRESET errors when\n * the database doesn't exist.\n */\nimport { Kysely, MssqlDialect, sql } from 'kysely';\nimport type { ConnectionConfig, ConnectionResult } from '../types.js';\nimport { MssqlLimitPlugin } from './mssql-limit-plugin.js';\n\n/**\n * Build tedious connection options from noorm config.\n *\n * Centralizes the tedious config so both the preflight check\n * and the real pool use the same settings.\n */\nfunction buildTediousConfig(\n Tedious: typeof import('tedious'),\n config: ConnectionConfig,\n database?: string,\n) {\n\n return new Tedious.Connection({\n server: config.host ?? 'localhost',\n authentication: {\n type: 'default',\n options: {\n userName: config.user,\n password: config.password,\n },\n },\n options: {\n port: config.port ?? 1433,\n database: database ?? config.database,\n trustServerCertificate: !config.ssl,\n encrypt: true,\n },\n });\n\n}\n\n/**\n * Verify the target database exists by querying sys.databases on master.\n *\n * Connects to 'master' first and checks sys.databases. Throws a clear\n * error if the database is missing, instead of letting tedious hang\n * with a cryptic ECONNRESET.\n */\nasync function verifyDatabaseExists(\n Tedious: typeof import('tedious'),\n Tarn: typeof import('tarn'),\n config: ConnectionConfig,\n): Promise<void> {\n\n const masterDb = new Kysely<unknown>({\n dialect: new MssqlDialect({\n tarn: {\n ...Tarn,\n options: {\n min: 0,\n max: 1,\n propagateCreateError: true,\n },\n },\n tedious: {\n ...Tedious,\n connectionFactory: () => buildTediousConfig(Tedious, config, 'master'),\n },\n }),\n plugins: [new MssqlLimitPlugin()],\n });\n\n try {\n\n const { rows } = await sql<{ name: string }>`\n SELECT name FROM sys.databases WHERE name = ${config.database}\n `.execute(masterDb);\n\n if (rows.length === 0) {\n\n throw new Error(\n `Database '${config.database}' does not exist on ${config.host ?? 'localhost'}:${config.port ?? 1433}`,\n );\n\n }\n\n }\n finally {\n\n await masterDb.destroy();\n\n }\n\n}\n\n/**\n * Create a SQL Server connection.\n *\n * Verifies the target database exists via master before opening\n * the connection pool. This avoids the tedious/tarn hang that\n * occurs when MSSQL rejects login for a non-existent database.\n *\n * @example\n * ```typescript\n * const conn = createMssqlConnection({\n * dialect: 'mssql',\n * host: 'localhost',\n * port: 1433,\n * database: 'myapp',\n * user: 'sa',\n * password: 'secret',\n * })\n * ```\n */\nexport async function createMssqlConnection(config: ConnectionConfig): Promise<ConnectionResult> {\n\n // Dynamic import to avoid compile-time dependency\n const Tedious = await import('tedious');\n const Tarn = await import('tarn');\n\n // Preflight: verify database exists via master\n await verifyDatabaseExists(Tedious, Tarn, config);\n\n const db = new Kysely<unknown>({\n dialect: new MssqlDialect({\n tarn: {\n ...Tarn,\n options: {\n min: config.pool?.min ?? 0,\n max: config.pool?.max ?? 10,\n propagateCreateError: true,\n },\n },\n tedious: {\n ...Tedious,\n connectionFactory: () => buildTediousConfig(Tedious, config),\n },\n }),\n plugins: [new MssqlLimitPlugin()],\n });\n\n return {\n db,\n dialect: 'mssql',\n destroy: () => db.destroy(),\n };\n\n}\n"]}
@@ -1,6 +1,8 @@
1
+ import { createRequire } from 'module';
2
+ import './chunk-D2XW2UOP.js';
1
3
  import { Kysely, MysqlDialect } from 'kysely';
2
4
 
3
- // src/core/connection/dialects/mysql.ts
5
+ createRequire(import.meta.url);
4
6
  async function createMysqlConnection(config) {
5
7
  const mysql2 = await import('mysql2');
6
8
  const createPool = mysql2.default?.createPool ?? mysql2.createPool;
@@ -24,5 +26,5 @@ async function createMysqlConnection(config) {
24
26
  }
25
27
 
26
28
  export { createMysqlConnection };
27
- //# sourceMappingURL=mysql-C2DR4TF7.js.map
28
- //# sourceMappingURL=mysql-C2DR4TF7.js.map
29
+ //# sourceMappingURL=mysql-UPMQUBLE.js.map
30
+ //# sourceMappingURL=mysql-UPMQUBLE.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../../src/core/connection/dialects/mysql.ts"],"names":[],"mappings":";;;;;AAwBA,eAAsB,sBAAsB,MAAA,EAAqD;AAG7F,EAAA,MAAM,MAAA,GAAS,MAAM,OAAO,QAAQ,CAAA;AACpC,EAAA,MAAM,UAAA,GAAa,MAAA,CAAO,OAAA,EAAS,UAAA,IAAc,MAAA,CAAO,UAAA;AAExD,EAAA,MAAM,OAAO,UAAA,CAAW;AAAA,IACpB,IAAA,EAAM,OAAO,IAAA,IAAQ,WAAA;AAAA,IACrB,IAAA,EAAM,OAAO,IAAA,IAAQ,IAAA;AAAA,IACrB,MAAM,MAAA,CAAO,IAAA;AAAA,IACb,UAAU,MAAA,CAAO,QAAA;AAAA,IACjB,UAAU,MAAA,CAAO,QAAA;AAAA,IACjB,eAAA,EAAiB,MAAA,CAAO,IAAA,EAAM,GAAA,IAAO,EAAA;AAAA,IACrC,GAAA,EAAK,MAAA,CAAO,GAAA,GAAM,EAAC,GAAI;AAAA,GAC1B,CAAA;AAED,EAAA,MAAM,EAAA,GAAK,IAAI,MAAA,CAAgB;AAAA,IAC3B,OAAA,EAAS,IAAI,YAAA,CAAa,EAAE,MAAM;AAAA,GACrC,CAAA;AAED,EAAA,OAAO;AAAA,IACH,EAAA;AAAA,IACA,OAAA,EAAS,OAAA;AAAA,IACT,OAAA,EAAS,MAAM,EAAA,CAAG,OAAA;AAAQ,GAC9B;AAEJ","file":"mysql-UPMQUBLE.js","sourcesContent":["/**\n * MySQL dialect adapter.\n *\n * Uses the 'mysql2' package for MySQL connections.\n * Install with: npm install mysql2\n */\nimport { Kysely, MysqlDialect } from 'kysely';\nimport type { ConnectionConfig, ConnectionResult } from '../types.js';\n\n/**\n * Create a MySQL connection.\n *\n * @example\n * ```typescript\n * const conn = createMysqlConnection({\n * dialect: 'mysql',\n * host: 'localhost',\n * port: 3306,\n * database: 'myapp',\n * user: 'root',\n * password: 'secret',\n * })\n * ```\n */\nexport async function createMysqlConnection(config: ConnectionConfig): Promise<ConnectionResult> {\n\n // Dynamic import to avoid compile-time dependency\n const mysql2 = await import('mysql2');\n const createPool = mysql2.default?.createPool ?? mysql2.createPool;\n\n const pool = createPool({\n host: config.host ?? 'localhost',\n port: config.port ?? 3306,\n user: config.user,\n password: config.password,\n database: config.database,\n connectionLimit: config.pool?.max ?? 10,\n ssl: config.ssl ? {} : undefined,\n });\n\n const db = new Kysely<unknown>({\n dialect: new MysqlDialect({ pool }),\n });\n\n return {\n db,\n dialect: 'mysql',\n destroy: () => db.destroy(),\n };\n\n}\n"]}
@@ -1,6 +1,8 @@
1
+ import { createRequire } from 'module';
2
+ import './chunk-D2XW2UOP.js';
1
3
  import { Kysely, PostgresDialect } from 'kysely';
2
4
 
3
- // src/core/connection/dialects/postgres.ts
5
+ createRequire(import.meta.url);
4
6
  async function createPostgresConnection(config) {
5
7
  const pg = await import('pg');
6
8
  const Pool = pg.default?.Pool ?? pg.Pool;
@@ -25,5 +27,5 @@ async function createPostgresConnection(config) {
25
27
  }
26
28
 
27
29
  export { createPostgresConnection };
28
- //# sourceMappingURL=postgres-SIDJBSIT.js.map
29
- //# sourceMappingURL=postgres-SIDJBSIT.js.map
30
+ //# sourceMappingURL=postgres-CPVTCR7W.js.map
31
+ //# sourceMappingURL=postgres-CPVTCR7W.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../../src/core/connection/dialects/postgres.ts"],"names":[],"mappings":";;;;;AAwBA,eAAsB,yBAClB,MAAA,EACyB;AAGzB,EAAA,MAAM,EAAA,GAAK,MAAM,OAAO,IAAI,CAAA;AAC5B,EAAA,MAAM,IAAA,GAAO,EAAA,CAAG,OAAA,EAAS,IAAA,IAAQ,EAAA,CAAG,IAAA;AAEpC,EAAA,MAAM,IAAA,GAAO,IAAI,IAAA,CAAK;AAAA,IAClB,IAAA,EAAM,OAAO,IAAA,IAAQ,WAAA;AAAA,IACrB,IAAA,EAAM,OAAO,IAAA,IAAQ,IAAA;AAAA,IACrB,MAAM,MAAA,CAAO,IAAA;AAAA,IACb,UAAU,MAAA,CAAO,QAAA;AAAA,IACjB,UAAU,MAAA,CAAO,QAAA;AAAA,IACjB,GAAA,EAAK,MAAA,CAAO,IAAA,EAAM,GAAA,IAAO,CAAA;AAAA,IACzB,GAAA,EAAK,MAAA,CAAO,IAAA,EAAM,GAAA,IAAO,EAAA;AAAA,IACzB,KAAK,MAAA,CAAO;AAAA,GACf,CAAA;AAED,EAAA,MAAM,EAAA,GAAK,IAAI,MAAA,CAAgB;AAAA,IAC3B,OAAA,EAAS,IAAI,eAAA,CAAgB,EAAE,MAAM;AAAA,GACxC,CAAA;AAED,EAAA,OAAO;AAAA,IACH,EAAA;AAAA,IACA,OAAA,EAAS,UAAA;AAAA,IACT,OAAA,EAAS,MAAM,EAAA,CAAG,OAAA;AAAQ,GAC9B;AAEJ","file":"postgres-CPVTCR7W.js","sourcesContent":["/**\n * PostgreSQL dialect adapter.\n *\n * Uses the 'pg' package for PostgreSQL connections.\n * Install with: npm install pg @types/pg\n */\nimport { Kysely, PostgresDialect } from 'kysely';\nimport type { ConnectionConfig, ConnectionResult } from '../types.js';\n\n/**\n * Create a PostgreSQL connection.\n *\n * @example\n * ```typescript\n * const conn = createPostgresConnection({\n * dialect: 'postgres',\n * host: 'localhost',\n * port: 5432,\n * database: 'myapp',\n * user: 'postgres',\n * password: 'secret',\n * })\n * ```\n */\nexport async function createPostgresConnection(\n config: ConnectionConfig,\n): Promise<ConnectionResult> {\n\n // Dynamic import to avoid compile-time dependency\n const pg = await import('pg');\n const Pool = pg.default?.Pool ?? pg.Pool;\n\n const pool = new Pool({\n host: config.host ?? 'localhost',\n port: config.port ?? 5432,\n user: config.user,\n password: config.password,\n database: config.database,\n min: config.pool?.min ?? 0,\n max: config.pool?.max ?? 10,\n ssl: config.ssl,\n });\n\n const db = new Kysely<unknown>({\n dialect: new PostgresDialect({ pool }),\n });\n\n return {\n db,\n dialect: 'postgres',\n destroy: () => db.destroy(),\n };\n\n}\n"]}
@@ -1,7 +1,9 @@
1
+ import { createRequire } from 'module';
2
+ import './chunk-D2XW2UOP.js';
1
3
  import { Kysely, SqliteDialect } from 'kysely';
2
4
  import Database from 'better-sqlite3';
3
5
 
4
- // src/core/connection/dialects/sqlite.ts
6
+ createRequire(import.meta.url);
5
7
  function createSqliteConnection(config) {
6
8
  const filename = config.filename ?? config.database;
7
9
  const db = new Kysely({
@@ -17,5 +19,5 @@ function createSqliteConnection(config) {
17
19
  }
18
20
 
19
21
  export { createSqliteConnection };
20
- //# sourceMappingURL=sqlite-5VZTBN5J.js.map
21
- //# sourceMappingURL=sqlite-5VZTBN5J.js.map
22
+ //# sourceMappingURL=sqlite-F3ZSSDUM.js.map
23
+ //# sourceMappingURL=sqlite-F3ZSSDUM.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../../src/core/connection/dialects/sqlite.ts"],"names":[],"mappings":";;;;;;AAsBO,SAAS,uBAAuB,MAAA,EAA4C;AAE/E,EAAA,MAAM,QAAA,GAAW,MAAA,CAAO,QAAA,IAAY,MAAA,CAAO,QAAA;AAE3C,EAAA,MAAM,EAAA,GAAK,IAAI,MAAA,CAAgB;AAAA,IAC3B,OAAA,EAAS,IAAI,aAAA,CAAc;AAAA,MACvB,QAAA,EAAU,IAAI,QAAA,CAAS,QAAQ;AAAA,KAClC;AAAA,GACJ,CAAA;AAED,EAAA,OAAO;AAAA,IACH,EAAA;AAAA,IACA,OAAA,EAAS,QAAA;AAAA,IACT,OAAA,EAAS,MAAM,EAAA,CAAG,OAAA;AAAQ,GAC9B;AAEJ","file":"sqlite-F3ZSSDUM.js","sourcesContent":["/**\n * SQLite dialect adapter.\n *\n * Uses better-sqlite3 for synchronous, fast SQLite access.\n * Great for local development and testing.\n */\nimport { Kysely, SqliteDialect } from 'kysely';\nimport Database from 'better-sqlite3';\nimport type { ConnectionConfig, ConnectionResult } from '../types.js';\n\n/**\n * Create a SQLite connection.\n *\n * @example\n * ```typescript\n * // In-memory database\n * const conn = createSqliteConnection({ dialect: 'sqlite', database: ':memory:' })\n *\n * // File-based database\n * const conn = createSqliteConnection({ dialect: 'sqlite', database: './data.db' })\n * ```\n */\nexport function createSqliteConnection(config: ConnectionConfig): ConnectionResult {\n\n const filename = config.filename ?? config.database;\n\n const db = new Kysely<unknown>({\n dialect: new SqliteDialect({\n database: new Database(filename),\n }),\n });\n\n return {\n db,\n dialect: 'sqlite',\n destroy: () => db.destroy(),\n };\n\n}\n"]}
@@ -0,0 +1,60 @@
1
+ import { createRequire } from 'module';
2
+ import './chunk-D2XW2UOP.js';
3
+ import { Kysely, SqliteDialect } from 'kysely';
4
+ import { Database } from 'bun:sqlite';
5
+
6
+ createRequire(import.meta.url);
7
+ var BunSqliteStatement = class {
8
+ #stmt;
9
+ constructor(stmt) {
10
+ this.#stmt = stmt;
11
+ }
12
+ get reader() {
13
+ return this.#stmt.columnNames.length > 0;
14
+ }
15
+ all(params) {
16
+ return this.#stmt.all(...params);
17
+ }
18
+ run(params) {
19
+ const result = this.#stmt.run(...params);
20
+ return {
21
+ changes: result.changes,
22
+ lastInsertRowid: result.lastInsertRowid
23
+ };
24
+ }
25
+ *iterate(params) {
26
+ const rows = this.#stmt.all(...params);
27
+ for (const row of rows) {
28
+ yield row;
29
+ }
30
+ }
31
+ };
32
+ var BunSqliteDatabase = class {
33
+ #db;
34
+ constructor(filename) {
35
+ this.#db = new Database(filename);
36
+ }
37
+ close() {
38
+ this.#db.close();
39
+ }
40
+ prepare(sql) {
41
+ return new BunSqliteStatement(this.#db.prepare(sql));
42
+ }
43
+ };
44
+ function createBunSqliteConnection(config) {
45
+ const filename = config.filename ?? config.database;
46
+ const db = new Kysely({
47
+ dialect: new SqliteDialect({
48
+ database: new BunSqliteDatabase(filename)
49
+ })
50
+ });
51
+ return {
52
+ db,
53
+ dialect: "sqlite",
54
+ destroy: () => db.destroy()
55
+ };
56
+ }
57
+
58
+ export { BunSqliteDatabase, createBunSqliteConnection };
59
+ //# sourceMappingURL=sqlite-bun-LMHUMGQI.js.map
60
+ //# sourceMappingURL=sqlite-bun-LMHUMGQI.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../../src/core/connection/dialects/sqlite-bun.ts"],"names":[],"mappings":";;;;;;AAmBA,IAAM,qBAAN,MAAyB;AAAA,EAErB,KAAA;AAAA,EAEA,YAAY,IAAA,EAAuC;AAE/C,IAAA,IAAA,CAAK,KAAA,GAAQ,IAAA;AAAA,EAEjB;AAAA,EAEA,IAAI,MAAA,GAAkB;AAElB,IAAA,OAAO,IAAA,CAAK,KAAA,CAAM,WAAA,CAAY,MAAA,GAAS,CAAA;AAAA,EAE3C;AAAA,EAEA,IAAI,MAAA,EAA2C;AAE3C,IAAA,OAAO,IAAA,CAAK,KAAA,CAAM,GAAA,CAAI,GAAG,MAA4B,CAAA;AAAA,EAEzD;AAAA,EAEA,IAAI,MAAA,EAAgG;AAEhG,IAAA,MAAM,MAAA,GAAS,IAAA,CAAK,KAAA,CAAM,GAAA,CAAI,GAAG,MAA4B,CAAA;AAE7D,IAAA,OAAO;AAAA,MACH,SAAS,MAAA,CAAO,OAAA;AAAA,MAChB,iBAAiB,MAAA,CAAO;AAAA,KAC5B;AAAA,EAEJ;AAAA,EAEA,CAAC,QAAQ,MAAA,EAA2D;AAEhE,IAAA,MAAM,IAAA,GAAO,IAAA,CAAK,KAAA,CAAM,GAAA,CAAI,GAAG,MAA4B,CAAA;AAE3D,IAAA,KAAA,MAAW,OAAO,IAAA,EAAM;AAEpB,MAAA,MAAM,GAAA;AAAA,IAEV;AAAA,EAEJ;AAEJ,CAAA;AAKO,IAAM,oBAAN,MAAwB;AAAA,EAE3B,GAAA;AAAA,EAEA,YAAY,QAAA,EAAkB;AAE1B,IAAA,IAAA,CAAK,GAAA,GAAM,IAAI,QAAA,CAAS,QAAQ,CAAA;AAAA,EAEpC;AAAA,EAEA,KAAA,GAAc;AAEV,IAAA,IAAA,CAAK,IAAI,KAAA,EAAM;AAAA,EAEnB;AAAA,EAEA,QAAQ,GAAA,EAAiC;AAErC,IAAA,OAAO,IAAI,kBAAA,CAAmB,IAAA,CAAK,GAAA,CAAI,OAAA,CAAQ,GAAG,CAAC,CAAA;AAAA,EAEvD;AAEJ;AAaO,SAAS,0BAA0B,MAAA,EAA4C;AAElF,EAAA,MAAM,QAAA,GAAW,MAAA,CAAO,QAAA,IAAY,MAAA,CAAO,QAAA;AAE3C,EAAA,MAAM,EAAA,GAAK,IAAI,MAAA,CAAgB;AAAA,IAC3B,OAAA,EAAS,IAAI,aAAA,CAAc;AAAA,MACvB,QAAA,EAAU,IAAI,iBAAA,CAAkB,QAAQ;AAAA,KAC3C;AAAA,GACJ,CAAA;AAED,EAAA,OAAO;AAAA,IACH,EAAA;AAAA,IACA,OAAA,EAAS,QAAA;AAAA,IACT,OAAA,EAAS,MAAM,EAAA,CAAG,OAAA;AAAQ,GAC9B;AAEJ","file":"sqlite-bun-LMHUMGQI.js","sourcesContent":["/**\n * Bun-native SQLite dialect adapter.\n *\n * Wraps bun:sqlite to match the interface Kysely's SqliteDialect expects.\n * Provides 3-6x faster SQLite operations compared to better-sqlite3\n * by leveraging Bun's built-in SQLite driver.\n */\nimport { Kysely, SqliteDialect } from 'kysely';\n// eslint-disable-next-line @typescript-eslint/ban-ts-comment\n// @ts-ignore — bun:sqlite resolution fails in dts-bundle-generator (Node-based tooling)\nimport { Database, type SQLQueryBindings } from 'bun:sqlite';\nimport type { ConnectionConfig, ConnectionResult } from '../types.js';\n\n/**\n * Statement wrapper converting Kysely's array args to bun:sqlite's spread args.\n *\n * Kysely's SqliteDialect calls stmt.all(params) with a single ReadonlyArray,\n * while bun:sqlite expects spread arguments: stmt.all(...params).\n */\nclass BunSqliteStatement {\n\n #stmt: ReturnType<Database['prepare']>;\n\n constructor(stmt: ReturnType<Database['prepare']>) {\n\n this.#stmt = stmt;\n\n }\n\n get reader(): boolean {\n\n return this.#stmt.columnNames.length > 0;\n\n }\n\n all(params: ReadonlyArray<unknown>): unknown[] {\n\n return this.#stmt.all(...params as SQLQueryBindings[]);\n\n }\n\n run(params: ReadonlyArray<unknown>): { changes: number | bigint; lastInsertRowid: number | bigint } {\n\n const result = this.#stmt.run(...params as SQLQueryBindings[]);\n\n return {\n changes: result.changes,\n lastInsertRowid: result.lastInsertRowid,\n };\n\n }\n\n *iterate(params: ReadonlyArray<unknown>): IterableIterator<unknown> {\n\n const rows = this.#stmt.all(...params as SQLQueryBindings[]);\n\n for (const row of rows) {\n\n yield row;\n\n }\n\n }\n\n}\n\n/**\n * Database wrapper matching Kysely's expected SqliteDatabase interface.\n */\nexport class BunSqliteDatabase {\n\n #db: Database;\n\n constructor(filename: string) {\n\n this.#db = new Database(filename);\n\n }\n\n close(): void {\n\n this.#db.close();\n\n }\n\n prepare(sql: string): BunSqliteStatement {\n\n return new BunSqliteStatement(this.#db.prepare(sql));\n\n }\n\n}\n\n/**\n * Create a SQLite connection using bun:sqlite.\n *\n * Drop-in replacement for createSqliteConnection when running under Bun.\n * Uses Bun's native SQLite driver for significantly faster operations.\n *\n * @example\n * ```typescript\n * const conn = createBunSqliteConnection({ dialect: 'sqlite', database: './data.db' })\n * ```\n */\nexport function createBunSqliteConnection(config: ConnectionConfig): ConnectionResult {\n\n const filename = config.filename ?? config.database;\n\n const db = new Kysely<unknown>({\n dialect: new SqliteDialect({\n database: new BunSqliteDatabase(filename) as never,\n }),\n });\n\n return {\n db,\n dialect: 'sqlite',\n destroy: () => db.destroy(),\n };\n\n}\n"]}
@@ -0,0 +1,8 @@
1
+ import { createRequire } from 'module';
2
+ export { deleteVaultSecret, getAllVaultSecrets, getVaultKey, getVaultSecret, getVaultStatus, initializeVault, listVaultSecretKeys, setVaultSecret, vaultSecretExists } from './chunk-ZKYTJJIF.js';
3
+ import './chunk-UDUDHOIB.js';
4
+ import './chunk-D2XW2UOP.js';
5
+
6
+ createRequire(import.meta.url);
7
+ //# sourceMappingURL=storage-TZNQBIX3.js.map
8
+ //# sourceMappingURL=storage-TZNQBIX3.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":[],"names":[],"mappings":"","file":"storage-TZNQBIX3.js"}
@@ -0,0 +1,7 @@
1
+ import { createRequire } from 'module';
2
+ export { loadYaml } from './chunk-YJBKNUTP.js';
3
+ import './chunk-D2XW2UOP.js';
4
+
5
+ createRequire(import.meta.url);
6
+ //# sourceMappingURL=yaml-XI7RQ2D5.js.map
7
+ //# sourceMappingURL=yaml-XI7RQ2D5.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":[],"names":[],"mappings":"","file":"yaml-XI7RQ2D5.js"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@noormdev/sdk",
3
- "version": "1.0.0-alpha.2",
3
+ "version": "1.0.0-alpha.20",
4
4
  "description": "Database schema & changeset manager SDK",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",
@@ -42,7 +42,7 @@
42
42
  }
43
43
  },
44
44
  "engines": {
45
- "node": ">=18"
45
+ "node": ">=22.13"
46
46
  },
47
47
  "keywords": [
48
48
  "database",
@@ -52,5 +52,9 @@
52
52
  "kysely",
53
53
  "noorm"
54
54
  ],
55
- "license": "ISC"
56
- }
55
+ "license": "ISC",
56
+ "repository": {
57
+ "type": "git",
58
+ "url": "https://github.com/noormdev/noorm"
59
+ }
60
+ }
@@ -1,299 +0,0 @@
1
- import { readFile, readdir, stat } from 'fs/promises';
2
- import { Eta } from 'eta';
3
- import { ObserverEngine } from '@logosdx/observer';
4
- import path from 'path';
5
- import { attempt } from '@logosdx/utils';
6
- import { pathToFileURL } from 'url';
7
- import JSON5 from 'json5';
8
- import { parse as parse$1 } from 'yaml';
9
- import { parse } from 'csv-parse/sync';
10
- import v from 'voca';
11
-
12
- // src/core/template/engine.ts
13
- var observer = new ObserverEngine({
14
- name: "noorm",
15
- spy: process.env["NOORM_DEBUG"] ? (action) => console.error(`[noorm:${action.fn}] ${String(action.event)}`) : void 0
16
- });
17
-
18
- // src/core/template/types.ts
19
- var TEMPLATE_EXTENSION = ".tmpl";
20
- var HELPER_FILENAME = "$helpers";
21
- var HELPER_EXTENSIONS = [".ts", ".js", ".mjs"];
22
- async function loadJs(filepath) {
23
- const url = pathToFileURL(filepath).href;
24
- const urlWithCacheBust = `${url}?t=${Date.now()}`;
25
- const mod = await import(urlWithCacheBust);
26
- return mod.default !== void 0 ? mod.default : mod;
27
- }
28
-
29
- // src/core/template/helpers.ts
30
- async function findHelperFiles(fromDir, projectRoot) {
31
- const helperPaths = [];
32
- let currentDir = path.resolve(fromDir);
33
- const root = path.resolve(projectRoot);
34
- while (currentDir.startsWith(root)) {
35
- const helperPath = await findHelperInDir(currentDir);
36
- if (helperPath) {
37
- helperPaths.unshift(helperPath);
38
- }
39
- const parentDir = path.dirname(currentDir);
40
- if (parentDir === currentDir) {
41
- break;
42
- }
43
- currentDir = parentDir;
44
- }
45
- return helperPaths;
46
- }
47
- async function findHelperInDir(dir) {
48
- for (const ext of HELPER_EXTENSIONS) {
49
- const filepath = path.join(dir, `${HELPER_FILENAME}${ext}`);
50
- const [stats] = await attempt(() => stat(filepath));
51
- if (stats?.isFile()) {
52
- return filepath;
53
- }
54
- }
55
- return null;
56
- }
57
- async function loadHelpers(fromDir, projectRoot) {
58
- const helperPaths = await findHelperFiles(fromDir, projectRoot);
59
- const merged = {};
60
- for (const filepath of helperPaths) {
61
- const [mod, err] = await attempt(() => loadJs(filepath));
62
- if (err) {
63
- observer.emit("error", {
64
- source: "template",
65
- error: err,
66
- context: { filepath, operation: "load-helpers" }
67
- });
68
- continue;
69
- }
70
- if (mod && typeof mod === "object") {
71
- const exports$1 = mod;
72
- const exportCount = Object.keys(exports$1).length;
73
- Object.assign(merged, exports$1);
74
- observer.emit("template:helpers", {
75
- filepath,
76
- count: exportCount
77
- });
78
- }
79
- }
80
- return merged;
81
- }
82
- async function loadJson5(filepath) {
83
- const content = await readFile(filepath, "utf-8");
84
- return JSON5.parse(content);
85
- }
86
- async function loadYaml(filepath) {
87
- const content = await readFile(filepath, "utf-8");
88
- return parse$1(content);
89
- }
90
- async function loadCsv(filepath) {
91
- const content = await readFile(filepath, "utf-8");
92
- return parse(content, {
93
- columns: true,
94
- skip_empty_lines: true,
95
- trim: true
96
- });
97
- }
98
- async function loadSql(filepath) {
99
- return readFile(filepath, "utf-8");
100
- }
101
-
102
- // src/core/template/loaders/index.ts
103
- var loaders = {
104
- ".json": loadJson5,
105
- ".json5": loadJson5,
106
- ".yaml": loadYaml,
107
- ".yml": loadYaml,
108
- ".csv": loadCsv,
109
- ".js": loadJs,
110
- ".mjs": loadJs,
111
- ".ts": loadJs,
112
- ".sql": loadSql
113
- };
114
- function hasLoader(ext) {
115
- return ext in loaders;
116
- }
117
- function getLoader(ext) {
118
- return loaders[ext];
119
- }
120
- async function loadDataFile(filepath) {
121
- const ext = path.extname(filepath).toLowerCase();
122
- const loader = getLoader(ext);
123
- if (!loader) {
124
- throw new Error(`No loader registered for extension: ${ext}`);
125
- }
126
- return loader(filepath);
127
- }
128
- function toContextKey(filename) {
129
- const ext = path.extname(filename);
130
- const base = path.basename(filename, ext);
131
- return v.camelCase(base);
132
- }
133
- function sqlEscape(value) {
134
- return value.replace(/'/g, "''");
135
- }
136
- function sqlQuote(value) {
137
- if (value === null) {
138
- return "NULL";
139
- }
140
- return `'${sqlEscape(String(value))}'`;
141
- }
142
- function generateUuid() {
143
- return crypto.randomUUID();
144
- }
145
- function isoNow() {
146
- return (/* @__PURE__ */ new Date()).toISOString();
147
- }
148
-
149
- // src/core/template/context.ts
150
- async function buildContext(templatePath, options = {}) {
151
- const templateDir = path.dirname(templatePath);
152
- const projectRoot = options.projectRoot ?? process.cwd();
153
- const helpers = await loadHelpers(templateDir, projectRoot);
154
- const dataFiles = await loadDataFilesInDir(templateDir);
155
- const hasLocalConfig = "config" in dataFiles;
156
- const ctx = {
157
- // Inherited helpers (can be overridden by data files with same name)
158
- ...helpers,
159
- // Auto-loaded data files
160
- ...dataFiles,
161
- // Config (only if no local config.* file)
162
- ...hasLocalConfig ? {} : { config: options.config },
163
- // Secrets
164
- secrets: options.secrets ?? {},
165
- globalSecrets: options.globalSecrets ?? {},
166
- // Environment
167
- env: process.env,
168
- // Built-in helpers
169
- include: createIncludeHelper(templateDir, projectRoot, options),
170
- escape: sqlEscape,
171
- quote: sqlQuote,
172
- json: (value) => JSON.stringify(value),
173
- now: isoNow,
174
- uuid: generateUuid
175
- };
176
- return ctx;
177
- }
178
- async function loadDataFilesInDir(dir) {
179
- const data = {};
180
- const [entries, readErr] = await attempt(() => readdir(dir, { withFileTypes: true }));
181
- if (readErr || !entries) {
182
- observer.emit("error", {
183
- source: "template",
184
- error: readErr ?? new Error("Failed to read directory"),
185
- context: { dir, operation: "scan-data-files" }
186
- });
187
- return data;
188
- }
189
- for (const entry of entries) {
190
- if (!entry.isFile()) {
191
- continue;
192
- }
193
- if (entry.name.startsWith(HELPER_FILENAME)) {
194
- continue;
195
- }
196
- if (entry.name.endsWith(".tmpl")) {
197
- continue;
198
- }
199
- const ext = path.extname(entry.name).toLowerCase();
200
- if (!hasLoader(ext)) {
201
- continue;
202
- }
203
- if (ext === ".sql") {
204
- continue;
205
- }
206
- const filepath = path.join(dir, entry.name);
207
- const key = toContextKey(entry.name);
208
- const [loaded, loadErr] = await attempt(() => loadDataFile(filepath));
209
- if (loadErr) {
210
- observer.emit("error", {
211
- source: "template",
212
- error: loadErr,
213
- context: { filepath, operation: "load-data-file" }
214
- });
215
- continue;
216
- }
217
- data[key] = loaded;
218
- observer.emit("template:load", {
219
- filepath,
220
- format: ext
221
- });
222
- }
223
- return data;
224
- }
225
- function createIncludeHelper(templateDir, projectRoot, options) {
226
- return async (includePath) => {
227
- const resolved = path.resolve(templateDir, includePath);
228
- if (!resolved.startsWith(projectRoot)) {
229
- throw new Error(`Include path escapes project root: ${includePath}`);
230
- }
231
- if (resolved.endsWith(".tmpl")) {
232
- const { processFile: processFile2 } = await import('./engine-B4JH5RQJ.js');
233
- const result = await processFile2(resolved, options);
234
- return result.sql;
235
- }
236
- const [content, err] = await attempt(() => loadDataFile(resolved));
237
- if (err) {
238
- throw new Error(`Failed to include '${includePath}': ${err.message}`);
239
- }
240
- if (typeof content === "string") {
241
- return content;
242
- }
243
- return JSON.stringify(content);
244
- };
245
- }
246
-
247
- // src/core/template/engine.ts
248
- var eta = new Eta({
249
- // Custom tags for code blocks
250
- tags: ["{%", "%}"],
251
- // Variable name for context ($ instead of it)
252
- varName: "$",
253
- // Don't auto-escape (SQL doesn't need HTML escaping)
254
- autoEscape: false,
255
- // Allow async functions in templates
256
- useWith: false,
257
- // Don't cache templates (we handle caching at a higher level)
258
- cache: false
259
- });
260
- function isTemplate(filepath) {
261
- return filepath.endsWith(TEMPLATE_EXTENSION);
262
- }
263
- async function renderTemplate(template, context) {
264
- return eta.renderStringAsync(template, context);
265
- }
266
- async function processFile(filepath, options = {}) {
267
- const content = await readFile(filepath, "utf-8");
268
- if (!isTemplate(filepath)) {
269
- return {
270
- sql: content,
271
- isTemplate: false
272
- };
273
- }
274
- const start = performance.now();
275
- const context = await buildContext(filepath, options);
276
- const sql = await renderTemplate(content, context);
277
- const durationMs = performance.now() - start;
278
- observer.emit("template:render", {
279
- filepath,
280
- durationMs
281
- });
282
- return {
283
- sql,
284
- isTemplate: true,
285
- durationMs
286
- };
287
- }
288
- async function processFiles(filepaths, options = {}) {
289
- const results = [];
290
- for (const filepath of filepaths) {
291
- const result = await processFile(filepath, options);
292
- results.push(result);
293
- }
294
- return results;
295
- }
296
-
297
- export { eta, isTemplate, observer, processFile, processFiles, renderTemplate };
298
- //# sourceMappingURL=chunk-MERTHCAJ.js.map
299
- //# sourceMappingURL=chunk-MERTHCAJ.js.map