@whitewall/blip-sdk 0.0.136 → 0.0.138

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 (54) hide show
  1. package/dist/cjs/client.js +1 -1
  2. package/dist/cjs/client.js.map +1 -1
  3. package/dist/esm/client.js +1 -1
  4. package/dist/esm/client.js.map +1 -1
  5. package/package.json +2 -2
  6. package/src/client.ts +117 -0
  7. package/src/index.ts +6 -0
  8. package/src/namespaces/account.ts +729 -0
  9. package/src/namespaces/activecampaign.ts +285 -0
  10. package/src/namespaces/analytics.ts +230 -0
  11. package/src/namespaces/billing.ts +17 -0
  12. package/src/namespaces/builder.ts +52 -0
  13. package/src/namespaces/configurations.ts +19 -0
  14. package/src/namespaces/context.ts +67 -0
  15. package/src/namespaces/desk.ts +679 -0
  16. package/src/namespaces/media.ts +39 -0
  17. package/src/namespaces/namespace.ts +125 -0
  18. package/src/namespaces/plugins.ts +223 -0
  19. package/src/namespaces/portal.ts +402 -0
  20. package/src/namespaces/scheduler.ts +88 -0
  21. package/src/namespaces/whatsapp.ts +383 -0
  22. package/src/sender/bliperror.ts +42 -0
  23. package/src/sender/enveloperesolver.ts +148 -0
  24. package/src/sender/gateway/customgatewaysender.ts +43 -0
  25. package/src/sender/http/httpsender.ts +94 -0
  26. package/src/sender/index.ts +7 -0
  27. package/src/sender/plugin/communication.ts +72 -0
  28. package/src/sender/plugin/pluginsender.ts +75 -0
  29. package/src/sender/security.ts +33 -0
  30. package/src/sender/sender.ts +145 -0
  31. package/src/sender/sessionnegotiator.ts +175 -0
  32. package/src/sender/tcp/tcpsender.ts +252 -0
  33. package/src/sender/throttler.ts +36 -0
  34. package/src/sender/websocket/websocketsender.ts +175 -0
  35. package/src/types/account.ts +84 -0
  36. package/src/types/analytics.ts +18 -0
  37. package/src/types/billing.ts +15 -0
  38. package/src/types/command.ts +47 -0
  39. package/src/types/commons.ts +16 -0
  40. package/src/types/desk.ts +51 -0
  41. package/src/types/envelope.ts +9 -0
  42. package/src/types/flow.ts +327 -0
  43. package/src/types/index.ts +13 -0
  44. package/src/types/message.ts +116 -0
  45. package/src/types/node.ts +86 -0
  46. package/src/types/notification.ts +18 -0
  47. package/src/types/plugins.ts +51 -0
  48. package/src/types/portal.ts +39 -0
  49. package/src/types/reason.ts +22 -0
  50. package/src/types/session.ts +22 -0
  51. package/src/types/whatsapp.ts +84 -0
  52. package/src/utils/odata.ts +114 -0
  53. package/src/utils/random.ts +3 -0
  54. package/src/utils/uri.ts +46 -0
