@ganju/utils 0.0.17 → 0.0.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 (57) hide show
  1. package/dist/constants.d.ts +8 -0
  2. package/dist/constants.d.ts.map +1 -1
  3. package/dist/constants.js +21 -4
  4. package/dist/crypto.d.ts +2 -2
  5. package/dist/crypto.d.ts.map +1 -1
  6. package/dist/crypto.js +1 -0
  7. package/dist/customCodeToken.d.ts +4 -0
  8. package/dist/customCodeToken.d.ts.map +1 -1
  9. package/dist/customCodeToken.js +9 -1
  10. package/dist/data.d.ts +2 -0
  11. package/dist/data.d.ts.map +1 -1
  12. package/dist/data.js +28 -1
  13. package/dist/dataApi.d.ts +133 -1
  14. package/dist/dataApi.d.ts.map +1 -1
  15. package/dist/dataApi.js +62 -1
  16. package/dist/dataDdl.d.ts.map +1 -1
  17. package/dist/dataDdl.js +3 -1
  18. package/dist/dataEngine.d.ts.map +1 -1
  19. package/dist/dataEngine.js +62 -0
  20. package/dist/dataRpc.d.ts +25 -0
  21. package/dist/dataRpc.d.ts.map +1 -1
  22. package/dist/dataTriggers.d.ts +203 -0
  23. package/dist/dataTriggers.d.ts.map +1 -0
  24. package/dist/dataTriggers.js +760 -0
  25. package/dist/dataTypes.d.ts +1 -0
  26. package/dist/dataTypes.d.ts.map +1 -1
  27. package/dist/index.d.ts +198 -2
  28. package/dist/index.d.ts.map +1 -1
  29. package/dist/index.js +27 -0
  30. package/dist/localizeDataError.d.ts +18 -0
  31. package/dist/localizeDataError.d.ts.map +1 -0
  32. package/dist/localizeDataError.js +359 -0
  33. package/dist/schema.d.ts +161 -0
  34. package/dist/schema.d.ts.map +1 -1
  35. package/dist/schema.js +146 -1
  36. package/dist/sdkConstants.d.ts +3 -0
  37. package/dist/sdkConstants.d.ts.map +1 -1
  38. package/dist/sdkConstants.js +4 -1
  39. package/dist/whatsappTemplates.d.ts +77 -0
  40. package/dist/whatsappTemplates.d.ts.map +1 -0
  41. package/dist/whatsappTemplates.js +402 -0
  42. package/package.json +1 -1
  43. package/src/constants.ts +28 -4
  44. package/src/crypto.ts +3 -2
  45. package/src/customCodeToken.ts +14 -1
  46. package/src/data.ts +40 -0
  47. package/src/dataApi.ts +78 -2
  48. package/src/dataDdl.ts +3 -1
  49. package/src/dataEngine.ts +70 -0
  50. package/src/dataRpc.ts +15 -0
  51. package/src/dataTriggers.ts +1134 -0
  52. package/src/dataTypes.ts +3 -0
  53. package/src/index.ts +65 -1
  54. package/src/localizeDataError.ts +593 -0
  55. package/src/schema.ts +170 -1
  56. package/src/sdkConstants.ts +3 -0
  57. package/src/whatsappTemplates.ts +465 -0
package/src/schema.ts CHANGED
@@ -24,6 +24,18 @@ import {
24
24
  DATA_MAX_WRITE_OPERATIONS,
25
25
  DATA_ON_DELETE
26
26
  } from './dataTypes';
27
+ import {
28
+ WHATSAPP_TEMPLATE_BODY_MAX,
29
+ WHATSAPP_TEMPLATE_BUTTON_MAX,
30
+ WHATSAPP_TEMPLATE_BUTTONS_MAX,
31
+ WHATSAPP_TEMPLATE_CATEGORIES,
32
+ WHATSAPP_TEMPLATE_EXAMPLE_MAX,
33
+ WHATSAPP_TEMPLATE_FOOTER_MAX,
34
+ WHATSAPP_TEMPLATE_HEADER_MAX,
35
+ WHATSAPP_TEMPLATE_LABEL_MAX,
36
+ WHATSAPP_TEMPLATE_NAME_MAX,
37
+ WHATSAPP_TEMPLATE_VARIABLES_MAX
38
+ } from './whatsappTemplates';
27
39
 
28
40
  // A prompt title becomes a slash command; it must not collide with a command
29
41
  // the channel runner handles itself (e.g. `/link`).
@@ -767,12 +779,75 @@ const DATA_QUERY_RUN_BODY = z.strictObject({
767
779
  timeZone: z.string().max(100).optional()
768
780
  });
