@ganju/utils 0.0.15 → 0.0.17

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 (77) hide show
  1. package/dist/constants.d.ts +26 -0
  2. package/dist/constants.d.ts.map +1 -1
  3. package/dist/constants.js +107 -9
  4. package/dist/customCodeToken.d.ts +11 -0
  5. package/dist/customCodeToken.d.ts.map +1 -1
  6. package/dist/customCodeToken.js +41 -1
  7. package/dist/data.d.ts +13 -0
  8. package/dist/data.d.ts.map +1 -0
  9. package/dist/data.js +103 -0
  10. package/dist/dataApi.d.ts +578 -0
  11. package/dist/dataApi.d.ts.map +1 -0
  12. package/dist/dataApi.js +399 -0
  13. package/dist/dataCompiler.d.ts +68 -0
  14. package/dist/dataCompiler.d.ts.map +1 -0
  15. package/dist/dataCompiler.js +730 -0
  16. package/dist/dataCsv.d.ts +20 -0
  17. package/dist/dataCsv.d.ts.map +1 -0
  18. package/dist/dataCsv.js +102 -0
  19. package/dist/dataDdl.d.ts +29 -0
  20. package/dist/dataDdl.d.ts.map +1 -0
  21. package/dist/dataDdl.js +354 -0
  22. package/dist/dataEngine.d.ts +143 -0
  23. package/dist/dataEngine.d.ts.map +1 -0
  24. package/dist/dataEngine.js +2042 -0
  25. package/dist/dataIdentifiers.d.ts +8 -0
  26. package/dist/dataIdentifiers.d.ts.map +1 -0
  27. package/dist/dataIdentifiers.js +55 -0
  28. package/dist/dataImport.d.ts +79 -0
  29. package/dist/dataImport.d.ts.map +1 -0
  30. package/dist/dataImport.js +453 -0
  31. package/dist/dataQueries.d.ts +73 -0
  32. package/dist/dataQueries.d.ts.map +1 -0
  33. package/dist/dataQueries.js +513 -0
  34. package/dist/dataRpc.d.ts +150 -0
  35. package/dist/dataRpc.d.ts.map +1 -0
  36. package/dist/dataRpc.js +2 -0
  37. package/dist/dataTools.d.ts +40 -0
  38. package/dist/dataTools.d.ts.map +1 -0
  39. package/dist/dataTools.js +280 -0
  40. package/dist/dataTypes.d.ts +159 -0
  41. package/dist/dataTypes.d.ts.map +1 -0
  42. package/dist/dataTypes.js +160 -0
  43. package/dist/index.d.ts +394 -8
  44. package/dist/index.d.ts.map +1 -1
  45. package/dist/index.js +4 -0
  46. package/dist/oauth.d.ts +14 -0
  47. package/dist/oauth.d.ts.map +1 -1
  48. package/dist/oauth.js +42 -2
  49. package/dist/resourceRerank.d.ts +3 -2
  50. package/dist/resourceRerank.d.ts.map +1 -1
  51. package/dist/resourceRerank.js +5 -2
  52. package/dist/schema.d.ts +376 -4
  53. package/dist/schema.d.ts.map +1 -1
  54. package/dist/schema.js +268 -1
  55. package/dist/sdkConstants.d.ts +1 -0
  56. package/dist/sdkConstants.d.ts.map +1 -1
  57. package/dist/sdkConstants.js +2 -1
  58. package/package.json +17 -2
  59. package/src/constants.ts +121 -9
  60. package/src/customCodeToken.ts +74 -0
  61. package/src/data.ts +108 -0
  62. package/src/dataApi.ts +479 -0
  63. package/src/dataCompiler.ts +952 -0
  64. package/src/dataCsv.ts +99 -0
  65. package/src/dataDdl.ts +419 -0
  66. package/src/dataEngine.ts +2773 -0
  67. package/src/dataIdentifiers.ts +63 -0
  68. package/src/dataImport.ts +557 -0
  69. package/src/dataQueries.ts +730 -0
  70. package/src/dataRpc.ts +132 -0
  71. package/src/dataTools.ts +338 -0
  72. package/src/dataTypes.ts +318 -0
  73. package/src/index.ts +13 -1
  74. package/src/oauth.ts +42 -1
  75. package/src/resourceRerank.ts +5 -2
  76. package/src/schema.ts +315 -1
  77. package/src/sdkConstants.ts +1 -0
