@ekodb/ekodb-client 0.16.0 → 0.18.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/functions.js CHANGED
@@ -4,6 +4,7 @@
4
4
  */
5
5
  Object.defineProperty(exports, "__esModule", { value: true });
6
6
  exports.Stage = exports.ChatMessage = void 0;
7
+ exports.parameterRef = parameterRef;
7
8
  exports.ChatMessage = {
8
9
  system: (content) => ({
9
10
  role: "system",
@@ -18,8 +19,17 @@ exports.ChatMessage = {
18
19
  content: content,
19
20
  }),
20
21
  };
22
+ function parameterRef(name) {
23
+ return { type: "Parameter", name };
24
+ }
21
25
  // Stage builder functions
22
26
  exports.Stage = {
27
+ /**
28
+ * Shorthand for `parameterRef(name)` — builds the structural placeholder
29
+ * `{"type": "Parameter", "name": name}`. See `parameterRef` for the full
30
+ * explanation and example.
31
+ */
32
+ param: (name) => parameterRef(name),
23
33
  findAll: (collection) => ({
24
34
  type: "FindAll",
25
35
  collection,
@@ -258,4 +268,306 @@ exports.Stage = {
258
268
  output_field,
259
269
  collection,
260
270
  }),
271
+ /**
272
+ * Bcrypt-hash a plaintext value and write the result into every record
273
+ * in the working data as `output_field`. Requires ekoDB >= 0.41.0.
274
+ *
275
+ * @param plain - Plaintext to hash. Typically a `"{{password}}"`
276
+ * placeholder that the substituter replaces with the call-time param
277
+ * before this stage runs.
278
+ * @param output_field - Field name to write the bcrypt hash into.
279
+ * @param cost - bcrypt cost factor (4..=31). Defaults to 12 when undefined.
280
+ */
281
+ bcryptHash: (plain, output_field, cost) => ({
282
+ type: "BcryptHash",
283
+ plain,
284
+ cost,
285
+ output_field,
286
+ }),
287
+ /**
288
+ * Verify a plaintext against a bcrypt hash stored on the first record in
289
+ * the working data. Writes a boolean into `output_field` on every
290
+ * working record. Pair with `Stage.if` to branch on success / failure.
291
+ * Requires ekoDB >= 0.41.0.
292
+ *
293
+ * @param plain - Plaintext to verify (typically `"{{password}}"`).
294
+ * @param hash_field - Name of the field on the current record that
295
+ * holds the stored bcrypt hash (e.g. `"password_hash"`).
296
+ * @param output_field - Field name to write the boolean result into.
297
+ */
298
+ bcryptVerify: (plain, hash_field, output_field) => ({
299
+ type: "BcryptVerify",
300
+ plain,
301
+ hash_field,
302
+ output_field,
303
+ }),
304
+ /**
305
+ * Generate a cryptographically-random token and add it to every record
306
+ * in the working data. Requires ekoDB >= 0.41.0.
307
+ *
308
+ * @param bytes - Number of random bytes to draw (1..=1024).
309
+ * @param output_field - Field name to write the encoded token into.
310
+ * @param encoding - `"hex"` (default) | `"base64"` | `"base64url"`.
311
+ */
312
+ randomToken: (bytes, output_field, encoding) => ({
313
+ type: "RandomToken",
314
+ bytes,
315
+ encoding,
316
+ output_field,
317
+ }),
318
+ /**
319
+ * Sign a JWT and write the resulting token to every working
320
+ * record. Pair with `Stage.bcryptVerify` to issue a session
321
+ * token after login. Use `"{{env.JWT_SECRET}}"` for `secret` so
322
+ * the LLM never sees the operator-owned signing key. `iat` and
323
+ * `exp` are auto-stamped when `expires_in_secs` is set.
324
+ * Requires ekoDB >= 0.42.0.
325
+ *
326
+ * @param claims - JWT payload claims.
327
+ * @param secret - Signing secret (typically `"{{env.JWT_SECRET}}"`).
328
+ * @param output_field - Field name to write the signed JWT into.
329
+ * @param expires_in_secs - Lifetime in seconds (auto-stamps `iat` + `exp`).
330
+ * @param algorithm - `"HS256"` (default) | `"HS384"` | `"HS512"`.
331
+ */
332
+ jwtSign: (claims, secret, output_field, expires_in_secs, algorithm) => ({
333
+ type: "JwtSign",
334
+ claims,
335
+ secret,
336
+ algorithm,
337
+ expires_in_secs,
338
+ output_field,
339
+ }),
340
+ /**
341
+ * Verify a JWT held in `token_field` on the first working record.
342
+ * On success writes the decoded claims object into `output_field`;
343
+ * on failure writes `null`. Branch with `Stage.if` matching
344
+ * `output_field == null` to reject. Requires ekoDB >= 0.42.0.
345
+ *
346
+ * @param token_field - Field on the working record holding the JWT.
347
+ * @param secret - Verification secret (must match the signing secret).
348
+ * @param output_field - Field name to write decoded claims into.
349
+ * @param algorithm - Expected algorithm (default `"HS256"`).
350
+ */
351
+ jwtVerify: (token_field, secret, output_field, algorithm) => ({
352
+ type: "JwtVerify",
353
+ token_field,
354
+ secret,
355
+ algorithm,
356
+ output_field,
357
+ }),
358
+ /**
359
+ * Send a transactional email. Today only the `"sendgrid"`
360
+ * provider is supported. Use `"{{env.SENDGRID_API_KEY}}"` for
361
+ * `api_key` so the LLM never sees the operator-owned secret.
362
+ * Set `html: true` to send `text/html`. The result envelope
363
+ * (`{provider_status, provider_message, provider}`) is written
364
+ * to `output_field` (default `"email_send"`).
365
+ * Requires ekoDB >= 0.42.0.
366
+ */
367
+ emailSend: (to, subject, body, from, api_key, options) => ({
368
+ type: "EmailSend",
369
+ to,
370
+ subject,
371
+ body,
372
+ from,
373
+ reply_to: options?.reply_to,
374
+ api_key,
375
+ provider: options?.provider,
376
+ html: options?.html,
377
+ output_field: options?.output_field,
378
+ }),
379
+ /**
380
+ * Try/Catch error handling for graceful failure recovery.
381
+ * Executes tryFunctions, and if any fail, executes catchFunctions.
382
+ *
383
+ * @param tryFunctions - Functions to attempt.
384
+ * @param catchFunctions - Functions to execute on failure.
385
+ * @param outputErrorField - Field name to store error details (default: "error").
386
+ */
387
+ tryCatch: (tryFunctions, catchFunctions, outputErrorField) => ({
388
+ type: "TryCatch",
389
+ try_functions: tryFunctions,
390
+ catch_functions: catchFunctions,
391
+ output_error_field: outputErrorField,
392
+ }),
393
+ /**
394
+ * Execute multiple functions in parallel (concurrently).
395
+ * All functions run simultaneously, results are merged.
396
+ *
397
+ * @param functions - Functions to execute concurrently.
398
+ * @param waitForAll - true = wait for all to complete, false = return on first completion.
399
+ */
400
+ parallel: (functions, waitForAll = true) => ({
401
+ type: "Parallel",
402
+ functions,
403
+ wait_for_all: waitForAll,
404
+ }),
405
+ /**
406
+ * Sleep/delay execution for rate limiting or timing control.
407
+ *
408
+ * @param durationMs - Duration in milliseconds: `1000` or `"{{delay_param}}"`.
409
+ */
410
+ sleep: (durationMs) => ({
411
+ type: "Sleep",
412
+ duration_ms: durationMs,
413
+ }),
414
+ /**
415
+ * Return a shaped response (final output formatting).
416
+ * Constructs the final response object from current execution context.
417
+ *
418
+ * @param fields - Fields to include in response with `{{param}}` substitution.
419
+ * @param statusCode - HTTP status code (default: 200).
420
+ */
421
+ returnResponse: (fields, statusCode) => ({
422
+ type: "Return",
423
+ fields,
424
+ status_code: statusCode,
425
+ }),
426
+ /**
427
+ * Validate data against a JSON schema before processing.
428
+ *
429
+ * @param schema - JSON Schema to validate against.
430
+ * @param dataField - Field containing data to validate.
431
+ * @param onError - Functions to execute on validation failure.
432
+ */
433
+ validate: (schema, dataField, onError) => ({
434
+ type: "Validate",
435
+ schema,
436
+ data_field: dataField,
437
+ on_error: onError,
438
+ }),
439
+ /**
440
+ * HMAC-SHA256/384/512 sign. Use for outbound webhook signing or
441
+ * pre-signed URL generation. Requires ekoDB >= 0.42.0.
442
+ */
443
+ hmacSign: (input, secret, output_field, options) => ({
444
+ type: "HmacSign",
445
+ input,
446
+ secret,
447
+ algorithm: options?.algorithm,
448
+ output_field,
449
+ encoding: options?.encoding,
450
+ }),
451
+ /** HMAC verify (constant-time). Writes a boolean. */
452
+ hmacVerify: (input, provided_mac, secret, output_field, options) => ({
453
+ type: "HmacVerify",
454
+ input,
455
+ provided_mac,
456
+ secret,
457
+ algorithm: options?.algorithm,
458
+ encoding: options?.encoding,
459
+ output_field,
460
+ }),
461
+ /** AES-256-GCM encrypt; writes `{ciphertext, nonce}` envelope. */
462
+ aesEncrypt: (plaintext, key, output_field, key_encoding) => ({
463
+ type: "AesEncrypt",
464
+ plaintext,
465
+ key,
466
+ key_encoding,
467
+ output_field,
468
+ }),
469
+ /** AES-256-GCM decrypt; reads envelope from `ciphertext_field`. */
470
+ aesDecrypt: (ciphertext_field, key, output_field, key_encoding) => ({
471
+ type: "AesDecrypt",
472
+ ciphertext_field,
473
+ key,
474
+ key_encoding,
475
+ output_field,
476
+ }),
477
+ /** Generate a v4 UUID into `output_field`. */
478
+ uuidGenerate: (output_field) => ({
479
+ type: "UuidGenerate",
480
+ output_field,
481
+ }),
482
+ /** TOTP code generation (RFC 6238). */
483
+ totpGenerate: (secret, output_field, options) => ({
484
+ type: "TotpGenerate",
485
+ secret,
486
+ digits: options?.digits,
487
+ period: options?.period,
488
+ algorithm: options?.algorithm,
489
+ output_field,
490
+ }),
491
+ /** TOTP verify; tolerates `skew` time-steps either side (default 1). */
492
+ totpVerify: (code, secret, output_field, options) => ({
493
+ type: "TotpVerify",
494
+ code,
495
+ secret,
496
+ digits: options?.digits,
497
+ period: options?.period,
498
+ algorithm: options?.algorithm,
499
+ skew: options?.skew,
500
+ output_field,
501
+ }),
502
+ /** Base64 encode (`url_safe = true` for URL-safe / no-pad). */
503
+ base64Encode: (input, output_field, url_safe) => ({
504
+ type: "Base64Encode",
505
+ input,
506
+ url_safe,
507
+ output_field,
508
+ }),
509
+ /** Base64 decode → UTF-8 string. Fail-closed. */
510
+ base64Decode: (input, output_field, url_safe) => ({
511
+ type: "Base64Decode",
512
+ input,
513
+ url_safe,
514
+ output_field,
515
+ }),
516
+ /** Hex encode (lowercase). */
517
+ hexEncode: (input, output_field) => ({
518
+ type: "HexEncode",
519
+ input,
520
+ output_field,
521
+ }),
522
+ /** Hex decode → UTF-8 string. Fail-closed. */
523
+ hexDecode: (input, output_field) => ({
524
+ type: "HexDecode",
525
+ input,
526
+ output_field,
527
+ }),
528
+ /** URL-friendly slug. */
529
+ slugify: (input, output_field) => ({
530
+ type: "Slugify",
531
+ input,
532
+ output_field,
533
+ }),
534
+ /**
535
+ * Idempotency-key claim (KV SETNX with TTL). Pass an idempotency
536
+ * key (typically `"{{idempotency_key}}"`) and a TTL; first call
537
+ * writes `{claimed: true, key}`, subsequent calls within the TTL
538
+ * write `{claimed: false, key, response}` so the caller can
539
+ * short-circuit. Requires ekoDB >= 0.42.0.
540
+ */
541
+ idempotencyClaim: (key, ttl_secs, output_field) => ({
542
+ type: "IdempotencyClaim",
543
+ key,
544
+ ttl_secs,
545
+ output_field,
546
+ }),
547
+ /**
548
+ * Fixed-window rate-limit gate. `on_exceed` either errors
549
+ * (`"fail"`, default) or writes `allowed: false` (`"skip"`).
550
+ */
551
+ rateLimit: (key, limit, window_secs, output_field, on_exceed) => ({
552
+ type: "RateLimit",
553
+ key,
554
+ limit,
555
+ window_secs,
556
+ on_exceed,
557
+ output_field,
558
+ }),
559
+ /** Distributed-lock acquire (token-fenced). */
560
+ lockAcquire: (key, ttl_secs, output_field) => ({
561
+ type: "LockAcquire",
562
+ key,
563
+ ttl_secs,
564
+ output_field,
565
+ }),
566
+ /** Distributed-lock release; only releases on token match. */
567
+ lockRelease: (key, token, output_field) => ({
568
+ type: "LockRelease",
569
+ key,
570
+ token,
571
+ output_field,
572
+ }),
261
573
  };
@@ -0,0 +1,9 @@
1
+ /**
2
+ * Unit tests for the stored-function builder helpers (Stage + parameterRef).
3
+ *
4
+ * These tests cover the pure-data construction helpers and the structural
5
+ * parameter placeholder. They don't hit a running ekoDB — server-side
6
+ * behavior is covered by the Rust integration tests in
7
+ * `ekodb/ekodb_server/tests/function_parameters_tests.rs`.
8
+ */
9
+ export {};