@noormdev/sdk 1.0.0-alpha.23 → 1.0.0-alpha.25

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.d.ts CHANGED
@@ -1971,6 +1971,38 @@ export interface ImportOptions {
1971
1971
  /** Truncate target table before import. Default: false. */
1972
1972
  truncate?: boolean;
1973
1973
  }
1974
+ /**
1975
+ * Extract the args type from a proc/func/tvf entry.
1976
+ *
1977
+ * Supports tuple form `[Args, Return]` and plain `void`.
1978
+ * Non-tuple entries pass through as-is for backward compat.
1979
+ *
1980
+ * @example
1981
+ * ```typescript
1982
+ * ExtractArgs<[{ id: number }, User]> // { id: number }
1983
+ * ExtractArgs<void> // void
1984
+ * ```
1985
+ */
1986
+ export type ExtractArgs<E> = E extends [
1987
+ infer A,
1988
+ unknown
1989
+ ] ? A : E;
1990
+ /**
1991
+ * Extract the return type from a proc/func/tvf entry.
1992
+ *
1993
+ * Returns the second element of a `[Args, Return]` tuple.
1994
+ * Falls back to `unknown` for `void` or non-tuple entries.
1995
+ *
1996
+ * @example
1997
+ * ```typescript
1998
+ * ExtractReturn<[{ id: number }, User]> // User
1999
+ * ExtractReturn<void> // unknown
2000
+ * ```
2001
+ */
2002
+ export type ExtractReturn<E> = E extends [
2003
+ unknown,
2004
+ infer R
2005
+ ] ? R : unknown;
1974
2006
  export interface ContextState {
1975
2007
  connection: ConnectionResult | null;
1976
2008
  config: Config;
@@ -3696,18 +3728,22 @@ export declare class NoormOps {
3696
3728
  * the impersonated principal. Mirrors Context's query surface without
3697
3729
  * lifecycle or noorm ops.
3698
3730
  */
3699
- export interface ImpersonatedScope<DB = unknown, Procs = object, Funcs = object> {
3731
+ export interface ImpersonatedScope<DB = unknown, Procs = object, Funcs = object, Tvfs = object> {
3700
3732
  kysely: Kysely<DB>;
3701
- proc: <T = unknown, N extends keyof Procs & string = keyof Procs & string>(name: N, ...args: Procs[N] extends void ? [
3733
+ proc: <N extends keyof Procs & string = keyof Procs & string, T = ExtractReturn<Procs[N]>>(name: N, ...args: ExtractArgs<Procs[N]> extends void ? [
3702
3734
  ] : [
3703
- params: Procs[N]
3735
+ params: ExtractArgs<Procs[N]>
3704
3736
  ]) => Promise<T[]>;
3705
- func: <T = unknown, N extends keyof Funcs & string = keyof Funcs & string>(name: N, ...args: Funcs[N] extends void ? [
3737
+ func: <N extends keyof Funcs & string = keyof Funcs & string, T = ExtractReturn<Funcs[N]>>(name: N, ...args: ExtractArgs<Funcs[N]> extends void ? [
3706
3738
  column: string
3707
3739
  ] : [
3708
- params: Funcs[N],
3740
+ params: ExtractArgs<Funcs[N]>,
3709
3741
  column: string
3710
3742
  ]) => Promise<T>;
3743
+ tvf: <N extends keyof Tvfs & string = keyof Tvfs & string, T = ExtractReturn<Tvfs[N]>>(name: N, ...args: ExtractArgs<Tvfs[N]> extends void ? [
3744
+ ] : [
3745
+ params: ExtractArgs<Tvfs[N]>
3746
+ ]) => Promise<T[]>;
3711
3747
  transaction: <T>(fn: (trx: Transaction<DB>) => Promise<T>) => Promise<T>;
3712
3748
  revert: () => Promise<void>;
3713
3749
  }
@@ -3743,7 +3779,7 @@ export declare class ImpersonationError extends Error {
3743
3779
  * await ctx.disconnect()
3744
3780
  * ```
3745
3781
  */
3746
- export declare class Context<DB = unknown, Procs = object, Funcs = object> {
3782
+ export declare class Context<DB = unknown, Procs = object, Funcs = object, Tvfs = object> {
3747
3783
  #private;
3748
3784
  constructor(config: Config, settings: Settings, identity: Identity, options: CreateContextOptions, projectRoot: string);
3749
3785
  get dialect(): Dialect;
@@ -3797,8 +3833,11 @@ export declare class Context<DB = unknown, Procs = object, Funcs = object> {
3797
3833
  *
3798
3834
  * @example
3799
3835
  * ```typescript
3800
- * // Named params
3801
- * const users = await ctx.proc<User>('get_users', { department_id: 1 });
3836
+ * // Return type inferred from tuple definition
3837
+ * const users = await ctx.proc('get_users', { department_id: 1 });
3838
+ *
3839
+ * // Explicit return type override
3840
+ * const users = await ctx.proc<'get_users', SpecialUser>('get_users', { department_id: 1 });
3802
3841
  *
3803
3842
  * // Positional params
3804
3843
  * await ctx.proc('simple_proc', [42, 'hello']);
@@ -3807,9 +3846,9 @@ export declare class Context<DB = unknown, Procs = object, Funcs = object> {
3807
3846
  * await ctx.proc('refresh_cache');
3808
3847
  * ```
3809
3848
  */
3810
- proc<T = unknown, N extends keyof Procs & string = keyof Procs & string>(name: N, ...args: Procs[N] extends void ? [
3849
+ proc<N extends keyof Procs & string = keyof Procs & string, T = ExtractReturn<Procs[N]>>(name: N, ...args: ExtractArgs<Procs[N]> extends void ? [
3811
3850
  ] : [
3812
- params: Procs[N]
3851
+ params: ExtractArgs<Procs[N]>
3813
3852
  ]): Promise<T[]>;
3814
3853
  /**
3815
3854
  * Call a database function and return the scalar result.
@@ -3819,22 +3858,45 @@ export declare class Context<DB = unknown, Procs = object, Funcs = object> {
3819
3858
  *
3820
3859
  * @example
3821
3860
  * ```typescript
3822
- * // Named params + column alias
3823
- * const result = await ctx.func<{ total: number }>('calc_total', { order_id: 42 }, 'total');
3861
+ * // Return type inferred from tuple definition
3862
+ * const result = await ctx.func('calc_total', { order_id: 42 }, 'total');
3824
3863
  *
3825
- * // Positional params + column alias
3826
- * const sum = await ctx.func<{ result: number }>('add_numbers', [1, 2], 'result');
3864
+ * // Explicit return type override
3865
+ * const result = await ctx.func<'calc_total', { total: number }>('calc_total', { order_id: 42 }, 'total');
3827
3866
  *
3828
3867
  * // No params — just column alias
3829
- * const ver = await ctx.func<{ v: string }>('get_version', 'v');
3868
+ * const ver = await ctx.func('get_version', 'v');
3830
3869
  * ```
3831
3870
  */
3832
- func<T = unknown, N extends keyof Funcs & string = keyof Funcs & string>(name: N, ...args: Funcs[N] extends void ? [
3871
+ func<N extends keyof Funcs & string = keyof Funcs & string, T = ExtractReturn<Funcs[N]>>(name: N, ...args: ExtractArgs<Funcs[N]> extends void ? [
3833
3872
  column: string
3834
3873
  ] : [
3835
- params: Funcs[N],
3874
+ params: ExtractArgs<Funcs[N]>,
3836
3875
  column: string
3837
3876
  ]): Promise<T>;
3877
+ /**
3878
+ * Call a table-valued function and return the result set.
3879
+ *
3880
+ * Generates SELECT * FROM name(...) with dialect-specific parameter
3881
+ * syntax. Returns multiple rows, unlike func() which returns a scalar.
3882
+ * Only supported on MSSQL and PostgreSQL — MySQL and SQLite throw.
3883
+ *
3884
+ * @example
3885
+ * ```typescript
3886
+ * // Return type inferred from tuple definition
3887
+ * const sessions = await ctx.tvf('validate_session', { session_key: key });
3888
+ *
3889
+ * // Explicit return type override
3890
+ * const sessions = await ctx.tvf<'validate_session', SpecialSession>('validate_session', { session_key: key });
3891
+ *
3892
+ * // No params
3893
+ * const items = await ctx.tvf('get_active_items');
3894
+ * ```
3895
+ */
3896
+ tvf<N extends keyof Tvfs & string = keyof Tvfs & string, T = ExtractReturn<Tvfs[N]>>(name: N, ...args: ExtractArgs<Tvfs[N]> extends void ? [
3897
+ ] : [
3898
+ params: ExtractArgs<Tvfs[N]>
3899
+ ]): Promise<T[]>;
3838
3900
  /**
3839
3901
  * Execute queries as a specific database principal.
3840
3902
  *
@@ -3855,8 +3917,8 @@ export declare class Context<DB = unknown, Procs = object, Funcs = object> {
3855
3917
  * await scope.revert();
3856
3918
  * ```
3857
3919
  */
3858
- impersonate<T>(username: string, fn: (scope: ImpersonatedScope<DB, Procs, Funcs>) => Promise<T>): Promise<T>;
3859
- impersonate(username: string): Promise<ImpersonatedScope<DB, Procs, Funcs>>;
3920
+ impersonate<T>(username: string, fn: (scope: ImpersonatedScope<DB, Procs, Funcs, Tvfs>) => Promise<T>): Promise<T>;
3921
+ impersonate(username: string): Promise<ImpersonatedScope<DB, Procs, Funcs, Tvfs>>;
3860
3922
  }
3861
3923
  /**
3862
3924
  * Error thrown when requireTest is enabled but config.isTest is false.
@@ -3925,7 +3987,7 @@ export declare class ProtectedConfigError extends Error {
3925
3987
  * const ctx = await createContext()
3926
3988
  * ```
3927
3989
  */
3928
- export declare function createContext<DB = unknown, Procs = object, Funcs = object>(options?: CreateContextOptions): Promise<Context<DB, Procs, Funcs>>;
3990
+ export declare function createContext<DB = unknown, Procs = object, Funcs = object, Tvfs = object>(options?: CreateContextOptions): Promise<Context<DB, Procs, Funcs, Tvfs>>;
3929
3991
 
3930
3992
  export {
3931
3993
  Lock$1 as Lock,
package/dist/index.js CHANGED
@@ -16828,6 +16828,27 @@ function buildFuncCall(dialect, name, column, params) {
16828
16828
  const joined = sql.join(values.map((v) => sql`${v}`));
16829
16829
  return sql`SELECT ${rawName}(${joined}) AS ${rawCol}`;
16830
16830
  }
16831
+ function buildTvfCall(dialect, name, params) {
16832
+ if (dialect === "sqlite") {
16833
+ throw new Error("SQLite does not support table-valued functions.");
16834
+ }
16835
+ if (dialect === "mysql") {
16836
+ throw new Error("MySQL does not support table-valued functions.");
16837
+ }
16838
+ const rawName = sql.raw(name);
16839
+ if (!params || Array.isArray(params) && params.length === 0 || !Array.isArray(params) && Object.keys(params).length === 0) {
16840
+ return sql`SELECT * FROM ${rawName}()`;
16841
+ }
16842
+ if (dialect === "postgres" && !Array.isArray(params)) {
16843
+ const parts = Object.entries(params).map(
16844
+ ([key, val]) => sql`${sql.raw(key)} => ${val}`
16845
+ );
16846
+ return sql`SELECT * FROM ${rawName}(${sql.join(parts)})`;
16847
+ }
16848
+ const values = Array.isArray(params) ? params : Object.values(params);
16849
+ const joined = sql.join(values.map((v) => sql`${v}`));
16850
+ return sql`SELECT * FROM ${rawName}(${joined})`;
16851
+ }
16831
16852
  function buildMssqlProc(rawName, params) {
16832
16853
  if (Array.isArray(params)) {
16833
16854
  const joined = sql.join(params.map((v) => sql`${v}`));
@@ -27218,6 +27239,12 @@ function buildScope(db, revertFn, dialect) {
27218
27239
  const result = await query.execute(db);
27219
27240
  return result.rows?.[0] ?? null;
27220
27241
  },
27242
+ async tvf(name, ...args) {
27243
+ const params = args[0];
27244
+ const query = buildTvfCall(dialect, name, params);
27245
+ const result = await query.execute(db);
27246
+ return result.rows ?? [];
27247
+ },
27221
27248
  async transaction(fn) {
27222
27249
  return db.transaction().execute(fn);
27223
27250
  },
@@ -27337,8 +27364,11 @@ var Context = class {
27337
27364
  *
27338
27365
  * @example
27339
27366
  * ```typescript
27340
- * // Named params
27341
- * const users = await ctx.proc<User>('get_users', { department_id: 1 });
27367
+ * // Return type inferred from tuple definition
27368
+ * const users = await ctx.proc('get_users', { department_id: 1 });
27369
+ *
27370
+ * // Explicit return type override
27371
+ * const users = await ctx.proc<'get_users', SpecialUser>('get_users', { department_id: 1 });
27342
27372
  *
27343
27373
  * // Positional params
27344
27374
  * await ctx.proc('simple_proc', [42, 'hello']);
@@ -27364,14 +27394,14 @@ var Context = class {
27364
27394
  *
27365
27395
  * @example
27366
27396
  * ```typescript
27367
- * // Named params + column alias
27368
- * const result = await ctx.func<{ total: number }>('calc_total', { order_id: 42 }, 'total');
27397
+ * // Return type inferred from tuple definition
27398
+ * const result = await ctx.func('calc_total', { order_id: 42 }, 'total');
27369
27399
  *
27370
- * // Positional params + column alias
27371
- * const sum = await ctx.func<{ result: number }>('add_numbers', [1, 2], 'result');
27400
+ * // Explicit return type override
27401
+ * const result = await ctx.func<'calc_total', { total: number }>('calc_total', { order_id: 42 }, 'total');
27372
27402
  *
27373
27403
  * // No params — just column alias
27374
- * const ver = await ctx.func<{ v: string }>('get_version', 'v');
27404
+ * const ver = await ctx.func('get_version', 'v');
27375
27405
  * ```
27376
27406
  */
27377
27407
  async func(name, ...args) {
@@ -27385,6 +27415,40 @@ var Context = class {
27385
27415
  const result = await query.execute(this.kysely);
27386
27416
  return result.rows?.[0] ?? null;
27387
27417
  }
27418
+ // ─────────────────────────────────────────────────────────
27419
+ // Table-Valued Functions
27420
+ // ─────────────────────────────────────────────────────────
27421
+ /**
27422
+ * Call a table-valued function and return the result set.
27423
+ *
27424
+ * Generates SELECT * FROM name(...) with dialect-specific parameter
27425
+ * syntax. Returns multiple rows, unlike func() which returns a scalar.
27426
+ * Only supported on MSSQL and PostgreSQL — MySQL and SQLite throw.
27427
+ *
27428
+ * @example
27429
+ * ```typescript
27430
+ * // Return type inferred from tuple definition
27431
+ * const sessions = await ctx.tvf('validate_session', { session_key: key });
27432
+ *
27433
+ * // Explicit return type override
27434
+ * const sessions = await ctx.tvf<'validate_session', SpecialSession>('validate_session', { session_key: key });
27435
+ *
27436
+ * // No params
27437
+ * const items = await ctx.tvf('get_active_items');
27438
+ * ```
27439
+ */
27440
+ async tvf(name, ...args) {
27441
+ if (this.dialect === "sqlite") {
27442
+ throw new Error("SQLite does not support table-valued functions.");
27443
+ }
27444
+ if (this.dialect === "mysql") {
27445
+ throw new Error("MySQL does not support table-valued functions.");
27446
+ }
27447
+ const params = args[0];
27448
+ const query = buildTvfCall(this.dialect, name, params);
27449
+ const result = await query.execute(this.kysely);
27450
+ return result.rows ?? [];
27451
+ }
27388
27452
  async impersonate(username, fn) {
27389
27453
  const strategy = dialectStrategy[this.dialect];
27390
27454
  if (!strategy) {