package/src/schema.ts CHANGED
@@ -11,6 +11,19 @@ import {
11
11
  PARTICIPANT_DAILY_LIMIT_MAX,
12
12
  PARTICIPANT_DAILY_LIMIT_OFF
13
13
  } from './channelCustomer';
14
+ import {
15
+ DATA_ACCESS_LEVELS,
16
+ DATA_COLUMN_TYPES,
17
+ DATA_MAX_COLUMNS,
18
+ DATA_MAX_DESCRIPTION,
19
+ DATA_MAX_ENUM_VALUES,
20
+ DATA_MAX_INSERT_ROWS,
21
+ DATA_MAX_LABEL,
22
+ DATA_IMPACT_MAX_IDS,
23
+ DATA_MAX_PAGE,
24
+ DATA_MAX_WRITE_OPERATIONS,
25
+ DATA_ON_DELETE
26
+ } from './dataTypes';
14
27
 
15
28
  // A prompt title becomes a slash command; it must not collide with a command
16
29
  // the channel runner handles itself (e.g. `/link`).
@@ -511,6 +524,256 @@ const ARTIFACT_REMOVE_RESOURCE = z.object({
511
524
  organizationId: z.uuid()
512
525
  });
513
526
 
527
+ const DATA_DATABASE_GET = z.object({
528
+ projectId: z.uuid(),
529
+ userId: z.uuid(),
530
+ organizationId: z.uuid()
531
+ });
532
+
533
+ // The name is what the owner types to delete it; it defaults to the
534
+ // project's slug. `replaceDeleted` starts over while a deleted database is
535
+ // still in its grace period, giving up the chance to restore it.
536
+ const DATA_DATABASE_CREATE = DATA_DATABASE_GET.extend({
537
+ name: z.string().trim().min(1).max(100).optional(),
538
+ replaceDeleted: z.boolean().optional()
539
+ });
540
+
541
+ const DATA_DATABASE_DELETE = DATA_DATABASE_GET.extend({
542
+ confirmName: z.string().min(1)
543
+ });
544
+
545
+ // The bodies and query strings of the Data API. Each one is what a client
546
+ // sends; the route schemas below add the path's ids. The database object
547
+ // checks every rule again (names, types, relations), so these describe the
548
+ // shape and leave the meaning to it.
549
+ const DATA_IDENTIFIER = z.string().min(1).max(63);
550
+ const DATA_DEFAULT_VALUE = z.union([
551
+ z.string(),
552
+ z.number(),
553
+ z.boolean(),
554
+ z.null()
555
+ ]);
556
+ const DATA_TEXT = (max: number) => z.string().max(max).nullable().optional();
557
+
558
+ const DATA_COLUMN_INPUT = z.strictObject({
559
+ name: DATA_IDENTIFIER,
560
+ type: z.enum(DATA_COLUMN_TYPES),
561
+ label: DATA_TEXT(DATA_MAX_LABEL),
562
+ description: DATA_TEXT(DATA_MAX_DESCRIPTION),
563
+ required: z.boolean().optional(),
564
+ unique: z.boolean().optional(),
565
+ filterable: z.boolean().optional(),
566
+ searchable: z.boolean().optional(),
567
+ personal: z.boolean().optional(),
568
+ values: z.array(z.string().min(1)).max(DATA_MAX_ENUM_VALUES).optional(),
569
+ table: DATA_IDENTIFIER.optional(),
570
+ onDelete: z.enum(DATA_ON_DELETE).optional(),
571
+ min: z.number().nullable().optional(),
572
+ default: DATA_DEFAULT_VALUE.optional()
573
+ });
574
+
575
+ // The CLI's schema file holds a list of these.
576
+ const DATA_TABLE_INPUT = z.strictObject({
577
+ name: DATA_IDENTIFIER,
578
+ label: DATA_TEXT(DATA_MAX_LABEL),
579
+ description: DATA_TEXT(DATA_MAX_DESCRIPTION),
580
+ displayColumn: DATA_IDENTIFIER.nullable().optional(),
581
+ access: z.enum(DATA_ACCESS_LEVELS).optional(),
582
+ customerScoped: z.boolean().optional(),
583
+ history: z.boolean().optional(),
584
+ columns: z.array(DATA_COLUMN_INPUT).max(DATA_MAX_COLUMNS)
585
+ });
586
+
587
+ const DATA_TABLE_PATCH = DATA_TABLE_INPUT.omit({ columns: true }).partial();
588
+
589
+ // A null puts the setting back to its default.
590
+ const DATA_COLUMN_PATCH = DATA_COLUMN_INPUT.partial();
591
+
592
+ const DATA_TABLE_DROP_BODY = z.strictObject({ confirmName: z.string().min(1) });
593
+
594
+ const DATA_ROW_VALUES = z.record(z.string(), z.unknown());
595
+
596
+ // A JSON value carried in a query string, e.g. `where={"status":"open"}`.
597
+ const DATA_JSON_PARAM = z.string().transform((text, ctx) => {
598
+ try {
599
+ return JSON.parse(text) as unknown;
600
+ } catch {
601
+ ctx.addIssue({
602
+ code: 'custom',
603
+ message: 'This is JSON, e.g. {"status":"open"}'
604
+ });
605
+ return z.NEVER;
606
+ }
607
+ });
608
+
609
+ // A comma-separated list in a query string: `sort=-created_at,name`.
610
+ const DATA_LIST_PARAM = z.string().transform(text =>
611
+ text
612
+ .split(',')
613
+ .map(item => item.trim())
614
+ .filter(Boolean)
615
+ );
616
+
617
+ const DATA_ROW_LIST_QUERY = z.strictObject({
618
+ where: DATA_JSON_PARAM.optional(),
619
+ sort: DATA_LIST_PARAM.optional(),
620
+ include: DATA_LIST_PARAM.optional(),
621
+ limit: z.coerce.number().int().min(1).max(DATA_MAX_PAGE).optional(),
622
+ cursor: z.string().max(2000).optional(),
623
+ q: z.string().max(500).optional(),
624
+ timeZone: z.string().max(64).optional()
625
+ });
626
+
627
+ const DATA_ROW_GET_QUERY = DATA_ROW_LIST_QUERY.pick({
628
+ include: true,
629
+ timeZone: true
630
+ });
631
+
632
+ const DATA_ROW_CREATE_BODY = z.union([
633
+ z.strictObject({ values: DATA_ROW_VALUES }),
634
+ z.strictObject({
635
+ rows: z.array(DATA_ROW_VALUES).min(1).max(DATA_MAX_INSERT_ROWS)
636
+ })
637
+ ]);
638
+
639
+ const DATA_ROW_VERSION = z.number().int().min(1);
640
+
641
+ // `set` takes values, or relative changes such as { "stock": { "decrement": 2 } }.
642
+ const DATA_ROW_UPDATE_BODY = z.strictObject({
643
+ set: DATA_ROW_VALUES,
644
+ version: DATA_ROW_VERSION.optional()
645
+ });
646
+
647
+ const DATA_ROW_DELETE_BODY = z.strictObject({
648
+ version: DATA_ROW_VERSION.optional()
649
+ });
650
+
651
+ const DATA_ROW_ID = z.coerce.number().int().min(1);
652
+
653
+ // Without `ids`, every row of the table.
654
+ const DATA_DELETE_PREVIEW_BODY = z.strictObject({
655
+ ids: z.array(z.number().int().min(1)).min(1).max(DATA_IMPACT_MAX_IDS).optional()
656
+ });
657
+
658
+ const DATA_WRITE_TARGET = {
659
+ table: DATA_IDENTIFIER,
660
+ id: z
661
+ .union([
662
+ z.number().int().min(1),
663
+ z.strictObject({ $ref: z.number().int().min(0) })
664
+ ])
665
+ .optional(),
666
+ where: z.record(z.string(), z.unknown()).optional(),
667
+ expect: z.number().int().min(0).optional(),
668
+ version: DATA_ROW_VERSION.optional()
669
+ };
670
+
671
+ // Applied together or not at all. A later step can use an earlier insert's
672
+ // id as { "$ref": <step> }.
673
+ const DATA_WRITE_OPERATION = z.discriminatedUnion('op', [
674
+ z.strictObject({
675
+ op: z.literal('insert'),
676
+ table: DATA_IDENTIFIER,
677
+ values: DATA_ROW_VALUES.optional(),
678
+ rows: z.array(DATA_ROW_VALUES).min(1).max(DATA_MAX_INSERT_ROWS).optional()
679
+ }),
680
+ z.strictObject({
681
+ op: z.literal('update'),
682
+ ...DATA_WRITE_TARGET,
683
+ set: DATA_ROW_VALUES
684
+ }),
685
+ z.strictObject({ op: z.literal('delete'), ...DATA_WRITE_TARGET })
686
+ ]);
687
+
688
+ const DATA_WRITE_BODY = z.strictObject({
689
+ operations: z
690
+ .array(DATA_WRITE_OPERATION)
691
+ .min(1)
692
+ .max(DATA_MAX_WRITE_OPERATIONS)
693
+ });
694
+
695
+ const DATA_ROW_HISTORY_QUERY = z.strictObject({
696
+ limit: z.coerce.number().int().min(1).max(100).optional(),
697
+ cursor: z.coerce.number().int().min(1).optional(),
698
+ timeZone: z.string().max(64).optional()
699
+ });
700
+
701
+ // A time within the last 30 days, or a bookmark this API handed out (a drop,
702
+ // a type change, or the restore to undo).
703
+ const DATA_RESTORE_POINT_BODY = z.union([
704
+ z.strictObject({
705
+ timestamp: z.union([z.iso.datetime({ offset: true }), z.number().int()])
706
+ }),
707
+ z.strictObject({ bookmark: z.string().min(1).max(200) })
708
+ ]);
709
+
710
+ // The database's own settings. `timeZone` is an IANA zone (America/Bogota),
711
+ // or null for UTC: datetimes come back in it for callers that send none.
712
+ const DATA_DATABASE_PATCH = z.strictObject({
713
+ timeZone: z
714
+ .string()
715
+ .max(100)
716
+ .refine(zone => {
717
+ try {
718
+ new Intl.DateTimeFormat('en-US', { timeZone: zone });
719
+ return true;
720
+ } catch {
721
+ return false;
722
+ }
723
+ }, 'Use an IANA time zone, such as America/Bogota.')
724
+ .nullable()
725
+ });
726
+
727
+ const DATA_EXPORT_BODY = z.strictObject({
728
+ format: z.enum(['jsonl', 'csv']).optional()
729
+ });
730
+
731
+ const DATA_EXPORT_QUERY = z.strictObject({
732
+ exportId: z.uuid().optional()
733
+ });
734
+
735
+ // Without `table`, the export's schema.json.
736
+ const DATA_EXPORT_FILE_QUERY = z.strictObject({
737
+ exportId: z.uuid(),
738
+ table: DATA_IDENTIFIER.optional()
739
+ });
740
+
741
+ const DATA_CHANGE_LIST_QUERY = z.strictObject({
742
+ limit: z.coerce.number().int().min(1).max(100).optional(),
743
+ cursor: z.uuid().optional()
744
+ });
745
+
746
+ // Named queries: a SELECT the owner writes once, with named parameters
747
+ // (`:from`), checked to only read when it is saved.
748
+ const DATA_QUERY_PARAM = z.strictObject({
749
+ name: DATA_IDENTIFIER,
750
+ type: z.enum(['text', 'integer', 'decimal', 'boolean', 'date', 'datetime']),
751
+ description: z.string().max(300).nullish(),
752
+ required: z.boolean().optional()
753
+ });
754
+
755
+ const DATA_QUERY_INPUT = z.strictObject({
756
+ name: DATA_IDENTIFIER,
757
+ description: z.string().max(300).nullish(),
758
+ sql: z.string().min(1).max(10_000),
759
+ params: z.array(DATA_QUERY_PARAM).max(20).optional(),
760
+ // Channel bots may run it from data-query.
761
+ assistant: z.boolean().optional()
762
+ });
763
+
764
+ const DATA_QUERY_RUN_BODY = z.strictObject({
765
+ params: z.record(z.string(), z.unknown()).optional(),
766
+ limit: z.number().int().min(1).max(500).optional(),
767
+ timeZone: z.string().max(100).optional()
768
+ });
769
+
770
+ const DATA_TABLE_PARAMS = DATA_DATABASE_GET.extend({ table: DATA_IDENTIFIER });
771
+ const DATA_COLUMN_PARAMS = DATA_TABLE_PARAMS.extend({
772
+ column: DATA_IDENTIFIER
773
+ });
774
+ const DATA_ROW_PARAMS = DATA_TABLE_PARAMS.extend({ id: DATA_ROW_ID });
775
+ const DATA_QUERY_PATH_PARAMS = DATA_DATABASE_GET.extend({ name: DATA_IDENTIFIER });
776
+
514
777
  const ARTIFACT_UPLOAD_RESOURCE_FILE = z.object({
515
778
  resourceId: z.uuid(),
516
779
  projectId: z.uuid(),
@@ -1141,7 +1404,17 @@ const CUSTOM_CODE_TOOL = z.object({
1141
1404
  description: z.string().max(2000).optional(),
1142
1405
  inputSchema: SCHEMA_DEFINITION.default({ type: 'object', properties: {} }),
1143
1406
  outputSchema: SCHEMA_DEFINITION.optional(),
1144
- annotations: TOOL_ANNOTATIONS.optional()
1407
+ annotations: TOOL_ANNOTATIONS.optional(),
1408
+ // What this function may do through ctx.data. Absent means everything: it
1409
+ // is the owner's code. Narrowing matters most for a function a channel bot
1410
+ // calls after reading customer text, and the broker enforces it, since
1411
+ // anything in the script can be edited.
1412
+ data: z
1413
+ .strictObject({
1414
+ access: z.enum(['read', 'write']).optional(),
1415
+ tables: z.array(z.string().min(1).max(63)).max(50).optional()
1416
+ })
1417
+ .optional()
1145
1418
  });
1146
1419
 
1147
1420
  // The manifest a `ganju deploy` (or the dashboard) uploads alongside a bundle.
@@ -1390,6 +1663,16 @@ const CUSTOM_CODE_BROKER_SECRET = z.object({
1390
1663
  name: z.string().min(1).max(200)
1391
1664
  });
1392
1665
 
1666
+ // One ctx.data call. `call` is the token the dispatcher signed for the
1667
+ // function being run, which the script hands back: the broker reads the
1668
+ // function's name from it, never from the script, and applies that
1669
+ // function's `data` narrowing.
1670
+ const CUSTOM_CODE_BROKER_DATA = z.object({
1671
+ call: z.string().min(1).max(4000),
1672
+ op: z.enum(['describe', 'query', 'write', 'run']),
1673
+ args: z.record(z.string(), z.unknown()).default({})
1674
+ });
1675
+
1393
1676
  const CUSTOM_CODE_BROKER_RESOURCE_SEARCH = z.object({
1394
1677
  query: z.string().min(1).max(2000),
1395
1678
  limit: z.number().int().positive().max(20).default(5)
@@ -1727,6 +2010,36 @@ export const Schema = {
1727
2010
  ARTIFACT_UPDATE_RESOURCE_VIEW,
1728
2011
  ARTIFACT_GET_RESOURCE,
1729
2012
  ARTIFACT_GET_RESOURCE_BY_ID,
2013
+ DATA_DATABASE_GET,
2014
+ DATA_DATABASE_CREATE,
2015
+ DATA_DATABASE_DELETE,
2016
+ DATA_COLUMN_INPUT,
2017
+ DATA_TABLE_INPUT,
2018
+ DATA_TABLE_PATCH,
2019
+ DATA_COLUMN_PATCH,
2020
+ DATA_TABLE_DROP_BODY,
2021
+ DATA_ROW_LIST_QUERY,
2022
+ DATA_ROW_GET_QUERY,
2023
+ DATA_ROW_CREATE_BODY,
2024
+ DATA_ROW_UPDATE_BODY,
2025
+ DATA_ROW_DELETE_BODY,
2026
+ DATA_DELETE_PREVIEW_BODY,
2027
+ DATA_WRITE_OPERATION,
2028
+ DATA_WRITE_BODY,
2029
+ DATA_ROW_HISTORY_QUERY,
2030
+ DATA_RESTORE_POINT_BODY,
2031
+ DATA_EXPORT_BODY,
2032
+ DATA_EXPORT_QUERY,
2033
+ DATA_EXPORT_FILE_QUERY,
2034
+ DATA_CHANGE_LIST_QUERY,
2035
+ DATA_TABLE_PARAMS,
2036
+ DATA_DATABASE_PATCH,
2037
+ DATA_QUERY_PARAM,
2038
+ DATA_QUERY_INPUT,
2039
+ DATA_QUERY_RUN_BODY,
2040
+ DATA_QUERY_PATH_PARAMS,
2041
+ DATA_COLUMN_PARAMS,
2042
+ DATA_ROW_PARAMS,
1730
2043
  ARTIFACT_REMOVE_RESOURCE,
1731
2044
  ARTIFACT_UPLOAD_RESOURCE_FILE,
1732
2045
  ARTIFACT_DOWNLOAD_RESOURCE_FILE,
@@ -1788,6 +2101,7 @@ export const Schema = {
1788
2101
  CUSTOM_CODE_INVOKE_RESPONSE,
1789
2102
  CUSTOM_CODE_BROKER_CONNECTION,
1790
2103
  CUSTOM_CODE_BROKER_SECRET,
2104
+ CUSTOM_CODE_BROKER_DATA,
1791
2105
  CUSTOM_CODE_BROKER_RESOURCE_SEARCH,
1792
2106
  CUSTOM_CODE_BROKER_RESOURCE_READ,
1793
2107
  CUSTOM_CODE_BROKER_RESOURCE_CREATE,
@@ -29,6 +29,7 @@ export const CUSTOM_CODE_BROKER_PATH_RESOURCES_LIST = '/resources/list';
29
29
  export const CUSTOM_CODE_BROKER_PATH_RESOURCES_CREATE = '/resources/create';
30
30
  export const CUSTOM_CODE_BROKER_PATH_RESOURCES_DELETE = '/resources/delete';
31
31
  export const CUSTOM_CODE_BROKER_PATH_SEND_FILE = '/send-file';
32
+ export const CUSTOM_CODE_BROKER_PATH_DATA = '/data';
32
33
 
33
34
  // Injected at upload time and echoed back by the health probe below. Uploading a
34
35
  // script into the dispatch namespace is not read-your-writes: dispatching to the