769
781
 
782
+ // A trigger, as the dashboard, the API and ganju.json's "triggers" write it:
783
+ // a table, an event, an optional condition and exactly one action. The
784
+ // object checks the rest (columns, fields used in texts) against the schema.
785
+ const DATA_TRIGGER_NAME = z
786
+ .string()
787
+ .regex(
788
+ /^[a-z][a-z0-9_-]{0,62}$/,
789
+ 'Lowercase letters, digits, _ and -, starting with a letter'
790
+ );
791
+ const DATA_TRIGGER_TEMPLATE = z.strictObject({
792
+ name: z.string().min(1).max(512),
793
+ language: z.string().min(1).max(20),
794
+ // Each {{n}} of the template in order: fixed text or a {{field}} of the row.
795
+ params: z.array(z.string().max(1024)).max(20).optional()
796
+ });
797
+ const DATA_TRIGGER_INPUT = z.strictObject({
798
+ name: DATA_TRIGGER_NAME.optional(),
799
+ description: z.string().max(300).nullish(),
800
+ table: DATA_IDENTIFIER,
801
+ on: z.enum(['insert', 'update', 'delete']),
802
+ // { column: { changedTo | changedFrom | equals: value, changed: true } },
803
+ // combined with { all: [...] } or { any: [...] }.
804
+ when: z.record(z.string(), z.unknown()).nullish(),
805
+ enabled: z.boolean().optional(),
806
+ // false: refuse to save over an existing trigger of this name.
807
+ replace: z.boolean().optional(),
808
+ // Runs a minute; past it events wait in the queue. 60 by default.
809
+ rateLimit: z.number().int().min(1).max(600).optional(),
810
+ function: z.string().min(1).max(64).optional(),
811
+ webhook: z.url().max(2000).optional(),
812
+ chat: z
813
+ .strictObject({
814
+ channelId: z.string().min(1).max(100),
815
+ chatId: z.union([z.string().min(1).max(200), z.number().int()]),
816
+ text: z.string().min(1).max(2000)
817
+ })
818
+ .optional(),
819
+ email: z
820
+ .strictObject({
821
+ to: z.union([z.email(), z.array(z.email()).min(1).max(10)]),
822
+ subject: z.string().min(1).max(200).optional(),
823
+ text: z.string().min(1).max(2000)
824
+ })
825
+ .optional(),
826
+ customer: z
827
+ .strictObject({
828
+ text: z.string().min(1).max(2000),
829
+ template: DATA_TRIGGER_TEMPLATE.optional()
830
+ })
831
+ .optional()
832
+ });
833
+ const DATA_TRIGGER_PATCH = z.strictObject({ enabled: z.boolean() });
834
+ const DATA_TRIGGER_DEPLOY_BODY = z.strictObject({
835
+ triggers: z.array(DATA_TRIGGER_INPUT).max(50)
836
+ });
837
+ const DATA_TRIGGER_RUN_LIST_QUERY = z.object({
838
+ limit: z.coerce.number().int().min(1).max(50).optional()
839
+ });
840
+
770
841
  const DATA_TABLE_PARAMS = DATA_DATABASE_GET.extend({ table: DATA_IDENTIFIER });
771
842
  const DATA_COLUMN_PARAMS = DATA_TABLE_PARAMS.extend({
772
843
  column: DATA_IDENTIFIER
773
844
  });
774
845
  const DATA_ROW_PARAMS = DATA_TABLE_PARAMS.extend({ id: DATA_ROW_ID });
775
846
  const DATA_QUERY_PATH_PARAMS = DATA_DATABASE_GET.extend({ name: DATA_IDENTIFIER });
847
+ const DATA_TRIGGER_PATH_PARAMS = DATA_DATABASE_GET.extend({ name: DATA_TRIGGER_NAME });
848
+ const DATA_TRIGGER_RUN_PARAMS = DATA_TRIGGER_PATH_PARAMS.extend({
849
+ runId: z.string().min(1).max(64)
850
+ });
776
851
 
