simplex-chat 6.5.0-beta.4.4 → 6.5.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.
@@ -74,7 +74,7 @@ Defined in: [src/api.ts:6](../src/api.ts#L6)
74
74
 
75
75
  ### stack?
76
76
 
77
- > `optional` **stack**: `string`
77
+ > `optional` **stack?**: `string`
78
78
 
79
79
  Defined in: [node\_modules/typescript/lib/lib.es5.d.ts:1078](../node_modules/typescript/lib/lib.es5.d.ts#L1078)
80
80
 
@@ -14,7 +14,7 @@ Bot address settings.
14
14
 
15
15
  ### autoAccept?
16
16
 
17
- > `optional` **autoAccept**: `boolean`
17
+ > `optional` **autoAccept?**: `boolean`
18
18
 
19
19
  Defined in: [src/api.ts:28](../src/api.ts#L28)
20
20
 
@@ -30,7 +30,7 @@ true
30
30
 
31
31
  ### businessAddress?
32
32
 
33
- > `optional` **businessAddress**: `boolean`
33
+ > `optional` **businessAddress?**: `boolean`
34
34
 
35
35
  Defined in: [src/api.ts:41](../src/api.ts#L41)
36
36
 
@@ -47,7 +47,7 @@ false
47
47
 
48
48
  ### welcomeMessage?
49
49
 
50
- > `optional` **welcomeMessage**: `string` \| `MsgContent`
50
+ > `optional` **welcomeMessage?**: `string` \| `MsgContent`
51
51
 
52
52
  Defined in: [src/api.ts:34](../src/api.ts#L34)
53
53
 
@@ -0,0 +1,64 @@
1
+ [**simplex-chat**](README.md)
2
+
3
+ ***
4
+
5
+ [simplex-chat](README.md) / [api](Namespace.api.md) / DbConfig
6
+
7
+ # Type Alias: DbConfig
8
+
9
+ > **DbConfig** = \{ `encryptionKey?`: `string`; `filePrefix`: `string`; `type`: `"sqlite"`; \} \| \{ `connectionString`: `string`; `schemaPrefix?`: `string`; `type`: `"postgres"`; \}
10
+
11
+ Defined in: [src/api.ts:65](../src/api.ts#L65)
12
+
13
+ Database configuration. The native library is built against exactly one
14
+ backend (see `simplex_backend` / `SIMPLEX_BACKEND` at install time); this
15
+ type makes the caller state which one they are targeting so field names
16
+ can't lie about their meaning.
17
+
18
+ ## Union Members
19
+
20
+ ### Type Literal
21
+
22
+ \{ `encryptionKey?`: `string`; `filePrefix`: `string`; `type`: `"sqlite"`; \}
23
+
24
+ #### encryptionKey?
25
+
26
+ > `optional` **encryptionKey?**: `string`
27
+
28
+ Optional SQLCipher encryption key. Empty/omitted = unencrypted.
29
+
30
+ #### filePrefix
31
+
32
+ > **filePrefix**: `string`
33
+
34
+ File prefix — two schema files are named `<prefix>_chat.db` and `<prefix>_agent.db`.
35
+
36
+ #### type
37
+
38
+ > **type**: `"sqlite"`
39
+
40
+ SQLite backend (default).
41
+
42
+ ***
43
+
44
+ ### Type Literal
45
+
46
+ \{ `connectionString`: `string`; `schemaPrefix?`: `string`; `type`: `"postgres"`; \}
47
+
48
+ #### connectionString
49
+
50
+ > **connectionString**: `string`
51
+
52
+ PostgreSQL connection string (e.g. `postgres://user:pass@host/db`).
53
+
54
+ #### schemaPrefix?
55
+
56
+ > `optional` **schemaPrefix?**: `string`
57
+
58
+ Schema prefix used to namespace tables. Defaults to `"simplex_v1"` when omitted.
59
+
60
+ #### type
61
+
62
+ > **type**: `"postgres"`
63
+
64
+ PostgreSQL backend (Linux x86_64 only, libpq5 required).
@@ -4,7 +4,7 @@
4
4
 
5
5
  [simplex-chat](README.md) / [api](Namespace.api.md) / EventSubscriberFunc
6
6
 
7
- # Type Alias: EventSubscriberFunc()\<K\>
7
+ # Type Alias: EventSubscriberFunc\<K\>
8
8
 
9
9
  > **EventSubscriberFunc**\<`K`\> = (`event`) => `void` \| `Promise`\<`void`\>
10
10
 
@@ -20,7 +20,7 @@ Defined in: [src/api.ts:50](../src/api.ts#L50)
20
20
 
21
21
  ### event
22
22
 
23
- `ChatEvent` & \{ `type`: `K`; \}
23
+ `ChatEvent` & `object`
24
24
 
25
25
  ## Returns
26
26
 
@@ -8,7 +8,7 @@
8
8
 
9
9
  > **run**(`__namedParameters`): `Promise`\<\[[`ChatApi`](api.Class.ChatApi.md), `User`, `UserContactLink` \| `undefined`\]\>
10
10
 
11
- Defined in: [src/bot.ts:49](../src/bot.ts#L49)
11
+ Defined in: [src/bot.ts:47](../src/bot.ts#L47)
12
12
 
13
13
  ## Parameters
14
14
 
@@ -6,43 +6,43 @@
6
6
 
7
7
  # Interface: BotConfig
8
8
 
9
- Defined in: [src/bot.ts:37](../src/bot.ts#L37)
9
+ Defined in: [src/bot.ts:35](../src/bot.ts#L35)
10
10
 
11
11
  ## Properties
12
12
 
13
13
  ### dbOpts
14
14
 
15
- > **dbOpts**: [`BotDbOpts`](bot.Interface.BotDbOpts.md)
15
+ > **dbOpts**: [`BotDbOpts`](bot.TypeAlias.BotDbOpts.md)
16
16
 
17
- Defined in: [src/bot.ts:39](../src/bot.ts#L39)
17
+ Defined in: [src/bot.ts:37](../src/bot.ts#L37)
18
18
 
19
19
  ***
20
20
 
21
21
  ### events?
22
22
 
23
- > `optional` **events**: [`EventSubscribers`](api.TypeAlias.EventSubscribers.md)
23
+ > `optional` **events?**: [`EventSubscribers`](api.TypeAlias.EventSubscribers.md)
24
24
 
25
- Defined in: [src/bot.ts:46](../src/bot.ts#L46)
25
+ Defined in: [src/bot.ts:44](../src/bot.ts#L44)
26
26
 
27
27
  ***
28
28
 
29
29
  ### onCommands?
30
30
 
31
- > `optional` **onCommands**: \{\[`key`: `string`\]: (`chatItem`, `command`) => `void` \| `Promise`\<`void`\> \| `undefined`; \}
31
+ > `optional` **onCommands?**: `object`
32
32
 
33
- Defined in: [src/bot.ts:43](../src/bot.ts#L43)
33
+ Defined in: [src/bot.ts:41](../src/bot.ts#L41)
34
34
 
35
35
  #### Index Signature
36
36
 
37
- \[`key`: `string`\]: (`chatItem`, `command`) => `void` \| `Promise`\<`void`\> \| `undefined`
37
+ \[`key`: `string`\]: ((`chatItem`, `command`) => `void` \| `Promise`\<`void`\>) \| `undefined`
38
38
 
39
39
  ***
40
40
 
41
- ### onMessage()?
41
+ ### onMessage?
42
42
 
43
- > `optional` **onMessage**: (`chatItem`, `content`) => `void` \| `Promise`\<`void`\>
43
+ > `optional` **onMessage?**: (`chatItem`, `content`) => `void` \| `Promise`\<`void`\>
44
44
 
45
- Defined in: [src/bot.ts:41](../src/bot.ts#L41)
45
+ Defined in: [src/bot.ts:39](../src/bot.ts#L39)
46
46
 
47
47
  #### Parameters
48
48
 
@@ -64,7 +64,7 @@ Defined in: [src/bot.ts:41](../src/bot.ts#L41)
64
64
 
65
65
  > **options**: [`BotOptions`](bot.Interface.BotOptions.md)
66
66
 
67
- Defined in: [src/bot.ts:40](../src/bot.ts#L40)
67
+ Defined in: [src/bot.ts:38](../src/bot.ts#L38)
68
68
 
69
69
  ***
70
70
 
@@ -72,4 +72,4 @@ Defined in: [src/bot.ts:40](../src/bot.ts#L40)
72
72
 
73
73
  > **profile**: `Profile`
74
74
 
75
- Defined in: [src/bot.ts:38](../src/bot.ts#L38)
75
+ Defined in: [src/bot.ts:36](../src/bot.ts#L36)
@@ -6,76 +6,76 @@
6
6
 
7
7
  # Interface: BotOptions
8
8
 
9
- Defined in: [src/bot.ts:13](../src/bot.ts#L13)
9
+ Defined in: [src/bot.ts:11](../src/bot.ts#L11)
10
10
 
11
11
  ## Properties
12
12
 
13
13
  ### addressSettings?
14
14
 
15
- > `optional` **addressSettings**: [`BotAddressSettings`](api.Interface.BotAddressSettings.md)
15
+ > `optional` **addressSettings?**: [`BotAddressSettings`](api.Interface.BotAddressSettings.md)
16
16
 
17
- Defined in: [src/bot.ts:17](../src/bot.ts#L17)
17
+ Defined in: [src/bot.ts:15](../src/bot.ts#L15)
18
18
 
19
19
  ***
20
20
 
21
21
  ### allowFiles?
22
22
 
23
- > `optional` **allowFiles**: `boolean`
23
+ > `optional` **allowFiles?**: `boolean`
24
24
 
25
- Defined in: [src/bot.ts:18](../src/bot.ts#L18)
25
+ Defined in: [src/bot.ts:16](../src/bot.ts#L16)
26
26
 
27
27
  ***
28
28
 
29
29
  ### commands?
30
30
 
31
- > `optional` **commands**: `ChatBotCommand`[]
31
+ > `optional` **commands?**: `ChatBotCommand`[]
32
32
 
33
- Defined in: [src/bot.ts:19](../src/bot.ts#L19)
33
+ Defined in: [src/bot.ts:17](../src/bot.ts#L17)
34
34
 
35
35
  ***
36
36
 
37
37
  ### createAddress?
38
38
 
39
- > `optional` **createAddress**: `boolean`
39
+ > `optional` **createAddress?**: `boolean`
40
40
 
41
- Defined in: [src/bot.ts:14](../src/bot.ts#L14)
41
+ Defined in: [src/bot.ts:12](../src/bot.ts#L12)
42
42
 
43
43
  ***
44
44
 
45
45
  ### logContacts?
46
46
 
47
- > `optional` **logContacts**: `boolean`
47
+ > `optional` **logContacts?**: `boolean`
48
48
 
49
- Defined in: [src/bot.ts:21](../src/bot.ts#L21)
49
+ Defined in: [src/bot.ts:19](../src/bot.ts#L19)
50
50
 
51
51
  ***
52
52
 
53
53
  ### logNetwork?
54
54
 
55
- > `optional` **logNetwork**: `boolean`
55
+ > `optional` **logNetwork?**: `boolean`
56
56
 
57
- Defined in: [src/bot.ts:22](../src/bot.ts#L22)
57
+ Defined in: [src/bot.ts:20](../src/bot.ts#L20)
58
58
 
59
59
  ***
60
60
 
61
61
  ### updateAddress?
62
62
 
63
- > `optional` **updateAddress**: `boolean`
63
+ > `optional` **updateAddress?**: `boolean`
64
64
 
65
- Defined in: [src/bot.ts:15](../src/bot.ts#L15)
65
+ Defined in: [src/bot.ts:13](../src/bot.ts#L13)
66
66
 
67
67
  ***
68
68
 
69
69
  ### updateProfile?
70
70
 
71
- > `optional` **updateProfile**: `boolean`
71
+ > `optional` **updateProfile?**: `boolean`
72
72
 
73
- Defined in: [src/bot.ts:16](../src/bot.ts#L16)
73
+ Defined in: [src/bot.ts:14](../src/bot.ts#L14)
74
74
 
75
75
  ***
76
76
 
77
77
  ### useBotProfile?
78
78
 
79
- > `optional` **useBotProfile**: `boolean`
79
+ > `optional` **useBotProfile?**: `boolean`
80
80
 
81
- Defined in: [src/bot.ts:20](../src/bot.ts#L20)
81
+ Defined in: [src/bot.ts:18](../src/bot.ts#L18)
@@ -0,0 +1,17 @@
1
+ [**simplex-chat**](README.md)
2
+
3
+ ***
4
+
5
+ [simplex-chat](README.md) / [bot](Namespace.bot.md) / BotDbOpts
6
+
7
+ # Type Alias: BotDbOpts
8
+
9
+ > **BotDbOpts** = [`DbConfig`](api.TypeAlias.DbConfig.md) & `object`
10
+
11
+ Defined in: [src/bot.ts:7](../src/bot.ts#L7)
12
+
13
+ ## Type Declaration
14
+
15
+ ### confirmMigrations?
16
+
17
+ > `optional` **confirmMigrations?**: [`MigrationConfirmation`](core.Enumeration.MigrationConfirmation.md)
@@ -16,7 +16,7 @@ Defined in: [src/core.ts:92](../src/core.ts#L92)
16
16
 
17
17
  ### Constructor
18
18
 
19
- > **new ChatAPIError**(`message`, `chatError`): `ChatAPIError`
19
+ > **new ChatAPIError**(`message`, `chatError?`): `ChatAPIError`
20
20
 
21
21
  Defined in: [src/core.ts:93](../src/core.ts#L93)
22
22
 
@@ -26,9 +26,9 @@ Defined in: [src/core.ts:93](../src/core.ts#L93)
26
26
 
27
27
  `string`
28
28
 
29
- ##### chatError
29
+ ##### chatError?
30
30
 
31
- `ChatError` | `undefined`
31
+ `ChatError` \| `undefined`
32
32
 
33
33
  #### Returns
34
34
 
@@ -74,7 +74,7 @@ Defined in: [node\_modules/typescript/lib/lib.es5.d.ts:1076](../node_modules/typ
74
74
 
75
75
  ### stack?
76
76
 
77
- > `optional` **stack**: `string`
77
+ > `optional` **stack?**: `string`
78
78
 
79
79
  Defined in: [node\_modules/typescript/lib/lib.es5.d.ts:1078](../node_modules/typescript/lib/lib.es5.d.ts#L1078)
80
80
 
@@ -74,7 +74,7 @@ Defined in: [node\_modules/typescript/lib/lib.es5.d.ts:1076](../node_modules/typ
74
74
 
75
75
  ### stack?
76
76
 
77
- > `optional` **stack**: `string`
77
+ > `optional` **stack?**: `string`
78
78
 
79
79
  Defined in: [node\_modules/typescript/lib/lib.es5.d.ts:1078](../node_modules/typescript/lib/lib.es5.d.ts#L1078)
80
80
 
@@ -18,7 +18,7 @@ Defined in: [src/core.ts:87](../src/core.ts#L87)
18
18
 
19
19
  ### error?
20
20
 
21
- > `optional` **error**: `ChatError`
21
+ > `optional` **error?**: `ChatError`
22
22
 
23
23
  Defined in: [src/core.ts:89](../src/core.ts#L89)
24
24
 
@@ -26,6 +26,6 @@ Defined in: [src/core.ts:89](../src/core.ts#L89)
26
26
 
27
27
  ### result?
28
28
 
29
- > `optional` **result**: `R`
29
+ > `optional` **result?**: `R`
30
30
 
31
31
  Defined in: [src/core.ts:88](../src/core.ts#L88)
@@ -2,7 +2,7 @@
2
2
  const {bot} = await import("../dist/index.js")
3
3
  const [chat, _user, _address] = await bot.run({
4
4
  profile: {displayName: "Squaring bot example", fullName: ""},
5
- dbOpts: {dbFilePrefix: "./squaring_bot", dbKey: ""},
5
+ dbOpts: {type: "sqlite", filePrefix: "./squaring_bot"},
6
6
  options: {
7
7
  addressSettings: {welcomeMessage: "Send a number, I will square it."},
8
8
  },
@@ -5,7 +5,7 @@ import {bot, util} from "../dist"
5
5
  const welcomeMessage = "Hello! I am a simple squaring bot.\n\nIf you send me a number, I will calculate its square."
6
6
  const [chat, _user, _address] = await bot.run({
7
7
  profile: {displayName: "Squaring bot example", fullName: ""},
8
- dbOpts: {dbFilePrefix: "./squaring_bot", dbKey: ""},
8
+ dbOpts: {type: "sqlite", filePrefix: "./squaring_bot"},
9
9
  options: {
10
10
  addressSettings: {autoAccept: true, welcomeMessage, businessAddress: false},
11
11
  commands: [ // commands to show in client UI
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "simplex-chat",
3
- "version": "6.5.0-beta.4.4",
3
+ "version": "6.5.0",
4
4
  "main": "dist/index.js",
5
5
  "types": "dist/index.d.ts",
6
6
  "files": [
@@ -24,7 +24,7 @@
24
24
  "docs": "typedoc"
25
25
  },
26
26
  "dependencies": {
27
- "@simplex-chat/types": "^0.3.0",
27
+ "@simplex-chat/types": "^0.5.0",
28
28
  "extract-zip": "^2.0.1",
29
29
  "fast-deep-equal": "^3.1.3",
30
30
  "node-addon-api": "^8.5.0"
package/src/api.ts CHANGED
@@ -56,6 +56,41 @@ interface EventSubscriber<K extends CEvt.Tag> {
56
56
  once: boolean
57
57
  }
58
58
 
59
+ /**
60
+ * Database configuration. The native library is built against exactly one
61
+ * backend (see `simplex_backend` / `SIMPLEX_BACKEND` at install time); this
62
+ * type makes the caller state which one they are targeting so field names
63
+ * can't lie about their meaning.
64
+ */
65
+ export type DbConfig =
66
+ | {
67
+ /** SQLite backend (default). */
68
+ type: "sqlite"
69
+ /** File prefix — two schema files are named `<prefix>_chat.db` and `<prefix>_agent.db`. */
70
+ filePrefix: string
71
+ /** Optional SQLCipher encryption key. Empty/omitted = unencrypted. */
72
+ encryptionKey?: string
73
+ }
74
+ | {
75
+ /** PostgreSQL backend (Linux x86_64 only, libpq5 required). */
76
+ type: "postgres"
77
+ /** Schema prefix used to namespace tables. Defaults to `"simplex_v1"` when omitted. */
78
+ schemaPrefix?: string
79
+ /** PostgreSQL connection string (e.g. `postgres://user:pass@host/db`). */
80
+ connectionString: string
81
+ }
82
+
83
+ function dbConfigToMigrateArgs(db: DbConfig): [string, string] {
84
+ switch (db.type) {
85
+ case "sqlite":
86
+ return [db.filePrefix, db.encryptionKey ?? ""]
87
+ case "postgres":
88
+ return [db.schemaPrefix ?? "", db.connectionString]
89
+ default:
90
+ throw new Error(`Invalid DbConfig: ${JSON.stringify(db satisfies never)}`)
91
+ }
92
+ }
93
+
59
94
  /**
60
95
  * Main API class for interacting with the chat core library.
61
96
  */
@@ -64,21 +99,20 @@ export class ChatApi {
64
99
  private eventsLoop: Promise<void> | undefined = undefined
65
100
  private subscribers: {[K in CEvt.Tag]?: EventSubscriber<K>[]} = {}
66
101
  private receivers: EventSubscriberFunc<CEvt.Tag>[] = []
67
-
102
+
68
103
  private constructor(protected ctrl_: bigint | undefined) {}
69
104
 
70
105
  /**
71
106
  * Initializes the ChatApi.
72
- * @param {string} dbFilePrefix - File prefix for the database files.
73
- * @param {string} [dbKey=""] - Database encryption key.
107
+ * @param {DbConfig} db - Database configuration (sqlite or postgres).
74
108
  * @param {core.MigrationConfirmation} [confirm=core.MigrationConfirmation.YesUp] - Migration confirmation mode.
75
109
  */
76
110
  static async init(
77
- dbFilePrefix: string,
78
- dbKey: string = "",
111
+ db: DbConfig,
79
112
  confirm = core.MigrationConfirmation.YesUp
80
113
  ): Promise<ChatApi> {
81
- const ctrl = await core.chatMigrateInit(dbFilePrefix, dbKey, confirm)
114
+ const [path, key] = dbConfigToMigrateArgs(db)
115
+ const ctrl = await core.chatMigrateInit(path, key, confirm)
82
116
  return new ChatApi(ctrl)
83
117
  }
84
118
 
@@ -654,7 +688,7 @@ export class ChatApi {
654
688
  * Network usage: interactive.
655
689
  */
656
690
  async apiConnectPlan(userId: number, connectionLink: string): Promise<[T.ConnectionPlan, T.CreatedConnLink]> {
657
- const r = await this.sendChatCmd(CC.APIConnectPlan.cmdString({userId, connectionLink}))
691
+ const r = await this.sendChatCmd(CC.APIConnectPlan.cmdString({userId, connectionLink, resolveKnown: false}))
658
692
  if (r.type === "connectionPlan") return [r.connectionPlan, r.connLink]
659
693
  throw new ChatCommandError("error getting connect plan", r)
660
694
  }
@@ -747,6 +781,47 @@ export class ChatApi {
747
781
  throw new ChatCommandError("error deleting chat", r)
748
782
  }
749
783
 
784
+ /**
785
+ * Set group custom data.
786
+ * Network usage: no.
787
+ */
788
+ async apiSetGroupCustomData(groupId: number, customData?: object): Promise<void> {
789
+ const r = await this.sendChatCmd(CC.APISetGroupCustomData.cmdString({groupId, customData}))
790
+ if (r.type === "cmdOk") return
791
+ throw new ChatCommandError("error setting group custom data", r)
792
+ }
793
+
794
+ /**
795
+ * Set contact custom data.
796
+ * Network usage: no.
797
+ */
798
+ async apiSetContactCustomData(contactId: number, customData?: object): Promise<void> {
799
+ const r = await this.sendChatCmd(CC.APISetContactCustomData.cmdString({contactId, customData}))
800
+ if (r.type === "cmdOk") return
801
+ throw new ChatCommandError("error setting contact custom data", r)
802
+ }
803
+
804
+ /**
805
+ * Set auto-accept member contacts.
806
+ * Network usage: no.
807
+ */
808
+ async apiSetAutoAcceptMemberContacts(userId: number, onOff: boolean): Promise<void> {
809
+ const r = await this.sendChatCmd(CC.APISetUserAutoAcceptMemberContacts.cmdString({userId, onOff}))
810
+ if (r.type === "cmdOk") return
811
+ throw new ChatCommandError("error setting auto-accept member contacts", r)
812
+ }
813
+
814
+ /**
815
+ * Get chat items.
816
+ * Network usage: no.
817
+ */
818
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
819
+ async apiGetChat(chatType: T.ChatType, chatId: number, count: number): Promise<any> {
820
+ const r: any = await this.sendChatCmd(`/_get chat ${T.ChatType.cmdString(chatType)}${chatId} count=${count}`)
821
+ if (r.type === "apiChat") return r.chat
822
+ throw new ChatCommandError("error getting chat", r)
823
+ }
824
+
750
825
  /**
751
826
  * Get active user profile
752
827
  * Network usage: no.
@@ -772,7 +847,7 @@ export class ChatApi {
772
847
  * Network usage: no.
773
848
  */
774
849
  async apiCreateActiveUser(profile?: T.Profile): Promise<T.User> {
775
- const r = await this.sendChatCmd(CC.CreateActiveUser.cmdString({newUser: {profile, pastTimestamp: false}}))
850
+ const r = await this.sendChatCmd(CC.CreateActiveUser.cmdString({newUser: {profile, pastTimestamp: false, userChatRelay: false}}))
776
851
  if (r.type === "activeUser") return r.user
777
852
  throw new ChatCommandError("unexpected response", r)
778
853
  }
@@ -831,4 +906,34 @@ export class ChatApi {
831
906
  const r = await this.sendChatCmd(CC.APISetContactPrefs.cmdString({contactId, preferences}))
832
907
  if (r.type !== "contactPrefsUpdated") throw new ChatCommandError("error setting contact prefs", r)
833
908
  }
909
+
910
+ /**
911
+ * Create a direct message contact with a group member.
912
+ * Returns the created contact.
913
+ * Network usage: interactive.
914
+ */
915
+ async apiCreateMemberContact(groupId: number, groupMemberId: number): Promise<T.Contact> {
916
+ const r: any = await this.sendChatCmd(`/_create member contact #${groupId} ${groupMemberId}`)
917
+ if (r.type === "newMemberContact") return r.contact
918
+ throw new ChatCommandError("error creating member contact", r)
919
+ }
920
+
921
+ /**
922
+ * Send a direct message invitation to a group member contact.
923
+ * The contact must have been created with {@link apiCreateMemberContact}.
924
+ * Network usage: interactive.
925
+ */
926
+ async apiSendMemberContactInvitation(contactId: number, message?: T.MsgContent | string): Promise<T.Contact> {
927
+ let cmd = `/_invite member contact @${contactId}`
928
+ if (message !== undefined) {
929
+ if (typeof message === "string") {
930
+ cmd += ` text ${message}`
931
+ } else {
932
+ cmd += ` json ${JSON.stringify(message)}`
933
+ }
934
+ }
935
+ const r: any = await this.sendChatCmd(cmd)
936
+ if (r.type === "newMemberContactSentInv") return r.contact
937
+ throw new ChatCommandError("error sending member contact invitation", r)
938
+ }
834
939
  }
package/src/bot.ts CHANGED
@@ -4,9 +4,7 @@ import * as core from "./core"
4
4
  import * as util from "./util"
5
5
  import equal = require("fast-deep-equal")
6
6
 
7
- export interface BotDbOpts {
8
- dbFilePrefix: string // two schema files will be named <prefix>_chat.db and <prefix>_agent.db
9
- dbKey?: string
7
+ export type BotDbOpts = api.DbConfig & {
10
8
  confirmMigrations?: core.MigrationConfirmation
11
9
  }
12
10
 
@@ -47,7 +45,7 @@ export interface BotConfig {
47
45
  }
48
46
 
49
47
  export async function run({profile, dbOpts, options = defaultOpts, onMessage, onCommands = {}, events = {}}: BotConfig): Promise<[api.ChatApi, T.User, T.UserContactLink | undefined]> {
50
- const bot = await api.ChatApi.init(dbOpts.dbFilePrefix, dbOpts.dbKey || "", dbOpts.confirmMigrations || core.MigrationConfirmation.YesUp)
48
+ const bot = await api.ChatApi.init(dbOpts, dbOpts.confirmMigrations || core.MigrationConfirmation.YesUp)
51
49
  const opts = fullOptions(options)
52
50
  if (onMessage) subscribeMessages(bot, onMessage)
53
51
  if (Object.keys(onCommands).length > 0) subscribeCommands(bot, onCommands)
@@ -4,7 +4,19 @@ const path = require('path');
4
4
  const extract = require('extract-zip');
5
5
 
6
6
  const GITHUB_REPO = 'simplex-chat/simplex-chat-libs';
7
- const RELEASE_TAG = 'v6.5.0-beta.4';
7
+ const RELEASE_TAG = 'v6.5.0';
8
+ const BACKEND = (process.env.SIMPLEX_BACKEND || process.env.npm_config_simplex_backend || 'sqlite').toLowerCase();
9
+
10
+ if (BACKEND !== 'sqlite' && BACKEND !== 'postgres') {
11
+ console.error(`✗ Invalid SIMPLEX_BACKEND: "${BACKEND}". Must be "sqlite" or "postgres".`);
12
+ process.exit(1);
13
+ }
14
+
15
+ if (BACKEND === 'postgres' && (process.platform !== 'linux' || process.arch !== 'x64')) {
16
+ console.error(`✗ SIMPLEX_BACKEND=postgres is only supported on Linux x86_64.`);
17
+ process.exit(1);
18
+ }
19
+
8
20
  const ROOT_DIR = process.cwd(); // Root of the package being installed
9
21
  const LIBS_DIR = path.join(ROOT_DIR, 'libs')
10
22
  const INSTALLED_FILE = path.join(LIBS_DIR, 'installed.txt');
@@ -56,11 +68,12 @@ function isAlreadyInstalled() {
56
68
 
57
69
  try {
58
70
  const installedVersion = fs.readFileSync(INSTALLED_FILE, 'utf-8').trim();
59
- if (installedVersion === RELEASE_TAG) {
60
- console.log(`✓ Libraries version ${RELEASE_TAG} already installed`);
71
+ const expectedVersion = `${RELEASE_TAG}:${BACKEND}`;
72
+ if (installedVersion === expectedVersion) {
73
+ console.log(`✓ Libraries version ${RELEASE_TAG}:${BACKEND} already installed`);
61
74
  return true;
62
75
  } else {
63
- console.log(`Version mismatch: installed ${installedVersion}, need ${RELEASE_TAG}`);
76
+ console.log(`Version mismatch: installed ${installedVersion}, need ${expectedVersion}`);
64
77
  cleanLibsDirectory();
65
78
  return false;
66
79
  }
@@ -79,12 +92,14 @@ async function install() {
79
92
 
80
93
  const { platformName, archName } = getPlatformInfo();
81
94
  const repoName = GITHUB_REPO.split('/')[1];
82
- const zipFilename = `${repoName}-${platformName}-${archName}.zip`;
95
+ const backendSuffix = BACKEND === 'postgres' ? '-postgres' : '';
96
+ const zipFilename = `${repoName}-${platformName}-${archName}${backendSuffix}.zip`;
83
97
  const ZIP_URL = `https://github.com/${GITHUB_REPO}/releases/download/${RELEASE_TAG}/${zipFilename}`;
84
98
  const ZIP_PATH = path.join(ROOT_DIR, zipFilename);
85
99
  const TEMP_EXTRACT_DIR = path.join(ROOT_DIR, '.temp-extract');
86
100
 
87
101
  console.log(`Detected: ${platformName} ${archName}`);
102
+ console.log(`Backend: ${BACKEND}`);
88
103
  console.log(`Downloading: ${zipFilename}`);
89
104
 
90
105
  // Create libs directory
@@ -124,8 +139,8 @@ async function install() {
124
139
  }
125
140
 
126
141
  // Write installed.txt with version
127
- fs.writeFileSync(INSTALLED_FILE, RELEASE_TAG, 'utf-8');
128
- console.log(`✓ Wrote version ${RELEASE_TAG} to installed.txt`);
142
+ fs.writeFileSync(INSTALLED_FILE, `${RELEASE_TAG}:${BACKEND}`, 'utf-8');
143
+ console.log(`✓ Wrote version ${RELEASE_TAG}:${BACKEND} to installed.txt`);
129
144
 
130
145
  // Cleanup
131
146
  fs.rmSync(TEMP_EXTRACT_DIR, { recursive: true, force: true });