@camstack/addon-cloudflare-tunnel 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/chunk-HHH5U2SN.mjs +174 -0
- package/dist/chunk-HHH5U2SN.mjs.map +1 -0
- package/dist/cloudflare-tunnel.addon.d.mts +39 -0
- package/dist/cloudflare-tunnel.addon.d.ts +39 -0
- package/dist/cloudflare-tunnel.addon.js +199 -0
- package/dist/cloudflare-tunnel.addon.js.map +1 -0
- package/dist/cloudflare-tunnel.addon.mjs +7 -0
- package/dist/cloudflare-tunnel.addon.mjs.map +1 -0
- package/dist/index.d.mts +2 -39
- package/dist/index.d.ts +2 -39
- package/dist/index.mjs +4 -168
- package/dist/index.mjs.map +1 -1
- package/package.json +4 -3
|
@@ -0,0 +1,174 @@
|
|
|
1
|
+
// src/cloudflare-tunnel.ts
|
|
2
|
+
import { randomUUID } from "crypto";
|
|
3
|
+
var CloudflareTunnelService = class {
|
|
4
|
+
constructor(config, logger, eventBus, processManager) {
|
|
5
|
+
this.config = config;
|
|
6
|
+
this.logger = logger;
|
|
7
|
+
this.eventBus = eventBus;
|
|
8
|
+
this.processManager = processManager;
|
|
9
|
+
}
|
|
10
|
+
id = "cloudflare-tunnel";
|
|
11
|
+
type = "cloudflare";
|
|
12
|
+
endpoint = null;
|
|
13
|
+
processId = null;
|
|
14
|
+
async start() {
|
|
15
|
+
this.logger.info(`Starting Cloudflare tunnel (${this.config.mode})`);
|
|
16
|
+
const processConfig = {
|
|
17
|
+
id: "cloudflared-tunnel",
|
|
18
|
+
label: "Cloudflare Tunnel",
|
|
19
|
+
command: "cloudflared",
|
|
20
|
+
args: this.config.mode === "quick" ? ["tunnel", "--url", `http://localhost:${this.config.localPort}`] : ["tunnel", "run", "--token", this.config.namedTunnelToken],
|
|
21
|
+
autoRestart: true,
|
|
22
|
+
maxRestarts: 5
|
|
23
|
+
};
|
|
24
|
+
this.processManager.register(processConfig);
|
|
25
|
+
await this.processManager.start("cloudflared-tunnel");
|
|
26
|
+
this.processId = "cloudflared-tunnel";
|
|
27
|
+
const publicUrl = this.config.mode === "named" ? "https://tunnel.example.com" : "https://pending.trycloudflare.com";
|
|
28
|
+
this.endpoint = {
|
|
29
|
+
id: "cloudflare-tunnel",
|
|
30
|
+
type: "tunnel",
|
|
31
|
+
provider: "cloudflare",
|
|
32
|
+
url: publicUrl,
|
|
33
|
+
internal: false,
|
|
34
|
+
capabilities: {
|
|
35
|
+
supportsWebRTC: false,
|
|
36
|
+
supportsWebSocket: true,
|
|
37
|
+
supportsSSE: true
|
|
38
|
+
},
|
|
39
|
+
priority: 50,
|
|
40
|
+
status: "online"
|
|
41
|
+
};
|
|
42
|
+
this.eventBus.emit({
|
|
43
|
+
id: randomUUID(),
|
|
44
|
+
timestamp: /* @__PURE__ */ new Date(),
|
|
45
|
+
source: { type: "addon", id: "cloudflare-tunnel" },
|
|
46
|
+
category: "network.tunnel.started",
|
|
47
|
+
data: { url: publicUrl }
|
|
48
|
+
});
|
|
49
|
+
return this.endpoint;
|
|
50
|
+
}
|
|
51
|
+
async stop() {
|
|
52
|
+
if (this.processId) {
|
|
53
|
+
await this.processManager.stop(this.processId);
|
|
54
|
+
}
|
|
55
|
+
this.endpoint = null;
|
|
56
|
+
this.eventBus.emit({
|
|
57
|
+
id: randomUUID(),
|
|
58
|
+
timestamp: /* @__PURE__ */ new Date(),
|
|
59
|
+
source: { type: "addon", id: "cloudflare-tunnel" },
|
|
60
|
+
category: "network.tunnel.stopped",
|
|
61
|
+
data: {}
|
|
62
|
+
});
|
|
63
|
+
}
|
|
64
|
+
getEndpoint() {
|
|
65
|
+
return this.endpoint;
|
|
66
|
+
}
|
|
67
|
+
getStatus() {
|
|
68
|
+
return {
|
|
69
|
+
connected: this.endpoint !== null,
|
|
70
|
+
publicUrl: this.endpoint?.url
|
|
71
|
+
};
|
|
72
|
+
}
|
|
73
|
+
};
|
|
74
|
+
|
|
75
|
+
// src/cloudflare-tunnel.addon.ts
|
|
76
|
+
var CloudflareTunnelAddon = class {
|
|
77
|
+
manifest = {
|
|
78
|
+
id: "cloudflare-tunnel",
|
|
79
|
+
name: "Cloudflare Tunnel",
|
|
80
|
+
version: "1.0.0",
|
|
81
|
+
capabilities: ["network-access"]
|
|
82
|
+
};
|
|
83
|
+
service = null;
|
|
84
|
+
currentConfig = {
|
|
85
|
+
mode: "quick",
|
|
86
|
+
localPort: 3e3
|
|
87
|
+
};
|
|
88
|
+
async initialize(context) {
|
|
89
|
+
this.currentConfig = {
|
|
90
|
+
mode: context.addonConfig.mode ?? this.currentConfig.mode,
|
|
91
|
+
namedTunnelToken: context.addonConfig.namedTunnelToken ?? this.currentConfig.namedTunnelToken,
|
|
92
|
+
localPort: context.addonConfig.localPort ?? this.currentConfig.localPort
|
|
93
|
+
};
|
|
94
|
+
context.logger.info("Cloudflare Tunnel addon initialized");
|
|
95
|
+
}
|
|
96
|
+
async shutdown() {
|
|
97
|
+
await this.service?.stop();
|
|
98
|
+
this.service = null;
|
|
99
|
+
}
|
|
100
|
+
/** Provide the ProcessManagerService to enable tunnel management */
|
|
101
|
+
setProcessManager(processManager, config, context) {
|
|
102
|
+
this.service = new CloudflareTunnelService(
|
|
103
|
+
config,
|
|
104
|
+
context.logger,
|
|
105
|
+
context.eventBus,
|
|
106
|
+
processManager
|
|
107
|
+
);
|
|
108
|
+
}
|
|
109
|
+
getService() {
|
|
110
|
+
if (!this.service) throw new Error("Cloudflare Tunnel not initialized");
|
|
111
|
+
return this.service;
|
|
112
|
+
}
|
|
113
|
+
getCapabilityProvider(name) {
|
|
114
|
+
if (name === "network-access" && this.service) {
|
|
115
|
+
return this.service;
|
|
116
|
+
}
|
|
117
|
+
return null;
|
|
118
|
+
}
|
|
119
|
+
getConfigSchema() {
|
|
120
|
+
return {
|
|
121
|
+
sections: [
|
|
122
|
+
{
|
|
123
|
+
id: "tunnel",
|
|
124
|
+
title: "Tunnel Settings",
|
|
125
|
+
fields: [
|
|
126
|
+
{
|
|
127
|
+
type: "select",
|
|
128
|
+
key: "mode",
|
|
129
|
+
label: "Tunnel Mode",
|
|
130
|
+
description: "Quick mode creates a temporary public URL; Named mode uses a persistent named tunnel with your Cloudflare account.",
|
|
131
|
+
options: [
|
|
132
|
+
{ value: "quick", label: "Quick Tunnel", description: "Temporary public URL, no Cloudflare account required" },
|
|
133
|
+
{ value: "named", label: "Named Tunnel", description: "Persistent tunnel using a Cloudflare tunnel token" }
|
|
134
|
+
]
|
|
135
|
+
},
|
|
136
|
+
{
|
|
137
|
+
type: "password",
|
|
138
|
+
key: "namedTunnelToken",
|
|
139
|
+
label: "Tunnel Token",
|
|
140
|
+
description: "Token from your Cloudflare Zero Trust dashboard (required for Named Tunnel mode)",
|
|
141
|
+
showToggle: true,
|
|
142
|
+
showWhen: { field: "mode", equals: "named" }
|
|
143
|
+
},
|
|
144
|
+
{
|
|
145
|
+
type: "number",
|
|
146
|
+
key: "localPort",
|
|
147
|
+
label: "Local Port",
|
|
148
|
+
description: "The local port that the tunnel will expose publicly",
|
|
149
|
+
min: 1,
|
|
150
|
+
max: 65535,
|
|
151
|
+
step: 1
|
|
152
|
+
}
|
|
153
|
+
]
|
|
154
|
+
}
|
|
155
|
+
]
|
|
156
|
+
};
|
|
157
|
+
}
|
|
158
|
+
getConfig() {
|
|
159
|
+
return { ...this.currentConfig };
|
|
160
|
+
}
|
|
161
|
+
async onConfigChange(config) {
|
|
162
|
+
this.currentConfig = {
|
|
163
|
+
mode: config.mode ?? this.currentConfig.mode,
|
|
164
|
+
namedTunnelToken: config.namedTunnelToken ?? this.currentConfig.namedTunnelToken,
|
|
165
|
+
localPort: config.localPort ?? this.currentConfig.localPort
|
|
166
|
+
};
|
|
167
|
+
}
|
|
168
|
+
};
|
|
169
|
+
|
|
170
|
+
export {
|
|
171
|
+
CloudflareTunnelService,
|
|
172
|
+
CloudflareTunnelAddon
|
|
173
|
+
};
|
|
174
|
+
//# sourceMappingURL=chunk-HHH5U2SN.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/cloudflare-tunnel.ts","../src/cloudflare-tunnel.addon.ts"],"sourcesContent":["import { randomUUID } from 'node:crypto'\nimport type {\n IScopedLogger, IEventBus,\n INetworkAccessProvider, INetworkEndpoint, NetworkAccessStatus,\n IProcessManager, ProcessConfig,\n} from '@camstack/types'\n\nexport interface CloudflareTunnelConfig {\n readonly mode: 'quick' | 'named'\n readonly namedTunnelToken?: string\n readonly localPort: number\n}\n\nexport class CloudflareTunnelService implements INetworkAccessProvider {\n readonly id = 'cloudflare-tunnel'\n readonly type = 'cloudflare'\n\n private endpoint: INetworkEndpoint | null = null\n private processId: string | null = null\n\n constructor(\n private readonly config: CloudflareTunnelConfig,\n private readonly logger: IScopedLogger,\n private readonly eventBus: IEventBus,\n private readonly processManager: IProcessManager,\n ) {}\n\n async start(): Promise<INetworkEndpoint> {\n this.logger.info(`Starting Cloudflare tunnel (${this.config.mode})`)\n\n const processConfig: ProcessConfig = {\n id: 'cloudflared-tunnel',\n label: 'Cloudflare Tunnel',\n command: 'cloudflared',\n args:\n this.config.mode === 'quick'\n ? ['tunnel', '--url', `http://localhost:${this.config.localPort}`]\n : ['tunnel', 'run', '--token', this.config.namedTunnelToken!],\n autoRestart: true,\n maxRestarts: 5,\n }\n\n this.processManager.register(processConfig)\n await this.processManager.start('cloudflared-tunnel')\n this.processId = 'cloudflared-tunnel'\n\n const publicUrl =\n this.config.mode === 'named'\n ? 'https://tunnel.example.com'\n : 'https://pending.trycloudflare.com'\n\n this.endpoint = {\n id: 'cloudflare-tunnel',\n type: 'tunnel',\n provider: 'cloudflare',\n url: publicUrl,\n internal: false,\n capabilities: {\n supportsWebRTC: false,\n supportsWebSocket: true,\n supportsSSE: true,\n },\n priority: 50,\n status: 'online',\n }\n\n this.eventBus.emit({\n id: randomUUID(),\n timestamp: new Date(),\n source: { type: 'addon', id: 'cloudflare-tunnel' },\n category: 'network.tunnel.started',\n data: { url: publicUrl },\n })\n\n return this.endpoint\n }\n\n async stop(): Promise<void> {\n if (this.processId) {\n await this.processManager.stop(this.processId)\n }\n this.endpoint = null\n\n this.eventBus.emit({\n id: randomUUID(),\n timestamp: new Date(),\n source: { type: 'addon', id: 'cloudflare-tunnel' },\n category: 'network.tunnel.stopped',\n data: {},\n })\n }\n\n getEndpoint(): INetworkEndpoint | null {\n return this.endpoint\n }\n\n getStatus(): NetworkAccessStatus {\n return {\n connected: this.endpoint !== null,\n publicUrl: this.endpoint?.url,\n }\n }\n}\n","import type {\n ICamstackAddon, AddonManifest, AddonContext,\n IConfigurable, ConfigUISchema, CapabilityProviderMap,\n IProcessManager,\n} from '@camstack/types'\nimport { CloudflareTunnelService } from './cloudflare-tunnel'\nimport type { CloudflareTunnelConfig } from './cloudflare-tunnel'\n\nexport class CloudflareTunnelAddon implements ICamstackAddon, IConfigurable {\n readonly manifest: AddonManifest = {\n id: 'cloudflare-tunnel',\n name: 'Cloudflare Tunnel',\n version: '1.0.0',\n capabilities: ['network-access'],\n }\n\n private service: CloudflareTunnelService | null = null\n private currentConfig: Partial<CloudflareTunnelConfig> = {\n mode: 'quick',\n localPort: 3000,\n }\n\n async initialize(context: AddonContext): Promise<void> {\n this.currentConfig = {\n mode: (context.addonConfig.mode as CloudflareTunnelConfig['mode']) ?? this.currentConfig.mode,\n namedTunnelToken: (context.addonConfig.namedTunnelToken as string | undefined) ?? this.currentConfig.namedTunnelToken,\n localPort: (context.addonConfig.localPort as number) ?? this.currentConfig.localPort,\n }\n // Service creation is deferred until processManager is provided via setProcessManager\n context.logger.info('Cloudflare Tunnel addon initialized')\n }\n\n async shutdown(): Promise<void> {\n await this.service?.stop()\n this.service = null\n }\n\n /** Provide the ProcessManagerService to enable tunnel management */\n setProcessManager(\n processManager: IProcessManager,\n config: CloudflareTunnelConfig,\n context: AddonContext,\n ): void {\n this.service = new CloudflareTunnelService(\n config,\n context.logger,\n context.eventBus,\n processManager,\n )\n }\n\n getService(): CloudflareTunnelService {\n if (!this.service) throw new Error('Cloudflare Tunnel not initialized')\n return this.service\n }\n\n getCapabilityProvider<K extends keyof CapabilityProviderMap>(\n name: K,\n ): CapabilityProviderMap[K] | null {\n if (name === 'network-access' && this.service) {\n return this.service as unknown as CapabilityProviderMap[K]\n }\n return null\n }\n\n getConfigSchema(): ConfigUISchema {\n return {\n sections: [\n {\n id: 'tunnel',\n title: 'Tunnel Settings',\n fields: [\n {\n type: 'select',\n key: 'mode',\n label: 'Tunnel Mode',\n description: 'Quick mode creates a temporary public URL; Named mode uses a persistent named tunnel with your Cloudflare account.',\n options: [\n { value: 'quick', label: 'Quick Tunnel', description: 'Temporary public URL, no Cloudflare account required' },\n { value: 'named', label: 'Named Tunnel', description: 'Persistent tunnel using a Cloudflare tunnel token' },\n ],\n },\n {\n type: 'password',\n key: 'namedTunnelToken',\n label: 'Tunnel Token',\n description: 'Token from your Cloudflare Zero Trust dashboard (required for Named Tunnel mode)',\n showToggle: true,\n showWhen: { field: 'mode', equals: 'named' },\n },\n {\n type: 'number',\n key: 'localPort',\n label: 'Local Port',\n description: 'The local port that the tunnel will expose publicly',\n min: 1,\n max: 65535,\n step: 1,\n },\n ],\n },\n ],\n }\n }\n\n getConfig(): Record<string, unknown> {\n return { ...this.currentConfig }\n }\n\n async onConfigChange(config: Record<string, unknown>): Promise<void> {\n this.currentConfig = {\n mode: (config.mode as CloudflareTunnelConfig['mode']) ?? this.currentConfig.mode,\n namedTunnelToken: (config.namedTunnelToken as string | undefined) ?? this.currentConfig.namedTunnelToken,\n localPort: (config.localPort as number) ?? this.currentConfig.localPort,\n }\n }\n}\n"],"mappings":"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","names":[]}
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import { INetworkAccessProvider, IScopedLogger, IEventBus, IProcessManager, INetworkEndpoint, NetworkAccessStatus, ICamstackAddon, IConfigurable, AddonManifest, AddonContext, CapabilityProviderMap, ConfigUISchema } from '@camstack/types';
|
|
2
|
+
|
|
3
|
+
interface CloudflareTunnelConfig {
|
|
4
|
+
readonly mode: 'quick' | 'named';
|
|
5
|
+
readonly namedTunnelToken?: string;
|
|
6
|
+
readonly localPort: number;
|
|
7
|
+
}
|
|
8
|
+
declare class CloudflareTunnelService implements INetworkAccessProvider {
|
|
9
|
+
private readonly config;
|
|
10
|
+
private readonly logger;
|
|
11
|
+
private readonly eventBus;
|
|
12
|
+
private readonly processManager;
|
|
13
|
+
readonly id = "cloudflare-tunnel";
|
|
14
|
+
readonly type = "cloudflare";
|
|
15
|
+
private endpoint;
|
|
16
|
+
private processId;
|
|
17
|
+
constructor(config: CloudflareTunnelConfig, logger: IScopedLogger, eventBus: IEventBus, processManager: IProcessManager);
|
|
18
|
+
start(): Promise<INetworkEndpoint>;
|
|
19
|
+
stop(): Promise<void>;
|
|
20
|
+
getEndpoint(): INetworkEndpoint | null;
|
|
21
|
+
getStatus(): NetworkAccessStatus;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
declare class CloudflareTunnelAddon implements ICamstackAddon, IConfigurable {
|
|
25
|
+
readonly manifest: AddonManifest;
|
|
26
|
+
private service;
|
|
27
|
+
private currentConfig;
|
|
28
|
+
initialize(context: AddonContext): Promise<void>;
|
|
29
|
+
shutdown(): Promise<void>;
|
|
30
|
+
/** Provide the ProcessManagerService to enable tunnel management */
|
|
31
|
+
setProcessManager(processManager: IProcessManager, config: CloudflareTunnelConfig, context: AddonContext): void;
|
|
32
|
+
getService(): CloudflareTunnelService;
|
|
33
|
+
getCapabilityProvider<K extends keyof CapabilityProviderMap>(name: K): CapabilityProviderMap[K] | null;
|
|
34
|
+
getConfigSchema(): ConfigUISchema;
|
|
35
|
+
getConfig(): Record<string, unknown>;
|
|
36
|
+
onConfigChange(config: Record<string, unknown>): Promise<void>;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
export { type CloudflareTunnelConfig as C, CloudflareTunnelAddon, CloudflareTunnelService as a };
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import { INetworkAccessProvider, IScopedLogger, IEventBus, IProcessManager, INetworkEndpoint, NetworkAccessStatus, ICamstackAddon, IConfigurable, AddonManifest, AddonContext, CapabilityProviderMap, ConfigUISchema } from '@camstack/types';
|
|
2
|
+
|
|
3
|
+
interface CloudflareTunnelConfig {
|
|
4
|
+
readonly mode: 'quick' | 'named';
|
|
5
|
+
readonly namedTunnelToken?: string;
|
|
6
|
+
readonly localPort: number;
|
|
7
|
+
}
|
|
8
|
+
declare class CloudflareTunnelService implements INetworkAccessProvider {
|
|
9
|
+
private readonly config;
|
|
10
|
+
private readonly logger;
|
|
11
|
+
private readonly eventBus;
|
|
12
|
+
private readonly processManager;
|
|
13
|
+
readonly id = "cloudflare-tunnel";
|
|
14
|
+
readonly type = "cloudflare";
|
|
15
|
+
private endpoint;
|
|
16
|
+
private processId;
|
|
17
|
+
constructor(config: CloudflareTunnelConfig, logger: IScopedLogger, eventBus: IEventBus, processManager: IProcessManager);
|
|
18
|
+
start(): Promise<INetworkEndpoint>;
|
|
19
|
+
stop(): Promise<void>;
|
|
20
|
+
getEndpoint(): INetworkEndpoint | null;
|
|
21
|
+
getStatus(): NetworkAccessStatus;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
declare class CloudflareTunnelAddon implements ICamstackAddon, IConfigurable {
|
|
25
|
+
readonly manifest: AddonManifest;
|
|
26
|
+
private service;
|
|
27
|
+
private currentConfig;
|
|
28
|
+
initialize(context: AddonContext): Promise<void>;
|
|
29
|
+
shutdown(): Promise<void>;
|
|
30
|
+
/** Provide the ProcessManagerService to enable tunnel management */
|
|
31
|
+
setProcessManager(processManager: IProcessManager, config: CloudflareTunnelConfig, context: AddonContext): void;
|
|
32
|
+
getService(): CloudflareTunnelService;
|
|
33
|
+
getCapabilityProvider<K extends keyof CapabilityProviderMap>(name: K): CapabilityProviderMap[K] | null;
|
|
34
|
+
getConfigSchema(): ConfigUISchema;
|
|
35
|
+
getConfig(): Record<string, unknown>;
|
|
36
|
+
onConfigChange(config: Record<string, unknown>): Promise<void>;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
export { type CloudflareTunnelConfig as C, CloudflareTunnelAddon, CloudflareTunnelService as a };
|
|
@@ -0,0 +1,199 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __defProp = Object.defineProperty;
|
|
3
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
4
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
5
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
6
|
+
var __export = (target, all) => {
|
|
7
|
+
for (var name in all)
|
|
8
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
9
|
+
};
|
|
10
|
+
var __copyProps = (to, from, except, desc) => {
|
|
11
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
12
|
+
for (let key of __getOwnPropNames(from))
|
|
13
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
14
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
15
|
+
}
|
|
16
|
+
return to;
|
|
17
|
+
};
|
|
18
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
19
|
+
|
|
20
|
+
// src/cloudflare-tunnel.addon.ts
|
|
21
|
+
var cloudflare_tunnel_addon_exports = {};
|
|
22
|
+
__export(cloudflare_tunnel_addon_exports, {
|
|
23
|
+
CloudflareTunnelAddon: () => CloudflareTunnelAddon
|
|
24
|
+
});
|
|
25
|
+
module.exports = __toCommonJS(cloudflare_tunnel_addon_exports);
|
|
26
|
+
|
|
27
|
+
// src/cloudflare-tunnel.ts
|
|
28
|
+
var import_node_crypto = require("crypto");
|
|
29
|
+
var CloudflareTunnelService = class {
|
|
30
|
+
constructor(config, logger, eventBus, processManager) {
|
|
31
|
+
this.config = config;
|
|
32
|
+
this.logger = logger;
|
|
33
|
+
this.eventBus = eventBus;
|
|
34
|
+
this.processManager = processManager;
|
|
35
|
+
}
|
|
36
|
+
id = "cloudflare-tunnel";
|
|
37
|
+
type = "cloudflare";
|
|
38
|
+
endpoint = null;
|
|
39
|
+
processId = null;
|
|
40
|
+
async start() {
|
|
41
|
+
this.logger.info(`Starting Cloudflare tunnel (${this.config.mode})`);
|
|
42
|
+
const processConfig = {
|
|
43
|
+
id: "cloudflared-tunnel",
|
|
44
|
+
label: "Cloudflare Tunnel",
|
|
45
|
+
command: "cloudflared",
|
|
46
|
+
args: this.config.mode === "quick" ? ["tunnel", "--url", `http://localhost:${this.config.localPort}`] : ["tunnel", "run", "--token", this.config.namedTunnelToken],
|
|
47
|
+
autoRestart: true,
|
|
48
|
+
maxRestarts: 5
|
|
49
|
+
};
|
|
50
|
+
this.processManager.register(processConfig);
|
|
51
|
+
await this.processManager.start("cloudflared-tunnel");
|
|
52
|
+
this.processId = "cloudflared-tunnel";
|
|
53
|
+
const publicUrl = this.config.mode === "named" ? "https://tunnel.example.com" : "https://pending.trycloudflare.com";
|
|
54
|
+
this.endpoint = {
|
|
55
|
+
id: "cloudflare-tunnel",
|
|
56
|
+
type: "tunnel",
|
|
57
|
+
provider: "cloudflare",
|
|
58
|
+
url: publicUrl,
|
|
59
|
+
internal: false,
|
|
60
|
+
capabilities: {
|
|
61
|
+
supportsWebRTC: false,
|
|
62
|
+
supportsWebSocket: true,
|
|
63
|
+
supportsSSE: true
|
|
64
|
+
},
|
|
65
|
+
priority: 50,
|
|
66
|
+
status: "online"
|
|
67
|
+
};
|
|
68
|
+
this.eventBus.emit({
|
|
69
|
+
id: (0, import_node_crypto.randomUUID)(),
|
|
70
|
+
timestamp: /* @__PURE__ */ new Date(),
|
|
71
|
+
source: { type: "addon", id: "cloudflare-tunnel" },
|
|
72
|
+
category: "network.tunnel.started",
|
|
73
|
+
data: { url: publicUrl }
|
|
74
|
+
});
|
|
75
|
+
return this.endpoint;
|
|
76
|
+
}
|
|
77
|
+
async stop() {
|
|
78
|
+
if (this.processId) {
|
|
79
|
+
await this.processManager.stop(this.processId);
|
|
80
|
+
}
|
|
81
|
+
this.endpoint = null;
|
|
82
|
+
this.eventBus.emit({
|
|
83
|
+
id: (0, import_node_crypto.randomUUID)(),
|
|
84
|
+
timestamp: /* @__PURE__ */ new Date(),
|
|
85
|
+
source: { type: "addon", id: "cloudflare-tunnel" },
|
|
86
|
+
category: "network.tunnel.stopped",
|
|
87
|
+
data: {}
|
|
88
|
+
});
|
|
89
|
+
}
|
|
90
|
+
getEndpoint() {
|
|
91
|
+
return this.endpoint;
|
|
92
|
+
}
|
|
93
|
+
getStatus() {
|
|
94
|
+
return {
|
|
95
|
+
connected: this.endpoint !== null,
|
|
96
|
+
publicUrl: this.endpoint?.url
|
|
97
|
+
};
|
|
98
|
+
}
|
|
99
|
+
};
|
|
100
|
+
|
|
101
|
+
// src/cloudflare-tunnel.addon.ts
|
|
102
|
+
var CloudflareTunnelAddon = class {
|
|
103
|
+
manifest = {
|
|
104
|
+
id: "cloudflare-tunnel",
|
|
105
|
+
name: "Cloudflare Tunnel",
|
|
106
|
+
version: "1.0.0",
|
|
107
|
+
capabilities: ["network-access"]
|
|
108
|
+
};
|
|
109
|
+
service = null;
|
|
110
|
+
currentConfig = {
|
|
111
|
+
mode: "quick",
|
|
112
|
+
localPort: 3e3
|
|
113
|
+
};
|
|
114
|
+
async initialize(context) {
|
|
115
|
+
this.currentConfig = {
|
|
116
|
+
mode: context.addonConfig.mode ?? this.currentConfig.mode,
|
|
117
|
+
namedTunnelToken: context.addonConfig.namedTunnelToken ?? this.currentConfig.namedTunnelToken,
|
|
118
|
+
localPort: context.addonConfig.localPort ?? this.currentConfig.localPort
|
|
119
|
+
};
|
|
120
|
+
context.logger.info("Cloudflare Tunnel addon initialized");
|
|
121
|
+
}
|
|
122
|
+
async shutdown() {
|
|
123
|
+
await this.service?.stop();
|
|
124
|
+
this.service = null;
|
|
125
|
+
}
|
|
126
|
+
/** Provide the ProcessManagerService to enable tunnel management */
|
|
127
|
+
setProcessManager(processManager, config, context) {
|
|
128
|
+
this.service = new CloudflareTunnelService(
|
|
129
|
+
config,
|
|
130
|
+
context.logger,
|
|
131
|
+
context.eventBus,
|
|
132
|
+
processManager
|
|
133
|
+
);
|
|
134
|
+
}
|
|
135
|
+
getService() {
|
|
136
|
+
if (!this.service) throw new Error("Cloudflare Tunnel not initialized");
|
|
137
|
+
return this.service;
|
|
138
|
+
}
|
|
139
|
+
getCapabilityProvider(name) {
|
|
140
|
+
if (name === "network-access" && this.service) {
|
|
141
|
+
return this.service;
|
|
142
|
+
}
|
|
143
|
+
return null;
|
|
144
|
+
}
|
|
145
|
+
getConfigSchema() {
|
|
146
|
+
return {
|
|
147
|
+
sections: [
|
|
148
|
+
{
|
|
149
|
+
id: "tunnel",
|
|
150
|
+
title: "Tunnel Settings",
|
|
151
|
+
fields: [
|
|
152
|
+
{
|
|
153
|
+
type: "select",
|
|
154
|
+
key: "mode",
|
|
155
|
+
label: "Tunnel Mode",
|
|
156
|
+
description: "Quick mode creates a temporary public URL; Named mode uses a persistent named tunnel with your Cloudflare account.",
|
|
157
|
+
options: [
|
|
158
|
+
{ value: "quick", label: "Quick Tunnel", description: "Temporary public URL, no Cloudflare account required" },
|
|
159
|
+
{ value: "named", label: "Named Tunnel", description: "Persistent tunnel using a Cloudflare tunnel token" }
|
|
160
|
+
]
|
|
161
|
+
},
|
|
162
|
+
{
|
|
163
|
+
type: "password",
|
|
164
|
+
key: "namedTunnelToken",
|
|
165
|
+
label: "Tunnel Token",
|
|
166
|
+
description: "Token from your Cloudflare Zero Trust dashboard (required for Named Tunnel mode)",
|
|
167
|
+
showToggle: true,
|
|
168
|
+
showWhen: { field: "mode", equals: "named" }
|
|
169
|
+
},
|
|
170
|
+
{
|
|
171
|
+
type: "number",
|
|
172
|
+
key: "localPort",
|
|
173
|
+
label: "Local Port",
|
|
174
|
+
description: "The local port that the tunnel will expose publicly",
|
|
175
|
+
min: 1,
|
|
176
|
+
max: 65535,
|
|
177
|
+
step: 1
|
|
178
|
+
}
|
|
179
|
+
]
|
|
180
|
+
}
|
|
181
|
+
]
|
|
182
|
+
};
|
|
183
|
+
}
|
|
184
|
+
getConfig() {
|
|
185
|
+
return { ...this.currentConfig };
|
|
186
|
+
}
|
|
187
|
+
async onConfigChange(config) {
|
|
188
|
+
this.currentConfig = {
|
|
189
|
+
mode: config.mode ?? this.currentConfig.mode,
|
|
190
|
+
namedTunnelToken: config.namedTunnelToken ?? this.currentConfig.namedTunnelToken,
|
|
191
|
+
localPort: config.localPort ?? this.currentConfig.localPort
|
|
192
|
+
};
|
|
193
|
+
}
|
|
194
|
+
};
|
|
195
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
196
|
+
0 && (module.exports = {
|
|
197
|
+
CloudflareTunnelAddon
|
|
198
|
+
});
|
|
199
|
+
//# sourceMappingURL=cloudflare-tunnel.addon.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/cloudflare-tunnel.addon.ts","../src/cloudflare-tunnel.ts"],"sourcesContent":["import type {\n ICamstackAddon, AddonManifest, AddonContext,\n IConfigurable, ConfigUISchema, CapabilityProviderMap,\n IProcessManager,\n} from '@camstack/types'\nimport { CloudflareTunnelService } from './cloudflare-tunnel'\nimport type { CloudflareTunnelConfig } from './cloudflare-tunnel'\n\nexport class CloudflareTunnelAddon implements ICamstackAddon, IConfigurable {\n readonly manifest: AddonManifest = {\n id: 'cloudflare-tunnel',\n name: 'Cloudflare Tunnel',\n version: '1.0.0',\n capabilities: ['network-access'],\n }\n\n private service: CloudflareTunnelService | null = null\n private currentConfig: Partial<CloudflareTunnelConfig> = {\n mode: 'quick',\n localPort: 3000,\n }\n\n async initialize(context: AddonContext): Promise<void> {\n this.currentConfig = {\n mode: (context.addonConfig.mode as CloudflareTunnelConfig['mode']) ?? this.currentConfig.mode,\n namedTunnelToken: (context.addonConfig.namedTunnelToken as string | undefined) ?? this.currentConfig.namedTunnelToken,\n localPort: (context.addonConfig.localPort as number) ?? this.currentConfig.localPort,\n }\n // Service creation is deferred until processManager is provided via setProcessManager\n context.logger.info('Cloudflare Tunnel addon initialized')\n }\n\n async shutdown(): Promise<void> {\n await this.service?.stop()\n this.service = null\n }\n\n /** Provide the ProcessManagerService to enable tunnel management */\n setProcessManager(\n processManager: IProcessManager,\n config: CloudflareTunnelConfig,\n context: AddonContext,\n ): void {\n this.service = new CloudflareTunnelService(\n config,\n context.logger,\n context.eventBus,\n processManager,\n )\n }\n\n getService(): CloudflareTunnelService {\n if (!this.service) throw new Error('Cloudflare Tunnel not initialized')\n return this.service\n }\n\n getCapabilityProvider<K extends keyof CapabilityProviderMap>(\n name: K,\n ): CapabilityProviderMap[K] | null {\n if (name === 'network-access' && this.service) {\n return this.service as unknown as CapabilityProviderMap[K]\n }\n return null\n }\n\n getConfigSchema(): ConfigUISchema {\n return {\n sections: [\n {\n id: 'tunnel',\n title: 'Tunnel Settings',\n fields: [\n {\n type: 'select',\n key: 'mode',\n label: 'Tunnel Mode',\n description: 'Quick mode creates a temporary public URL; Named mode uses a persistent named tunnel with your Cloudflare account.',\n options: [\n { value: 'quick', label: 'Quick Tunnel', description: 'Temporary public URL, no Cloudflare account required' },\n { value: 'named', label: 'Named Tunnel', description: 'Persistent tunnel using a Cloudflare tunnel token' },\n ],\n },\n {\n type: 'password',\n key: 'namedTunnelToken',\n label: 'Tunnel Token',\n description: 'Token from your Cloudflare Zero Trust dashboard (required for Named Tunnel mode)',\n showToggle: true,\n showWhen: { field: 'mode', equals: 'named' },\n },\n {\n type: 'number',\n key: 'localPort',\n label: 'Local Port',\n description: 'The local port that the tunnel will expose publicly',\n min: 1,\n max: 65535,\n step: 1,\n },\n ],\n },\n ],\n }\n }\n\n getConfig(): Record<string, unknown> {\n return { ...this.currentConfig }\n }\n\n async onConfigChange(config: Record<string, unknown>): Promise<void> {\n this.currentConfig = {\n mode: (config.mode as CloudflareTunnelConfig['mode']) ?? this.currentConfig.mode,\n namedTunnelToken: (config.namedTunnelToken as string | undefined) ?? this.currentConfig.namedTunnelToken,\n localPort: (config.localPort as number) ?? this.currentConfig.localPort,\n }\n }\n}\n","import { randomUUID } from 'node:crypto'\nimport type {\n IScopedLogger, IEventBus,\n INetworkAccessProvider, INetworkEndpoint, NetworkAccessStatus,\n IProcessManager, ProcessConfig,\n} from '@camstack/types'\n\nexport interface CloudflareTunnelConfig {\n readonly mode: 'quick' | 'named'\n readonly namedTunnelToken?: string\n readonly localPort: number\n}\n\nexport class CloudflareTunnelService implements INetworkAccessProvider {\n readonly id = 'cloudflare-tunnel'\n readonly type = 'cloudflare'\n\n private endpoint: INetworkEndpoint | null = null\n private processId: string | null = null\n\n constructor(\n private readonly config: CloudflareTunnelConfig,\n private readonly logger: IScopedLogger,\n private readonly eventBus: IEventBus,\n private readonly processManager: IProcessManager,\n ) {}\n\n async start(): Promise<INetworkEndpoint> {\n this.logger.info(`Starting Cloudflare tunnel (${this.config.mode})`)\n\n const processConfig: ProcessConfig = {\n id: 'cloudflared-tunnel',\n label: 'Cloudflare Tunnel',\n command: 'cloudflared',\n args:\n this.config.mode === 'quick'\n ? ['tunnel', '--url', `http://localhost:${this.config.localPort}`]\n : ['tunnel', 'run', '--token', this.config.namedTunnelToken!],\n autoRestart: true,\n maxRestarts: 5,\n }\n\n this.processManager.register(processConfig)\n await this.processManager.start('cloudflared-tunnel')\n this.processId = 'cloudflared-tunnel'\n\n const publicUrl =\n this.config.mode === 'named'\n ? 'https://tunnel.example.com'\n : 'https://pending.trycloudflare.com'\n\n this.endpoint = {\n id: 'cloudflare-tunnel',\n type: 'tunnel',\n provider: 'cloudflare',\n url: publicUrl,\n internal: false,\n capabilities: {\n supportsWebRTC: false,\n supportsWebSocket: true,\n supportsSSE: true,\n },\n priority: 50,\n status: 'online',\n }\n\n this.eventBus.emit({\n id: randomUUID(),\n timestamp: new Date(),\n source: { type: 'addon', id: 'cloudflare-tunnel' },\n category: 'network.tunnel.started',\n data: { url: publicUrl },\n })\n\n return this.endpoint\n }\n\n async stop(): Promise<void> {\n if (this.processId) {\n await this.processManager.stop(this.processId)\n }\n this.endpoint = null\n\n this.eventBus.emit({\n id: randomUUID(),\n timestamp: new Date(),\n source: { type: 'addon', id: 'cloudflare-tunnel' },\n category: 'network.tunnel.stopped',\n data: {},\n })\n }\n\n getEndpoint(): INetworkEndpoint | null {\n return this.endpoint\n }\n\n getStatus(): NetworkAccessStatus {\n return {\n connected: this.endpoint !== null,\n publicUrl: this.endpoint?.url,\n }\n }\n}\n"],"mappings":"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","names":[]}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":[],"sourcesContent":[],"mappings":"","names":[]}
|
package/dist/index.d.mts
CHANGED
|
@@ -1,39 +1,2 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
interface CloudflareTunnelConfig {
|
|
4
|
-
readonly mode: 'quick' | 'named';
|
|
5
|
-
readonly namedTunnelToken?: string;
|
|
6
|
-
readonly localPort: number;
|
|
7
|
-
}
|
|
8
|
-
declare class CloudflareTunnelService implements INetworkAccessProvider {
|
|
9
|
-
private readonly config;
|
|
10
|
-
private readonly logger;
|
|
11
|
-
private readonly eventBus;
|
|
12
|
-
private readonly processManager;
|
|
13
|
-
readonly id = "cloudflare-tunnel";
|
|
14
|
-
readonly type = "cloudflare";
|
|
15
|
-
private endpoint;
|
|
16
|
-
private processId;
|
|
17
|
-
constructor(config: CloudflareTunnelConfig, logger: IScopedLogger, eventBus: IEventBus, processManager: IProcessManager);
|
|
18
|
-
start(): Promise<INetworkEndpoint>;
|
|
19
|
-
stop(): Promise<void>;
|
|
20
|
-
getEndpoint(): INetworkEndpoint | null;
|
|
21
|
-
getStatus(): NetworkAccessStatus;
|
|
22
|
-
}
|
|
23
|
-
|
|
24
|
-
declare class CloudflareTunnelAddon implements ICamstackAddon, IConfigurable {
|
|
25
|
-
readonly manifest: AddonManifest;
|
|
26
|
-
private service;
|
|
27
|
-
private currentConfig;
|
|
28
|
-
initialize(context: AddonContext): Promise<void>;
|
|
29
|
-
shutdown(): Promise<void>;
|
|
30
|
-
/** Provide the ProcessManagerService to enable tunnel management */
|
|
31
|
-
setProcessManager(processManager: IProcessManager, config: CloudflareTunnelConfig, context: AddonContext): void;
|
|
32
|
-
getService(): CloudflareTunnelService;
|
|
33
|
-
getCapabilityProvider<K extends keyof CapabilityProviderMap>(name: K): CapabilityProviderMap[K] | null;
|
|
34
|
-
getConfigSchema(): ConfigUISchema;
|
|
35
|
-
getConfig(): Record<string, unknown>;
|
|
36
|
-
onConfigChange(config: Record<string, unknown>): Promise<void>;
|
|
37
|
-
}
|
|
38
|
-
|
|
39
|
-
export { CloudflareTunnelAddon, type CloudflareTunnelConfig, CloudflareTunnelService };
|
|
1
|
+
export { CloudflareTunnelAddon, C as CloudflareTunnelConfig, a as CloudflareTunnelService } from './cloudflare-tunnel.addon.mjs';
|
|
2
|
+
import '@camstack/types';
|
package/dist/index.d.ts
CHANGED
|
@@ -1,39 +1,2 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
interface CloudflareTunnelConfig {
|
|
4
|
-
readonly mode: 'quick' | 'named';
|
|
5
|
-
readonly namedTunnelToken?: string;
|
|
6
|
-
readonly localPort: number;
|
|
7
|
-
}
|
|
8
|
-
declare class CloudflareTunnelService implements INetworkAccessProvider {
|
|
9
|
-
private readonly config;
|
|
10
|
-
private readonly logger;
|
|
11
|
-
private readonly eventBus;
|
|
12
|
-
private readonly processManager;
|
|
13
|
-
readonly id = "cloudflare-tunnel";
|
|
14
|
-
readonly type = "cloudflare";
|
|
15
|
-
private endpoint;
|
|
16
|
-
private processId;
|
|
17
|
-
constructor(config: CloudflareTunnelConfig, logger: IScopedLogger, eventBus: IEventBus, processManager: IProcessManager);
|
|
18
|
-
start(): Promise<INetworkEndpoint>;
|
|
19
|
-
stop(): Promise<void>;
|
|
20
|
-
getEndpoint(): INetworkEndpoint | null;
|
|
21
|
-
getStatus(): NetworkAccessStatus;
|
|
22
|
-
}
|
|
23
|
-
|
|
24
|
-
declare class CloudflareTunnelAddon implements ICamstackAddon, IConfigurable {
|
|
25
|
-
readonly manifest: AddonManifest;
|
|
26
|
-
private service;
|
|
27
|
-
private currentConfig;
|
|
28
|
-
initialize(context: AddonContext): Promise<void>;
|
|
29
|
-
shutdown(): Promise<void>;
|
|
30
|
-
/** Provide the ProcessManagerService to enable tunnel management */
|
|
31
|
-
setProcessManager(processManager: IProcessManager, config: CloudflareTunnelConfig, context: AddonContext): void;
|
|
32
|
-
getService(): CloudflareTunnelService;
|
|
33
|
-
getCapabilityProvider<K extends keyof CapabilityProviderMap>(name: K): CapabilityProviderMap[K] | null;
|
|
34
|
-
getConfigSchema(): ConfigUISchema;
|
|
35
|
-
getConfig(): Record<string, unknown>;
|
|
36
|
-
onConfigChange(config: Record<string, unknown>): Promise<void>;
|
|
37
|
-
}
|
|
38
|
-
|
|
39
|
-
export { CloudflareTunnelAddon, type CloudflareTunnelConfig, CloudflareTunnelService };
|
|
1
|
+
export { CloudflareTunnelAddon, C as CloudflareTunnelConfig, a as CloudflareTunnelService } from './cloudflare-tunnel.addon.js';
|
|
2
|
+
import '@camstack/types';
|
package/dist/index.mjs
CHANGED
|
@@ -1,171 +1,7 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
this.config = config;
|
|
6
|
-
this.logger = logger;
|
|
7
|
-
this.eventBus = eventBus;
|
|
8
|
-
this.processManager = processManager;
|
|
9
|
-
}
|
|
10
|
-
id = "cloudflare-tunnel";
|
|
11
|
-
type = "cloudflare";
|
|
12
|
-
endpoint = null;
|
|
13
|
-
processId = null;
|
|
14
|
-
async start() {
|
|
15
|
-
this.logger.info(`Starting Cloudflare tunnel (${this.config.mode})`);
|
|
16
|
-
const processConfig = {
|
|
17
|
-
id: "cloudflared-tunnel",
|
|
18
|
-
label: "Cloudflare Tunnel",
|
|
19
|
-
command: "cloudflared",
|
|
20
|
-
args: this.config.mode === "quick" ? ["tunnel", "--url", `http://localhost:${this.config.localPort}`] : ["tunnel", "run", "--token", this.config.namedTunnelToken],
|
|
21
|
-
autoRestart: true,
|
|
22
|
-
maxRestarts: 5
|
|
23
|
-
};
|
|
24
|
-
this.processManager.register(processConfig);
|
|
25
|
-
await this.processManager.start("cloudflared-tunnel");
|
|
26
|
-
this.processId = "cloudflared-tunnel";
|
|
27
|
-
const publicUrl = this.config.mode === "named" ? "https://tunnel.example.com" : "https://pending.trycloudflare.com";
|
|
28
|
-
this.endpoint = {
|
|
29
|
-
id: "cloudflare-tunnel",
|
|
30
|
-
type: "tunnel",
|
|
31
|
-
provider: "cloudflare",
|
|
32
|
-
url: publicUrl,
|
|
33
|
-
internal: false,
|
|
34
|
-
capabilities: {
|
|
35
|
-
supportsWebRTC: false,
|
|
36
|
-
supportsWebSocket: true,
|
|
37
|
-
supportsSSE: true
|
|
38
|
-
},
|
|
39
|
-
priority: 50,
|
|
40
|
-
status: "online"
|
|
41
|
-
};
|
|
42
|
-
this.eventBus.emit({
|
|
43
|
-
id: randomUUID(),
|
|
44
|
-
timestamp: /* @__PURE__ */ new Date(),
|
|
45
|
-
source: { type: "addon", id: "cloudflare-tunnel" },
|
|
46
|
-
category: "network.tunnel.started",
|
|
47
|
-
data: { url: publicUrl }
|
|
48
|
-
});
|
|
49
|
-
return this.endpoint;
|
|
50
|
-
}
|
|
51
|
-
async stop() {
|
|
52
|
-
if (this.processId) {
|
|
53
|
-
await this.processManager.stop(this.processId);
|
|
54
|
-
}
|
|
55
|
-
this.endpoint = null;
|
|
56
|
-
this.eventBus.emit({
|
|
57
|
-
id: randomUUID(),
|
|
58
|
-
timestamp: /* @__PURE__ */ new Date(),
|
|
59
|
-
source: { type: "addon", id: "cloudflare-tunnel" },
|
|
60
|
-
category: "network.tunnel.stopped",
|
|
61
|
-
data: {}
|
|
62
|
-
});
|
|
63
|
-
}
|
|
64
|
-
getEndpoint() {
|
|
65
|
-
return this.endpoint;
|
|
66
|
-
}
|
|
67
|
-
getStatus() {
|
|
68
|
-
return {
|
|
69
|
-
connected: this.endpoint !== null,
|
|
70
|
-
publicUrl: this.endpoint?.url
|
|
71
|
-
};
|
|
72
|
-
}
|
|
73
|
-
};
|
|
74
|
-
|
|
75
|
-
// src/cloudflare-tunnel.addon.ts
|
|
76
|
-
var CloudflareTunnelAddon = class {
|
|
77
|
-
manifest = {
|
|
78
|
-
id: "cloudflare-tunnel",
|
|
79
|
-
name: "Cloudflare Tunnel",
|
|
80
|
-
version: "1.0.0",
|
|
81
|
-
capabilities: ["network-access"]
|
|
82
|
-
};
|
|
83
|
-
service = null;
|
|
84
|
-
currentConfig = {
|
|
85
|
-
mode: "quick",
|
|
86
|
-
localPort: 3e3
|
|
87
|
-
};
|
|
88
|
-
async initialize(context) {
|
|
89
|
-
this.currentConfig = {
|
|
90
|
-
mode: context.addonConfig.mode ?? this.currentConfig.mode,
|
|
91
|
-
namedTunnelToken: context.addonConfig.namedTunnelToken ?? this.currentConfig.namedTunnelToken,
|
|
92
|
-
localPort: context.addonConfig.localPort ?? this.currentConfig.localPort
|
|
93
|
-
};
|
|
94
|
-
context.logger.info("Cloudflare Tunnel addon initialized");
|
|
95
|
-
}
|
|
96
|
-
async shutdown() {
|
|
97
|
-
await this.service?.stop();
|
|
98
|
-
this.service = null;
|
|
99
|
-
}
|
|
100
|
-
/** Provide the ProcessManagerService to enable tunnel management */
|
|
101
|
-
setProcessManager(processManager, config, context) {
|
|
102
|
-
this.service = new CloudflareTunnelService(
|
|
103
|
-
config,
|
|
104
|
-
context.logger,
|
|
105
|
-
context.eventBus,
|
|
106
|
-
processManager
|
|
107
|
-
);
|
|
108
|
-
}
|
|
109
|
-
getService() {
|
|
110
|
-
if (!this.service) throw new Error("Cloudflare Tunnel not initialized");
|
|
111
|
-
return this.service;
|
|
112
|
-
}
|
|
113
|
-
getCapabilityProvider(name) {
|
|
114
|
-
if (name === "network-access" && this.service) {
|
|
115
|
-
return this.service;
|
|
116
|
-
}
|
|
117
|
-
return null;
|
|
118
|
-
}
|
|
119
|
-
getConfigSchema() {
|
|
120
|
-
return {
|
|
121
|
-
sections: [
|
|
122
|
-
{
|
|
123
|
-
id: "tunnel",
|
|
124
|
-
title: "Tunnel Settings",
|
|
125
|
-
fields: [
|
|
126
|
-
{
|
|
127
|
-
type: "select",
|
|
128
|
-
key: "mode",
|
|
129
|
-
label: "Tunnel Mode",
|
|
130
|
-
description: "Quick mode creates a temporary public URL; Named mode uses a persistent named tunnel with your Cloudflare account.",
|
|
131
|
-
options: [
|
|
132
|
-
{ value: "quick", label: "Quick Tunnel", description: "Temporary public URL, no Cloudflare account required" },
|
|
133
|
-
{ value: "named", label: "Named Tunnel", description: "Persistent tunnel using a Cloudflare tunnel token" }
|
|
134
|
-
]
|
|
135
|
-
},
|
|
136
|
-
{
|
|
137
|
-
type: "password",
|
|
138
|
-
key: "namedTunnelToken",
|
|
139
|
-
label: "Tunnel Token",
|
|
140
|
-
description: "Token from your Cloudflare Zero Trust dashboard (required for Named Tunnel mode)",
|
|
141
|
-
showToggle: true,
|
|
142
|
-
showWhen: { field: "mode", equals: "named" }
|
|
143
|
-
},
|
|
144
|
-
{
|
|
145
|
-
type: "number",
|
|
146
|
-
key: "localPort",
|
|
147
|
-
label: "Local Port",
|
|
148
|
-
description: "The local port that the tunnel will expose publicly",
|
|
149
|
-
min: 1,
|
|
150
|
-
max: 65535,
|
|
151
|
-
step: 1
|
|
152
|
-
}
|
|
153
|
-
]
|
|
154
|
-
}
|
|
155
|
-
]
|
|
156
|
-
};
|
|
157
|
-
}
|
|
158
|
-
getConfig() {
|
|
159
|
-
return { ...this.currentConfig };
|
|
160
|
-
}
|
|
161
|
-
async onConfigChange(config) {
|
|
162
|
-
this.currentConfig = {
|
|
163
|
-
mode: config.mode ?? this.currentConfig.mode,
|
|
164
|
-
namedTunnelToken: config.namedTunnelToken ?? this.currentConfig.namedTunnelToken,
|
|
165
|
-
localPort: config.localPort ?? this.currentConfig.localPort
|
|
166
|
-
};
|
|
167
|
-
}
|
|
168
|
-
};
|
|
1
|
+
import {
|
|
2
|
+
CloudflareTunnelAddon,
|
|
3
|
+
CloudflareTunnelService
|
|
4
|
+
} from "./chunk-HHH5U2SN.mjs";
|
|
169
5
|
export {
|
|
170
6
|
CloudflareTunnelAddon,
|
|
171
7
|
CloudflareTunnelService
|
package/dist/index.mjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/cloudflare-tunnel.ts","../src/cloudflare-tunnel.addon.ts"],"sourcesContent":["import { randomUUID } from 'node:crypto'\nimport type {\n IScopedLogger, IEventBus,\n INetworkAccessProvider, INetworkEndpoint, NetworkAccessStatus,\n IProcessManager, ProcessConfig,\n} from '@camstack/types'\n\nexport interface CloudflareTunnelConfig {\n readonly mode: 'quick' | 'named'\n readonly namedTunnelToken?: string\n readonly localPort: number\n}\n\nexport class CloudflareTunnelService implements INetworkAccessProvider {\n readonly id = 'cloudflare-tunnel'\n readonly type = 'cloudflare'\n\n private endpoint: INetworkEndpoint | null = null\n private processId: string | null = null\n\n constructor(\n private readonly config: CloudflareTunnelConfig,\n private readonly logger: IScopedLogger,\n private readonly eventBus: IEventBus,\n private readonly processManager: IProcessManager,\n ) {}\n\n async start(): Promise<INetworkEndpoint> {\n this.logger.info(`Starting Cloudflare tunnel (${this.config.mode})`)\n\n const processConfig: ProcessConfig = {\n id: 'cloudflared-tunnel',\n label: 'Cloudflare Tunnel',\n command: 'cloudflared',\n args:\n this.config.mode === 'quick'\n ? ['tunnel', '--url', `http://localhost:${this.config.localPort}`]\n : ['tunnel', 'run', '--token', this.config.namedTunnelToken!],\n autoRestart: true,\n maxRestarts: 5,\n }\n\n this.processManager.register(processConfig)\n await this.processManager.start('cloudflared-tunnel')\n this.processId = 'cloudflared-tunnel'\n\n const publicUrl =\n this.config.mode === 'named'\n ? 'https://tunnel.example.com'\n : 'https://pending.trycloudflare.com'\n\n this.endpoint = {\n id: 'cloudflare-tunnel',\n type: 'tunnel',\n provider: 'cloudflare',\n url: publicUrl,\n internal: false,\n capabilities: {\n supportsWebRTC: false,\n supportsWebSocket: true,\n supportsSSE: true,\n },\n priority: 50,\n status: 'online',\n }\n\n this.eventBus.emit({\n id: randomUUID(),\n timestamp: new Date(),\n source: { type: 'addon', id: 'cloudflare-tunnel' },\n category: 'network.tunnel.started',\n data: { url: publicUrl },\n })\n\n return this.endpoint\n }\n\n async stop(): Promise<void> {\n if (this.processId) {\n await this.processManager.stop(this.processId)\n }\n this.endpoint = null\n\n this.eventBus.emit({\n id: randomUUID(),\n timestamp: new Date(),\n source: { type: 'addon', id: 'cloudflare-tunnel' },\n category: 'network.tunnel.stopped',\n data: {},\n })\n }\n\n getEndpoint(): INetworkEndpoint | null {\n return this.endpoint\n }\n\n getStatus(): NetworkAccessStatus {\n return {\n connected: this.endpoint !== null,\n publicUrl: this.endpoint?.url,\n }\n }\n}\n","import type {\n ICamstackAddon, AddonManifest, AddonContext,\n IConfigurable, ConfigUISchema, CapabilityProviderMap,\n IProcessManager,\n} from '@camstack/types'\nimport { CloudflareTunnelService } from './cloudflare-tunnel'\nimport type { CloudflareTunnelConfig } from './cloudflare-tunnel'\n\nexport class CloudflareTunnelAddon implements ICamstackAddon, IConfigurable {\n readonly manifest: AddonManifest = {\n id: 'cloudflare-tunnel',\n name: 'Cloudflare Tunnel',\n version: '1.0.0',\n capabilities: ['network-access'],\n }\n\n private service: CloudflareTunnelService | null = null\n private currentConfig: Partial<CloudflareTunnelConfig> = {\n mode: 'quick',\n localPort: 3000,\n }\n\n async initialize(context: AddonContext): Promise<void> {\n this.currentConfig = {\n mode: (context.addonConfig.mode as CloudflareTunnelConfig['mode']) ?? this.currentConfig.mode,\n namedTunnelToken: (context.addonConfig.namedTunnelToken as string | undefined) ?? this.currentConfig.namedTunnelToken,\n localPort: (context.addonConfig.localPort as number) ?? this.currentConfig.localPort,\n }\n // Service creation is deferred until processManager is provided via setProcessManager\n context.logger.info('Cloudflare Tunnel addon initialized')\n }\n\n async shutdown(): Promise<void> {\n await this.service?.stop()\n this.service = null\n }\n\n /** Provide the ProcessManagerService to enable tunnel management */\n setProcessManager(\n processManager: IProcessManager,\n config: CloudflareTunnelConfig,\n context: AddonContext,\n ): void {\n this.service = new CloudflareTunnelService(\n config,\n context.logger,\n context.eventBus,\n processManager,\n )\n }\n\n getService(): CloudflareTunnelService {\n if (!this.service) throw new Error('Cloudflare Tunnel not initialized')\n return this.service\n }\n\n getCapabilityProvider<K extends keyof CapabilityProviderMap>(\n name: K,\n ): CapabilityProviderMap[K] | null {\n if (name === 'network-access' && this.service) {\n return this.service as unknown as CapabilityProviderMap[K]\n }\n return null\n }\n\n getConfigSchema(): ConfigUISchema {\n return {\n sections: [\n {\n id: 'tunnel',\n title: 'Tunnel Settings',\n fields: [\n {\n type: 'select',\n key: 'mode',\n label: 'Tunnel Mode',\n description: 'Quick mode creates a temporary public URL; Named mode uses a persistent named tunnel with your Cloudflare account.',\n options: [\n { value: 'quick', label: 'Quick Tunnel', description: 'Temporary public URL, no Cloudflare account required' },\n { value: 'named', label: 'Named Tunnel', description: 'Persistent tunnel using a Cloudflare tunnel token' },\n ],\n },\n {\n type: 'password',\n key: 'namedTunnelToken',\n label: 'Tunnel Token',\n description: 'Token from your Cloudflare Zero Trust dashboard (required for Named Tunnel mode)',\n showToggle: true,\n showWhen: { field: 'mode', equals: 'named' },\n },\n {\n type: 'number',\n key: 'localPort',\n label: 'Local Port',\n description: 'The local port that the tunnel will expose publicly',\n min: 1,\n max: 65535,\n step: 1,\n },\n ],\n },\n ],\n }\n }\n\n getConfig(): Record<string, unknown> {\n return { ...this.currentConfig }\n }\n\n async onConfigChange(config: Record<string, unknown>): Promise<void> {\n this.currentConfig = {\n mode: (config.mode as CloudflareTunnelConfig['mode']) ?? this.currentConfig.mode,\n namedTunnelToken: (config.namedTunnelToken as string | undefined) ?? this.currentConfig.namedTunnelToken,\n localPort: (config.localPort as number) ?? this.currentConfig.localPort,\n }\n }\n}\n"],"mappings":"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","names":[]}
|
|
1
|
+
{"version":3,"sources":[],"sourcesContent":[],"mappings":"","names":[]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@camstack/addon-cloudflare-tunnel",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.4",
|
|
4
4
|
"description": "Cloudflare Tunnel addon for CamStack",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"camstack",
|
|
@@ -32,7 +32,7 @@
|
|
|
32
32
|
"addons": [
|
|
33
33
|
{
|
|
34
34
|
"id": "cloudflare-tunnel",
|
|
35
|
-
"entry": "./dist/addon.js",
|
|
35
|
+
"entry": "./dist/cloudflare-tunnel.addon.js",
|
|
36
36
|
"slot": null,
|
|
37
37
|
"capabilities": [
|
|
38
38
|
{
|
|
@@ -49,7 +49,8 @@
|
|
|
49
49
|
"scripts": {
|
|
50
50
|
"build": "tsup",
|
|
51
51
|
"dev": "tsup --watch",
|
|
52
|
-
"typecheck": "tsc --noEmit"
|
|
52
|
+
"typecheck": "tsc --noEmit",
|
|
53
|
+
"publish": "npm publish --access public"
|
|
53
54
|
},
|
|
54
55
|
"peerDependencies": {
|
|
55
56
|
"@camstack/types": "^0.1.0"
|