@camstack/addon-cloudflare 1.0.2 → 1.0.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/{dist-FQAxmoZY.js → dist-BaLJK4dE.js} +122 -27
- package/dist/{dist-gS41k7Cx.mjs → dist-COIj-4Zk.mjs} +122 -27
- package/dist/tunnel/cloudflare-tunnel.addon.js +189 -5
- package/dist/tunnel/cloudflare-tunnel.addon.mjs +163 -5
- package/dist/turn/cloudflare-turn.addon.js +1 -1
- package/dist/turn/cloudflare-turn.addon.mjs +1 -1
- package/package.json +1 -1
|
@@ -5130,14 +5130,15 @@ var EventCategory = /* @__PURE__ */ function(EventCategory) {
|
|
|
5130
5130
|
EventCategory["DeviceSleeping"] = "device.sleeping";
|
|
5131
5131
|
EventCategory["RetentionCleanup"] = "retention.cleanup";
|
|
5132
5132
|
/**
|
|
5133
|
-
*
|
|
5134
|
-
*
|
|
5135
|
-
*
|
|
5136
|
-
* to
|
|
5137
|
-
*
|
|
5138
|
-
* Spec: docs/superpowers/specs/2026-05-21-addons-bulk-update-progress-design.md
|
|
5133
|
+
* Legacy bulk-update progress snapshot (payload `BulkUpdateState`). No longer
|
|
5134
|
+
* emitted — F3 removed the coordinator that produced it; "Update all" now runs
|
|
5135
|
+
* as one lifecycle engine job (`AddonsJobProgress`/`AddonsJobLog`). Retained
|
|
5136
|
+
* (with `BulkUpdateState`) only to avoid regenerating the event maps; removed
|
|
5137
|
+
* in F4 once live bulk progress is re-implemented over the engine events.
|
|
5139
5138
|
*/
|
|
5140
5139
|
EventCategory["AddonsBulkUpdateProgress"] = "addons.bulk-update-progress";
|
|
5140
|
+
EventCategory["AddonsJobProgress"] = "addons.job-progress";
|
|
5141
|
+
EventCategory["AddonsJobLog"] = "addons.job-log";
|
|
5141
5142
|
/**
|
|
5142
5143
|
* A container's child visibility toggled (hidden/shown). Emitted by the
|
|
5143
5144
|
* `accessories` cap when a child device is hidden or revealed.
|
|
@@ -16018,6 +16019,69 @@ method(_void(), array(IntegrationWithStateSchema)), method(object({ id: string()
|
|
|
16018
16019
|
kind: "mutation",
|
|
16019
16020
|
auth: "admin"
|
|
16020
16021
|
});
|
|
16022
|
+
var jobKindSchema = _enum([
|
|
16023
|
+
"install",
|
|
16024
|
+
"update",
|
|
16025
|
+
"uninstall",
|
|
16026
|
+
"restart"
|
|
16027
|
+
]);
|
|
16028
|
+
var taskPhaseSchema = _enum([
|
|
16029
|
+
"queued",
|
|
16030
|
+
"fetching",
|
|
16031
|
+
"staged",
|
|
16032
|
+
"validating",
|
|
16033
|
+
"applying",
|
|
16034
|
+
"restarting",
|
|
16035
|
+
"applied",
|
|
16036
|
+
"done",
|
|
16037
|
+
"failed",
|
|
16038
|
+
"skipped"
|
|
16039
|
+
]);
|
|
16040
|
+
var taskTargetSchema = _enum(["framework", "addon"]);
|
|
16041
|
+
var taskLogEntrySchema = object({
|
|
16042
|
+
tsMs: number(),
|
|
16043
|
+
nodeId: string(),
|
|
16044
|
+
packageName: string(),
|
|
16045
|
+
phase: taskPhaseSchema,
|
|
16046
|
+
message: string()
|
|
16047
|
+
});
|
|
16048
|
+
var lifecycleTaskSchema = object({
|
|
16049
|
+
taskId: string(),
|
|
16050
|
+
nodeId: string(),
|
|
16051
|
+
packageName: string(),
|
|
16052
|
+
fromVersion: string().nullable(),
|
|
16053
|
+
toVersion: string(),
|
|
16054
|
+
target: taskTargetSchema,
|
|
16055
|
+
phase: taskPhaseSchema,
|
|
16056
|
+
stagedPath: string().nullable(),
|
|
16057
|
+
attempts: number(),
|
|
16058
|
+
steps: array(taskLogEntrySchema),
|
|
16059
|
+
error: string().nullable(),
|
|
16060
|
+
startedAtMs: number().nullable(),
|
|
16061
|
+
finishedAtMs: number().nullable()
|
|
16062
|
+
});
|
|
16063
|
+
var lifecycleJobStateSchema = _enum([
|
|
16064
|
+
"running",
|
|
16065
|
+
"completed",
|
|
16066
|
+
"failed",
|
|
16067
|
+
"partially-failed",
|
|
16068
|
+
"cancelled"
|
|
16069
|
+
]);
|
|
16070
|
+
var lifecycleJobScopeSchema = _enum([
|
|
16071
|
+
"single",
|
|
16072
|
+
"bulk",
|
|
16073
|
+
"cluster"
|
|
16074
|
+
]);
|
|
16075
|
+
var lifecycleJobSchema = object({
|
|
16076
|
+
jobId: string(),
|
|
16077
|
+
kind: jobKindSchema,
|
|
16078
|
+
createdAtMs: number(),
|
|
16079
|
+
createdBy: string(),
|
|
16080
|
+
scope: lifecycleJobScopeSchema,
|
|
16081
|
+
tasks: array(lifecycleTaskSchema),
|
|
16082
|
+
state: lifecycleJobStateSchema,
|
|
16083
|
+
schemaVersion: literal(1)
|
|
16084
|
+
});
|
|
16021
16085
|
/**
|
|
16022
16086
|
* addons — system-scoped singleton capability for addon package
|
|
16023
16087
|
* management (install, update, configure, restart) and per-addon log
|
|
@@ -16200,7 +16264,7 @@ var BulkUpdatePhaseSchema = _enum([
|
|
|
16200
16264
|
"restarting",
|
|
16201
16265
|
"finalizing"
|
|
16202
16266
|
]);
|
|
16203
|
-
|
|
16267
|
+
object({
|
|
16204
16268
|
id: string(),
|
|
16205
16269
|
nodeId: string(),
|
|
16206
16270
|
startedAtMs: number(),
|
|
@@ -16303,20 +16367,7 @@ method(_void(), array(AddonListItemSchema).readonly()), method(object({
|
|
|
16303
16367
|
}), UpdateFrameworkPackageResultSchema, {
|
|
16304
16368
|
kind: "mutation",
|
|
16305
16369
|
auth: "admin"
|
|
16306
|
-
}), method(object({
|
|
16307
|
-
nodeId: string(),
|
|
16308
|
-
items: array(object({
|
|
16309
|
-
name: string(),
|
|
16310
|
-
version: string(),
|
|
16311
|
-
isSystem: boolean()
|
|
16312
|
-
})).readonly()
|
|
16313
|
-
}), object({ id: string() }), {
|
|
16314
|
-
kind: "mutation",
|
|
16315
|
-
auth: "admin"
|
|
16316
|
-
}), method(object({ id: string() }), BulkUpdateStateSchema.nullable(), { auth: "admin" }), method(object({ id: string() }), object({ cancelled: boolean() }), {
|
|
16317
|
-
kind: "mutation",
|
|
16318
|
-
auth: "admin"
|
|
16319
|
-
}), method(object({ nodeId: string().optional() }), array(BulkUpdateStateSchema).readonly(), { auth: "admin" }), method(object({ name: string() }), array(PackageVersionInfoSchema).readonly()), method(object({ addonId: string() }), RestartAddonResultSchema, {
|
|
16370
|
+
}), method(object({ name: string() }), array(PackageVersionInfoSchema).readonly()), method(object({ addonId: string() }), RestartAddonResultSchema, {
|
|
16320
16371
|
kind: "mutation",
|
|
16321
16372
|
auth: "admin"
|
|
16322
16373
|
}), method(object({ packageName: string() }), object({ success: literal(true) }), {
|
|
@@ -16338,6 +16389,24 @@ method(_void(), array(AddonListItemSchema).readonly()), method(object({
|
|
|
16338
16389
|
kind: "mutation",
|
|
16339
16390
|
auth: "admin"
|
|
16340
16391
|
}), method(CustomActionInputSchema, unknown(), { kind: "mutation" }), method(object({
|
|
16392
|
+
kind: _enum([
|
|
16393
|
+
"install",
|
|
16394
|
+
"update",
|
|
16395
|
+
"uninstall",
|
|
16396
|
+
"restart"
|
|
16397
|
+
]),
|
|
16398
|
+
targets: array(object({
|
|
16399
|
+
name: string().min(1),
|
|
16400
|
+
version: string().min(1)
|
|
16401
|
+
})).min(1),
|
|
16402
|
+
nodeIds: array(string()).optional()
|
|
16403
|
+
}), object({ jobId: string() }), {
|
|
16404
|
+
kind: "mutation",
|
|
16405
|
+
auth: "admin"
|
|
16406
|
+
}), method(object({ jobId: string() }), lifecycleJobSchema.nullable(), { auth: "admin" }), method(object({ activeOnly: boolean().optional() }), array(lifecycleJobSchema), { auth: "admin" }), method(object({ jobId: string() }), object({ cancelled: boolean() }), {
|
|
16407
|
+
kind: "mutation",
|
|
16408
|
+
auth: "admin"
|
|
16409
|
+
}), method(object({
|
|
16341
16410
|
addonId: string(),
|
|
16342
16411
|
level: LogLevelSchema$1.optional()
|
|
16343
16412
|
}), LogStreamEntrySchema, { kind: "subscription" });
|
|
@@ -16378,7 +16447,7 @@ Object.freeze({
|
|
|
16378
16447
|
addonId: null,
|
|
16379
16448
|
access: "create"
|
|
16380
16449
|
},
|
|
16381
|
-
"addons.
|
|
16450
|
+
"addons.cancelJob": {
|
|
16382
16451
|
capName: "addons",
|
|
16383
16452
|
capScope: "system",
|
|
16384
16453
|
addonId: null,
|
|
@@ -16408,7 +16477,7 @@ Object.freeze({
|
|
|
16408
16477
|
addonId: null,
|
|
16409
16478
|
access: "view"
|
|
16410
16479
|
},
|
|
16411
|
-
"addons.
|
|
16480
|
+
"addons.getJob": {
|
|
16412
16481
|
capName: "addons",
|
|
16413
16482
|
capScope: "system",
|
|
16414
16483
|
addonId: null,
|
|
@@ -16456,19 +16525,19 @@ Object.freeze({
|
|
|
16456
16525
|
addonId: null,
|
|
16457
16526
|
access: "view"
|
|
16458
16527
|
},
|
|
16459
|
-
"addons.
|
|
16528
|
+
"addons.listCapabilityProviders": {
|
|
16460
16529
|
capName: "addons",
|
|
16461
16530
|
capScope: "system",
|
|
16462
16531
|
addonId: null,
|
|
16463
16532
|
access: "view"
|
|
16464
16533
|
},
|
|
16465
|
-
"addons.
|
|
16534
|
+
"addons.listFrameworkPackages": {
|
|
16466
16535
|
capName: "addons",
|
|
16467
16536
|
capScope: "system",
|
|
16468
16537
|
addonId: null,
|
|
16469
16538
|
access: "view"
|
|
16470
16539
|
},
|
|
16471
|
-
"addons.
|
|
16540
|
+
"addons.listJobs": {
|
|
16472
16541
|
capName: "addons",
|
|
16473
16542
|
capScope: "system",
|
|
16474
16543
|
addonId: null,
|
|
@@ -16552,7 +16621,7 @@ Object.freeze({
|
|
|
16552
16621
|
addonId: null,
|
|
16553
16622
|
access: "create"
|
|
16554
16623
|
},
|
|
16555
|
-
"addons.
|
|
16624
|
+
"addons.startJob": {
|
|
16556
16625
|
capName: "addons",
|
|
16557
16626
|
capScope: "system",
|
|
16558
16627
|
addonId: null,
|
|
@@ -20539,6 +20608,32 @@ Object.freeze({
|
|
|
20539
20608
|
"network-access": "ingress",
|
|
20540
20609
|
"smtp-provider": "email"
|
|
20541
20610
|
});
|
|
20611
|
+
var frameworkSwapPackageSchema = object({
|
|
20612
|
+
name: string(),
|
|
20613
|
+
stagedPath: string(),
|
|
20614
|
+
backupPath: string(),
|
|
20615
|
+
toVersion: string(),
|
|
20616
|
+
fromVersion: string().nullable()
|
|
20617
|
+
});
|
|
20618
|
+
object({
|
|
20619
|
+
jobId: string(),
|
|
20620
|
+
taskId: string(),
|
|
20621
|
+
packages: array(frameworkSwapPackageSchema),
|
|
20622
|
+
requestedAtMs: number(),
|
|
20623
|
+
schemaVersion: literal(1)
|
|
20624
|
+
});
|
|
20625
|
+
object({
|
|
20626
|
+
jobId: string(),
|
|
20627
|
+
taskId: string(),
|
|
20628
|
+
backups: array(object({
|
|
20629
|
+
name: string(),
|
|
20630
|
+
backupPath: string(),
|
|
20631
|
+
livePath: string()
|
|
20632
|
+
})),
|
|
20633
|
+
appliedAtMs: number(),
|
|
20634
|
+
bootAttempts: number(),
|
|
20635
|
+
schemaVersion: literal(1)
|
|
20636
|
+
});
|
|
20542
20637
|
//#endregion
|
|
20543
20638
|
Object.defineProperty(exports, "BaseAddon", {
|
|
20544
20639
|
enumerable: true,
|
|
@@ -5130,14 +5130,15 @@ var EventCategory = /* @__PURE__ */ function(EventCategory) {
|
|
|
5130
5130
|
EventCategory["DeviceSleeping"] = "device.sleeping";
|
|
5131
5131
|
EventCategory["RetentionCleanup"] = "retention.cleanup";
|
|
5132
5132
|
/**
|
|
5133
|
-
*
|
|
5134
|
-
*
|
|
5135
|
-
*
|
|
5136
|
-
* to
|
|
5137
|
-
*
|
|
5138
|
-
* Spec: docs/superpowers/specs/2026-05-21-addons-bulk-update-progress-design.md
|
|
5133
|
+
* Legacy bulk-update progress snapshot (payload `BulkUpdateState`). No longer
|
|
5134
|
+
* emitted — F3 removed the coordinator that produced it; "Update all" now runs
|
|
5135
|
+
* as one lifecycle engine job (`AddonsJobProgress`/`AddonsJobLog`). Retained
|
|
5136
|
+
* (with `BulkUpdateState`) only to avoid regenerating the event maps; removed
|
|
5137
|
+
* in F4 once live bulk progress is re-implemented over the engine events.
|
|
5139
5138
|
*/
|
|
5140
5139
|
EventCategory["AddonsBulkUpdateProgress"] = "addons.bulk-update-progress";
|
|
5140
|
+
EventCategory["AddonsJobProgress"] = "addons.job-progress";
|
|
5141
|
+
EventCategory["AddonsJobLog"] = "addons.job-log";
|
|
5141
5142
|
/**
|
|
5142
5143
|
* A container's child visibility toggled (hidden/shown). Emitted by the
|
|
5143
5144
|
* `accessories` cap when a child device is hidden or revealed.
|
|
@@ -16018,6 +16019,69 @@ method(_void(), array(IntegrationWithStateSchema)), method(object({ id: string()
|
|
|
16018
16019
|
kind: "mutation",
|
|
16019
16020
|
auth: "admin"
|
|
16020
16021
|
});
|
|
16022
|
+
var jobKindSchema = _enum([
|
|
16023
|
+
"install",
|
|
16024
|
+
"update",
|
|
16025
|
+
"uninstall",
|
|
16026
|
+
"restart"
|
|
16027
|
+
]);
|
|
16028
|
+
var taskPhaseSchema = _enum([
|
|
16029
|
+
"queued",
|
|
16030
|
+
"fetching",
|
|
16031
|
+
"staged",
|
|
16032
|
+
"validating",
|
|
16033
|
+
"applying",
|
|
16034
|
+
"restarting",
|
|
16035
|
+
"applied",
|
|
16036
|
+
"done",
|
|
16037
|
+
"failed",
|
|
16038
|
+
"skipped"
|
|
16039
|
+
]);
|
|
16040
|
+
var taskTargetSchema = _enum(["framework", "addon"]);
|
|
16041
|
+
var taskLogEntrySchema = object({
|
|
16042
|
+
tsMs: number(),
|
|
16043
|
+
nodeId: string(),
|
|
16044
|
+
packageName: string(),
|
|
16045
|
+
phase: taskPhaseSchema,
|
|
16046
|
+
message: string()
|
|
16047
|
+
});
|
|
16048
|
+
var lifecycleTaskSchema = object({
|
|
16049
|
+
taskId: string(),
|
|
16050
|
+
nodeId: string(),
|
|
16051
|
+
packageName: string(),
|
|
16052
|
+
fromVersion: string().nullable(),
|
|
16053
|
+
toVersion: string(),
|
|
16054
|
+
target: taskTargetSchema,
|
|
16055
|
+
phase: taskPhaseSchema,
|
|
16056
|
+
stagedPath: string().nullable(),
|
|
16057
|
+
attempts: number(),
|
|
16058
|
+
steps: array(taskLogEntrySchema),
|
|
16059
|
+
error: string().nullable(),
|
|
16060
|
+
startedAtMs: number().nullable(),
|
|
16061
|
+
finishedAtMs: number().nullable()
|
|
16062
|
+
});
|
|
16063
|
+
var lifecycleJobStateSchema = _enum([
|
|
16064
|
+
"running",
|
|
16065
|
+
"completed",
|
|
16066
|
+
"failed",
|
|
16067
|
+
"partially-failed",
|
|
16068
|
+
"cancelled"
|
|
16069
|
+
]);
|
|
16070
|
+
var lifecycleJobScopeSchema = _enum([
|
|
16071
|
+
"single",
|
|
16072
|
+
"bulk",
|
|
16073
|
+
"cluster"
|
|
16074
|
+
]);
|
|
16075
|
+
var lifecycleJobSchema = object({
|
|
16076
|
+
jobId: string(),
|
|
16077
|
+
kind: jobKindSchema,
|
|
16078
|
+
createdAtMs: number(),
|
|
16079
|
+
createdBy: string(),
|
|
16080
|
+
scope: lifecycleJobScopeSchema,
|
|
16081
|
+
tasks: array(lifecycleTaskSchema),
|
|
16082
|
+
state: lifecycleJobStateSchema,
|
|
16083
|
+
schemaVersion: literal(1)
|
|
16084
|
+
});
|
|
16021
16085
|
/**
|
|
16022
16086
|
* addons — system-scoped singleton capability for addon package
|
|
16023
16087
|
* management (install, update, configure, restart) and per-addon log
|
|
@@ -16200,7 +16264,7 @@ var BulkUpdatePhaseSchema = _enum([
|
|
|
16200
16264
|
"restarting",
|
|
16201
16265
|
"finalizing"
|
|
16202
16266
|
]);
|
|
16203
|
-
|
|
16267
|
+
object({
|
|
16204
16268
|
id: string(),
|
|
16205
16269
|
nodeId: string(),
|
|
16206
16270
|
startedAtMs: number(),
|
|
@@ -16303,20 +16367,7 @@ method(_void(), array(AddonListItemSchema).readonly()), method(object({
|
|
|
16303
16367
|
}), UpdateFrameworkPackageResultSchema, {
|
|
16304
16368
|
kind: "mutation",
|
|
16305
16369
|
auth: "admin"
|
|
16306
|
-
}), method(object({
|
|
16307
|
-
nodeId: string(),
|
|
16308
|
-
items: array(object({
|
|
16309
|
-
name: string(),
|
|
16310
|
-
version: string(),
|
|
16311
|
-
isSystem: boolean()
|
|
16312
|
-
})).readonly()
|
|
16313
|
-
}), object({ id: string() }), {
|
|
16314
|
-
kind: "mutation",
|
|
16315
|
-
auth: "admin"
|
|
16316
|
-
}), method(object({ id: string() }), BulkUpdateStateSchema.nullable(), { auth: "admin" }), method(object({ id: string() }), object({ cancelled: boolean() }), {
|
|
16317
|
-
kind: "mutation",
|
|
16318
|
-
auth: "admin"
|
|
16319
|
-
}), method(object({ nodeId: string().optional() }), array(BulkUpdateStateSchema).readonly(), { auth: "admin" }), method(object({ name: string() }), array(PackageVersionInfoSchema).readonly()), method(object({ addonId: string() }), RestartAddonResultSchema, {
|
|
16370
|
+
}), method(object({ name: string() }), array(PackageVersionInfoSchema).readonly()), method(object({ addonId: string() }), RestartAddonResultSchema, {
|
|
16320
16371
|
kind: "mutation",
|
|
16321
16372
|
auth: "admin"
|
|
16322
16373
|
}), method(object({ packageName: string() }), object({ success: literal(true) }), {
|
|
@@ -16338,6 +16389,24 @@ method(_void(), array(AddonListItemSchema).readonly()), method(object({
|
|
|
16338
16389
|
kind: "mutation",
|
|
16339
16390
|
auth: "admin"
|
|
16340
16391
|
}), method(CustomActionInputSchema, unknown(), { kind: "mutation" }), method(object({
|
|
16392
|
+
kind: _enum([
|
|
16393
|
+
"install",
|
|
16394
|
+
"update",
|
|
16395
|
+
"uninstall",
|
|
16396
|
+
"restart"
|
|
16397
|
+
]),
|
|
16398
|
+
targets: array(object({
|
|
16399
|
+
name: string().min(1),
|
|
16400
|
+
version: string().min(1)
|
|
16401
|
+
})).min(1),
|
|
16402
|
+
nodeIds: array(string()).optional()
|
|
16403
|
+
}), object({ jobId: string() }), {
|
|
16404
|
+
kind: "mutation",
|
|
16405
|
+
auth: "admin"
|
|
16406
|
+
}), method(object({ jobId: string() }), lifecycleJobSchema.nullable(), { auth: "admin" }), method(object({ activeOnly: boolean().optional() }), array(lifecycleJobSchema), { auth: "admin" }), method(object({ jobId: string() }), object({ cancelled: boolean() }), {
|
|
16407
|
+
kind: "mutation",
|
|
16408
|
+
auth: "admin"
|
|
16409
|
+
}), method(object({
|
|
16341
16410
|
addonId: string(),
|
|
16342
16411
|
level: LogLevelSchema$1.optional()
|
|
16343
16412
|
}), LogStreamEntrySchema, { kind: "subscription" });
|
|
@@ -16378,7 +16447,7 @@ Object.freeze({
|
|
|
16378
16447
|
addonId: null,
|
|
16379
16448
|
access: "create"
|
|
16380
16449
|
},
|
|
16381
|
-
"addons.
|
|
16450
|
+
"addons.cancelJob": {
|
|
16382
16451
|
capName: "addons",
|
|
16383
16452
|
capScope: "system",
|
|
16384
16453
|
addonId: null,
|
|
@@ -16408,7 +16477,7 @@ Object.freeze({
|
|
|
16408
16477
|
addonId: null,
|
|
16409
16478
|
access: "view"
|
|
16410
16479
|
},
|
|
16411
|
-
"addons.
|
|
16480
|
+
"addons.getJob": {
|
|
16412
16481
|
capName: "addons",
|
|
16413
16482
|
capScope: "system",
|
|
16414
16483
|
addonId: null,
|
|
@@ -16456,19 +16525,19 @@ Object.freeze({
|
|
|
16456
16525
|
addonId: null,
|
|
16457
16526
|
access: "view"
|
|
16458
16527
|
},
|
|
16459
|
-
"addons.
|
|
16528
|
+
"addons.listCapabilityProviders": {
|
|
16460
16529
|
capName: "addons",
|
|
16461
16530
|
capScope: "system",
|
|
16462
16531
|
addonId: null,
|
|
16463
16532
|
access: "view"
|
|
16464
16533
|
},
|
|
16465
|
-
"addons.
|
|
16534
|
+
"addons.listFrameworkPackages": {
|
|
16466
16535
|
capName: "addons",
|
|
16467
16536
|
capScope: "system",
|
|
16468
16537
|
addonId: null,
|
|
16469
16538
|
access: "view"
|
|
16470
16539
|
},
|
|
16471
|
-
"addons.
|
|
16540
|
+
"addons.listJobs": {
|
|
16472
16541
|
capName: "addons",
|
|
16473
16542
|
capScope: "system",
|
|
16474
16543
|
addonId: null,
|
|
@@ -16552,7 +16621,7 @@ Object.freeze({
|
|
|
16552
16621
|
addonId: null,
|
|
16553
16622
|
access: "create"
|
|
16554
16623
|
},
|
|
16555
|
-
"addons.
|
|
16624
|
+
"addons.startJob": {
|
|
16556
16625
|
capName: "addons",
|
|
16557
16626
|
capScope: "system",
|
|
16558
16627
|
addonId: null,
|
|
@@ -20539,5 +20608,31 @@ Object.freeze({
|
|
|
20539
20608
|
"network-access": "ingress",
|
|
20540
20609
|
"smtp-provider": "email"
|
|
20541
20610
|
});
|
|
20611
|
+
var frameworkSwapPackageSchema = object({
|
|
20612
|
+
name: string(),
|
|
20613
|
+
stagedPath: string(),
|
|
20614
|
+
backupPath: string(),
|
|
20615
|
+
toVersion: string(),
|
|
20616
|
+
fromVersion: string().nullable()
|
|
20617
|
+
});
|
|
20618
|
+
object({
|
|
20619
|
+
jobId: string(),
|
|
20620
|
+
taskId: string(),
|
|
20621
|
+
packages: array(frameworkSwapPackageSchema),
|
|
20622
|
+
requestedAtMs: number(),
|
|
20623
|
+
schemaVersion: literal(1)
|
|
20624
|
+
});
|
|
20625
|
+
object({
|
|
20626
|
+
jobId: string(),
|
|
20627
|
+
taskId: string(),
|
|
20628
|
+
backups: array(object({
|
|
20629
|
+
name: string(),
|
|
20630
|
+
backupPath: string(),
|
|
20631
|
+
livePath: string()
|
|
20632
|
+
})),
|
|
20633
|
+
appliedAtMs: number(),
|
|
20634
|
+
bootAttempts: number(),
|
|
20635
|
+
schemaVersion: literal(1)
|
|
20636
|
+
});
|
|
20542
20637
|
//#endregion
|
|
20543
20638
|
export { networkAccessCapability as a, array as c, literal as d, number as f, defineCustomActions as i, boolean as l, string as m, EventCategory as n, turnProviderCapability as o, object as p, customAction as r, _enum as s, BaseAddon as t, discriminatedUnion as u };
|
|
@@ -1,7 +1,38 @@
|
|
|
1
1
|
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
2
|
-
|
|
2
|
+
//#region \0rolldown/runtime.js
|
|
3
|
+
var __create = Object.create;
|
|
4
|
+
var __defProp = Object.defineProperty;
|
|
5
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
6
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
7
|
+
var __getProtoOf = Object.getPrototypeOf;
|
|
8
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
9
|
+
var __copyProps = (to, from, except, desc) => {
|
|
10
|
+
if (from && typeof from === "object" || typeof from === "function") for (var keys = __getOwnPropNames(from), i = 0, n = keys.length, key; i < n; i++) {
|
|
11
|
+
key = keys[i];
|
|
12
|
+
if (!__hasOwnProp.call(to, key) && key !== except) __defProp(to, key, {
|
|
13
|
+
get: ((k) => from[k]).bind(null, key),
|
|
14
|
+
enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable
|
|
15
|
+
});
|
|
16
|
+
}
|
|
17
|
+
return to;
|
|
18
|
+
};
|
|
19
|
+
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", {
|
|
20
|
+
value: mod,
|
|
21
|
+
enumerable: true
|
|
22
|
+
}) : target, mod));
|
|
23
|
+
//#endregion
|
|
24
|
+
const require_dist = require("../dist-BaLJK4dE.js");
|
|
25
|
+
let node_path = require("node:path");
|
|
26
|
+
node_path = __toESM(node_path);
|
|
3
27
|
let node_crypto = require("node:crypto");
|
|
4
28
|
let node_child_process = require("node:child_process");
|
|
29
|
+
let node_fs = require("node:fs");
|
|
30
|
+
node_fs = __toESM(node_fs);
|
|
31
|
+
let node_fs_promises = require("node:fs/promises");
|
|
32
|
+
node_fs_promises = __toESM(node_fs_promises);
|
|
33
|
+
let node_os = require("node:os");
|
|
34
|
+
node_os = __toESM(node_os);
|
|
35
|
+
let node_stream_promises = require("node:stream/promises");
|
|
5
36
|
//#region src/tunnel/cloudflare-tunnel.ts
|
|
6
37
|
/**
|
|
7
38
|
* Direct child_process.spawn() driver for the `cloudflared` binary.
|
|
@@ -23,19 +54,23 @@ var CloudflareTunnelService = class CloudflareTunnelService {
|
|
|
23
54
|
config;
|
|
24
55
|
logger;
|
|
25
56
|
eventBus;
|
|
57
|
+
resolveCloudflaredBin;
|
|
26
58
|
id = "cloudflare-tunnel";
|
|
27
59
|
type = "cloudflare";
|
|
28
60
|
endpoint = null;
|
|
29
61
|
lastError;
|
|
30
62
|
child = null;
|
|
63
|
+
/** Resolved cloudflared path/command (set on first start, reused on restart). */
|
|
64
|
+
cloudflaredBin = "cloudflared";
|
|
31
65
|
restartCount = 0;
|
|
32
66
|
intentionalStop = false;
|
|
33
67
|
static MAX_RESTARTS = 5;
|
|
34
68
|
static STOP_GRACE_MS = 5e3;
|
|
35
|
-
constructor(config, logger, eventBus) {
|
|
69
|
+
constructor(config, logger, eventBus, resolveCloudflaredBin = async () => "cloudflared") {
|
|
36
70
|
this.config = config;
|
|
37
71
|
this.logger = logger;
|
|
38
72
|
this.eventBus = eventBus;
|
|
73
|
+
this.resolveCloudflaredBin = resolveCloudflaredBin;
|
|
39
74
|
}
|
|
40
75
|
async start() {
|
|
41
76
|
this.logger.info("Starting Cloudflare tunnel", {
|
|
@@ -76,6 +111,18 @@ var CloudflareTunnelService = class CloudflareTunnelService {
|
|
|
76
111
|
this.intentionalStop = false;
|
|
77
112
|
this.restartCount = 0;
|
|
78
113
|
this.lastError = void 0;
|
|
114
|
+
try {
|
|
115
|
+
this.cloudflaredBin = await this.resolveCloudflaredBin();
|
|
116
|
+
} catch (err) {
|
|
117
|
+
this.logger.error("Failed to provision cloudflared binary", {
|
|
118
|
+
meta: { error: err instanceof Error ? err.message : String(err) },
|
|
119
|
+
tags: {
|
|
120
|
+
topic: "tunnel",
|
|
121
|
+
phase: "provision-error"
|
|
122
|
+
}
|
|
123
|
+
});
|
|
124
|
+
throw err;
|
|
125
|
+
}
|
|
79
126
|
this.spawnChild();
|
|
80
127
|
const placeholderHost = this.config.mode === "custom" ? this.config.customHostname : "pending.trycloudflare.com";
|
|
81
128
|
this.endpoint = {
|
|
@@ -192,7 +239,7 @@ var CloudflareTunnelService = class CloudflareTunnelService {
|
|
|
192
239
|
const args = [...debugFlags, ...tunnelArgs];
|
|
193
240
|
let child;
|
|
194
241
|
try {
|
|
195
|
-
child = (0, node_child_process.spawn)(
|
|
242
|
+
child = (0, node_child_process.spawn)(this.cloudflaredBin, args, { stdio: [
|
|
196
243
|
"ignore",
|
|
197
244
|
"pipe",
|
|
198
245
|
"pipe"
|
|
@@ -340,6 +387,130 @@ var CloudflareTunnelService = class CloudflareTunnelService {
|
|
|
340
387
|
});
|
|
341
388
|
}
|
|
342
389
|
};
|
|
390
|
+
var RELEASE_BASE = "https://github.com/cloudflare/cloudflared/releases/download";
|
|
391
|
+
/**
|
|
392
|
+
* Map a Node `platform`/`arch` to the matching cloudflared release asset.
|
|
393
|
+
* Pure + exported for testing. Throws on an unsupported combination.
|
|
394
|
+
*/
|
|
395
|
+
function cloudflaredAsset(platform, arch) {
|
|
396
|
+
const a = arch === "x64" ? "amd64" : arch === "arm64" ? "arm64" : arch === "arm" ? "arm" : null;
|
|
397
|
+
if (a === null) throw new Error(`cloudflared: unsupported arch '${arch}'`);
|
|
398
|
+
switch (platform) {
|
|
399
|
+
case "linux": return {
|
|
400
|
+
fileName: `cloudflared-linux-${a}`,
|
|
401
|
+
isArchive: false
|
|
402
|
+
};
|
|
403
|
+
case "darwin": return {
|
|
404
|
+
fileName: `cloudflared-darwin-${a === "arm64" ? "amd64" : a}.tgz`,
|
|
405
|
+
isArchive: true
|
|
406
|
+
};
|
|
407
|
+
case "win32": return {
|
|
408
|
+
fileName: `cloudflared-windows-${a}.exe`,
|
|
409
|
+
isArchive: false
|
|
410
|
+
};
|
|
411
|
+
default: throw new Error(`cloudflared: unsupported platform '${platform}'`);
|
|
412
|
+
}
|
|
413
|
+
}
|
|
414
|
+
/** Resolve a working `cloudflared` from PATH, or null if not runnable. */
|
|
415
|
+
async function cloudflaredOnPath() {
|
|
416
|
+
return await runsOk("cloudflared") ? "cloudflared" : null;
|
|
417
|
+
}
|
|
418
|
+
/** True when `<bin> --version` exits 0 (binary present + executable). */
|
|
419
|
+
function runsOk(bin) {
|
|
420
|
+
return new Promise((resolve) => {
|
|
421
|
+
let done = false;
|
|
422
|
+
const finish = (ok) => {
|
|
423
|
+
if (!done) {
|
|
424
|
+
done = true;
|
|
425
|
+
resolve(ok);
|
|
426
|
+
}
|
|
427
|
+
};
|
|
428
|
+
try {
|
|
429
|
+
const child = (0, node_child_process.spawn)(bin, ["--version"], { stdio: "ignore" });
|
|
430
|
+
child.on("error", () => finish(false));
|
|
431
|
+
child.on("exit", (code) => finish(code === 0));
|
|
432
|
+
setTimeout(() => {
|
|
433
|
+
child.kill("SIGKILL");
|
|
434
|
+
finish(false);
|
|
435
|
+
}, 5e3);
|
|
436
|
+
} catch {
|
|
437
|
+
finish(false);
|
|
438
|
+
}
|
|
439
|
+
});
|
|
440
|
+
}
|
|
441
|
+
async function downloadTo(url, dest) {
|
|
442
|
+
const res = await fetch(url, { redirect: "follow" });
|
|
443
|
+
if (!res.ok || !res.body) throw new Error(`cloudflared download failed: HTTP ${res.status} for ${url}`);
|
|
444
|
+
const tmp = `${dest}.partial`;
|
|
445
|
+
await (0, node_stream_promises.pipeline)(res.body, node_fs.createWriteStream(tmp));
|
|
446
|
+
await node_fs_promises.rename(tmp, dest);
|
|
447
|
+
}
|
|
448
|
+
/** Extract the `cloudflared` entry from a downloaded .tgz into `destBin`. */
|
|
449
|
+
async function extractArchive(archivePath, destBin, logger) {
|
|
450
|
+
const dir = node_path.dirname(destBin);
|
|
451
|
+
await new Promise((resolve, reject) => {
|
|
452
|
+
const child = (0, node_child_process.spawn)("tar", [
|
|
453
|
+
"-xzf",
|
|
454
|
+
archivePath,
|
|
455
|
+
"-C",
|
|
456
|
+
dir
|
|
457
|
+
], { stdio: "inherit" });
|
|
458
|
+
child.on("error", reject);
|
|
459
|
+
child.on("exit", (code) => code === 0 ? resolve() : reject(/* @__PURE__ */ new Error(`tar exited ${code}`)));
|
|
460
|
+
});
|
|
461
|
+
if (!node_fs.existsSync(destBin)) logger.warn("cloudflared archive did not yield expected binary name", {
|
|
462
|
+
meta: { destBin },
|
|
463
|
+
tags: {
|
|
464
|
+
topic: "tunnel",
|
|
465
|
+
phase: "extract"
|
|
466
|
+
}
|
|
467
|
+
});
|
|
468
|
+
await node_fs_promises.rm(archivePath, { force: true });
|
|
469
|
+
}
|
|
470
|
+
/**
|
|
471
|
+
* Return a path/command for a runnable `cloudflared`, downloading + caching it
|
|
472
|
+
* on first use. Prefers an existing PATH install; otherwise caches under
|
|
473
|
+
* `binDir`. Throws (with an actionable message) if it cannot be provisioned.
|
|
474
|
+
*/
|
|
475
|
+
async function ensureCloudflared(opts) {
|
|
476
|
+
const onPath = await cloudflaredOnPath();
|
|
477
|
+
if (onPath) return onPath;
|
|
478
|
+
const cached = node_path.join(opts.binDir, node_os.platform() === "win32" ? "cloudflared.exe" : "cloudflared");
|
|
479
|
+
if (node_fs.existsSync(cached) && await runsOk(cached)) return cached;
|
|
480
|
+
const version = opts.version ?? "2025.4.2";
|
|
481
|
+
const asset = cloudflaredAsset(node_os.platform(), node_os.arch());
|
|
482
|
+
const url = `${RELEASE_BASE}/${version}/${asset.fileName}`;
|
|
483
|
+
await node_fs_promises.mkdir(opts.binDir, { recursive: true });
|
|
484
|
+
opts.logger.info("Provisioning cloudflared (not on PATH) — downloading", {
|
|
485
|
+
meta: {
|
|
486
|
+
version,
|
|
487
|
+
asset: asset.fileName,
|
|
488
|
+
dest: cached
|
|
489
|
+
},
|
|
490
|
+
tags: {
|
|
491
|
+
topic: "tunnel",
|
|
492
|
+
phase: "provision"
|
|
493
|
+
}
|
|
494
|
+
});
|
|
495
|
+
if (asset.isArchive) {
|
|
496
|
+
const archive = node_path.join(opts.binDir, asset.fileName);
|
|
497
|
+
await downloadTo(url, archive);
|
|
498
|
+
await extractArchive(archive, cached, opts.logger);
|
|
499
|
+
} else await downloadTo(url, cached);
|
|
500
|
+
await node_fs_promises.chmod(cached, 493);
|
|
501
|
+
if (!await runsOk(cached)) throw new Error(`cloudflared downloaded to ${cached} but is not runnable`);
|
|
502
|
+
opts.logger.info("cloudflared ready", {
|
|
503
|
+
meta: {
|
|
504
|
+
path: cached,
|
|
505
|
+
version
|
|
506
|
+
},
|
|
507
|
+
tags: {
|
|
508
|
+
topic: "tunnel",
|
|
509
|
+
phase: "provision-done"
|
|
510
|
+
}
|
|
511
|
+
});
|
|
512
|
+
return cached;
|
|
513
|
+
}
|
|
343
514
|
//#endregion
|
|
344
515
|
//#region src/tunnel/cloudflare-api.ts
|
|
345
516
|
/**
|
|
@@ -666,6 +837,19 @@ var CloudflareTunnelAddon = class extends require_dist.BaseAddon {
|
|
|
666
837
|
}
|
|
667
838
|
return "127.0.0.1";
|
|
668
839
|
}
|
|
840
|
+
/**
|
|
841
|
+
* Resolve the `cloudflared` binary path once per addon lifetime (PATH install,
|
|
842
|
+
* or a copy downloaded + cached under `<dataDir>/bin`). Memoized so the
|
|
843
|
+
* (possible) download happens at most once, on the first tunnel start.
|
|
844
|
+
*/
|
|
845
|
+
cloudflaredBinPromise;
|
|
846
|
+
resolveCloudflared() {
|
|
847
|
+
this.cloudflaredBinPromise ??= ensureCloudflared({
|
|
848
|
+
binDir: node_path.join(this.ctx.dataDir, "bin"),
|
|
849
|
+
logger: this.ctx.logger
|
|
850
|
+
});
|
|
851
|
+
return this.cloudflaredBinPromise;
|
|
852
|
+
}
|
|
669
853
|
async onInitialize() {
|
|
670
854
|
if (this.config.localPort === 3001) {
|
|
671
855
|
this.ctx.logger.warn("Resetting stale localPort=3001 (Vite admin-ui dev port) → 0 (auto)", { tags: {
|
|
@@ -679,7 +863,7 @@ var CloudflareTunnelAddon = class extends require_dist.BaseAddon {
|
|
|
679
863
|
...this.config,
|
|
680
864
|
localPort: this.resolveLocalPort(),
|
|
681
865
|
localHost
|
|
682
|
-
}, this.ctx.logger, this.ctx.eventBus);
|
|
866
|
+
}, this.ctx.logger, this.ctx.eventBus, () => this.resolveCloudflared());
|
|
683
867
|
this.ctx.logger.info("Cloudflare Tunnel addon initialized", { meta: {
|
|
684
868
|
mode: this.config.mode,
|
|
685
869
|
hasCustomToken: !!this.config.customTunnelToken
|
|
@@ -735,7 +919,7 @@ var CloudflareTunnelAddon = class extends require_dist.BaseAddon {
|
|
|
735
919
|
...this.config,
|
|
736
920
|
localPort: this.resolveLocalPort(),
|
|
737
921
|
localHost
|
|
738
|
-
}, this.ctx.logger, this.ctx.eventBus);
|
|
922
|
+
}, this.ctx.logger, this.ctx.eventBus, () => this.resolveCloudflared());
|
|
739
923
|
if (this.isRunCapable()) {
|
|
740
924
|
this.ctx.logger.info("config changed — (re-)spawning tunnel", {
|
|
741
925
|
meta: {
|
|
@@ -1,6 +1,11 @@
|
|
|
1
|
-
import { a as networkAccessCapability, c as array, d as literal, f as number, i as defineCustomActions, l as boolean, m as string, n as EventCategory, p as object, r as customAction, s as _enum, t as BaseAddon } from "../dist-
|
|
1
|
+
import { a as networkAccessCapability, c as array, d as literal, f as number, i as defineCustomActions, l as boolean, m as string, n as EventCategory, p as object, r as customAction, s as _enum, t as BaseAddon } from "../dist-COIj-4Zk.mjs";
|
|
2
|
+
import * as path from "node:path";
|
|
2
3
|
import { randomUUID } from "node:crypto";
|
|
3
4
|
import { spawn } from "node:child_process";
|
|
5
|
+
import * as fs from "node:fs";
|
|
6
|
+
import * as fsp from "node:fs/promises";
|
|
7
|
+
import * as os from "node:os";
|
|
8
|
+
import { pipeline } from "node:stream/promises";
|
|
4
9
|
//#region src/tunnel/cloudflare-tunnel.ts
|
|
5
10
|
/**
|
|
6
11
|
* Direct child_process.spawn() driver for the `cloudflared` binary.
|
|
@@ -22,19 +27,23 @@ var CloudflareTunnelService = class CloudflareTunnelService {
|
|
|
22
27
|
config;
|
|
23
28
|
logger;
|
|
24
29
|
eventBus;
|
|
30
|
+
resolveCloudflaredBin;
|
|
25
31
|
id = "cloudflare-tunnel";
|
|
26
32
|
type = "cloudflare";
|
|
27
33
|
endpoint = null;
|
|
28
34
|
lastError;
|
|
29
35
|
child = null;
|
|
36
|
+
/** Resolved cloudflared path/command (set on first start, reused on restart). */
|
|
37
|
+
cloudflaredBin = "cloudflared";
|
|
30
38
|
restartCount = 0;
|
|
31
39
|
intentionalStop = false;
|
|
32
40
|
static MAX_RESTARTS = 5;
|
|
33
41
|
static STOP_GRACE_MS = 5e3;
|
|
34
|
-
constructor(config, logger, eventBus) {
|
|
42
|
+
constructor(config, logger, eventBus, resolveCloudflaredBin = async () => "cloudflared") {
|
|
35
43
|
this.config = config;
|
|
36
44
|
this.logger = logger;
|
|
37
45
|
this.eventBus = eventBus;
|
|
46
|
+
this.resolveCloudflaredBin = resolveCloudflaredBin;
|
|
38
47
|
}
|
|
39
48
|
async start() {
|
|
40
49
|
this.logger.info("Starting Cloudflare tunnel", {
|
|
@@ -75,6 +84,18 @@ var CloudflareTunnelService = class CloudflareTunnelService {
|
|
|
75
84
|
this.intentionalStop = false;
|
|
76
85
|
this.restartCount = 0;
|
|
77
86
|
this.lastError = void 0;
|
|
87
|
+
try {
|
|
88
|
+
this.cloudflaredBin = await this.resolveCloudflaredBin();
|
|
89
|
+
} catch (err) {
|
|
90
|
+
this.logger.error("Failed to provision cloudflared binary", {
|
|
91
|
+
meta: { error: err instanceof Error ? err.message : String(err) },
|
|
92
|
+
tags: {
|
|
93
|
+
topic: "tunnel",
|
|
94
|
+
phase: "provision-error"
|
|
95
|
+
}
|
|
96
|
+
});
|
|
97
|
+
throw err;
|
|
98
|
+
}
|
|
78
99
|
this.spawnChild();
|
|
79
100
|
const placeholderHost = this.config.mode === "custom" ? this.config.customHostname : "pending.trycloudflare.com";
|
|
80
101
|
this.endpoint = {
|
|
@@ -191,7 +212,7 @@ var CloudflareTunnelService = class CloudflareTunnelService {
|
|
|
191
212
|
const args = [...debugFlags, ...tunnelArgs];
|
|
192
213
|
let child;
|
|
193
214
|
try {
|
|
194
|
-
child = spawn(
|
|
215
|
+
child = spawn(this.cloudflaredBin, args, { stdio: [
|
|
195
216
|
"ignore",
|
|
196
217
|
"pipe",
|
|
197
218
|
"pipe"
|
|
@@ -339,6 +360,130 @@ var CloudflareTunnelService = class CloudflareTunnelService {
|
|
|
339
360
|
});
|
|
340
361
|
}
|
|
341
362
|
};
|
|
363
|
+
var RELEASE_BASE = "https://github.com/cloudflare/cloudflared/releases/download";
|
|
364
|
+
/**
|
|
365
|
+
* Map a Node `platform`/`arch` to the matching cloudflared release asset.
|
|
366
|
+
* Pure + exported for testing. Throws on an unsupported combination.
|
|
367
|
+
*/
|
|
368
|
+
function cloudflaredAsset(platform, arch) {
|
|
369
|
+
const a = arch === "x64" ? "amd64" : arch === "arm64" ? "arm64" : arch === "arm" ? "arm" : null;
|
|
370
|
+
if (a === null) throw new Error(`cloudflared: unsupported arch '${arch}'`);
|
|
371
|
+
switch (platform) {
|
|
372
|
+
case "linux": return {
|
|
373
|
+
fileName: `cloudflared-linux-${a}`,
|
|
374
|
+
isArchive: false
|
|
375
|
+
};
|
|
376
|
+
case "darwin": return {
|
|
377
|
+
fileName: `cloudflared-darwin-${a === "arm64" ? "amd64" : a}.tgz`,
|
|
378
|
+
isArchive: true
|
|
379
|
+
};
|
|
380
|
+
case "win32": return {
|
|
381
|
+
fileName: `cloudflared-windows-${a}.exe`,
|
|
382
|
+
isArchive: false
|
|
383
|
+
};
|
|
384
|
+
default: throw new Error(`cloudflared: unsupported platform '${platform}'`);
|
|
385
|
+
}
|
|
386
|
+
}
|
|
387
|
+
/** Resolve a working `cloudflared` from PATH, or null if not runnable. */
|
|
388
|
+
async function cloudflaredOnPath() {
|
|
389
|
+
return await runsOk("cloudflared") ? "cloudflared" : null;
|
|
390
|
+
}
|
|
391
|
+
/** True when `<bin> --version` exits 0 (binary present + executable). */
|
|
392
|
+
function runsOk(bin) {
|
|
393
|
+
return new Promise((resolve) => {
|
|
394
|
+
let done = false;
|
|
395
|
+
const finish = (ok) => {
|
|
396
|
+
if (!done) {
|
|
397
|
+
done = true;
|
|
398
|
+
resolve(ok);
|
|
399
|
+
}
|
|
400
|
+
};
|
|
401
|
+
try {
|
|
402
|
+
const child = spawn(bin, ["--version"], { stdio: "ignore" });
|
|
403
|
+
child.on("error", () => finish(false));
|
|
404
|
+
child.on("exit", (code) => finish(code === 0));
|
|
405
|
+
setTimeout(() => {
|
|
406
|
+
child.kill("SIGKILL");
|
|
407
|
+
finish(false);
|
|
408
|
+
}, 5e3);
|
|
409
|
+
} catch {
|
|
410
|
+
finish(false);
|
|
411
|
+
}
|
|
412
|
+
});
|
|
413
|
+
}
|
|
414
|
+
async function downloadTo(url, dest) {
|
|
415
|
+
const res = await fetch(url, { redirect: "follow" });
|
|
416
|
+
if (!res.ok || !res.body) throw new Error(`cloudflared download failed: HTTP ${res.status} for ${url}`);
|
|
417
|
+
const tmp = `${dest}.partial`;
|
|
418
|
+
await pipeline(res.body, fs.createWriteStream(tmp));
|
|
419
|
+
await fsp.rename(tmp, dest);
|
|
420
|
+
}
|
|
421
|
+
/** Extract the `cloudflared` entry from a downloaded .tgz into `destBin`. */
|
|
422
|
+
async function extractArchive(archivePath, destBin, logger) {
|
|
423
|
+
const dir = path.dirname(destBin);
|
|
424
|
+
await new Promise((resolve, reject) => {
|
|
425
|
+
const child = spawn("tar", [
|
|
426
|
+
"-xzf",
|
|
427
|
+
archivePath,
|
|
428
|
+
"-C",
|
|
429
|
+
dir
|
|
430
|
+
], { stdio: "inherit" });
|
|
431
|
+
child.on("error", reject);
|
|
432
|
+
child.on("exit", (code) => code === 0 ? resolve() : reject(/* @__PURE__ */ new Error(`tar exited ${code}`)));
|
|
433
|
+
});
|
|
434
|
+
if (!fs.existsSync(destBin)) logger.warn("cloudflared archive did not yield expected binary name", {
|
|
435
|
+
meta: { destBin },
|
|
436
|
+
tags: {
|
|
437
|
+
topic: "tunnel",
|
|
438
|
+
phase: "extract"
|
|
439
|
+
}
|
|
440
|
+
});
|
|
441
|
+
await fsp.rm(archivePath, { force: true });
|
|
442
|
+
}
|
|
443
|
+
/**
|
|
444
|
+
* Return a path/command for a runnable `cloudflared`, downloading + caching it
|
|
445
|
+
* on first use. Prefers an existing PATH install; otherwise caches under
|
|
446
|
+
* `binDir`. Throws (with an actionable message) if it cannot be provisioned.
|
|
447
|
+
*/
|
|
448
|
+
async function ensureCloudflared(opts) {
|
|
449
|
+
const onPath = await cloudflaredOnPath();
|
|
450
|
+
if (onPath) return onPath;
|
|
451
|
+
const cached = path.join(opts.binDir, os.platform() === "win32" ? "cloudflared.exe" : "cloudflared");
|
|
452
|
+
if (fs.existsSync(cached) && await runsOk(cached)) return cached;
|
|
453
|
+
const version = opts.version ?? "2025.4.2";
|
|
454
|
+
const asset = cloudflaredAsset(os.platform(), os.arch());
|
|
455
|
+
const url = `${RELEASE_BASE}/${version}/${asset.fileName}`;
|
|
456
|
+
await fsp.mkdir(opts.binDir, { recursive: true });
|
|
457
|
+
opts.logger.info("Provisioning cloudflared (not on PATH) — downloading", {
|
|
458
|
+
meta: {
|
|
459
|
+
version,
|
|
460
|
+
asset: asset.fileName,
|
|
461
|
+
dest: cached
|
|
462
|
+
},
|
|
463
|
+
tags: {
|
|
464
|
+
topic: "tunnel",
|
|
465
|
+
phase: "provision"
|
|
466
|
+
}
|
|
467
|
+
});
|
|
468
|
+
if (asset.isArchive) {
|
|
469
|
+
const archive = path.join(opts.binDir, asset.fileName);
|
|
470
|
+
await downloadTo(url, archive);
|
|
471
|
+
await extractArchive(archive, cached, opts.logger);
|
|
472
|
+
} else await downloadTo(url, cached);
|
|
473
|
+
await fsp.chmod(cached, 493);
|
|
474
|
+
if (!await runsOk(cached)) throw new Error(`cloudflared downloaded to ${cached} but is not runnable`);
|
|
475
|
+
opts.logger.info("cloudflared ready", {
|
|
476
|
+
meta: {
|
|
477
|
+
path: cached,
|
|
478
|
+
version
|
|
479
|
+
},
|
|
480
|
+
tags: {
|
|
481
|
+
topic: "tunnel",
|
|
482
|
+
phase: "provision-done"
|
|
483
|
+
}
|
|
484
|
+
});
|
|
485
|
+
return cached;
|
|
486
|
+
}
|
|
342
487
|
//#endregion
|
|
343
488
|
//#region src/tunnel/cloudflare-api.ts
|
|
344
489
|
/**
|
|
@@ -665,6 +810,19 @@ var CloudflareTunnelAddon = class extends BaseAddon {
|
|
|
665
810
|
}
|
|
666
811
|
return "127.0.0.1";
|
|
667
812
|
}
|
|
813
|
+
/**
|
|
814
|
+
* Resolve the `cloudflared` binary path once per addon lifetime (PATH install,
|
|
815
|
+
* or a copy downloaded + cached under `<dataDir>/bin`). Memoized so the
|
|
816
|
+
* (possible) download happens at most once, on the first tunnel start.
|
|
817
|
+
*/
|
|
818
|
+
cloudflaredBinPromise;
|
|
819
|
+
resolveCloudflared() {
|
|
820
|
+
this.cloudflaredBinPromise ??= ensureCloudflared({
|
|
821
|
+
binDir: path.join(this.ctx.dataDir, "bin"),
|
|
822
|
+
logger: this.ctx.logger
|
|
823
|
+
});
|
|
824
|
+
return this.cloudflaredBinPromise;
|
|
825
|
+
}
|
|
668
826
|
async onInitialize() {
|
|
669
827
|
if (this.config.localPort === 3001) {
|
|
670
828
|
this.ctx.logger.warn("Resetting stale localPort=3001 (Vite admin-ui dev port) → 0 (auto)", { tags: {
|
|
@@ -678,7 +836,7 @@ var CloudflareTunnelAddon = class extends BaseAddon {
|
|
|
678
836
|
...this.config,
|
|
679
837
|
localPort: this.resolveLocalPort(),
|
|
680
838
|
localHost
|
|
681
|
-
}, this.ctx.logger, this.ctx.eventBus);
|
|
839
|
+
}, this.ctx.logger, this.ctx.eventBus, () => this.resolveCloudflared());
|
|
682
840
|
this.ctx.logger.info("Cloudflare Tunnel addon initialized", { meta: {
|
|
683
841
|
mode: this.config.mode,
|
|
684
842
|
hasCustomToken: !!this.config.customTunnelToken
|
|
@@ -734,7 +892,7 @@ var CloudflareTunnelAddon = class extends BaseAddon {
|
|
|
734
892
|
...this.config,
|
|
735
893
|
localPort: this.resolveLocalPort(),
|
|
736
894
|
localHost
|
|
737
|
-
}, this.ctx.logger, this.ctx.eventBus);
|
|
895
|
+
}, this.ctx.logger, this.ctx.eventBus, () => this.resolveCloudflared());
|
|
738
896
|
if (this.isRunCapable()) {
|
|
739
897
|
this.ctx.logger.info("config changed — (re-)spawning tunnel", {
|
|
740
898
|
meta: {
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
2
|
-
const require_dist = require("../dist-
|
|
2
|
+
const require_dist = require("../dist-BaLJK4dE.js");
|
|
3
3
|
//#region src/turn/cloudflare-turn.ts
|
|
4
4
|
/**
|
|
5
5
|
* Cloudflare returns ICE servers in several flavours depending on which
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { d as literal, f as number, i as defineCustomActions, l as boolean, m as string, o as turnProviderCapability, p as object, r as customAction, t as BaseAddon, u as discriminatedUnion } from "../dist-
|
|
1
|
+
import { d as literal, f as number, i as defineCustomActions, l as boolean, m as string, o as turnProviderCapability, p as object, r as customAction, t as BaseAddon, u as discriminatedUnion } from "../dist-COIj-4Zk.mjs";
|
|
2
2
|
//#region src/turn/cloudflare-turn.ts
|
|
3
3
|
/**
|
|
4
4
|
* Cloudflare returns ICE servers in several flavours depending on which
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@camstack/addon-cloudflare",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.4",
|
|
4
4
|
"description": "Cloudflare bundle — Tunnel (network-access) + TURN relay (turn-provider). Multi-entry npm package shipping 2 addons under a single bundle.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"camstack",
|