777
852
  const ARTIFACT_UPLOAD_RESOURCE_FILE = z.object({
778
853
  resourceId: z.uuid(),
@@ -1409,12 +1484,18 @@ const CUSTOM_CODE_TOOL = z.object({
1409
1484
  // is the owner's code. Narrowing matters most for a function a channel bot
1410
1485
  // calls after reading customer text, and the broker enforces it, since
1411
1486
  // anything in the script can be edited.
1487
+ // false: deployed and run by triggers, but never offered to the assistant
1488
+ // (left out of tools/list, and not counted toward its tools).
1489
+ expose: z.boolean().optional(),
1412
1490
  data: z
1413
1491
  .strictObject({
1414
1492
  access: z.enum(['read', 'write']).optional(),
1415
1493
  tables: z.array(z.string().min(1).max(63)).max(50).optional()
1416
1494
  })
1417
- .optional()
1495
+ .optional(),
1496
+ // true: the function may message customers and chats through ctx.channels.
1497
+ // Left out, the broker refuses it.
1498
+ channels: z.boolean().optional()
1418
1499
  });
1419
1500
 
1420
1501
  // The manifest a `ganju deploy` (or the dashboard) uploads alongside a bundle.
@@ -1673,6 +1754,26 @@ const CUSTOM_CODE_BROKER_DATA = z.object({
1673
1754
  args: z.record(z.string(), z.unknown()).default({})
1674
1755
  });
1675
1756
 
1757
+ // ctx.channels: a message to a customer the bot has spoken with, or a post
1758
+ // to a chat the bot is in. `call` names the function, as for ctx.data.
1759
+ const CUSTOM_CODE_BROKER_CHANNELS_SEND = z.object({
1760
+ call: z.string().min(1).max(4000),
1761
+ participantId: z.string().min(1).max(100),
1762
+ text: z.string().min(1).max(4000).optional(),
1763
+ template: DATA_TRIGGER_TEMPLATE.optional()
1764
+ });
1765
+ // ctx.channels.templates: the approved WhatsApp templates of the project's
1766
+ // channels.
1767
+ const CUSTOM_CODE_BROKER_CHANNELS_TEMPLATES = z.object({
1768
+ call: z.string().min(1).max(4000)
1769
+ });
1770
+ const CUSTOM_CODE_BROKER_CHANNELS_POST = z.object({
1771
+ call: z.string().min(1).max(4000),
1772
+ channelId: z.string().min(1).max(100),
1773
+ chatId: z.union([z.string().min(1).max(200), z.number().int()]),
1774
+ text: z.string().min(1).max(4000)
1775
+ });
1776
+
1676
1777
  const CUSTOM_CODE_BROKER_RESOURCE_SEARCH = z.object({
1677
1778
  query: z.string().min(1).max(2000),
1678
1779
  limit: z.number().int().positive().max(20).default(5)
@@ -1916,6 +2017,60 @@ const CHANNEL_LIST_MESSAGES = z.object({
1916
2017
  organizationId: z.uuid()
1917
2018
  });
1918
2019
 
2020
+ const CHANNEL_WHATSAPP_PARAMS = z.object({
2021
+ channelId: z.uuid(),
2022
+ projectId: z.uuid(),
2023
+ userId: z.uuid(),
2024
+ organizationId: z.uuid()
2025
+ });
2026
+
2027
+ // A new access token, the business account's id, or both, for a WhatsApp
2028
+ // channel's message templates. The rest of its credentials stay as they are.
2029
+ const CHANNEL_WHATSAPP_ACCOUNT = z
2030
+ .strictObject({
2031
+ accessToken: z.string().trim().min(20).max(2000).optional(),
2032
+ businessAccountId: z
2033
+ .string()
2034
+ .trim()
2035
+ .regex(/^\d{5,30}$/, 'The business account id is a number')
2036
+ .optional()
2037
+ })
2038
+ .refine(
2039
+ v => v.accessToken !== undefined || v.businessAccountId !== undefined,
2040
+ 'Give a new access token, the business account id, or both'
2041
+ );
2042
+
2043
+ // A WhatsApp message template as the dashboard writes it. Meta's own rules
2044
+ // are checked with checkWhatsappTemplate before it is sent for review.
2045
+ const CHANNEL_WHATSAPP_TEMPLATE_CONTENT = z.strictObject({
2046
+ category: z.enum(WHATSAPP_TEMPLATE_CATEGORIES),
2047
+ header: z.string().max(WHATSAPP_TEMPLATE_HEADER_MAX).nullish(),
2048
+ body: z.string().trim().min(1).max(WHATSAPP_TEMPLATE_BODY_MAX),
2049
+ footer: z.string().max(WHATSAPP_TEMPLATE_FOOTER_MAX).nullish(),
2050
+ buttons: z
2051
+ .array(z.string().max(WHATSAPP_TEMPLATE_BUTTON_MAX))
2052
+ .max(WHATSAPP_TEMPLATE_BUTTONS_MAX)
2053
+ .optional(),
2054
+ // {{n}}'s example value and label are at n - 1.
2055
+ examples: z
2056
+ .array(z.string().max(WHATSAPP_TEMPLATE_EXAMPLE_MAX))
2057
+ .max(WHATSAPP_TEMPLATE_VARIABLES_MAX)
2058
+ .optional(),
2059
+ labels: z
2060
+ .array(z.string().max(WHATSAPP_TEMPLATE_LABEL_MAX))
2061
+ .max(WHATSAPP_TEMPLATE_VARIABLES_MAX)
2062
+ .optional()
2063
+ });
2064
+ const CHANNEL_WHATSAPP_TEMPLATE_CREATE = CHANNEL_WHATSAPP_TEMPLATE_CONTENT.extend(
2065
+ {
2066
+ name: z.string().trim().min(1).max(WHATSAPP_TEMPLATE_NAME_MAX),
2067
+ language: z.string().trim().min(2).max(10)
2068
+ }
2069
+ );
2070
+ const CHANNEL_WHATSAPP_TEMPLATE_PARAMS = CHANNEL_WHATSAPP_PARAMS.extend({
2071
+ templateId: z.uuid()
2072
+ });
2073
+
1919
2074
  const CHANNEL_CREATE_VIEW = CHANNEL_CREATE.omit({
1920
2075
  projectId: true,
1921
2076
  userId: true,
@@ -2038,6 +2193,12 @@ export const Schema = {
2038
2193
  DATA_QUERY_INPUT,
2039
2194
  DATA_QUERY_RUN_BODY,
2040
2195
  DATA_QUERY_PATH_PARAMS,
2196
+ DATA_TRIGGER_INPUT,
2197
+ DATA_TRIGGER_PATCH,
2198
+ DATA_TRIGGER_DEPLOY_BODY,
2199
+ DATA_TRIGGER_RUN_LIST_QUERY,
2200
+ DATA_TRIGGER_PATH_PARAMS,
2201
+ DATA_TRIGGER_RUN_PARAMS,
2041
2202
  DATA_COLUMN_PARAMS,
2042
2203
  DATA_ROW_PARAMS,
2043
2204
  ARTIFACT_REMOVE_RESOURCE,
@@ -2074,6 +2235,11 @@ export const Schema = {
2074
2235
  CHANNEL_REMOVE,
2075
2236
  CHANNEL_LIST_CONVERSATIONS,
2076
2237
  CHANNEL_LIST_MESSAGES,
2238
+ CHANNEL_WHATSAPP_PARAMS,
2239
+ CHANNEL_WHATSAPP_ACCOUNT,
2240
+ CHANNEL_WHATSAPP_TEMPLATE_CREATE,
2241
+ CHANNEL_WHATSAPP_TEMPLATE_CONTENT,
2242
+ CHANNEL_WHATSAPP_TEMPLATE_PARAMS,
2077
2243
  ARTIFACT_UPDATE_RESOURCE_SHOW_SOURCE,
2078
2244
  ARTIFACT_UPDATE_RESOURCE_SYNC_INTERVAL,
2079
2245
  ARTIFACT_SYNC_RESOURCE,
@@ -2102,6 +2268,9 @@ export const Schema = {
2102
2268
  CUSTOM_CODE_BROKER_CONNECTION,
2103
2269
  CUSTOM_CODE_BROKER_SECRET,
2104
2270
  CUSTOM_CODE_BROKER_DATA,
2271
+ CUSTOM_CODE_BROKER_CHANNELS_SEND,
2272
+ CUSTOM_CODE_BROKER_CHANNELS_POST,
2273
+ CUSTOM_CODE_BROKER_CHANNELS_TEMPLATES,
2105
2274
  CUSTOM_CODE_BROKER_RESOURCE_SEARCH,
2106
2275
  CUSTOM_CODE_BROKER_RESOURCE_READ,
2107
2276
  CUSTOM_CODE_BROKER_RESOURCE_CREATE,
@@ -30,6 +30,9 @@ 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
32
  export const CUSTOM_CODE_BROKER_PATH_DATA = '/data';
33
+ export const CUSTOM_CODE_BROKER_PATH_CHANNELS_SEND = '/channels/send';
34
+ export const CUSTOM_CODE_BROKER_PATH_CHANNELS_POST = '/channels/post';
35
+ export const CUSTOM_CODE_BROKER_PATH_CHANNELS_TEMPLATES = '/channels/templates';
33
36
 
34
37
  // Injected at upload time and echoed back by the health probe below. Uploading a
35
38
  // script into the dispatch namespace is not read-your-writes: dispatching to the