@wspc/cli 0.1.3 → 0.1.4
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.js +169 -133
- package/dist/cli.js.map +1 -1
- package/dist/index.d.ts +2 -2
- package/dist/index.js +2 -2
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/cli.js
CHANGED
|
@@ -1464,9 +1464,9 @@ function createConsistencyFetch(opts) {
|
|
|
1464
1464
|
}
|
|
1465
1465
|
|
|
1466
1466
|
// src/version.ts
|
|
1467
|
-
var VERSION = "0.1.
|
|
1467
|
+
var VERSION = "0.1.4";
|
|
1468
1468
|
var SPEC_SHA = "e0bbc1e3";
|
|
1469
|
-
var SPEC_FETCHED_AT = "2026-06-
|
|
1469
|
+
var SPEC_FETCHED_AT = "2026-06-22T06:55:37.490Z";
|
|
1470
1470
|
var API_BASE = "https://api.wspc.ai";
|
|
1471
1471
|
|
|
1472
1472
|
// src/index.ts
|
|
@@ -3294,7 +3294,7 @@ var pushTestCommand = new Command45("test").description("Send a test push notifi
|
|
|
3294
3294
|
}
|
|
3295
3295
|
render({ kind: "push_test", display: { "shape": "object", "fields": ["ok", "status", "detail", "durationMs"], "format": { "ok": "bool-badge" } } }, result.data);
|
|
3296
3296
|
if (result.data?.ok === false) {
|
|
3297
|
-
process.
|
|
3297
|
+
process.exitCode = 1;
|
|
3298
3298
|
}
|
|
3299
3299
|
});
|
|
3300
3300
|
|
|
@@ -3872,13 +3872,15 @@ async function ensureClientId(opts) {
|
|
|
3872
3872
|
apiBase: opts.baseUrl,
|
|
3873
3873
|
fetchImpl: opts.fetchImpl
|
|
3874
3874
|
});
|
|
3875
|
-
|
|
3876
|
-
|
|
3875
|
+
let existing;
|
|
3876
|
+
await opts.store.update((c) => {
|
|
3877
|
+
existing = c.envs[opts.envName]?.client_id;
|
|
3878
|
+
if (existing) return;
|
|
3879
|
+
const targetEnv = c.envs[opts.envName] ??= { api_base: opts.baseUrl, accounts: {} };
|
|
3880
|
+
targetEnv.api_base = opts.baseUrl;
|
|
3881
|
+
targetEnv.accounts ??= {};
|
|
3882
|
+
});
|
|
3877
3883
|
if (existing) return existing;
|
|
3878
|
-
const targetEnv = c.envs[opts.envName] ??= { api_base: opts.baseUrl, accounts: {} };
|
|
3879
|
-
targetEnv.api_base = opts.baseUrl;
|
|
3880
|
-
targetEnv.accounts ??= {};
|
|
3881
|
-
await opts.store.write(c);
|
|
3882
3884
|
const res = await fetchImpl(`${opts.baseUrl}/auth/oauth/register`, {
|
|
3883
3885
|
method: "POST",
|
|
3884
3886
|
headers: { "content-type": "application/json" },
|
|
@@ -3894,12 +3896,18 @@ async function ensureClientId(opts) {
|
|
|
3894
3896
|
}
|
|
3895
3897
|
const body = await res.json();
|
|
3896
3898
|
if (!body.client_id) throw new Error("client_registration_failed: missing client_id in response");
|
|
3897
|
-
|
|
3898
|
-
|
|
3899
|
-
|
|
3900
|
-
|
|
3901
|
-
|
|
3902
|
-
|
|
3899
|
+
let clientId = body.client_id;
|
|
3900
|
+
await opts.store.update((c) => {
|
|
3901
|
+
const env = c.envs[opts.envName] ??= { api_base: opts.baseUrl, accounts: {} };
|
|
3902
|
+
env.api_base = opts.baseUrl;
|
|
3903
|
+
env.accounts ??= {};
|
|
3904
|
+
if (env.client_id) {
|
|
3905
|
+
clientId = env.client_id;
|
|
3906
|
+
return;
|
|
3907
|
+
}
|
|
3908
|
+
env.client_id = body.client_id;
|
|
3909
|
+
});
|
|
3910
|
+
return clientId;
|
|
3903
3911
|
}
|
|
3904
3912
|
|
|
3905
3913
|
// src/handwritten/auth/fetch-me.ts
|
|
@@ -3956,36 +3964,36 @@ async function runLogin(opts) {
|
|
|
3956
3964
|
const now = opts.now ?? Date.now;
|
|
3957
3965
|
const me = opts.fetchMe ?? ((o) => fetchMe(o));
|
|
3958
3966
|
if (opts.apiKey) {
|
|
3959
|
-
|
|
3960
|
-
|
|
3961
|
-
|
|
3962
|
-
|
|
3967
|
+
await opts.store.update((initial) => {
|
|
3968
|
+
getOrCreateEnv(initial, envName, opts.baseUrl);
|
|
3969
|
+
initial.current_env = envName;
|
|
3970
|
+
});
|
|
3963
3971
|
const who2 = await me({
|
|
3964
3972
|
baseUrl: opts.baseUrl,
|
|
3965
3973
|
token: opts.apiKey,
|
|
3966
3974
|
store: opts.store,
|
|
3967
3975
|
envName
|
|
3968
3976
|
});
|
|
3969
|
-
|
|
3970
|
-
|
|
3971
|
-
|
|
3972
|
-
|
|
3973
|
-
|
|
3974
|
-
|
|
3975
|
-
|
|
3976
|
-
|
|
3977
|
-
|
|
3978
|
-
|
|
3979
|
-
|
|
3980
|
-
|
|
3981
|
-
|
|
3982
|
-
|
|
3983
|
-
|
|
3984
|
-
|
|
3977
|
+
await opts.store.update((c) => {
|
|
3978
|
+
const env = getOrCreateEnv(c, envName, opts.baseUrl);
|
|
3979
|
+
const prev = env.accounts[who2.email] ?? { email: who2.email };
|
|
3980
|
+
const acct = env.accounts[who2.email] = {
|
|
3981
|
+
...prev,
|
|
3982
|
+
email: who2.email,
|
|
3983
|
+
user_id: who2.user_id,
|
|
3984
|
+
api_key: opts.apiKey
|
|
3985
|
+
};
|
|
3986
|
+
delete acct.refresh_token;
|
|
3987
|
+
delete acct.access_token;
|
|
3988
|
+
delete acct.access_token_expires_at;
|
|
3989
|
+
env.current_account = who2.email;
|
|
3990
|
+
if (who2.email !== LEGACY_ACCOUNT_KEY) delete env.accounts[LEGACY_ACCOUNT_KEY];
|
|
3991
|
+
c.current_env = envName;
|
|
3992
|
+
});
|
|
3985
3993
|
opts.output.write(`${green("\u2713")} logged in (api key) as ${bold(who2.email)} ${dim(`\u2192 env "${envName}"`)}`);
|
|
3986
3994
|
return;
|
|
3987
3995
|
}
|
|
3988
|
-
const ensureClient = opts.ensureClient ?? ((
|
|
3996
|
+
const ensureClient = opts.ensureClient ?? ((env) => ensureClientId({ store: opts.store, envName: env, baseUrl: opts.baseUrl }));
|
|
3989
3997
|
const clientId = opts.clientId ?? await ensureClient(envName);
|
|
3990
3998
|
const flow = opts.deviceFlow ?? runDeviceFlow;
|
|
3991
3999
|
const result = await flow({
|
|
@@ -4005,22 +4013,22 @@ async function runLogin(opts) {
|
|
|
4005
4013
|
store: opts.store,
|
|
4006
4014
|
envName
|
|
4007
4015
|
});
|
|
4008
|
-
|
|
4009
|
-
|
|
4010
|
-
|
|
4011
|
-
|
|
4012
|
-
|
|
4013
|
-
|
|
4014
|
-
|
|
4015
|
-
|
|
4016
|
-
|
|
4017
|
-
|
|
4018
|
-
|
|
4019
|
-
|
|
4020
|
-
|
|
4021
|
-
|
|
4022
|
-
|
|
4023
|
-
|
|
4016
|
+
await opts.store.update((c) => {
|
|
4017
|
+
const env = getOrCreateEnv(c, envName, opts.baseUrl);
|
|
4018
|
+
const prev = env.accounts[who.email] ?? { email: who.email };
|
|
4019
|
+
const acct = env.accounts[who.email] = {
|
|
4020
|
+
...prev,
|
|
4021
|
+
email: who.email,
|
|
4022
|
+
user_id: who.user_id,
|
|
4023
|
+
refresh_token: result.refresh_token,
|
|
4024
|
+
access_token: result.access_token,
|
|
4025
|
+
access_token_expires_at: now() + result.expires_in * 1e3
|
|
4026
|
+
};
|
|
4027
|
+
delete acct.api_key;
|
|
4028
|
+
env.current_account = who.email;
|
|
4029
|
+
if (who.email !== LEGACY_ACCOUNT_KEY) delete env.accounts[LEGACY_ACCOUNT_KEY];
|
|
4030
|
+
c.current_env = envName;
|
|
4031
|
+
});
|
|
4024
4032
|
opts.output.writeJson({ event: "login_success", email: who.email });
|
|
4025
4033
|
opts.output.write(`${green("\u2713")} logged in as ${bold(who.email)} ${dim(`\u2192 env "${envName}"`)}`);
|
|
4026
4034
|
}
|
|
@@ -4057,27 +4065,32 @@ import { Command as Command63 } from "commander";
|
|
|
4057
4065
|
|
|
4058
4066
|
// src/handwritten/auth/logout.ts
|
|
4059
4067
|
async function runLogout(opts) {
|
|
4060
|
-
|
|
4061
|
-
|
|
4062
|
-
|
|
4063
|
-
|
|
4064
|
-
|
|
4065
|
-
|
|
4066
|
-
const
|
|
4067
|
-
env.accounts
|
|
4068
|
-
|
|
4069
|
-
|
|
4070
|
-
|
|
4071
|
-
|
|
4072
|
-
|
|
4073
|
-
|
|
4074
|
-
|
|
4075
|
-
|
|
4076
|
-
|
|
4077
|
-
|
|
4078
|
-
|
|
4079
|
-
|
|
4080
|
-
|
|
4068
|
+
let removed = [];
|
|
4069
|
+
let newActive;
|
|
4070
|
+
let removedSingleAccount = false;
|
|
4071
|
+
await opts.store.update((c) => {
|
|
4072
|
+
const envName = opts.envName ?? c.current_env;
|
|
4073
|
+
if (!envName || !c.envs[envName]) return;
|
|
4074
|
+
const env = c.envs[envName];
|
|
4075
|
+
env.accounts ??= {};
|
|
4076
|
+
if (opts.all) {
|
|
4077
|
+
removed = Object.keys(env.accounts);
|
|
4078
|
+
env.accounts = {};
|
|
4079
|
+
env.current_account = void 0;
|
|
4080
|
+
return;
|
|
4081
|
+
}
|
|
4082
|
+
const target = opts.email ?? env.current_account ?? (Object.keys(env.accounts).length === 1 ? Object.keys(env.accounts)[0] : void 0);
|
|
4083
|
+
if (!target || !env.accounts[target]) return;
|
|
4084
|
+
delete env.accounts[target];
|
|
4085
|
+
removed = [target];
|
|
4086
|
+
removedSingleAccount = true;
|
|
4087
|
+
if (env.current_account === target) {
|
|
4088
|
+
const remaining = Object.keys(env.accounts);
|
|
4089
|
+
env.current_account = remaining.length === 1 ? remaining[0] : void 0;
|
|
4090
|
+
}
|
|
4091
|
+
newActive = env.current_account;
|
|
4092
|
+
});
|
|
4093
|
+
return removedSingleAccount ? { removed, newActive } : { removed };
|
|
4081
4094
|
}
|
|
4082
4095
|
|
|
4083
4096
|
// src/handwritten/commands/logout.ts
|
|
@@ -4121,10 +4134,9 @@ registerRenderer("whoami", (data) => {
|
|
|
4121
4134
|
}
|
|
4122
4135
|
});
|
|
4123
4136
|
async function backfillActiveEmail(store, envName, email, userId) {
|
|
4124
|
-
|
|
4125
|
-
|
|
4126
|
-
|
|
4127
|
-
}
|
|
4137
|
+
await store.update((cfg) => {
|
|
4138
|
+
rekeyLegacyAccount(cfg, envName, email, userId);
|
|
4139
|
+
});
|
|
4128
4140
|
}
|
|
4129
4141
|
var whoamiCommand = new Command64("whoami").description("Show the active env, signed-in account, and organization").action(async () => {
|
|
4130
4142
|
const store = new ConfigStore();
|
|
@@ -4199,24 +4211,24 @@ registerRenderer("config_show", (data) => {
|
|
|
4199
4211
|
process.stdout.write(table(headers, rows));
|
|
4200
4212
|
});
|
|
4201
4213
|
async function setConfigKey(store, key, value) {
|
|
4202
|
-
|
|
4203
|
-
|
|
4204
|
-
|
|
4205
|
-
|
|
4206
|
-
|
|
4207
|
-
|
|
4208
|
-
|
|
4209
|
-
|
|
4210
|
-
|
|
4211
|
-
|
|
4212
|
-
|
|
4213
|
-
|
|
4214
|
-
|
|
4215
|
-
|
|
4216
|
-
|
|
4217
|
-
|
|
4218
|
-
|
|
4219
|
-
|
|
4214
|
+
await store.update((c) => {
|
|
4215
|
+
const resolved = resolveAccount(c, { accountOverride: process.env.WSPC_ACCOUNT });
|
|
4216
|
+
const env = c.envs[resolved.envName];
|
|
4217
|
+
if (!env) throw new Error(`env "${resolved.envName}" not found`);
|
|
4218
|
+
const acct = env.accounts[resolved.email];
|
|
4219
|
+
if (!acct) throw new Error(`account "${resolved.email}" not found`);
|
|
4220
|
+
switch (key) {
|
|
4221
|
+
case "actor":
|
|
4222
|
+
if (value !== "user" && value !== "agent") throw new Error("actor must be 'user' or 'agent'");
|
|
4223
|
+
acct.actor = value;
|
|
4224
|
+
break;
|
|
4225
|
+
case "agent-label":
|
|
4226
|
+
acct.agent_label = value;
|
|
4227
|
+
break;
|
|
4228
|
+
default:
|
|
4229
|
+
throw new Error(`unknown config key: ${key}`);
|
|
4230
|
+
}
|
|
4231
|
+
});
|
|
4220
4232
|
}
|
|
4221
4233
|
configCommand.command("show").description("List configured envs (tokens redacted, current marked with \u2713)").action(async () => {
|
|
4222
4234
|
const c = await new ConfigStore().read();
|
|
@@ -4242,10 +4254,10 @@ configCommand.command("set <key> <value>").description("Set a field on the activ
|
|
|
4242
4254
|
});
|
|
4243
4255
|
configCommand.command("use <env>").description("Switch current_env").action(async (env) => {
|
|
4244
4256
|
const store = new ConfigStore();
|
|
4245
|
-
|
|
4246
|
-
|
|
4247
|
-
|
|
4248
|
-
|
|
4257
|
+
await store.update((c) => {
|
|
4258
|
+
if (!c.envs[env]) throw new Error(`env "${env}" not found`);
|
|
4259
|
+
c.current_env = env;
|
|
4260
|
+
});
|
|
4249
4261
|
process.stdout.write(`\u2713 current_env=${env}
|
|
4250
4262
|
`);
|
|
4251
4263
|
});
|
|
@@ -4266,15 +4278,15 @@ async function listAccounts(store) {
|
|
|
4266
4278
|
}));
|
|
4267
4279
|
}
|
|
4268
4280
|
async function switchAccount(store, email) {
|
|
4269
|
-
|
|
4270
|
-
|
|
4271
|
-
|
|
4272
|
-
|
|
4273
|
-
|
|
4274
|
-
|
|
4275
|
-
|
|
4276
|
-
|
|
4277
|
-
|
|
4281
|
+
await store.update((c) => {
|
|
4282
|
+
const envName = c.current_env;
|
|
4283
|
+
if (!envName || !c.envs[envName]) throw new Error("no current env; run `wspc login` first");
|
|
4284
|
+
const env = c.envs[envName];
|
|
4285
|
+
if (!env.accounts?.[email]) {
|
|
4286
|
+
throw new Error(`no account '${email}' in env '${envName}'. Run \`wspc account ls\` or \`wspc login\`.`);
|
|
4287
|
+
}
|
|
4288
|
+
env.current_account = email;
|
|
4289
|
+
});
|
|
4278
4290
|
}
|
|
4279
4291
|
registerRenderer("account_ls", (data) => {
|
|
4280
4292
|
const rows = data.accounts;
|
|
@@ -4495,11 +4507,12 @@ import { pipeline } from "stream/promises";
|
|
|
4495
4507
|
function parseContentDispositionFilename(header) {
|
|
4496
4508
|
if (!header) return void 0;
|
|
4497
4509
|
if (!header.toLowerCase().startsWith("attachment")) return void 0;
|
|
4498
|
-
const quoted = header.match(/filename="([^"]
|
|
4499
|
-
if (quoted) return quoted[1];
|
|
4510
|
+
const quoted = header.match(/filename="([^"]*)"/i);
|
|
4500
4511
|
const unquoted = header.match(/filename=([^;\s]+)/i);
|
|
4501
|
-
|
|
4502
|
-
return void 0;
|
|
4512
|
+
const filename = quoted?.[1] ?? unquoted?.[1];
|
|
4513
|
+
if (!filename || filename === "." || filename === "..") return void 0;
|
|
4514
|
+
if (filename.includes("/") || filename.includes("\\")) return void 0;
|
|
4515
|
+
return filename;
|
|
4503
4516
|
}
|
|
4504
4517
|
|
|
4505
4518
|
// src/handwritten/commands/email/attachment.ts
|
|
@@ -6064,7 +6077,11 @@ function createDriveRealtimeSource(args) {
|
|
|
6064
6077
|
const message = parseDriveRealtimeMessage(data);
|
|
6065
6078
|
if (message.type === "ready") {
|
|
6066
6079
|
if (message.replayed > 0) {
|
|
6067
|
-
handlers?.onEvent(
|
|
6080
|
+
handlers?.onEvent({
|
|
6081
|
+
debounce_ms: 2e3,
|
|
6082
|
+
reason: "ready_replay",
|
|
6083
|
+
...message.cursor === void 0 ? {} : { cursor: message.cursor }
|
|
6084
|
+
});
|
|
6068
6085
|
}
|
|
6069
6086
|
if (message.cursor !== void 0) {
|
|
6070
6087
|
await persistBestEffort({ ...currentRealtime, last_cursor: message.cursor });
|
|
@@ -6072,10 +6089,12 @@ function createDriveRealtimeSource(args) {
|
|
|
6072
6089
|
return;
|
|
6073
6090
|
}
|
|
6074
6091
|
if (message.type === "library_changed") {
|
|
6075
|
-
handlers?.onEvent(
|
|
6092
|
+
handlers?.onEvent({
|
|
6076
6093
|
debounce_ms: 2e3,
|
|
6077
|
-
reason: "library_changed"
|
|
6078
|
-
|
|
6094
|
+
reason: "library_changed",
|
|
6095
|
+
...message.cursor === void 0 ? {} : { cursor: message.cursor },
|
|
6096
|
+
...message.path === void 0 ? {} : { path: message.path }
|
|
6097
|
+
});
|
|
6079
6098
|
if (message.cursor !== void 0) {
|
|
6080
6099
|
await persistBestEffort({ ...currentRealtime, last_cursor: message.cursor, last_event_at: driveIsoTimestamp(clock) });
|
|
6081
6100
|
}
|
|
@@ -6083,7 +6102,11 @@ function createDriveRealtimeSource(args) {
|
|
|
6083
6102
|
}
|
|
6084
6103
|
if (message.type === "resync_required") {
|
|
6085
6104
|
const reason = message.reason ?? "resync_required";
|
|
6086
|
-
handlers?.onEvent(
|
|
6105
|
+
handlers?.onEvent({
|
|
6106
|
+
immediate: true,
|
|
6107
|
+
reason,
|
|
6108
|
+
...message.cursor === void 0 ? {} : { cursor: message.cursor }
|
|
6109
|
+
});
|
|
6087
6110
|
if (message.cursor !== void 0 || isInvalidCursorReason(reason)) {
|
|
6088
6111
|
await persistBestEffort(resyncRealtimeState(currentRealtime, message.cursor, reason, driveIsoTimestamp(clock)));
|
|
6089
6112
|
}
|
|
@@ -6148,22 +6171,37 @@ function parseDriveRealtimeMessage(raw) {
|
|
|
6148
6171
|
const messageType = typeof value.type === "string" ? value.type : void 0;
|
|
6149
6172
|
const cursor = typeof value.cursor === "string" ? value.cursor : void 0;
|
|
6150
6173
|
if (messageType === "ready") {
|
|
6151
|
-
return
|
|
6174
|
+
return {
|
|
6175
|
+
type: "ready",
|
|
6176
|
+
replayed: typeof value.replayed === "number" ? value.replayed : 0,
|
|
6177
|
+
...cursor === void 0 ? {} : { cursor }
|
|
6178
|
+
};
|
|
6152
6179
|
}
|
|
6153
6180
|
if (messageType === "library_changed") {
|
|
6154
|
-
return
|
|
6181
|
+
return {
|
|
6182
|
+
type: "library_changed",
|
|
6183
|
+
...cursor === void 0 ? {} : { cursor },
|
|
6184
|
+
...typeof value.path === "string" ? { path: value.path } : {}
|
|
6185
|
+
};
|
|
6155
6186
|
}
|
|
6156
6187
|
if (messageType === "resync_required") {
|
|
6157
|
-
return
|
|
6188
|
+
return {
|
|
6189
|
+
type: "resync_required",
|
|
6190
|
+
...cursor === void 0 ? {} : { cursor },
|
|
6191
|
+
...typeof value.reason === "string" ? { reason: value.reason } : {}
|
|
6192
|
+
};
|
|
6158
6193
|
}
|
|
6159
6194
|
if (messageType === "error") {
|
|
6160
|
-
return
|
|
6161
|
-
|
|
6162
|
-
"
|
|
6163
|
-
typeof value.message === "string" ? redactedRealtimeError(value.message) :
|
|
6164
|
-
|
|
6195
|
+
return {
|
|
6196
|
+
type: "error",
|
|
6197
|
+
...typeof value.code === "string" ? { code: value.code } : {},
|
|
6198
|
+
...typeof value.message === "string" ? { message: redactedRealtimeError(value.message) } : {}
|
|
6199
|
+
};
|
|
6165
6200
|
}
|
|
6166
|
-
return
|
|
6201
|
+
return {
|
|
6202
|
+
type: "unknown",
|
|
6203
|
+
...messageType === void 0 ? {} : { message_type: messageType }
|
|
6204
|
+
};
|
|
6167
6205
|
}
|
|
6168
6206
|
function redactedRealtimeError(error) {
|
|
6169
6207
|
const text = error instanceof Error ? error.message : String(error);
|
|
@@ -6187,7 +6225,11 @@ function resyncRealtimeState(realtime, cursor, reason, lastEventAt) {
|
|
|
6187
6225
|
const { last_cursor: _lastCursor, ...next } = realtime;
|
|
6188
6226
|
return { ...next, last_event_at: lastEventAt };
|
|
6189
6227
|
}
|
|
6190
|
-
return
|
|
6228
|
+
return {
|
|
6229
|
+
...realtime,
|
|
6230
|
+
last_event_at: lastEventAt,
|
|
6231
|
+
...cursor === void 0 ? {} : { last_cursor: cursor }
|
|
6232
|
+
};
|
|
6191
6233
|
}
|
|
6192
6234
|
function isInvalidCursorReason(reason) {
|
|
6193
6235
|
return /\bcursor[_ -]?(invalid|expired|gone|missing|not[_ -]?found)\b|\binvalid[_ -]?cursor\b/i.test(reason);
|
|
@@ -6195,12 +6237,6 @@ function isInvalidCursorReason(reason) {
|
|
|
6195
6237
|
function isRealtimeAuthError(error) {
|
|
6196
6238
|
return /\b(401|403|auth|authorization|unauthorized|forbidden)\b/i.test(String(error));
|
|
6197
6239
|
}
|
|
6198
|
-
function optionalString(target, key, value) {
|
|
6199
|
-
if (typeof value !== "string") {
|
|
6200
|
-
return target;
|
|
6201
|
-
}
|
|
6202
|
-
return { ...target, [key]: value };
|
|
6203
|
-
}
|
|
6204
6240
|
function nativeWebSocketConnector(url, handlers, init) {
|
|
6205
6241
|
const WebSocketWithInit = WebSocket;
|
|
6206
6242
|
const ws = new WebSocketWithInit(url.toString(), init);
|