@yaebal/panel 0.0.2 → 0.0.5

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.
@@ -1 +1 @@
1
- {"version":3,"file":"panel-html.js","sourceRoot":"","sources":["../src/panel-html.ts"],"names":[],"mappings":"AAAA,0FAA0F;AAC1F,MAAM,CAAC,MAAM,UAAU,GAAG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;QA4OlB,CAAC"}
1
+ {"version":3,"file":"panel-html.js","sourceRoot":"","sources":["../src/panel-html.ts"],"names":[],"mappings":"AAAA,0FAA0F;AAC1F,MAAM,CAAC,MAAM,UAAU,GAAG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;QAqhBlB,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"serve.d.ts","sourceRoot":"","sources":["../src/serve.ts"],"names":[],"mappings":"AAAA,OAAO,EAAwB,KAAK,MAAM,EAAqC,MAAM,WAAW,CAAC;AAEjG,iDAAiD;AACjD,MAAM,WAAW,YAAY;IAC5B,yBAAyB;IACzB,IAAI,EAAE,MAAM,CAAC;IACb,2EAA2E;IAC3E,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,4CAA4C;IAC5C,QAAQ,CAAC,EAAE,CAAC,IAAI,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,IAAI,CAAC,EAAE,MAAM,CAAA;KAAE,KAAK,IAAI,CAAC;CAC3D;AA0BD;;;;;;;;;GASG;AACH,wBAAgB,KAAK,CACpB,OAAO,EAAE,CAAC,OAAO,EAAE,OAAO,KAAK,OAAO,CAAC,QAAQ,CAAC,GAAG,QAAQ,EAC3D,OAAO,EAAE,YAAY,GACnB,MAAM,CAeR"}
1
+ {"version":3,"file":"serve.d.ts","sourceRoot":"","sources":["../src/serve.ts"],"names":[],"mappings":"AAAA,OAAO,EAAsC,KAAK,MAAM,EAAuB,MAAM,WAAW,CAAC;AAEjG,iDAAiD;AACjD,MAAM,WAAW,YAAY;IAC5B,yBAAyB;IACzB,IAAI,EAAE,MAAM,CAAC;IACb,2EAA2E;IAC3E,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,4CAA4C;IAC5C,QAAQ,CAAC,EAAE,CAAC,IAAI,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,IAAI,CAAC,EAAE,MAAM,CAAA;KAAE,KAAK,IAAI,CAAC;CAC3D;AA0BD;;;;;;;;;GASG;AACH,wBAAgB,KAAK,CACpB,OAAO,EAAE,CAAC,OAAO,EAAE,OAAO,KAAK,OAAO,CAAC,QAAQ,CAAC,GAAG,QAAQ,EAC3D,OAAO,EAAE,YAAY,GACnB,MAAM,CAeR"}
package/lib/serve.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"serve.js","sourceRoot":"","sources":["../src/serve.ts"],"names":[],"mappings":"AAAA,OAAO,EAA0D,YAAY,EAAE,MAAM,WAAW,CAAC;AAYjG,yFAAyF;AACzF,SAAS,SAAS,CAAC,GAAoB;IACtC,MAAM,IAAI,GAAG,GAAG,CAAC,OAAO,CAAC,IAAI,IAAI,WAAW,CAAC;IAC7C,MAAM,GAAG,GAAG,UAAU,IAAI,GAAG,GAAG,CAAC,GAAG,IAAI,GAAG,EAAE,CAAC;IAE9C,MAAM,MAAM,GAAG,GAAG,CAAC,MAAM,IAAI,KAAK,CAAC;IACnC,MAAM,OAAO,GAAG,MAAM,KAAK,KAAK,IAAI,MAAM,KAAK,MAAM,CAAC;IAEtD,OAAO,IAAI,OAAO,CAAC,GAAG,EAAE;QACvB,MAAM;QACN,OAAO,EAAE,GAAG,CAAC,OAAiC;QAC9C,4EAA4E;QAC5E,IAAI,EAAE,OAAO,CAAC,CAAC,CAAE,GAAiC,CAAC,CAAC,CAAC,SAAS;QAC9D,mDAAmD;QACnD,MAAM,EAAE,MAAM;KACC,CAAC,CAAC;AACnB,CAAC;AAED,yEAAyE;AACzE,KAAK,UAAU,aAAa,CAAC,GAAmB,EAAE,QAAkB;IACnE,GAAG,CAAC,SAAS,CAAC,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC,WAAW,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAC,CAAC;IACrE,GAAG,CAAC,GAAG,CAAC,MAAM,CAAC,IAAI,CAAC,MAAM,QAAQ,CAAC,WAAW,EAAE,CAAC,CAAC,CAAC;AACpD,CAAC;AAED;;;;;;;;;GASG;AACH,MAAM,UAAU,KAAK,CACpB,OAA2D,EAC3D,OAAqB;IAErB,MAAM,MAAM,GAAG,YAAY,CAAC,CAAC,GAAG,EAAE,GAAG,EAAE,EAAE;QACxC,OAAO,CAAC,OAAO,CAAC,OAAO,CAAC,SAAS,CAAC,GAAG,CAAC,CAAC,CAAC;aACtC,IAAI,CAAC,CAAC,QAAQ,EAAE,EAAE,CAAC,aAAa,CAAC,GAAG,EAAE,QAAQ,CAAC,CAAC;aAChD,KAAK,CAAC,GAAG,EAAE;YACX,IAAI,CAAC,GAAG,CAAC,WAAW;gBAAE,GAAG,CAAC,SAAS,CAAC,GAAG,CAAC,CAAC;YACzC,GAAG,CAAC,GAAG,CAAC,gBAAgB,CAAC,CAAC;QAC3B,CAAC,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;IAEH,MAAM,CAAC,MAAM,CAAC,OAAO,CAAC,IAAI,EAAE,OAAO,CAAC,IAAI,EAAE,GAAG,EAAE;QAC9C,OAAO,CAAC,QAAQ,EAAE,CAAC,EAAE,IAAI,EAAE,OAAO,CAAC,IAAI,EAAE,IAAI,EAAE,OAAO,CAAC,IAAI,EAAE,CAAC,CAAC;IAChE,CAAC,CAAC,CAAC;IAEH,OAAO,MAAM,CAAC;AACf,CAAC"}
1
+ {"version":3,"file":"serve.js","sourceRoot":"","sources":["../src/serve.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAA0D,MAAM,WAAW,CAAC;AAYjG,yFAAyF;AACzF,SAAS,SAAS,CAAC,GAAoB;IACtC,MAAM,IAAI,GAAG,GAAG,CAAC,OAAO,CAAC,IAAI,IAAI,WAAW,CAAC;IAC7C,MAAM,GAAG,GAAG,UAAU,IAAI,GAAG,GAAG,CAAC,GAAG,IAAI,GAAG,EAAE,CAAC;IAE9C,MAAM,MAAM,GAAG,GAAG,CAAC,MAAM,IAAI,KAAK,CAAC;IACnC,MAAM,OAAO,GAAG,MAAM,KAAK,KAAK,IAAI,MAAM,KAAK,MAAM,CAAC;IAEtD,OAAO,IAAI,OAAO,CAAC,GAAG,EAAE;QACvB,MAAM;QACN,OAAO,EAAE,GAAG,CAAC,OAAiC;QAC9C,4EAA4E;QAC5E,IAAI,EAAE,OAAO,CAAC,CAAC,CAAE,GAAiC,CAAC,CAAC,CAAC,SAAS;QAC9D,mDAAmD;QACnD,MAAM,EAAE,MAAM;KACC,CAAC,CAAC;AACnB,CAAC;AAED,yEAAyE;AACzE,KAAK,UAAU,aAAa,CAAC,GAAmB,EAAE,QAAkB;IACnE,GAAG,CAAC,SAAS,CAAC,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC,WAAW,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAC,CAAC;IACrE,GAAG,CAAC,GAAG,CAAC,MAAM,CAAC,IAAI,CAAC,MAAM,QAAQ,CAAC,WAAW,EAAE,CAAC,CAAC,CAAC;AACpD,CAAC;AAED;;;;;;;;;GASG;AACH,MAAM,UAAU,KAAK,CACpB,OAA2D,EAC3D,OAAqB;IAErB,MAAM,MAAM,GAAG,YAAY,CAAC,CAAC,GAAG,EAAE,GAAG,EAAE,EAAE;QACxC,OAAO,CAAC,OAAO,CAAC,OAAO,CAAC,SAAS,CAAC,GAAG,CAAC,CAAC,CAAC;aACtC,IAAI,CAAC,CAAC,QAAQ,EAAE,EAAE,CAAC,aAAa,CAAC,GAAG,EAAE,QAAQ,CAAC,CAAC;aAChD,KAAK,CAAC,GAAG,EAAE;YACX,IAAI,CAAC,GAAG,CAAC,WAAW;gBAAE,GAAG,CAAC,SAAS,CAAC,GAAG,CAAC,CAAC;YACzC,GAAG,CAAC,GAAG,CAAC,gBAAgB,CAAC,CAAC;QAC3B,CAAC,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;IAEH,MAAM,CAAC,MAAM,CAAC,OAAO,CAAC,IAAI,EAAE,OAAO,CAAC,IAAI,EAAE,GAAG,EAAE;QAC9C,OAAO,CAAC,QAAQ,EAAE,CAAC,EAAE,IAAI,EAAE,OAAO,CAAC,IAAI,EAAE,IAAI,EAAE,OAAO,CAAC,IAAI,EAAE,CAAC,CAAC;IAChE,CAAC,CAAC,CAAC;IAEH,OAAO,MAAM,CAAC;AACf,CAAC"}
package/lib/sqlite.d.ts CHANGED
@@ -1,5 +1,5 @@
1
1
  import { DatabaseSync } from "node:sqlite";
2
- import type { HistoryOptions, PanelChat, PanelEvent, PanelMessage, PanelStore } from "./index.js";
2
+ import type { HistoryOptions, PanelChat, PanelChatRecord, PanelEvent, PanelMessage, PanelStore } from "./index.js";
3
3
  /** options for {@link SqlitePanelStore}. */
4
4
  export interface SqlitePanelStoreOptions {
5
5
  /** sqlite file path, or `":memory:"` (default). ignored when `db` is provided. */
@@ -19,10 +19,7 @@ export interface SqlitePanelStoreOptions {
19
19
  export declare class SqlitePanelStore implements PanelStore {
20
20
  #private;
21
21
  constructor(options?: SqlitePanelStoreOptions);
22
- record(chat: {
23
- id: number;
24
- name?: string;
25
- }, message: PanelMessage): void;
22
+ record(chat: PanelChatRecord, message: PanelMessage): void;
26
23
  chats(): PanelChat[];
27
24
  history(chatId: number, options?: HistoryOptions): PanelMessage[];
28
25
  subscribe(listener: (event: PanelEvent) => void): () => void;
@@ -1 +1 @@
1
- {"version":3,"file":"sqlite.d.ts","sourceRoot":"","sources":["../src/sqlite.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAC3C,OAAO,KAAK,EACX,cAAc,EAEd,SAAS,EACT,UAAU,EACV,YAAY,EACZ,UAAU,EACV,MAAM,YAAY,CAAC;AAEpB,4CAA4C;AAC5C,MAAM,WAAW,uBAAuB;IACvC,kFAAkF;IAClF,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,oEAAoE;IACpE,EAAE,CAAC,EAAE,YAAY,CAAC;CAClB;AAED;;;;;;;;GAQG;AACH,qBAAa,gBAAiB,YAAW,UAAU;;gBAItC,OAAO,GAAE,uBAA4B;IAsBjD,MAAM,CAAC,IAAI,EAAE;QAAE,EAAE,EAAE,MAAM,CAAC;QAAC,IAAI,CAAC,EAAE,MAAM,CAAA;KAAE,EAAE,OAAO,EAAE,YAAY,GAAG,IAAI;IAmCxE,KAAK,IAAI,SAAS,EAAE;IAapB,OAAO,CAAC,MAAM,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,cAAc,GAAG,YAAY,EAAE;IA6BjE,SAAS,CAAC,QAAQ,EAAE,CAAC,KAAK,EAAE,UAAU,KAAK,IAAI,GAAG,MAAM,IAAI;IAK5D,yEAAyE;IACzE,KAAK,IAAI,IAAI;CAGb"}
1
+ {"version":3,"file":"sqlite.d.ts","sourceRoot":"","sources":["../src/sqlite.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAC3C,OAAO,KAAK,EACX,cAAc,EAEd,SAAS,EACT,eAAe,EACf,UAAU,EAEV,YAAY,EAEZ,UAAU,EACV,MAAM,YAAY,CAAC;AAUpB,4CAA4C;AAC5C,MAAM,WAAW,uBAAuB;IACvC,kFAAkF;IAClF,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,oEAAoE;IACpE,EAAE,CAAC,EAAE,YAAY,CAAC;CAClB;AAED;;;;;;;;GAQG;AACH,qBAAa,gBAAiB,YAAW,UAAU;;gBAItC,OAAO,GAAE,uBAA4B;IAqCjD,MAAM,CAAC,IAAI,EAAE,eAAe,EAAE,OAAO,EAAE,YAAY,GAAG,IAAI;IAwD1D,KAAK,IAAI,SAAS,EAAE;IAmCpB,OAAO,CAAC,MAAM,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,cAAc,GAAG,YAAY,EAAE;IAiCjE,SAAS,CAAC,QAAQ,EAAE,CAAC,KAAK,EAAE,UAAU,KAAK,IAAI,GAAG,MAAM,IAAI;IAK5D,yEAAyE;IACzE,KAAK,IAAI,IAAI;CAGb"}
package/lib/sqlite.js CHANGED
@@ -1,4 +1,12 @@
1
1
  import { DatabaseSync } from "node:sqlite";
2
+ function addColumn(db, table, definition) {
3
+ try {
4
+ db.exec(`ALTER TABLE ${table} ADD COLUMN ${definition}`);
5
+ }
6
+ catch {
7
+ // Existing sqlite stores from older panel versions simply already have the column.
8
+ }
9
+ }
2
10
  /**
3
11
  * a persistent {@link PanelStore} backed by node's built-in `node:sqlite` (node 22.5+).
4
12
  * zero third-party deps. import from `@yaebal/panel/sqlite`.
@@ -15,10 +23,15 @@ export class SqlitePanelStore {
15
23
  this.#db = options.db ?? new DatabaseSync(options.path ?? ":memory:");
16
24
  this.#db.exec(`
17
25
  CREATE TABLE IF NOT EXISTS panel_chats (
18
- id INTEGER PRIMARY KEY,
19
- name TEXT,
20
- last_text TEXT NOT NULL,
21
- last_date INTEGER NOT NULL
26
+ id INTEGER PRIMARY KEY,
27
+ name TEXT,
28
+ first_name TEXT,
29
+ last_name TEXT,
30
+ username TEXT,
31
+ last_text TEXT NOT NULL,
32
+ last_date INTEGER NOT NULL,
33
+ last_attachment TEXT,
34
+ last_event TEXT
22
35
  );
23
36
  CREATE TABLE IF NOT EXISTS panel_messages (
24
37
  id INTEGER PRIMARY KEY AUTOINCREMENT,
@@ -27,25 +40,53 @@ export class SqlitePanelStore {
27
40
  text TEXT NOT NULL,
28
41
  date INTEGER NOT NULL,
29
42
  attachments TEXT,
30
- media_group TEXT
43
+ media_group TEXT,
44
+ keyboard TEXT,
45
+ event TEXT
31
46
  );
32
47
  CREATE INDEX IF NOT EXISTS panel_messages_chat ON panel_messages (chat_id, date);
33
48
  `);
49
+ addColumn(this.#db, "panel_chats", "first_name TEXT");
50
+ addColumn(this.#db, "panel_chats", "last_name TEXT");
51
+ addColumn(this.#db, "panel_chats", "username TEXT");
52
+ addColumn(this.#db, "panel_chats", "last_attachment TEXT");
53
+ addColumn(this.#db, "panel_chats", "last_event TEXT");
54
+ addColumn(this.#db, "panel_messages", "keyboard TEXT");
55
+ addColumn(this.#db, "panel_messages", "event TEXT");
34
56
  }
35
57
  record(chat, message) {
36
58
  this.#db
37
- .prepare("INSERT INTO panel_messages (chat_id, direction, text, date, attachments, media_group) VALUES (?, ?, ?, ?, ?, ?)")
38
- .run(chat.id, message.direction, message.text, message.date, message.attachments ? JSON.stringify(message.attachments) : null, message.mediaGroupId ?? null);
59
+ .prepare("INSERT INTO panel_messages (chat_id, direction, text, date, attachments, media_group, keyboard, event) VALUES (?, ?, ?, ?, ?, ?, ?, ?)")
60
+ .run(chat.id, message.direction, message.text, message.date, message.attachments ? JSON.stringify(message.attachments) : null, message.mediaGroupId ?? null, message.keyboard ? JSON.stringify(message.keyboard) : null, message.event ? JSON.stringify(message.event) : null);
39
61
  // keep the name when an outgoing message omits it; COALESCE the existing row's value
40
62
  this.#db
41
63
  .prepare(`
42
- INSERT INTO panel_chats (id, name, last_text, last_date) VALUES (:id, :name, :text, :date)
64
+ INSERT INTO panel_chats (
65
+ id, name, first_name, last_name, username, last_text, last_date, last_attachment, last_event
66
+ ) VALUES (
67
+ :id, :name, :firstName, :lastName, :username, :text, :date, :lastAttachment, :lastEvent
68
+ )
43
69
  ON CONFLICT(id) DO UPDATE SET
44
70
  name = COALESCE(:name, panel_chats.name),
71
+ first_name = COALESCE(:firstName, panel_chats.first_name),
72
+ last_name = COALESCE(:lastName, panel_chats.last_name),
73
+ username = COALESCE(:username, panel_chats.username),
45
74
  last_text = :text,
46
- last_date = :date
75
+ last_date = :date,
76
+ last_attachment = :lastAttachment,
77
+ last_event = :lastEvent
47
78
  `)
48
- .run({ id: chat.id, name: chat.name ?? null, text: message.text, date: message.date });
79
+ .run({
80
+ id: chat.id,
81
+ name: chat.name ?? null,
82
+ firstName: chat.firstName ?? null,
83
+ lastName: chat.lastName ?? null,
84
+ username: chat.username ?? null,
85
+ text: message.text,
86
+ date: message.date,
87
+ lastAttachment: message.attachments?.[0]?.type ?? null,
88
+ lastEvent: message.event?.type ?? null,
89
+ });
49
90
  // brand-new chat with no name → give it a stable fallback label
50
91
  this.#db
51
92
  .prepare("UPDATE panel_chats SET name = ? WHERE id = ? AND name IS NULL")
@@ -56,14 +97,27 @@ export class SqlitePanelStore {
56
97
  }
57
98
  chats() {
58
99
  const rows = this.#db
59
- .prepare("SELECT id, name, last_text, last_date FROM panel_chats ORDER BY last_date DESC")
100
+ .prepare("SELECT id, name, first_name, last_name, username, last_text, last_date, last_attachment, last_event FROM panel_chats ORDER BY last_date DESC")
60
101
  .all();
61
- return rows.map((r) => ({
62
- id: r.id,
63
- name: r.name ?? `chat ${r.id}`,
64
- lastText: r.last_text,
65
- lastDate: r.last_date,
66
- }));
102
+ return rows.map((r) => {
103
+ const chat = {
104
+ id: r.id,
105
+ name: r.name ?? `chat ${r.id}`,
106
+ lastText: r.last_text,
107
+ lastDate: r.last_date,
108
+ };
109
+ if (r.first_name)
110
+ chat.firstName = r.first_name;
111
+ if (r.last_name)
112
+ chat.lastName = r.last_name;
113
+ if (r.username)
114
+ chat.username = r.username;
115
+ if (r.last_attachment)
116
+ chat.lastAttachmentType = r.last_attachment;
117
+ if (r.last_event)
118
+ chat.lastEventType = r.last_event;
119
+ return chat;
120
+ });
67
121
  }
68
122
  history(chatId, options) {
69
123
  const before = options?.before ?? Number.MAX_SAFE_INTEGER;
@@ -71,7 +125,7 @@ export class SqlitePanelStore {
71
125
  // grab the most recent `limit` rows older than `before`, then return ascending
72
126
  const rows = this.#db
73
127
  .prepare(`
74
- SELECT direction, text, date, attachments, media_group FROM panel_messages
128
+ SELECT direction, text, date, attachments, media_group, keyboard, event FROM panel_messages
75
129
  WHERE chat_id = ? AND date < ?
76
130
  ORDER BY date DESC, id DESC LIMIT ?
77
131
  `)
@@ -82,6 +136,10 @@ export class SqlitePanelStore {
82
136
  msg.attachments = JSON.parse(r.attachments);
83
137
  if (r.media_group)
84
138
  msg.mediaGroupId = r.media_group;
139
+ if (r.keyboard)
140
+ msg.keyboard = JSON.parse(r.keyboard);
141
+ if (r.event)
142
+ msg.event = JSON.parse(r.event);
85
143
  return msg;
86
144
  });
87
145
  }
package/lib/sqlite.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"sqlite.js","sourceRoot":"","sources":["../src/sqlite.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"sqlite.js","sourceRoot":"","sources":["../src/sqlite.ts"],"names":[],"mappings":"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"}
@@ -1,8 +1,21 @@
1
1
  import assert from "node:assert/strict";
2
2
  import test from "node:test";
3
- import { SqlitePanelStore } from "./sqlite.js";
4
- test("SqlitePanelStore: records, lists newest-first, paginates and emits events", () => {
5
- const store = new SqlitePanelStore(); // :memory:
3
+ // `node:sqlite` (and therefore `SqlitePanelStore`) is only available on node 22.5+.
4
+ // on older runtimes a static import of "./sqlite.js" throws ERR_UNKNOWN_BUILTIN_MODULE
5
+ // at module-evaluation time, which would fail the whole file. import it lazily and
6
+ // skip the suite when the builtin is missing instead.
7
+ let SqlitePanelStore;
8
+ try {
9
+ ({ SqlitePanelStore } = await import("./sqlite.js"));
10
+ }
11
+ catch {
12
+ SqlitePanelStore = undefined;
13
+ }
14
+ const skip = SqlitePanelStore ? false : "node:sqlite unavailable (requires node 22.5+)";
15
+ // non-undefined alias for the test bodies (only reached when not skipped)
16
+ const Store = SqlitePanelStore;
17
+ test("SqlitePanelStore: records, lists newest-first, paginates and emits events", { skip }, () => {
18
+ const store = new Store(); // :memory:
6
19
  const events = [];
7
20
  store.subscribe((e) => events.push(e.chatId));
8
21
  store.record({ id: 1, name: "@sam" }, { direction: "in", text: "hi", date: 10 });
@@ -21,22 +34,42 @@ test("SqlitePanelStore: records, lists newest-first, paginates and emits events"
21
34
  assert.ok(events.length >= 2);
22
35
  store.close();
23
36
  });
24
- test("SqlitePanelStore persists attachments and media_group_id round-trip", () => {
25
- const store = new SqlitePanelStore();
26
- store.record({ id: 1, name: "@u" }, {
37
+ test("SqlitePanelStore persists attachments and media_group_id round-trip", { skip }, () => {
38
+ const store = new Store();
39
+ store.record({ id: 1, name: "@u", firstName: "Uma", lastName: "Ray", username: "u" }, {
27
40
  direction: "in",
28
41
  text: "[photo]",
29
42
  date: 1,
30
43
  attachments: [{ type: "photo", fileId: "f1" }],
31
44
  mediaGroupId: "G1",
45
+ keyboard: {
46
+ type: "inline",
47
+ rows: [[{ text: "Open", kind: "callback", callbackData: "open" }]],
48
+ },
32
49
  });
33
- store.record({ id: 1, name: "@u" }, { direction: "out", text: "thanks", date: 2 });
50
+ store.record({ id: 1, name: "@u" }, {
51
+ direction: "in",
52
+ text: "button clicked: open",
53
+ date: 2,
54
+ event: { type: "callback", title: "button clicked", detail: "open", data: "open" },
55
+ });
56
+ const chat = store.chats()[0];
57
+ assert.equal(chat?.firstName, "Uma");
58
+ assert.equal(chat?.lastName, "Ray");
59
+ assert.equal(chat?.username, "u");
60
+ assert.equal(chat?.lastAttachmentType, undefined);
61
+ assert.equal(chat?.lastEventType, "callback");
34
62
  const hist = store.history(1);
35
63
  assert.deepEqual(hist[0]?.attachments, [{ type: "photo", fileId: "f1" }]);
36
64
  assert.equal(hist[0]?.mediaGroupId, "G1");
37
- // plain text message has no attachments/group keys
65
+ assert.deepEqual(hist[0]?.keyboard, {
66
+ type: "inline",
67
+ rows: [[{ text: "Open", kind: "callback", callbackData: "open" }]],
68
+ });
69
+ // event message has no attachments/group keys
38
70
  assert.equal(hist[1]?.attachments, undefined);
39
71
  assert.equal(hist[1]?.mediaGroupId, undefined);
72
+ assert.equal(hist[1]?.event?.type, "callback");
40
73
  store.close();
41
74
  });
42
75
  //# sourceMappingURL=sqlite.test.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"sqlite.test.js","sourceRoot":"","sources":["../src/sqlite.test.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"sqlite.test.js","sourceRoot":"","sources":["../src/sqlite.test.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@yaebal/panel",
3
- "version": "0.0.2",
3
+ "version": "0.0.5",
4
4
  "description": "yaebal panel — an operator panel: view chats and reply from the browser.",
5
5
  "type": "module",
6
6
  "main": "./lib/index.js",
@@ -24,7 +24,7 @@
24
24
  "src"
25
25
  ],
26
26
  "dependencies": {
27
- "@yaebal/core": "0.0.1"
27
+ "@yaebal/core": "0.0.8"
28
28
  },
29
29
  "devDependencies": {
30
30
  "@types/node": "latest"
package/src/index.test.ts CHANGED
@@ -1,12 +1,25 @@
1
1
  import assert from "node:assert/strict";
2
2
  import test from "node:test";
3
3
  import { Composer, Context, type Middleware } from "@yaebal/core";
4
- import { MemoryPanelStore, panelHandler, recordOutgoing, recorder } from "./index.js";
4
+ import {
5
+ MemoryPanelStore,
6
+ panelHandler,
7
+ recorder,
8
+ recordOutgoing,
9
+ recordTelegramUpdate,
10
+ } from "./index.js";
11
+ import { PANEL_HTML } from "./panel-html.js";
5
12
 
6
13
  const noop = async () => {};
7
14
  const entry = <C extends Context>(c: Composer<C>) =>
8
15
  c.toMiddleware() as unknown as Middleware<Context>;
9
16
 
17
+ test("PANEL_HTML inline script parses", () => {
18
+ const script = PANEL_HTML.match(/<script>([\s\S]*?)<\/script>/)?.[1];
19
+ assert.ok(script);
20
+ assert.doesNotThrow(() => new Function(script));
21
+ });
22
+
10
23
  test("MemoryPanelStore records, preserves names, sorts and reads history", () => {
11
24
  const s = new MemoryPanelStore();
12
25
 
@@ -49,6 +62,8 @@ test("recorder logs incoming private text into the store", async () => {
49
62
  assert.equal(hist[0]?.text, "hello");
50
63
  assert.equal(hist[0]?.direction, "in");
51
64
  assert.equal(store.chats()[0]?.name, "@sam");
65
+ assert.equal(store.chats()[0]?.firstName, "Sam");
66
+ assert.equal(store.chats()[0]?.username, "sam");
52
67
  });
53
68
 
54
69
  function fakePanel() {
@@ -108,7 +123,7 @@ test("panel send posts via the api and logs an outgoing message", async () => {
108
123
  );
109
124
  assert.equal(res.status, 200);
110
125
  assert.deepEqual(sent, [{ chat_id: 1, text: "yo" }]);
111
-
126
+
112
127
  const last = store.history(1).at(-1);
113
128
  assert.equal(last?.direction, "out");
114
129
  assert.equal(last?.text, "yo");
@@ -165,6 +180,62 @@ test("recorder captures a caption as the message text", async () => {
165
180
  assert.equal(store.history(8)[0]?.text, "the report");
166
181
  });
167
182
 
183
+ test("recordTelegramUpdate records framework-agnostic callback events", async () => {
184
+ const store = new MemoryPanelStore();
185
+
186
+ await recordTelegramUpdate(store, {
187
+ update_id: 1,
188
+ callback_query: {
189
+ id: "cb1",
190
+ from: { id: 7, is_bot: false, first_name: "Pat", last_name: "Lee", username: "pat" },
191
+ message: { message_id: 2, chat: { id: 7, type: "private" } },
192
+ data: "demo:open",
193
+ },
194
+ });
195
+
196
+ const chat = store.chats()[0];
197
+ const msg = store.history(7)[0];
198
+
199
+ assert.equal(chat?.firstName, "Pat");
200
+ assert.equal(chat?.lastName, "Lee");
201
+ assert.equal(chat?.lastEventType, "callback");
202
+ assert.equal(msg?.event?.type, "callback");
203
+ assert.equal(msg?.event?.data, "demo:open");
204
+ });
205
+
206
+ test("recorder captures inline keyboards for timeline previews", async () => {
207
+ const store = new MemoryPanelStore();
208
+
209
+ await recordTelegramUpdate(store, {
210
+ update_id: 1,
211
+ message: {
212
+ message_id: 1,
213
+ date: 0,
214
+ chat: { id: 9, type: "private" },
215
+ from: { id: 9, is_bot: false, first_name: "Key" },
216
+ text: "choose",
217
+ reply_markup: {
218
+ inline_keyboard: [
219
+ [
220
+ { text: "Open", callback_data: "open" },
221
+ { text: "Docs", url: "https://yaeb.al" },
222
+ ],
223
+ ],
224
+ },
225
+ },
226
+ });
227
+
228
+ assert.deepEqual(store.history(9)[0]?.keyboard, {
229
+ type: "inline",
230
+ rows: [
231
+ [
232
+ { text: "Open", kind: "callback", callbackData: "open" },
233
+ { text: "Docs", kind: "url", url: "https://yaeb.al" },
234
+ ],
235
+ ],
236
+ });
237
+ });
238
+
168
239
  test("panel send rejects an empty/missing text with 400", async () => {
169
240
  const { handler, sent } = fakePanel();
170
241
 
@@ -194,6 +265,25 @@ test("panel send forwards whitelisted extras (parse_mode) to sendMessage", async
194
265
  assert.deepEqual(sent, [{ chat_id: 1, text: "*hi*", parse_mode: "MarkdownV2" }]);
195
266
  });
196
267
 
268
+ test("panel send forwards and self-records reply_markup previews", async () => {
269
+ const { handler, sent, store } = fakePanel();
270
+ const replyMarkup = { inline_keyboard: [[{ text: "Open", callback_data: "open" }]] };
271
+
272
+ await handler(
273
+ new Request("http://x/api/chats/1/send?token=secret", {
274
+ method: "POST",
275
+ headers: { "content-type": "application/json" },
276
+ body: JSON.stringify({ text: "choose", reply_markup: replyMarkup }),
277
+ }),
278
+ );
279
+
280
+ assert.deepEqual(sent.at(-1), { chat_id: 1, text: "choose", reply_markup: replyMarkup });
281
+ assert.deepEqual(store.history(1).at(-1)?.keyboard, {
282
+ type: "inline",
283
+ rows: [[{ text: "Open", kind: "callback", callbackData: "open" }]],
284
+ });
285
+ });
286
+
197
287
  test("panel API returns 404 for an unknown path", async () => {
198
288
  const { handler } = fakePanel();
199
289
 
@@ -320,11 +410,16 @@ test("SSE stream advertises text/event-stream and forwards a record event", asyn
320
410
  const res = await handler(new Request("http://x/api/stream?token=secret"));
321
411
  assert.match(res.headers.get("content-type") ?? "", /text\/event-stream/);
322
412
 
323
- const reader = res.body!.getReader();
413
+ const reader = res.body?.getReader();
414
+ assert.ok(reader);
324
415
  await reader.read(); // ": connected"
416
+
325
417
  store.record({ id: 1, name: "@u" }, { direction: "in", text: "ping", date: 1 });
418
+
326
419
  const { value } = await reader.read();
420
+ assert.ok(value);
327
421
  assert.match(new TextDecoder().decode(value), /event: record/);
422
+
328
423
  await reader.cancel();
329
424
  });
330
425
 
@@ -420,7 +515,12 @@ test("recorder extracts a document with name + mime", async () => {
420
515
  date: 0,
421
516
  chat: { id: 8, type: "private" },
422
517
  from: { id: 8, is_bot: false, first_name: "Lee" },
423
- document: { file_id: "doc1", file_unique_id: "d", file_name: "report.pdf", mime_type: "application/pdf" },
518
+ document: {
519
+ file_id: "doc1",
520
+ file_unique_id: "d",
521
+ file_name: "report.pdf",
522
+ mime_type: "application/pdf",
523
+ },
424
524
  },
425
525
  } as never,
426
526
  updateType: "message",