lopata 0.11.0 → 0.12.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +1 -1
- package/src/cli/dev.ts +11 -0
- package/src/lopata-config.ts +2 -0
- package/src/route-matcher.ts +12 -2
- package/src/vite-plugin/dev-server-plugin.ts +12 -0
- package/src/vite-plugin/index.ts +3 -0
package/package.json
CHANGED
package/src/cli/dev.ts
CHANGED
|
@@ -140,6 +140,12 @@ export async function run(ctx: CliContext) {
|
|
|
140
140
|
|
|
141
141
|
// Build route dispatcher (aux workers only — main is the fallback)
|
|
142
142
|
routeDispatcher = new RouteDispatcher(mainManager)
|
|
143
|
+
|
|
144
|
+
// Register main worker host patterns so they take priority over wildcard aux hosts
|
|
145
|
+
if (lopataConfig.hosts?.length) {
|
|
146
|
+
routeDispatcher.addHostWorker(mainManager, mainConfig.name, lopataConfig.hosts)
|
|
147
|
+
}
|
|
148
|
+
|
|
143
149
|
for (const workerDef of lopataConfig.workers ?? []) {
|
|
144
150
|
const auxMgr = registry.getManager(workerDef.name)
|
|
145
151
|
if (!auxMgr) continue
|
|
@@ -159,6 +165,11 @@ export async function run(ctx: CliContext) {
|
|
|
159
165
|
|
|
160
166
|
// Expose host routes to the dashboard API
|
|
161
167
|
const hostRoutes: Array<{ pattern: string; workerName: string }> = []
|
|
168
|
+
if (lopataConfig.hosts?.length) {
|
|
169
|
+
for (const host of lopataConfig.hosts) {
|
|
170
|
+
hostRoutes.push({ pattern: host, workerName: mainConfig.name })
|
|
171
|
+
}
|
|
172
|
+
}
|
|
162
173
|
for (const workerDef of lopataConfig.workers ?? []) {
|
|
163
174
|
if (!workerDef.hosts) continue
|
|
164
175
|
for (const host of workerDef.hosts) {
|
package/src/lopata-config.ts
CHANGED
|
@@ -4,6 +4,8 @@ import { dirname, join, resolve } from 'node:path'
|
|
|
4
4
|
export interface LopataConfig {
|
|
5
5
|
/** Path to the main worker's wrangler config (HTTP entrypoint) */
|
|
6
6
|
main: string
|
|
7
|
+
/** Host patterns that route to the main worker (takes priority over wildcard auxiliary hosts). */
|
|
8
|
+
hosts?: string[]
|
|
7
9
|
/** Auxiliary workers, each with a service name and wrangler config path */
|
|
8
10
|
workers?: Array<{
|
|
9
11
|
name: string
|
package/src/route-matcher.ts
CHANGED
|
@@ -77,6 +77,12 @@ export function matchHost(hostname: string, pattern: string): boolean {
|
|
|
77
77
|
return false
|
|
78
78
|
}
|
|
79
79
|
|
|
80
|
+
/** Check if host patterns contain any wildcard entries (e.g. `*.localhost`). */
|
|
81
|
+
function hasWildcardHost(patterns?: string[]): boolean {
|
|
82
|
+
if (!patterns) return false
|
|
83
|
+
return patterns.some(p => p.includes('*'))
|
|
84
|
+
}
|
|
85
|
+
|
|
80
86
|
/** Count the number of path segments in a pattern (ignoring trailing wildcard). */
|
|
81
87
|
function segmentCount(pattern: string): number {
|
|
82
88
|
const clean = pattern.replace(/\/?\*$/, '')
|
|
@@ -90,6 +96,8 @@ interface RouteEntry {
|
|
|
90
96
|
manager: RoutableManager
|
|
91
97
|
/** When set, this route only matches requests whose hostname matches one of these patterns. */
|
|
92
98
|
hostPatterns?: string[]
|
|
99
|
+
/** Pre-computed: true if any hostPattern contains a wildcard. Used for sort ordering. */
|
|
100
|
+
hasWildcardHost: boolean
|
|
93
101
|
}
|
|
94
102
|
|
|
95
103
|
/**
|
|
@@ -143,7 +151,7 @@ export class RouteDispatcher {
|
|
|
143
151
|
continue
|
|
144
152
|
}
|
|
145
153
|
|
|
146
|
-
this.routes.push({ pattern, workerName, manager, hostPatterns })
|
|
154
|
+
this.routes.push({ pattern, workerName, manager, hostPatterns, hasWildcardHost: hasWildcardHost(hostPatterns) })
|
|
147
155
|
this.sorted = false
|
|
148
156
|
}
|
|
149
157
|
}
|
|
@@ -152,7 +160,7 @@ export class RouteDispatcher {
|
|
|
152
160
|
addHostWorker(manager: RoutableManager, workerName: string, hostPatterns: string[]): void {
|
|
153
161
|
// Clear existing routes for this worker to support re-registration
|
|
154
162
|
this.routes = this.routes.filter(r => r.workerName !== workerName)
|
|
155
|
-
this.routes.push({ pattern: '/*', workerName, manager, hostPatterns })
|
|
163
|
+
this.routes.push({ pattern: '/*', workerName, manager, hostPatterns, hasWildcardHost: hasWildcardHost(hostPatterns) })
|
|
156
164
|
this.sorted = false
|
|
157
165
|
}
|
|
158
166
|
|
|
@@ -175,6 +183,8 @@ export class RouteDispatcher {
|
|
|
175
183
|
const aSlashStar = a.pattern.endsWith('/*')
|
|
176
184
|
const bSlashStar = b.pattern.endsWith('/*')
|
|
177
185
|
if (aSlashStar !== bSlashStar) return aSlashStar ? -1 : 1
|
|
186
|
+
// Exact host patterns beat wildcard host patterns (e.g. admin.localhost before *.localhost)
|
|
187
|
+
if (a.hasWildcardHost !== b.hasWildcardHost) return a.hasWildcardHost ? 1 : -1
|
|
178
188
|
// Longer pattern string as tiebreaker
|
|
179
189
|
return b.pattern.length - a.pattern.length
|
|
180
190
|
})
|
|
@@ -8,6 +8,7 @@ import { extractHostname, RouteDispatcher } from '../route-matcher.ts'
|
|
|
8
8
|
interface DevServerPluginOptions {
|
|
9
9
|
configPath?: string
|
|
10
10
|
envName: string
|
|
11
|
+
hosts?: string[]
|
|
11
12
|
auxiliaryWorkers?: { configPath: string; name?: string; hosts?: string[] }[]
|
|
12
13
|
}
|
|
13
14
|
|
|
@@ -425,6 +426,12 @@ export function devServerPlugin(options: DevServerPluginOptions): Plugin {
|
|
|
425
426
|
|
|
426
427
|
// Build route dispatcher (aux workers only — main is the fallback)
|
|
427
428
|
routeDispatcher = new RouteDispatcher(mainAdapter)
|
|
429
|
+
|
|
430
|
+
// Register main worker host patterns so they take priority over wildcard aux hosts
|
|
431
|
+
if (options.hosts?.length) {
|
|
432
|
+
routeDispatcher.addHostWorker(mainAdapter, config.name, options.hosts)
|
|
433
|
+
}
|
|
434
|
+
|
|
428
435
|
for (const workerDef of options.auxiliaryWorkers) {
|
|
429
436
|
const cached = auxConfigs.get(workerDef.configPath)
|
|
430
437
|
if (!cached) continue
|
|
@@ -446,6 +453,11 @@ export function devServerPlugin(options: DevServerPluginOptions): Plugin {
|
|
|
446
453
|
|
|
447
454
|
// Expose host routes to the dashboard API
|
|
448
455
|
const hostRoutes: Array<{ pattern: string; workerName: string }> = []
|
|
456
|
+
if (options.hosts?.length) {
|
|
457
|
+
for (const host of options.hosts) {
|
|
458
|
+
hostRoutes.push({ pattern: host, workerName: config.name })
|
|
459
|
+
}
|
|
460
|
+
}
|
|
449
461
|
for (const workerDef of options.auxiliaryWorkers) {
|
|
450
462
|
if (!workerDef.hosts) continue
|
|
451
463
|
const cached = auxConfigs.get(workerDef.configPath)
|
package/src/vite-plugin/index.ts
CHANGED
|
@@ -10,6 +10,8 @@ export interface LopataPluginConfig {
|
|
|
10
10
|
configPath?: string
|
|
11
11
|
/** Vite environment name for SSR. Default: "ssr" */
|
|
12
12
|
viteEnvironment?: { name?: string }
|
|
13
|
+
/** Host patterns that route to the main worker (takes priority over wildcard auxiliary hosts). */
|
|
14
|
+
hosts?: string[]
|
|
13
15
|
/** Auxiliary workers loaded via native Bun import (not through Vite). */
|
|
14
16
|
auxiliaryWorkers?: { configPath: string; name?: string; hosts?: string[] }[]
|
|
15
17
|
}
|
|
@@ -36,6 +38,7 @@ export function lopata(config?: LopataPluginConfig): Plugin[] {
|
|
|
36
38
|
devServerPlugin({
|
|
37
39
|
configPath: config?.configPath,
|
|
38
40
|
envName,
|
|
41
|
+
hosts: config?.hosts,
|
|
39
42
|
auxiliaryWorkers: config?.auxiliaryWorkers,
|
|
40
43
|
}),
|
|
41
44
|
reactRouterPlugin(),
|