@@ -0,0 +1,22 @@
1
+ import type { Authentication } from '../sender/security.ts'
2
+ import type { Envelope } from './envelope.ts'
3
+ import type { Reason } from './reason.ts'
4
+
5
+ export type Session = Envelope & {
6
+ state: 'new' | 'negotiating' | 'authenticating' | 'established' | 'finishing' | 'finished' | 'failed'
7
+
8
+ encryptionOptions?: Array<string>
9
+ compressionOptions?: Array<string>
10
+ schemeOptions?: Array<string>
11
+
12
+ encryption?: string
13
+ compression?: string
14
+ scheme?: string
15
+
16
+ authentication?: Omit<Authentication, 'scheme'>
17
+ reason?: Reason
18
+ }
19
+
20
+ export const isSession = (value: Envelope): value is Session => {
21
+ return 'state' in value
22
+ }
@@ -0,0 +1,84 @@
1
+ export type WhatsappFlow = {
2
+ id: string
3
+ name: string
4
+ status: 'DRAFT' | 'PUBLISHED' | 'DEPRECATED'
5
+ categories: Array<string>
6
+ validation_errors: Array<{
7
+ error: string
8
+ error_type: string
9
+ message: string
10
+ }>
11
+ preview: {
12
+ preview_url: string
13
+ expires_at: string
14
+ }
15
+ endpoint_uri?: string
16
+ }
17
+
18
+ // Components ref.: https://developers.facebook.com/docs/whatsapp/business-management-api/message-templates/components
19
+
20
+ export type HandleFormats = 'IMAGE' | 'VIDEO' | 'DOCUMENT'
21
+
22
+ type ExampleType<T extends 'TEXT' | 'LOCATION' | HandleFormats> = T extends 'TEXT'
23
+ ? { header_text?: Array<string> }
24
+ : T extends HandleFormats
25
+ ? { header_handle?: Array<string> }
26
+ : never
27
+
28
+ export type HeaderComponent<T extends 'TEXT' | 'LOCATION' | HandleFormats> = {
29
+ type: 'HEADER'
30
+ format: T
31
+ example: ExampleType<T>
32
+ }
33
+
34
+ export type BodyComponent = {
35
+ type: 'BODY'
36
+ text: string
37
+ example?: {
38
+ body_text: [Array<string>]
39
+ }
40
+ }
41
+
42
+ export type FooterComponent = {
43
+ type: 'FOOTER'
44
+ text: string
45
+ }
46
+
47
+ export type ButtonComponent = {
48
+ type: 'BUTTONS'
49
+ buttons: Array<{
50
+ type: string
51
+ // biome-ignore lint/suspicious/noExplicitAny: Too hard to type this properly
52
+ [key: string]: any
53
+ }>
54
+ }
55
+
56
+ export type CarouselComponent = {
57
+ type: 'CAROUSEL'
58
+ cards: Array<{
59
+ components: Array<UnknownComponent>
60
+ }>
61
+ }
62
+
63
+ export type UnknownComponent =
64
+ | HeaderComponent<'TEXT' | 'LOCATION' | HandleFormats>
65
+ | BodyComponent
66
+ | FooterComponent
67
+ | ButtonComponent
68
+ | CarouselComponent
69
+
70
+ export type MessageTemplate = {
71
+ id: string
72
+ name: string
73
+ category: 'AUTHENTICATION' | 'MARKETING' | 'UTILITY'
74
+ status: 'APPROVED' | 'REJECTED' | 'PENDING'
75
+ rejected_reason: string
76
+ language: string
77
+ last_update_time: string
78
+ components: Array<UnknownComponent>
79
+ }
80
+
81
+ export type MessageTemplateVariable = {
82
+ type: 'BODY' | 'MEDIA' | 'BUTTON'
83
+ example?: string
84
+ }
@@ -0,0 +1,114 @@
1
+ type Primitive = string | number | Date | boolean
2
+
3
+ export class ODataFilter<T> {
4
+ private filterParts: Array<string> = []
5
+
6
+ private getFormattedValue(value: Primitive | unknown): string {
7
+ if (typeof value === 'string') {
8
+ return `'${value.replace(/'/g, '%27%27')}'`
9
+ } else if (value instanceof Date) {
10
+ return `datetimeoffset'${value.toISOString()}'`
11
+ } else if (typeof value === 'undefined' || value === null) {
12
+ return 'null'
13
+ } else {
14
+ return value.toString()
15
+ }
16
+ }
17
+
18
+ private addCondition(condition: string) {
19
+ this.filterParts.push(condition)
20
+ }
21
+
22
+ eq<K extends keyof T>(field: K, value: T[K]): ODataFilter<T> {
23
+ this.addCondition(`${String(field)} eq ${this.getFormattedValue(value)}`)
24
+ return this
25
+ }
26
+
27
+ ne<K extends keyof T>(field: K, value: T[K]): ODataFilter<T> {
28
+ this.addCondition(`${String(field)} ne ${this.getFormattedValue(value)}`)
29
+ return this
30
+ }
31
+
32
+ gt<K extends keyof T>(field: K, value: T[K] | Date): ODataFilter<T> {
33
+ this.addCondition(`${String(field)} gt ${this.getFormattedValue(value)}`)
34
+ return this
35
+ }
36
+
37
+ ge<K extends keyof T>(field: K, value: T[K] | Date): ODataFilter<T> {
38
+ this.addCondition(`${String(field)} ge ${this.getFormattedValue(value)}`)
39
+ return this
40
+ }
41
+
42
+ lt<K extends keyof T>(field: K, value: T[K] | Date): ODataFilter<T> {
43
+ this.addCondition(`${String(field)} lt ${this.getFormattedValue(value)}`)
44
+ return this
45
+ }
46
+
47
+ le<K extends keyof T>(field: K, value: T[K] | Date): ODataFilter<T> {
48
+ this.addCondition(`${String(field)} le ${this.getFormattedValue(value)}`)
49
+ return this
50
+ }
51
+
52
+ in<K extends keyof T>(field: K, values: Array<T[K]>): ODataFilter<T> {
53
+ const formattedValues = values.map((v) => this.getFormattedValue(v)).join(',')
54
+ this.addCondition(`${String(field)} in (${formattedValues})`)
55
+ return this
56
+ }
57
+
58
+ startsWith<K extends keyof T>(field: K, value: string): ODataFilter<T> {
59
+ this.addCondition(`startswith(${String(field)}, ${this.getFormattedValue(value)})`)
60
+ return this
61
+ }
62
+
63
+ endsWith<K extends keyof T>(field: K, value: string): ODataFilter<T> {
64
+ this.addCondition(`endswith(${String(field)}, ${this.getFormattedValue(value)})`)
65
+ return this
66
+ }
67
+
68
+ contains<K extends keyof T>(field: K, value: string): ODataFilter<T> {
69
+ this.addCondition(`contains(${String(field)}, ${this.getFormattedValue(value)})`)
70
+ return this
71
+ }
72
+
73
+ includes<K extends keyof T>(field: K, value: string): ODataFilter<T> {
74
+ this.addCondition(`substringof(${this.getFormattedValue(value)}, ${String(field)}) eq true`)
75
+ return this
76
+ }
77
+
78
+ notIncludes<K extends keyof T>(field: K, value: string): ODataFilter<T> {
79
+ this.addCondition(`substringof(${this.getFormattedValue(value)}, ${String(field)}) eq false`)
80
+ return this
81
+ }
82
+
83
+ and(filterBuilder: (filter: ODataFilter<T>) => ODataFilter<T>): ODataFilter<T> {
84
+ const newFilter = filterBuilder(new ODataFilter<T>())
85
+ if (newFilter.filterParts.length > 0) {
86
+ if (this.filterParts.length > 0) {
87
+ this.addCondition(`${this.toString()} and (${newFilter})`)
88
+ } else {
89
+ this.addCondition(`(${newFilter})`)
90
+ }
91
+ this.filterParts = [this.filterParts.pop()!] // keep only the latest compound condition
92
+ }
93
+ return this
94
+ }
95
+
96
+ or(filterBuilder: (filter: ODataFilter<T>) => ODataFilter<T>): ODataFilter<T> {
97
+ const newFilter = filterBuilder(new ODataFilter<T>())
98
+ if (newFilter.filterParts.length > 0) {
99
+ if (this.filterParts.length > 0) {
100
+ this.addCondition(`${this.toString()} or (${newFilter})`)
101
+ } else {
102
+ this.addCondition(`(${newFilter})`)
103
+ }
104
+ this.filterParts = [this.filterParts.pop()!] // keep only the latest compound condition
105
+ }
106
+ return this
107
+ }
108
+
109
+ toString(): string {
110
+ return this.filterParts.join(' and ')
111
+ }
112
+ }
113
+
114
+ export const filter = <T>(): ODataFilter<T> => new ODataFilter<T>()
@@ -0,0 +1,3 @@
1
+ export const randomId = () => {
2
+ return Math.random().toString(36).substring(2)
3
+ }
@@ -0,0 +1,46 @@
1
+ export interface URI {
2
+ path: string
3
+ // native URLSearchParams is not worth here
4
+ // we can't use URLSearchParams.toString() because it encodes the spaces as `+` instead of `%20`
5
+ // causing issues in some cases like odata queries
6
+ // also not encoding the keys is good for dev readability (lime doesn't care much about it)
7
+ query: Map<string, string>
8
+ }
9
+
10
+ export const uri = (parts: TemplateStringsArray, ...vars: Array<unknown>): URI => {
11
+ let queryObject: Record<string, unknown> | undefined
12
+ const last = vars[vars.length - 1]
13
+ if (last && last.constructor === Object) {
14
+ queryObject = last as Record<string, unknown>
15
+ vars.splice(vars.length - 1, 1)
16
+ }
17
+
18
+ const stringify = (v: unknown): string =>
19
+ v === undefined || v === null ? '' : v instanceof Date ? v.toISOString() : String(v)
20
+
21
+ const raw = parts.map((part, i) => part + encodeURIComponent(stringify(vars[i]))).join('')
22
+
23
+ const [path, rawQuery = ''] = raw.split('?', 2)
24
+ const query = new Map(new URLSearchParams(rawQuery))
25
+
26
+ if (queryObject) {
27
+ for (const [key, value] of Object.entries(queryObject)) {
28
+ if (value !== undefined && value !== null) {
29
+ query.set(key, stringify(value))
30
+ }
31
+ }
32
+ }
33
+
34
+ return { path, query }
35
+ }
36
+
37
+ export const uriToString = (uri: URI): string => {
38
+ if (uri.query.size === 0) {
39
+ return uri.path
40
+ }
41
+
42
+ const query = Array.from(uri.query)
43
+ .map(([key, value]) => `${key}=${encodeURIComponent(value)}`)
44
+ .join('&')
45
+ return `${uri.path}?${query}`
46
+ }