@open-wa/wa-automate 5.3.0 → 5.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.
- package/dist/cli-runtime-BGz4DzHq.d.cts.map +1 -1
- package/dist/{cli-runtime-BHx1nVhT.cjs → cli-runtime-BRj_LUIT.cjs} +503 -115
- package/dist/cli-runtime-BRj_LUIT.cjs.map +1 -0
- package/dist/cli.cjs +1 -1
- package/dist/index.cjs +86 -305
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +9 -7
- package/dist/index.d.cts.map +1 -1
- package/dist/{init-CTh6gc8w.cjs → init-CUhC5Wkq.cjs} +4 -4
- package/dist/{init-CTh6gc8w.cjs.map → init-CUhC5Wkq.cjs.map} +1 -1
- package/package.json +21 -12
- package/dist/cli-runtime-BHx1nVhT.cjs.map +0 -1
package/dist/index.cjs
CHANGED
|
@@ -1,19 +1,72 @@
|
|
|
1
1
|
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
2
|
-
const require_cli_runtime = require("./cli-runtime-
|
|
2
|
+
const require_cli_runtime = require("./cli-runtime-BRj_LUIT.cjs");
|
|
3
3
|
let _open_wa_api = require("@open-wa/api");
|
|
4
4
|
let node_path = require("node:path");
|
|
5
5
|
let _open_wa_logger = require("@open-wa/logger");
|
|
6
6
|
let _open_wa_session_sync = require("@open-wa/session-sync");
|
|
7
7
|
let _open_wa_core = require("@open-wa/core");
|
|
8
|
-
let _open_wa_client = require("@open-wa/client");
|
|
9
|
-
let _open_wa_driver_lightpanda = require("@open-wa/driver-lightpanda");
|
|
10
|
-
let _open_wa_driver_puppeteer = require("@open-wa/driver-puppeteer");
|
|
11
8
|
let _open_wa_config = require("@open-wa/config");
|
|
12
|
-
let
|
|
13
|
-
|
|
14
|
-
|
|
9
|
+
let _open_wa_schema = require("@open-wa/schema");
|
|
10
|
+
//#region src/server/lifecycle-manager.ts
|
|
11
|
+
var APILifecycleManager = class {
|
|
12
|
+
config;
|
|
13
|
+
server;
|
|
14
|
+
_sessionConnected = false;
|
|
15
|
+
constructor(config) {
|
|
16
|
+
this.config = config;
|
|
17
|
+
}
|
|
18
|
+
async initialize() {
|
|
19
|
+
const sink = require_cli_runtime.getCliOutputSink();
|
|
20
|
+
switch (this.config.apiLifecycle) {
|
|
21
|
+
case "immediate":
|
|
22
|
+
sink.status({
|
|
23
|
+
phase: "server.starting",
|
|
24
|
+
sessionId: this.config.sessionId,
|
|
25
|
+
detail: "Starting full API immediately"
|
|
26
|
+
});
|
|
27
|
+
await this.startFullAPI();
|
|
28
|
+
break;
|
|
29
|
+
case "post-connection":
|
|
30
|
+
this.waitForConnection();
|
|
31
|
+
break;
|
|
32
|
+
case "hybrid":
|
|
33
|
+
sink.status({
|
|
34
|
+
phase: "server.starting",
|
|
35
|
+
sessionId: this.config.sessionId,
|
|
36
|
+
detail: "Starting minimal API (QR only)"
|
|
37
|
+
});
|
|
38
|
+
await this.startMinimalAPI();
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
async waitForConnection() {
|
|
42
|
+
require_cli_runtime.getCliOutputSink().write({
|
|
43
|
+
level: "info",
|
|
44
|
+
message: "Waiting for session connection before starting API..."
|
|
45
|
+
});
|
|
46
|
+
}
|
|
47
|
+
async startFullAPI() {
|
|
48
|
+
require_cli_runtime.getCliOutputSink().write({
|
|
49
|
+
level: "info",
|
|
50
|
+
message: "Starting full API immediately..."
|
|
51
|
+
});
|
|
52
|
+
this.server = new require_cli_runtime.WAServer(this.config);
|
|
53
|
+
await this.server.start();
|
|
54
|
+
}
|
|
55
|
+
async startMinimalAPI() {
|
|
56
|
+
require_cli_runtime.getCliOutputSink().write({
|
|
57
|
+
level: "info",
|
|
58
|
+
message: "Starting minimal API (QR only)..."
|
|
59
|
+
});
|
|
60
|
+
this.server = new require_cli_runtime.WAServer(this.config);
|
|
61
|
+
await this.server.start();
|
|
62
|
+
}
|
|
63
|
+
async stop() {
|
|
64
|
+
if (this.server) await this.server.stop();
|
|
65
|
+
}
|
|
66
|
+
};
|
|
67
|
+
//#endregion
|
|
15
68
|
//#region src/session/SessionArchiveManager.ts
|
|
16
|
-
var SessionArchiveManager = class
|
|
69
|
+
var SessionArchiveManager = class {
|
|
17
70
|
config;
|
|
18
71
|
logger = (0, _open_wa_logger.createLogger)({ component: "SessionArchiveManager" });
|
|
19
72
|
localCompression;
|
|
@@ -76,17 +129,6 @@ var SessionArchiveManager = class SessionArchiveManager {
|
|
|
76
129
|
if (!this.s3Sync) return null;
|
|
77
130
|
return this.s3Sync.getDownloadUrl(filename, expiresIn);
|
|
78
131
|
}
|
|
79
|
-
static createFromConfig(config) {
|
|
80
|
-
if (!config.legacyDataDirAuth) throw new Error("Profile archives require legacyDataDirAuth: true; compact sessions sync through the client");
|
|
81
|
-
if (!config.s3Sync) throw new Error("Session archive management requires s3Sync configuration");
|
|
82
|
-
return new SessionArchiveManager({
|
|
83
|
-
sessionId: config.sessionId,
|
|
84
|
-
dataDir: config.userDataDir || config.sessionDataPath || "./.wwebjs",
|
|
85
|
-
s3Config: config.s3Sync,
|
|
86
|
-
syncInterval: config.s3Sync.syncInterval,
|
|
87
|
-
watchLocalChanges: config.s3Sync.enableLocalCompression !== false
|
|
88
|
-
});
|
|
89
|
-
}
|
|
90
132
|
get archivePath() {
|
|
91
133
|
return (0, node_path.join)((0, node_path.dirname)(this.config.dataDir), `${this.config.sessionId}.data.zst`);
|
|
92
134
|
}
|
|
@@ -101,303 +143,34 @@ var SessionArchiveManager = class SessionArchiveManager {
|
|
|
101
143
|
}
|
|
102
144
|
};
|
|
103
145
|
//#endregion
|
|
104
|
-
//#region src/
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
sessionArchiveManager;
|
|
109
|
-
_sessionConnected = false;
|
|
110
|
-
constructor(config) {
|
|
111
|
-
this.config = config;
|
|
112
|
-
if (config.legacyDataDirAuth && config.s3Sync) this.sessionArchiveManager = SessionArchiveManager.createFromConfig(config);
|
|
113
|
-
}
|
|
114
|
-
async initialize() {
|
|
115
|
-
const sink = require_cli_runtime.getCliOutputSink();
|
|
116
|
-
switch (this.config.apiLifecycle) {
|
|
117
|
-
case "immediate":
|
|
118
|
-
sink.status({
|
|
119
|
-
phase: "server.starting",
|
|
120
|
-
sessionId: this.config.sessionId,
|
|
121
|
-
detail: "Starting full API immediately"
|
|
122
|
-
});
|
|
123
|
-
await this.startFullAPI();
|
|
124
|
-
break;
|
|
125
|
-
case "post-connection":
|
|
126
|
-
this.waitForConnection();
|
|
127
|
-
break;
|
|
128
|
-
case "hybrid":
|
|
129
|
-
sink.status({
|
|
130
|
-
phase: "server.starting",
|
|
131
|
-
sessionId: this.config.sessionId,
|
|
132
|
-
detail: "Starting minimal API (QR only)"
|
|
133
|
-
});
|
|
134
|
-
await this.startMinimalAPI();
|
|
135
|
-
}
|
|
136
|
-
if (this.sessionArchiveManager) await this.sessionArchiveManager.start();
|
|
137
|
-
}
|
|
138
|
-
async waitForConnection() {
|
|
139
|
-
require_cli_runtime.getCliOutputSink().write({
|
|
140
|
-
level: "info",
|
|
141
|
-
message: "Waiting for session connection before starting API..."
|
|
142
|
-
});
|
|
143
|
-
}
|
|
144
|
-
async startFullAPI() {
|
|
145
|
-
require_cli_runtime.getCliOutputSink().write({
|
|
146
|
-
level: "info",
|
|
147
|
-
message: "Starting full API immediately..."
|
|
148
|
-
});
|
|
149
|
-
this.server = new require_cli_runtime.WAServer(this.config);
|
|
150
|
-
await this.server.start();
|
|
151
|
-
}
|
|
152
|
-
async startMinimalAPI() {
|
|
153
|
-
require_cli_runtime.getCliOutputSink().write({
|
|
154
|
-
level: "info",
|
|
155
|
-
message: "Starting minimal API (QR only)..."
|
|
156
|
-
});
|
|
157
|
-
this.server = new require_cli_runtime.WAServer(this.config);
|
|
158
|
-
await this.server.start();
|
|
159
|
-
}
|
|
160
|
-
async stop() {
|
|
161
|
-
if (this.sessionArchiveManager) await this.sessionArchiveManager.stop();
|
|
162
|
-
if (this.server) await this.server.stop();
|
|
163
|
-
}
|
|
164
|
-
};
|
|
165
|
-
//#endregion
|
|
166
|
-
//#region src/runtime-client.ts
|
|
167
|
-
function readChromePathCache(cacheFilePath) {
|
|
168
|
-
try {
|
|
169
|
-
if (!(0, node_fs.existsSync)(cacheFilePath)) return;
|
|
170
|
-
const raw = JSON.parse((0, node_fs.readFileSync)(cacheFilePath, "utf8"));
|
|
171
|
-
if (!raw || typeof raw !== "object") return;
|
|
172
|
-
return { executablePath: typeof raw.executablePath === "string" ? raw.executablePath : void 0 };
|
|
173
|
-
} catch {
|
|
174
|
-
return;
|
|
175
|
-
}
|
|
176
|
-
}
|
|
177
|
-
function writeChromePathCache(executablePath, cacheFilePath) {
|
|
178
|
-
(0, node_fs.mkdirSync)((0, node_path.dirname)(cacheFilePath), { recursive: true });
|
|
179
|
-
(0, node_fs.writeFileSync)(cacheFilePath, JSON.stringify({
|
|
180
|
-
executablePath,
|
|
181
|
-
updatedAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
182
|
-
}, null, 2), "utf8");
|
|
183
|
-
}
|
|
184
|
-
function clearChromePathCache(cacheFilePath) {
|
|
185
|
-
if ((0, node_fs.existsSync)(cacheFilePath)) (0, node_fs.rmSync)(cacheFilePath, { force: true });
|
|
186
|
-
}
|
|
187
|
-
function isUsableExecutablePath(executablePath) {
|
|
188
|
-
return !!executablePath && (0, node_fs.existsSync)(executablePath);
|
|
189
|
-
}
|
|
190
|
-
function getExplicitUseChromePreference(rawConfigs) {
|
|
191
|
-
const explicitConfigSources = [
|
|
192
|
-
rawConfigs?.file,
|
|
193
|
-
rawConfigs?.env,
|
|
194
|
-
rawConfigs?.cli,
|
|
195
|
-
rawConfigs?.programmatic
|
|
196
|
-
];
|
|
197
|
-
for (let index = explicitConfigSources.length - 1; index >= 0; index -= 1) {
|
|
198
|
-
const source = explicitConfigSources[index];
|
|
199
|
-
if (source?.useChrome !== void 0) return source.useChrome;
|
|
200
|
-
}
|
|
201
|
-
}
|
|
202
|
-
function shouldPreferLocalChrome(config, rawConfigs, defaultPreference = true) {
|
|
203
|
-
if (config.useLightpanda) return false;
|
|
204
|
-
if (config.executablePath) return false;
|
|
205
|
-
const explicitUseChrome = getExplicitUseChromePreference(rawConfigs);
|
|
206
|
-
if (explicitUseChrome !== void 0) return explicitUseChrome;
|
|
207
|
-
return defaultPreference;
|
|
208
|
-
}
|
|
209
|
-
async function resolveExecutablePath(config, options) {
|
|
210
|
-
if (config.executablePath) return {
|
|
211
|
-
executablePath: config.executablePath,
|
|
212
|
-
source: "config"
|
|
213
|
-
};
|
|
214
|
-
if (!(options.preferLocalChrome ?? config.useChrome)) return { source: "driver_default" };
|
|
215
|
-
const cachedPath = readChromePathCache(options.cacheFilePath)?.executablePath;
|
|
216
|
-
if (isUsableExecutablePath(cachedPath)) return {
|
|
217
|
-
executablePath: cachedPath,
|
|
218
|
-
source: "cache"
|
|
219
|
-
};
|
|
220
|
-
if (cachedPath) clearChromePathCache(options.cacheFilePath);
|
|
221
|
-
const { Launcher } = await import("chrome-launcher");
|
|
222
|
-
const detectedPath = Launcher.getInstallations().find((installationPath) => isUsableExecutablePath(installationPath));
|
|
223
|
-
if (detectedPath) {
|
|
224
|
-
writeChromePathCache(detectedPath, options.cacheFilePath);
|
|
225
|
-
return {
|
|
226
|
-
executablePath: detectedPath,
|
|
227
|
-
source: "chrome_installation"
|
|
228
|
-
};
|
|
229
|
-
}
|
|
230
|
-
clearChromePathCache(options.cacheFilePath);
|
|
231
|
-
return {
|
|
232
|
-
source: "driver_default",
|
|
233
|
-
warning: "Chrome resolution warning: no valid local Chrome installation was found. Falling back to Puppeteer/default driver browser resolution."
|
|
234
|
-
};
|
|
235
|
-
}
|
|
236
|
-
function resolveLightpandaExecutablePath(config) {
|
|
237
|
-
const executablePath = config.lightpanda?.executablePath;
|
|
238
|
-
if (executablePath) return {
|
|
239
|
-
executablePath,
|
|
240
|
-
source: "lightpanda_config"
|
|
241
|
-
};
|
|
242
|
-
return { source: "lightpanda_sdk_default" };
|
|
243
|
-
}
|
|
244
|
-
async function selectRuntimeDriver(config, options) {
|
|
245
|
-
if (config.useLightpanda) return {
|
|
246
|
-
driver: new _open_wa_driver_lightpanda.LightpandaDriver(),
|
|
247
|
-
engineLabel: "Lightpanda",
|
|
248
|
-
executableResolution: resolveLightpandaExecutablePath(config),
|
|
249
|
-
preferLocalChrome: false
|
|
250
|
-
};
|
|
251
|
-
const preferLocalChrome = shouldPreferLocalChrome(config, options.rawConfigs, options.defaultPreferLocalChrome ?? true);
|
|
252
|
-
const executableResolution = await resolveExecutablePath(config, {
|
|
253
|
-
preferLocalChrome,
|
|
254
|
-
cacheFilePath: options.cacheFilePath
|
|
255
|
-
});
|
|
256
|
-
return {
|
|
257
|
-
driver: new _open_wa_driver_puppeteer.PuppeteerDriver(),
|
|
258
|
-
engineLabel: "Puppeteer",
|
|
259
|
-
executableResolution,
|
|
260
|
-
preferLocalChrome
|
|
261
|
-
};
|
|
262
|
-
}
|
|
263
|
-
function toCreateClientOptions(config, driverSelection, options = {}) {
|
|
264
|
-
return {
|
|
265
|
-
sessionId: config.sessionId,
|
|
266
|
-
driver: driverSelection.driver,
|
|
267
|
-
deleteSessionDataOnLogout: config.deleteSessionDataOnLogout,
|
|
268
|
-
killClientOnLogout: config.killClientOnLogout,
|
|
269
|
-
legacyDataDirAuth: config.legacyDataDirAuth,
|
|
270
|
-
sessionDataPath: config.sessionDataPath,
|
|
271
|
-
sessionData: config.sessionData,
|
|
272
|
-
skipSessionSave: config.skipSessionSave,
|
|
273
|
-
sessionDataBucketAuth: config.sessionDataBucketAuth,
|
|
274
|
-
s3Sync: config.s3Sync,
|
|
275
|
-
debug: options.debug ?? (config.logLevel === "debug" || config.logConsole),
|
|
276
|
-
headless: config.headless,
|
|
277
|
-
qrTimeoutMs: typeof config.qrTimeout === "number" ? config.qrTimeout * 1e3 : void 0,
|
|
278
|
-
authTimeoutMs: typeof config.authTimeout === "number" ? config.authTimeout * 1e3 : void 0,
|
|
279
|
-
executablePath: driverSelection.executableResolution.executablePath,
|
|
280
|
-
browserArgs: config.chromiumArgs,
|
|
281
|
-
browser: config.browser,
|
|
282
|
-
allowDangerousBrowserArgs: config.allowDangerousBrowserArgs,
|
|
283
|
-
userDataDir: config.userDataDir,
|
|
284
|
-
ephemeral: config.ephemeral,
|
|
285
|
-
linkCode: config.linkCode,
|
|
286
|
-
qrMax: config.qrMax,
|
|
287
|
-
oorTimeoutMs: config.oorTimeout * 1e3,
|
|
288
|
-
logConsole: config.logConsole,
|
|
289
|
-
logConsoleErrors: config.logConsoleErrors,
|
|
290
|
-
blockCrashLogs: config.blockCrashLogs,
|
|
291
|
-
blockAssets: config.blockAssets,
|
|
292
|
-
safeMode: config.safeMode,
|
|
293
|
-
lightpanda: config.useLightpanda ? config.lightpanda : void 0,
|
|
294
|
-
licenseKey: config.licenseKey,
|
|
295
|
-
patchConfig: {
|
|
296
|
-
ghPatch: config.ghPatch,
|
|
297
|
-
cachedPatch: config.cachedPatch
|
|
298
|
-
}
|
|
299
|
-
};
|
|
300
|
-
}
|
|
301
|
-
/** Private profile storage, stable for this project directory and session name. */
|
|
302
|
-
function privateSessionDirectory(sessionId) {
|
|
303
|
-
const project = (0, node_crypto.createHash)("sha256").update((0, node_fs.realpathSync)(process.cwd())).digest("hex").slice(0, 24);
|
|
304
|
-
const session = (0, node_crypto.createHash)("sha256").update(sessionId).digest("hex").slice(0, 24);
|
|
305
|
-
const root = (0, node_path.resolve)((0, node_os.homedir)(), ".open-wa", "sessions");
|
|
306
|
-
const directory = (0, node_path.resolve)(root, project, session);
|
|
307
|
-
(0, node_fs.mkdirSync)(directory, {
|
|
308
|
-
recursive: true,
|
|
309
|
-
mode: 448
|
|
310
|
-
});
|
|
311
|
-
for (const path of [
|
|
312
|
-
root,
|
|
313
|
-
(0, node_path.dirname)(directory),
|
|
314
|
-
directory
|
|
315
|
-
]) (0, node_fs.chmodSync)(path, 448);
|
|
316
|
-
return directory;
|
|
317
|
-
}
|
|
318
|
-
/** Start WhatsApp, display QR login when needed, and return a ready messaging client. */
|
|
319
|
-
async function create(options = {}) {
|
|
320
|
-
const { driver, sessionData, sessionDataBucketAuth, s3Sync, ...configOverrides } = options;
|
|
321
|
-
const { config, rawConfigs } = await (0, _open_wa_config.resolveConfig)({
|
|
322
|
-
programmaticOverrides: {
|
|
323
|
-
qrTimeout: 0,
|
|
324
|
-
...configOverrides
|
|
325
|
-
},
|
|
326
|
-
skipConfigFile: true,
|
|
327
|
-
skipEnv: true,
|
|
328
|
-
includeRawConfigs: true
|
|
329
|
-
});
|
|
330
|
-
const coreOptions = toCreateClientOptions(config, await selectRuntimeDriver(config, {
|
|
331
|
-
rawConfigs,
|
|
332
|
-
cacheFilePath: (0, node_path.resolve)(process.cwd(), ".open-wa", "chrome-executable-path.json"),
|
|
333
|
-
defaultPreferLocalChrome: false
|
|
334
|
-
}));
|
|
335
|
-
if (driver) coreOptions.driver = driver;
|
|
336
|
-
coreOptions.sessionData = sessionData;
|
|
337
|
-
coreOptions.sessionDataBucketAuth = sessionDataBucketAuth;
|
|
338
|
-
coreOptions.s3Sync = s3Sync;
|
|
339
|
-
if (config.legacyDataDirAuth && !config.ephemeral && configOverrides.userDataDir === void 0 && configOverrides.sessionDataPath === void 0) {
|
|
340
|
-
coreOptions.userDataDir = privateSessionDirectory(config.sessionId);
|
|
341
|
-
coreOptions.sessionDataPath = coreOptions.userDataDir;
|
|
342
|
-
}
|
|
343
|
-
const core = await (0, _open_wa_core.createClient)(coreOptions);
|
|
344
|
-
const sink = require_cli_runtime.getCliOutputSink();
|
|
345
|
-
const onQr = (event) => {
|
|
346
|
-
if (config.qrLogSkip || !event.details?.qr) return;
|
|
347
|
-
sink.write({
|
|
348
|
-
level: "info",
|
|
349
|
-
message: "Open WhatsApp on your sending phone: Linked Devices → Link a Device, then scan this QR code."
|
|
350
|
-
});
|
|
351
|
-
sink.qr({
|
|
352
|
-
qr: event.details.qr,
|
|
353
|
-
sessionId: config.sessionId
|
|
354
|
-
});
|
|
355
|
-
};
|
|
356
|
-
const onLinkCode = (event) => {
|
|
357
|
-
if (event.details?.linkCode && !config.qrLogSkip) sink.write({
|
|
358
|
-
level: "info",
|
|
359
|
-
message: `Enter this link code on your sending phone: ${event.details.linkCode}`
|
|
360
|
-
});
|
|
361
|
-
};
|
|
362
|
-
core.events.on("launch.auth.qr.generated", onQr);
|
|
363
|
-
core.events.on("launch.auth.linkCode.generated", onLinkCode);
|
|
364
|
-
let client;
|
|
365
|
-
try {
|
|
366
|
-
client = new _open_wa_client.Client({
|
|
367
|
-
client: core,
|
|
368
|
-
transport: core.getTransport()
|
|
369
|
-
});
|
|
370
|
-
await client.start();
|
|
371
|
-
if (core.getState() !== "READY" || !core.getReadiness().exposureSafe) throw new Error("WhatsApp startup finished without a messaging-ready session.");
|
|
372
|
-
return client;
|
|
373
|
-
} catch (error) {
|
|
374
|
-
try {
|
|
375
|
-
if (client) await client.stop("startup-failure");
|
|
376
|
-
else await core.stop("startup-failure");
|
|
377
|
-
} catch {}
|
|
378
|
-
throw error;
|
|
379
|
-
} finally {
|
|
380
|
-
core.events.off("launch.auth.qr.generated", onQr);
|
|
381
|
-
core.events.off("launch.auth.linkCode.generated", onLinkCode);
|
|
382
|
-
}
|
|
146
|
+
//#region src/index.ts
|
|
147
|
+
async function ensureBrowser(...args) {
|
|
148
|
+
const { ensureBrowser: provisionBrowser } = await import("@open-wa/driver-puppeteer");
|
|
149
|
+
return provisionBrowser(...args);
|
|
383
150
|
}
|
|
384
151
|
//#endregion
|
|
385
152
|
exports.APILifecycleManager = APILifecycleManager;
|
|
386
|
-
Object.defineProperty(exports, "
|
|
153
|
+
Object.defineProperty(exports, "ConfigSchema", {
|
|
387
154
|
enumerable: true,
|
|
388
155
|
get: function() {
|
|
389
|
-
return _open_wa_config.
|
|
156
|
+
return _open_wa_config.ConfigSchema;
|
|
390
157
|
}
|
|
391
158
|
});
|
|
392
|
-
Object.defineProperty(exports, "
|
|
159
|
+
Object.defineProperty(exports, "MessageAck", {
|
|
393
160
|
enumerable: true,
|
|
394
161
|
get: function() {
|
|
395
|
-
return
|
|
162
|
+
return _open_wa_schema.MessageAck;
|
|
396
163
|
}
|
|
397
164
|
});
|
|
398
165
|
exports.SessionArchiveManager = SessionArchiveManager;
|
|
166
|
+
Object.defineProperty(exports, "SimpleListener", {
|
|
167
|
+
enumerable: true,
|
|
168
|
+
get: function() {
|
|
169
|
+
return _open_wa_schema.SimpleListener;
|
|
170
|
+
}
|
|
171
|
+
});
|
|
399
172
|
exports.WAServer = require_cli_runtime.WAServer;
|
|
400
|
-
exports.create = create;
|
|
173
|
+
exports.create = require_cli_runtime.create;
|
|
401
174
|
Object.defineProperty(exports, "createApiMiddleware", {
|
|
402
175
|
enumerable: true,
|
|
403
176
|
get: function() {
|
|
@@ -417,18 +190,26 @@ Object.defineProperty(exports, "createClient", {
|
|
|
417
190
|
}
|
|
418
191
|
});
|
|
419
192
|
exports.createConsoleOutputSink = require_cli_runtime.createConsoleOutputSink;
|
|
420
|
-
|
|
193
|
+
exports.ensureBrowser = ensureBrowser;
|
|
194
|
+
Object.defineProperty(exports, "ev", {
|
|
421
195
|
enumerable: true,
|
|
422
196
|
get: function() {
|
|
423
|
-
return
|
|
197
|
+
return _open_wa_core.ev;
|
|
424
198
|
}
|
|
425
199
|
});
|
|
426
200
|
exports.getCliOutputSink = require_cli_runtime.getCliOutputSink;
|
|
201
|
+
Object.defineProperty(exports, "onGlobalEvent", {
|
|
202
|
+
enumerable: true,
|
|
203
|
+
get: function() {
|
|
204
|
+
return _open_wa_core.onGlobalEvent;
|
|
205
|
+
}
|
|
206
|
+
});
|
|
427
207
|
exports.parseCliArgs = require_cli_runtime.parseCliArgs;
|
|
428
208
|
exports.resetCliOutputSink = require_cli_runtime.resetCliOutputSink;
|
|
429
209
|
exports.runCli = require_cli_runtime.main;
|
|
430
210
|
exports.setCliOutputSink = require_cli_runtime.setCliOutputSink;
|
|
431
211
|
exports.startCli = require_cli_runtime.start;
|
|
212
|
+
var _open_wa_client = require("@open-wa/client");
|
|
432
213
|
Object.keys(_open_wa_client).forEach(function(k) {
|
|
433
214
|
if (k !== "default" && !Object.prototype.hasOwnProperty.call(exports, k)) Object.defineProperty(exports, k, {
|
|
434
215
|
enumerable: true,
|
package/dist/index.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.cjs","names":["createLogger","LocalSessionCompression","S3SyncManager","join","dirname","getCliOutputSink","WAServer","existsSync","readFileSync","dirname","LightpandaDriver","PuppeteerDriver","createHash","realpathSync","resolve","homedir","resolveConfig","createCoreClient","getCliOutputSink","Client"],"sources":["../src/session/SessionArchiveManager.ts","../src/server/lifecycle-manager.ts","../src/runtime-client.ts"],"sourcesContent":["import { dirname, join } from 'node:path';\nimport type { Config } from '@open-wa/config';\nimport { createLogger } from '@open-wa/logger';\nimport { LocalSessionCompression, S3SyncManager, type S3Config } from '@open-wa/session-sync';\n\nexport interface SessionArchiveManagerConfig {\n sessionId: string;\n dataDir: string;\n s3Config: S3Config;\n syncInterval?: number;\n watchLocalChanges?: boolean;\n}\n\nexport class SessionArchiveManager {\n private readonly logger = createLogger({ component: 'SessionArchiveManager' });\n private localCompression?: LocalSessionCompression;\n private s3Sync?: S3SyncManager;\n private syncTimer?: NodeJS.Timeout;\n private started = false;\n\n constructor(private readonly config: SessionArchiveManagerConfig) {\n this.logger.info('session_archive_manager_initialized', { sessionId: config.sessionId });\n }\n\n async start(): Promise<void> {\n if (this.started) return;\n this.started = true;\n\n this.localCompression = new LocalSessionCompression({\n sessionPath: this.config.dataDir,\n sessionId: this.config.sessionId,\n outputPath: this.archivePath,\n intervalMs: this.config.syncInterval,\n });\n if (this.config.watchLocalChanges !== false) {\n this.localCompression.start();\n this.logger.info('local_session_compression_started');\n }\n\n this.s3Sync = new S3SyncManager(this.config.s3Config);\n this.startPeriodicSync();\n this.logger.info('s3_session_sync_started');\n }\n\n async stop(): Promise<void> {\n if (this.syncTimer) {\n clearInterval(this.syncTimer);\n this.syncTimer = undefined;\n }\n\n this.localCompression?.stop();\n this.localCompression = undefined;\n this.s3Sync = undefined;\n this.started = false;\n this.logger.info('session_archive_manager_stopped');\n }\n\n async backupSession(): Promise<string | null> {\n if (!this.s3Sync || !this.localCompression) {\n this.logger.warn('session_archive_manager_not_started');\n return null;\n }\n\n try {\n await this.localCompression.compress();\n const filename = await this.s3Sync.backupSession(this.archivePath);\n this.logger.info('session_backed_up', { filename });\n return filename;\n } catch (error) {\n this.logger.error('session_backup_failed', { error });\n throw error;\n }\n }\n\n async restoreSession(filename: string): Promise<void> {\n if (!this.s3Sync) {\n throw new Error('Session archive manager is not started');\n }\n\n const restored = await this.s3Sync.restoreSession(filename, this.config.dataDir);\n if (!restored) {\n throw new Error(`Failed to restore session backup: ${filename}`);\n }\n this.logger.info('session_restored', { filename });\n }\n\n async getSessionBackupUrl(filename: string, expiresIn = 3600): Promise<string | null> {\n if (!this.s3Sync) {\n return null;\n }\n\n return this.s3Sync.getDownloadUrl(filename, expiresIn);\n }\n\n static createFromConfig(config: Config): SessionArchiveManager {\n if (!config.legacyDataDirAuth) {\n throw new Error('Profile archives require legacyDataDirAuth: true; compact sessions sync through the client');\n }\n if (!config.s3Sync) {\n throw new Error('Session archive management requires s3Sync configuration');\n }\n\n return new SessionArchiveManager({\n sessionId: config.sessionId,\n dataDir: config.userDataDir || config.sessionDataPath || './.wwebjs',\n s3Config: config.s3Sync,\n syncInterval: config.s3Sync.syncInterval,\n watchLocalChanges: config.s3Sync.enableLocalCompression !== false,\n });\n }\n\n private get archivePath(): string {\n return join(dirname(this.config.dataDir), `${this.config.sessionId}.data.zst`);\n }\n\n private startPeriodicSync(): void {\n if (!this.s3Sync || this.syncTimer) return;\n\n this.syncTimer = setInterval(() => {\n void this.backupSession().catch((error) => {\n this.logger.error('periodic_session_sync_failed', { error });\n });\n }, this.config.syncInterval ?? 600_000);\n this.syncTimer.unref();\n }\n}\n","import { WAServer } from './hono-server';\nimport type { Config } from '@open-wa/config';\nimport { SessionArchiveManager } from '../session/SessionArchiveManager';\nimport { getCliOutputSink } from '../cli/output-sink';\n\nexport class APILifecycleManager {\n private config: Config;\n private server?: WAServer;\n private sessionArchiveManager?: SessionArchiveManager;\n // @ts-ignore\n private _sessionConnected: boolean = false;\n\n constructor(config: Config) {\n this.config = config;\n \n // Compact checkpoints are synced by the client; profile archives are legacy-only.\n if (config.legacyDataDirAuth && config.s3Sync) {\n this.sessionArchiveManager = SessionArchiveManager.createFromConfig(config);\n }\n }\n\n public async initialize(): Promise<void> {\n const sink = getCliOutputSink();\n switch (this.config.apiLifecycle) {\n case 'immediate':\n sink.status({ phase: 'server.starting', sessionId: this.config.sessionId, detail: 'Starting full API immediately' });\n await this.startFullAPI();\n break;\n case 'post-connection':\n this.waitForConnection();\n break;\n case 'hybrid':\n sink.status({ phase: 'server.starting', sessionId: this.config.sessionId, detail: 'Starting minimal API (QR only)' });\n await this.startMinimalAPI();\n break;\n }\n \n // Start session manager after all other initialization\n if (this.sessionArchiveManager) {\n await this.sessionArchiveManager.start();\n }\n }\n\n private async waitForConnection(): Promise<void> {\n getCliOutputSink().write({ level: 'info', message: 'Waiting for session connection before starting API...' });\n // This will be called by the orchestrator or main entry point when session connects\n }\n\n private async startFullAPI(): Promise<void> {\n getCliOutputSink().write({ level: 'info', message: 'Starting full API immediately...' });\n this.server = new WAServer(this.config);\n await this.server.start();\n }\n\n private async startMinimalAPI(): Promise<void> {\n getCliOutputSink().write({ level: 'info', message: 'Starting minimal API (QR only)...' });\n \n // Create server with full config but we might restrict routes in the future\n // For now, hybrid mode just starts the server, but logic inside routes (like sendText)\n // should check if session is connected before execution.\n // In a more advanced implementation, we would only register public routes here.\n \n this.server = new WAServer(this.config);\n await this.server.start();\n }\n \n public async stop(): Promise<void> {\n // Stop session manager first\n if (this.sessionArchiveManager) {\n await this.sessionArchiveManager.stop();\n }\n \n // Then stop server\n if (this.server) {\n await this.server.stop();\n }\n }\n}\n","import { createClient as createCoreClient, type CreateClientOptions, type OpenWAEventMap } from '@open-wa/core';\nimport { Client } from '@open-wa/client';\nimport { resolveConfig, type PartialConfig, type Config, type TrackedConfig } from '@open-wa/config';\nimport { LightpandaDriver } from '@open-wa/driver-lightpanda';\nimport { PuppeteerDriver } from '@open-wa/driver-puppeteer';\nimport { chmodSync, existsSync, mkdirSync, readFileSync, realpathSync, rmSync, writeFileSync } from 'node:fs';\nimport { createHash } from 'node:crypto';\nimport { homedir } from 'node:os';\nimport { dirname, resolve } from 'node:path';\nimport { getCliOutputSink } from './cli/output-sink';\n\nexport interface ExecutablePathResolution {\n executablePath?: string;\n source:\n | 'config'\n | 'cache'\n | 'chrome_installation'\n | 'driver_default'\n | 'lightpanda_config'\n | 'lightpanda_sdk_default';\n warning?: string;\n}\n\nexport interface DriverSelection {\n driver: PuppeteerDriver | LightpandaDriver;\n engineLabel: 'Puppeteer' | 'Lightpanda';\n executableResolution: ExecutablePathResolution;\n preferLocalChrome: boolean;\n}\n\nfunction readChromePathCache(cacheFilePath: string): { executablePath?: string } | undefined {\n try {\n if (!existsSync(cacheFilePath)) {\n return undefined;\n }\n\n const raw = JSON.parse(readFileSync(cacheFilePath, 'utf8')) as { executablePath?: string };\n if (!raw || typeof raw !== 'object') {\n return undefined;\n }\n\n return {\n executablePath: typeof raw.executablePath === 'string' ? raw.executablePath : undefined,\n };\n } catch {\n return undefined;\n }\n}\n\nfunction writeChromePathCache(executablePath: string, cacheFilePath: string): void {\n mkdirSync(dirname(cacheFilePath), { recursive: true });\n writeFileSync(cacheFilePath, JSON.stringify({ executablePath, updatedAt: new Date().toISOString() }, null, 2), 'utf8');\n}\n\nfunction clearChromePathCache(cacheFilePath: string): void {\n if (existsSync(cacheFilePath)) {\n rmSync(cacheFilePath, { force: true });\n }\n}\n\nfunction isUsableExecutablePath(executablePath?: string): executablePath is string {\n return !!executablePath && existsSync(executablePath);\n}\n\nfunction getExplicitUseChromePreference(rawConfigs?: TrackedConfig['rawConfigs']): boolean | undefined {\n const explicitConfigSources = [\n rawConfigs?.file,\n rawConfigs?.env,\n rawConfigs?.cli,\n rawConfigs?.programmatic,\n ];\n\n for (let index = explicitConfigSources.length - 1; index >= 0; index -= 1) {\n const source = explicitConfigSources[index];\n if (source?.useChrome !== undefined) {\n return source.useChrome;\n }\n }\n\n return undefined;\n}\n\nexport function shouldPreferLocalChrome(\n config: Config,\n rawConfigs?: TrackedConfig['rawConfigs'],\n defaultPreference = true,\n): boolean {\n if (config.useLightpanda) {\n return false;\n }\n\n if (config.executablePath) {\n return false;\n }\n\n const explicitUseChrome = getExplicitUseChromePreference(rawConfigs);\n if (explicitUseChrome !== undefined) {\n return explicitUseChrome;\n }\n\n return defaultPreference;\n}\n\nexport async function resolveExecutablePath(\n config: Config,\n options: {\n preferLocalChrome?: boolean;\n cacheFilePath: string;\n }\n): Promise<ExecutablePathResolution> {\n if (config.executablePath) {\n return {\n executablePath: config.executablePath,\n source: 'config',\n };\n }\n\n const preferLocalChrome = options.preferLocalChrome ?? config.useChrome;\n if (!preferLocalChrome) {\n return {\n source: 'driver_default',\n };\n }\n\n const cachedPath = readChromePathCache(options.cacheFilePath)?.executablePath;\n if (isUsableExecutablePath(cachedPath)) {\n return {\n executablePath: cachedPath,\n source: 'cache',\n };\n }\n\n if (cachedPath) {\n clearChromePathCache(options.cacheFilePath);\n }\n\n const { Launcher } = await import('chrome-launcher');\n const detectedPath = Launcher.getInstallations().find((installationPath) => isUsableExecutablePath(installationPath));\n\n if (detectedPath) {\n writeChromePathCache(detectedPath, options.cacheFilePath);\n return {\n executablePath: detectedPath,\n source: 'chrome_installation',\n };\n }\n\n clearChromePathCache(options.cacheFilePath);\n\n return {\n source: 'driver_default',\n warning: 'Chrome resolution warning: no valid local Chrome installation was found. Falling back to Puppeteer/default driver browser resolution.',\n };\n}\n\nexport function resolveLightpandaExecutablePath(config: Config): ExecutablePathResolution {\n const executablePath = config.lightpanda?.executablePath;\n if (executablePath) {\n return {\n executablePath,\n source: 'lightpanda_config',\n };\n }\n\n return {\n source: 'lightpanda_sdk_default',\n };\n}\n\nexport async function selectRuntimeDriver(\n config: Config,\n options: {\n rawConfigs?: TrackedConfig['rawConfigs'];\n cacheFilePath: string;\n defaultPreferLocalChrome?: boolean;\n }\n): Promise<DriverSelection> {\n if (config.useLightpanda) {\n return {\n driver: new LightpandaDriver(),\n engineLabel: 'Lightpanda',\n executableResolution: resolveLightpandaExecutablePath(config),\n preferLocalChrome: false,\n };\n }\n\n const preferLocalChrome = shouldPreferLocalChrome(config, options.rawConfigs, options.defaultPreferLocalChrome ?? true);\n const executableResolution = await resolveExecutablePath(config, {\n preferLocalChrome,\n cacheFilePath: options.cacheFilePath,\n });\n\n return {\n driver: new PuppeteerDriver(),\n engineLabel: 'Puppeteer',\n executableResolution,\n preferLocalChrome,\n };\n}\n\nexport function toCreateClientOptions(\n config: Config,\n driverSelection: DriverSelection,\n options: {\n debug?: boolean;\n } = {},\n): CreateClientOptions {\n return {\n sessionId: config.sessionId,\n driver: driverSelection.driver,\n deleteSessionDataOnLogout: config.deleteSessionDataOnLogout,\n killClientOnLogout: config.killClientOnLogout,\n legacyDataDirAuth: config.legacyDataDirAuth,\n sessionDataPath: config.sessionDataPath,\n sessionData: config.sessionData,\n skipSessionSave: config.skipSessionSave,\n sessionDataBucketAuth: config.sessionDataBucketAuth,\n s3Sync: config.s3Sync,\n debug: options.debug ?? (config.logLevel === 'debug' || config.logConsole),\n headless: config.headless,\n qrTimeoutMs: typeof config.qrTimeout === 'number' ? config.qrTimeout * 1000 : undefined,\n authTimeoutMs: typeof config.authTimeout === 'number' ? config.authTimeout * 1000 : undefined,\n executablePath: driverSelection.executableResolution.executablePath,\n browserArgs: config.chromiumArgs,\n browser: config.browser,\n allowDangerousBrowserArgs: config.allowDangerousBrowserArgs,\n userDataDir: config.userDataDir,\n ephemeral: config.ephemeral,\n linkCode: config.linkCode,\n qrMax: config.qrMax,\n oorTimeoutMs: config.oorTimeout * 1000,\n logConsole: config.logConsole,\n logConsoleErrors: config.logConsoleErrors,\n blockCrashLogs: config.blockCrashLogs,\n blockAssets: config.blockAssets,\n safeMode: config.safeMode,\n lightpanda: config.useLightpanda ? config.lightpanda : undefined,\n licenseKey: config.licenseKey as any,\n patchConfig: { ghPatch: config.ghPatch, cachedPatch: config.cachedPatch },\n };\n}\n\n/** Options for the ready-to-use messaging client. */\nexport type CreateOptions = Omit<PartialConfig, 's3Sync'> & {\n s3Sync?: Omit<NonNullable<PartialConfig['s3Sync']>, 'region' | 'syncInterval'> & {\n region?: string;\n syncInterval?: number;\n };\n /** Override the default Puppeteer driver. */\n driver?: CreateClientOptions['driver'];\n};\n\n/** Private profile storage, stable for this project directory and session name. */\nfunction privateSessionDirectory(sessionId: string): string {\n const project = createHash('sha256').update(realpathSync(process.cwd())).digest('hex').slice(0, 24);\n const session = createHash('sha256').update(sessionId).digest('hex').slice(0, 24);\n const root = resolve(homedir(), '.open-wa', 'sessions');\n const directory = resolve(root, project, session);\n mkdirSync(directory, { recursive: true, mode: 0o700 });\n // Protect existing directories too; Chromium stores authentication here.\n for (const path of [root, dirname(directory), directory]) chmodSync(path, 0o700);\n return directory;\n}\n\n/** Start WhatsApp, display QR login when needed, and return a ready messaging client. */\nexport async function create(options: CreateOptions = {}): Promise<Client> {\n const { driver, sessionData, sessionDataBucketAuth, s3Sync, ...configOverrides } = options;\n const { config, rawConfigs } = await resolveConfig({\n programmaticOverrides: {\n qrTimeout: 0, ...configOverrides,\n // Session seeds and bucket credentials bypass tracked/debug config.\n },\n skipConfigFile: true,\n skipEnv: true,\n includeRawConfigs: true,\n });\n\n const driverSelection = await selectRuntimeDriver(config, {\n rawConfigs,\n cacheFilePath: resolve(process.cwd(), '.open-wa', 'chrome-executable-path.json'),\n defaultPreferLocalChrome: false,\n });\n\n const coreOptions = toCreateClientOptions(config, driverSelection);\n if (driver) coreOptions.driver = driver;\n coreOptions.sessionData = sessionData;\n coreOptions.sessionDataBucketAuth = sessionDataBucketAuth;\n coreOptions.s3Sync = s3Sync;\n if (config.legacyDataDirAuth && !config.ephemeral && configOverrides.userDataDir === undefined && configOverrides.sessionDataPath === undefined) {\n coreOptions.userDataDir = privateSessionDirectory(config.sessionId);\n coreOptions.sessionDataPath = coreOptions.userDataDir;\n }\n\n const core = await createCoreClient(coreOptions);\n const sink = getCliOutputSink();\n const onQr = (event: OpenWAEventMap['launch.auth.qr.generated']) => {\n if (config.qrLogSkip || !event.details?.qr) return;\n sink.write({ level: 'info', message: 'Open WhatsApp on your sending phone: Linked Devices → Link a Device, then scan this QR code.' });\n sink.qr({ qr: event.details.qr, sessionId: config.sessionId });\n };\n const onLinkCode = (event: OpenWAEventMap['launch.auth.linkCode.generated']) => {\n if (event.details?.linkCode && !config.qrLogSkip) {\n sink.write({ level: 'info', message: `Enter this link code on your sending phone: ${event.details.linkCode}` });\n }\n };\n core.events.on('launch.auth.qr.generated', onQr);\n core.events.on('launch.auth.linkCode.generated', onLinkCode);\n let client: Client | undefined;\n try {\n client = new Client({ client: core, transport: core.getTransport() });\n await client.start();\n if (core.getState() !== 'READY' || !core.getReadiness().exposureSafe) {\n throw new Error('WhatsApp startup finished without a messaging-ready session.');\n }\n return client;\n } catch (error) {\n try {\n if (client) await client.stop('startup-failure');\n else await core.stop('startup-failure');\n } catch {\n // Keep the startup failure as the actionable error.\n }\n throw error;\n } finally {\n core.events.off('launch.auth.qr.generated', onQr);\n core.events.off('launch.auth.linkCode.generated', onLinkCode);\n }\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index.cjs","names":["getCliOutputSink","WAServer","createLogger","LocalSessionCompression","S3SyncManager","join","dirname"],"sources":["../src/server/lifecycle-manager.ts","../src/session/SessionArchiveManager.ts","../src/index.ts"],"sourcesContent":["import { WAServer } from './hono-server';\nimport type { Config } from '@open-wa/config';\nimport { getCliOutputSink } from '../cli/output-sink';\n\nexport class APILifecycleManager {\n private config: Config;\n private server?: WAServer;\n // @ts-ignore\n private _sessionConnected: boolean = false;\n\n constructor(config: Config) {\n this.config = config;\n }\n\n public async initialize(): Promise<void> {\n const sink = getCliOutputSink();\n switch (this.config.apiLifecycle) {\n case 'immediate':\n sink.status({ phase: 'server.starting', sessionId: this.config.sessionId, detail: 'Starting full API immediately' });\n await this.startFullAPI();\n break;\n case 'post-connection':\n this.waitForConnection();\n break;\n case 'hybrid':\n sink.status({ phase: 'server.starting', sessionId: this.config.sessionId, detail: 'Starting minimal API (QR only)' });\n await this.startMinimalAPI();\n break;\n }\n }\n\n private async waitForConnection(): Promise<void> {\n getCliOutputSink().write({ level: 'info', message: 'Waiting for session connection before starting API...' });\n // This will be called by the orchestrator or main entry point when session connects\n }\n\n private async startFullAPI(): Promise<void> {\n getCliOutputSink().write({ level: 'info', message: 'Starting full API immediately...' });\n this.server = new WAServer(this.config);\n await this.server.start();\n }\n\n private async startMinimalAPI(): Promise<void> {\n getCliOutputSink().write({ level: 'info', message: 'Starting minimal API (QR only)...' });\n \n // Create server with full config but we might restrict routes in the future\n // For now, hybrid mode just starts the server, but logic inside routes (like sendText)\n // should check if session is connected before execution.\n // In a more advanced implementation, we would only register public routes here.\n \n this.server = new WAServer(this.config);\n await this.server.start();\n }\n \n public async stop(): Promise<void> {\n if (this.server) {\n await this.server.stop();\n }\n }\n}\n","import { dirname, join } from 'node:path';\nimport { createLogger } from '@open-wa/logger';\nimport { LocalSessionCompression, S3SyncManager, type S3Config } from '@open-wa/session-sync';\n\nexport interface SessionArchiveManagerConfig {\n sessionId: string;\n dataDir: string;\n s3Config: S3Config;\n syncInterval?: number;\n watchLocalChanges?: boolean;\n}\n\nexport class SessionArchiveManager {\n private readonly logger = createLogger({ component: 'SessionArchiveManager' });\n private localCompression?: LocalSessionCompression;\n private s3Sync?: S3SyncManager;\n private syncTimer?: NodeJS.Timeout;\n private started = false;\n\n constructor(private readonly config: SessionArchiveManagerConfig) {\n this.logger.info('session_archive_manager_initialized', { sessionId: config.sessionId });\n }\n\n async start(): Promise<void> {\n if (this.started) return;\n this.started = true;\n\n this.localCompression = new LocalSessionCompression({\n sessionPath: this.config.dataDir,\n sessionId: this.config.sessionId,\n outputPath: this.archivePath,\n intervalMs: this.config.syncInterval,\n });\n if (this.config.watchLocalChanges !== false) {\n this.localCompression.start();\n this.logger.info('local_session_compression_started');\n }\n\n this.s3Sync = new S3SyncManager(this.config.s3Config);\n this.startPeriodicSync();\n this.logger.info('s3_session_sync_started');\n }\n\n async stop(): Promise<void> {\n if (this.syncTimer) {\n clearInterval(this.syncTimer);\n this.syncTimer = undefined;\n }\n\n this.localCompression?.stop();\n this.localCompression = undefined;\n this.s3Sync = undefined;\n this.started = false;\n this.logger.info('session_archive_manager_stopped');\n }\n\n async backupSession(): Promise<string | null> {\n if (!this.s3Sync || !this.localCompression) {\n this.logger.warn('session_archive_manager_not_started');\n return null;\n }\n\n try {\n await this.localCompression.compress();\n const filename = await this.s3Sync.backupSession(this.archivePath);\n this.logger.info('session_backed_up', { filename });\n return filename;\n } catch (error) {\n this.logger.error('session_backup_failed', { error });\n throw error;\n }\n }\n\n async restoreSession(filename: string): Promise<void> {\n if (!this.s3Sync) {\n throw new Error('Session archive manager is not started');\n }\n\n const restored = await this.s3Sync.restoreSession(filename, this.config.dataDir);\n if (!restored) {\n throw new Error(`Failed to restore session backup: ${filename}`);\n }\n this.logger.info('session_restored', { filename });\n }\n\n async getSessionBackupUrl(filename: string, expiresIn = 3600): Promise<string | null> {\n if (!this.s3Sync) {\n return null;\n }\n\n return this.s3Sync.getDownloadUrl(filename, expiresIn);\n }\n\n private get archivePath(): string {\n return join(dirname(this.config.dataDir), `${this.config.sessionId}.data.zst`);\n }\n\n private startPeriodicSync(): void {\n if (!this.s3Sync || this.syncTimer) return;\n\n this.syncTimer = setInterval(() => {\n void this.backupSession().catch((error) => {\n this.logger.error('periodic_session_sync_failed', { error });\n });\n }, this.config.syncInterval ?? 600_000);\n this.syncTimer.unref();\n }\n}\n","export { WAServer } from './server/hono-server';\nexport { APILifecycleManager } from './server/lifecycle-manager';\nexport { SessionArchiveManager } from './session/SessionArchiveManager';\nexport { main as runCli, start as startCli, parseCliArgs } from './cli-runtime';\nexport type { CliRuntimeResult } from './cli-runtime';\nexport { createConsoleOutputSink, getCliOutputSink, resetCliOutputSink, setCliOutputSink } from './cli/output-sink';\nexport type { CliOutputEntry, CliOutputLevel, CliOutputSink, CliQrPayload, CliStatusUpdate } from './cli/output-sink';\nexport { ConfigSchema } from '@open-wa/config';\nexport type { Config } from '@open-wa/config';\nexport { SimpleListener, MessageAck } from '@open-wa/schema';\nexport { createApiServer, createApiMiddleware } from '@open-wa/api';\nexport * from '@open-wa/client';\nexport { createClient } from '@open-wa/core';\nexport { ev, onGlobalEvent } from '@open-wa/core';\nexport type { CreateClientOptions, OpenWAClient, PortableSessionStatus } from '@open-wa/core';\nexport { create } from './runtime-client';\nexport type { CreateOptions } from './runtime-client';\nexport async function ensureBrowser(...args: Parameters<typeof import('@open-wa/driver-puppeteer').ensureBrowser>): Promise<string> {\n const { ensureBrowser: provisionBrowser } = await import('@open-wa/driver-puppeteer');\n return provisionBrowser(...args);\n}\n"],"mappings":"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"}
|
package/dist/index.d.cts
CHANGED
|
@@ -3,15 +3,13 @@ import { Client } from "@open-wa/client";
|
|
|
3
3
|
import { createApiMiddleware, createApiServer } from "@open-wa/api";
|
|
4
4
|
import { Config, Config as Config$1, ConfigSchema, PartialConfig } from "@open-wa/config";
|
|
5
5
|
import { S3Config } from "@open-wa/session-sync";
|
|
6
|
-
import {
|
|
7
|
-
import "@open-wa/
|
|
8
|
-
import { ensureBrowser } from "@open-wa/driver-puppeteer";
|
|
6
|
+
import { MessageAck, SimpleListener } from "@open-wa/schema";
|
|
7
|
+
import { CreateClientOptions, CreateClientOptions as CreateClientOptions$1, OpenWAClient, PortableSessionStatus, createClient, ev, onGlobalEvent } from "@open-wa/core";
|
|
9
8
|
export * from "@open-wa/client";
|
|
10
9
|
//#region src/server/lifecycle-manager.d.ts
|
|
11
10
|
export declare class APILifecycleManager {
|
|
12
11
|
private config;
|
|
13
12
|
private server?;
|
|
14
|
-
private sessionArchiveManager?;
|
|
15
13
|
private _sessionConnected;
|
|
16
14
|
constructor(config: Config$1);
|
|
17
15
|
initialize(): Promise<void>;
|
|
@@ -42,7 +40,6 @@ export declare class SessionArchiveManager {
|
|
|
42
40
|
backupSession(): Promise<string | null>;
|
|
43
41
|
restoreSession(filename: string): Promise<void>;
|
|
44
42
|
getSessionBackupUrl(filename: string, expiresIn?: number): Promise<string | null>;
|
|
45
|
-
static createFromConfig(config: Config$1): SessionArchiveManager;
|
|
46
43
|
private get archivePath();
|
|
47
44
|
private startPeriodicSync;
|
|
48
45
|
}
|
|
@@ -67,6 +64,7 @@ interface CliOutputSink {
|
|
|
67
64
|
write(entry: CliOutputEntry): void;
|
|
68
65
|
status(update: CliStatusUpdate): void;
|
|
69
66
|
qr(payload: CliQrPayload): void;
|
|
67
|
+
promptChoice?(question: string, choices: readonly string[]): Promise<number>;
|
|
70
68
|
}
|
|
71
69
|
export declare function createConsoleOutputSink(): CliOutputSink;
|
|
72
70
|
export declare function getCliOutputSink(): CliOutputSink;
|
|
@@ -74,7 +72,8 @@ export declare function setCliOutputSink(sink: CliOutputSink): void;
|
|
|
74
72
|
export declare function resetCliOutputSink(): void;
|
|
75
73
|
//#endregion
|
|
76
74
|
//#region src/runtime-client.d.ts
|
|
77
|
-
type CreateOptions = Omit<PartialConfig, 's3Sync'> & {
|
|
75
|
+
type CreateOptions = Omit<PartialConfig, 's3Sync' | 'calling'> & {
|
|
76
|
+
calling?: import('@open-wa/schema').CallingOptions;
|
|
78
77
|
s3Sync?: Omit<NonNullable<PartialConfig['s3Sync']>, 'region' | 'syncInterval'> & {
|
|
79
78
|
region?: string;
|
|
80
79
|
syncInterval?: number;
|
|
@@ -83,5 +82,8 @@ type CreateOptions = Omit<PartialConfig, 's3Sync'> & {
|
|
|
83
82
|
};
|
|
84
83
|
export declare function create(options?: CreateOptions): Promise<Client>;
|
|
85
84
|
//#endregion
|
|
86
|
-
|
|
85
|
+
//#region src/index.d.ts
|
|
86
|
+
export declare function ensureBrowser(...args: Parameters<typeof import('@open-wa/driver-puppeteer').ensureBrowser>): Promise<string>;
|
|
87
|
+
//#endregion
|
|
88
|
+
export { type CliOutputEntry, type CliOutputLevel, type CliOutputSink, type CliQrPayload, type CliRuntimeResult, type CliStatusUpdate, type Config, ConfigSchema, type CreateClientOptions, type CreateOptions, MessageAck, type OpenWAClient, type PortableSessionStatus, SimpleListener, WAServer, createApiMiddleware, createApiServer, createClient, ev, onGlobalEvent, parseCliArgs, main as runCli, start as startCli };
|
|
87
89
|
//# sourceMappingURL=index.d.cts.map
|
package/dist/index.d.cts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.cts","names":["Config","
|
|
1
|
+
{"version":3,"file":"index.d.cts","names":["Config","CreateClientOptions"],"sources":["../src/server/lifecycle-manager.ts","../src/session/SessionArchiveManager.ts","../src/cli/output-sink.ts","../src/runtime-client.ts","../src/index.ts"],"mappings":";;;;;;;;;qBAIa;UACD;UACA;UAEA;EAER,YAAY,QAAQA;EAIP,cAAc;UAiBb;UAKA;UAMA;EAYD,QAAQ;;;;UClDR;EACb;EACA;EACA,UAAU;EACV;EACA;;qBAGS;mBAOoB;mBANZ;UACT;UACA;UACA;UACA;EAER,YAA6B,QAAQ;EAI/B,SAAS;EAoBT,QAAQ;EAaR,iBAAiB;EAiBjB,eAAe,mBAAmB;EAYlC,oBAAoB,kBAAkB,qBAAmB;cAQnD;UAIJ;;;;KC/FA;UAEK;EACf,OAAO;EACP;EACA,OAAO;;UAGQ;EACf;EAgBA;EACA;;UAGe;EACf;EACA;;UAGe;EACf,MAAM,OAAO;EACb,OAAO,QAAQ;EACf,GAAG,SAAS;EACZ,cAAc,kBAAkB,6BAA6B;;wBAyC/C,2BAA2B;wBAmB3B,oBAAoB;wBAIpB,iBAAiB,MAAM;wBAIvB;;;KC6OJ,gBAAgB,KAAK;EAC7B,oCAAoC;EACpC,SAAS,KAAK,YAAY;IACtB;IACA;;EAGJ,SAASC;;wBAIS,OAAO,UAAS,gBAAqB,QAAQ;;;wBCnV7C,iBAAiB,MAAM,sDAAsD,iBAAiB"}
|
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
const require_cli_runtime = require("./cli-runtime-
|
|
1
|
+
const require_cli_runtime = require("./cli-runtime-BRj_LUIT.cjs");
|
|
2
2
|
let node_path = require("node:path");
|
|
3
|
-
let node_child_process = require("node:child_process");
|
|
4
3
|
let node_fs_promises = require("node:fs/promises");
|
|
4
|
+
let node_child_process = require("node:child_process");
|
|
5
5
|
//#region package.json
|
|
6
|
-
var version = "5.
|
|
6
|
+
var version = "5.5.0";
|
|
7
7
|
//#endregion
|
|
8
8
|
//#region src/cli/init.ts
|
|
9
9
|
const starter = `import { create } from '@open-wa/wa-automate';
|
|
@@ -111,4 +111,4 @@ async function initProject(args) {
|
|
|
111
111
|
//#endregion
|
|
112
112
|
exports.initProject = initProject;
|
|
113
113
|
|
|
114
|
-
//# sourceMappingURL=init-
|
|
114
|
+
//# sourceMappingURL=init-CUhC5Wkq.cjs.map
|