@celsoft/platform 0.6.0 → 0.8.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/adapters/cloudflare.d.ts +11 -10
- package/dist/adapters/cloudflare.js +29 -22
- package/dist/adapters/cloudflare.js.map +1 -1
- package/dist/adapters/github.d.ts +2 -1
- package/dist/adapters/github.js +5 -0
- package/dist/adapters/github.js.map +1 -1
- package/dist/adapters/process.d.ts +3 -1
- package/dist/adapters/process.js +13 -1
- package/dist/adapters/process.js.map +1 -1
- package/dist/adapters/r2.d.ts +15 -0
- package/dist/adapters/r2.js +99 -0
- package/dist/adapters/r2.js.map +1 -0
- package/dist/adapters/registry.d.ts +14 -0
- package/dist/adapters/registry.js +42 -0
- package/dist/adapters/registry.js.map +1 -0
- package/dist/cli.js +29 -8
- package/dist/cli.js.map +1 -1
- package/dist/config.d.ts +1 -0
- package/dist/config.js +6 -2
- package/dist/config.js.map +1 -1
- package/dist/fakes.d.ts +19 -9
- package/dist/fakes.js +51 -20
- package/dist/fakes.js.map +1 -1
- package/dist/legacy.d.ts +10 -0
- package/dist/legacy.js +13 -0
- package/dist/legacy.js.map +1 -0
- package/dist/lifecycle.d.ts +8 -2
- package/dist/lifecycle.js +201 -77
- package/dist/lifecycle.js.map +1 -1
- package/dist/ports.d.ts +25 -10
- package/dist/runtime/files.js +1 -4
- package/dist/runtime/files.js.map +1 -1
- package/dist/runtime/guard.js +2 -1
- package/dist/runtime/guard.js.map +1 -1
- package/dist/runtime/index.d.ts +16 -2
- package/dist/runtime/index.js +87 -44
- package/dist/runtime/index.js.map +1 -1
- package/dist/runtime/live-client.d.ts +19 -0
- package/dist/runtime/live-client.js +74 -0
- package/dist/runtime/live-client.js.map +1 -0
- package/dist/runtime/live.d.ts +29 -0
- package/dist/runtime/live.js +158 -0
- package/dist/runtime/live.js.map +1 -0
- package/dist/target.d.ts +2 -1
- package/dist/target.js +9 -7
- package/dist/target.js.map +1 -1
- package/dist/wrangler-config.d.ts +2 -0
- package/dist/wrangler-config.js +12 -2
- package/dist/wrangler-config.js.map +1 -1
- package/package.json +3 -2
- package/schema.json +6 -1
- package/dist/ownership.d.ts +0 -16
- package/dist/ownership.js +0 -40
- package/dist/ownership.js.map +0 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"guard.js","sourceRoot":"","sources":["../../src/runtime/guard.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,WAAW,CAAC;AAEtC,MAAM,CAAC,MAAM,UAAU,GAAG,cAAc,CAAC;AAEzC,MAAM,UAAU,GAAG,CAAC,mCAAmC,EAAE,qBAAqB,EAAE,YAAY,CAAC,CAAC;AAC9F,MAAM,MAAM,GAAG,CAAC,MAAM,EAAE,KAAK,EAAE,OAAO,EAAE,QAAQ,CAAC,CAAC;AAElD,2FAA2F;AAC3F,mEAAmE;AACnE,MAAM,UAAU,eAAe,CAAC,OAAgB,EAAE,GAAQ;IACxD,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,OAAO,CAAC,MAAM,CAAC;QAAE,OAAO,KAAK,CAAC;IACnD,MAAM,IAAI,GAAG,OAAO,CAAC,OAAO,CAAC,GAAG,CAAC,cAAc,CAAC,EAAE,KAAK,CAAC,GAAG,EAAE,CAAC,CAAC,CAAC,CAAC,CAAE,CAAC,IAAI,EAAE,CAAC,WAAW,EAAE,IAAI,EAAE,CAAC;IAC/F,IAAI,CAAC,UAAU,CAAC,QAAQ,CAAC,IAAI,CAAC;QAAE,OAAO,KAAK,CAAC;IAC7C,OAAO,OAAO,CAAC,OAAO,CAAC,GAAG,CAAC,QAAQ,CAAC,KAAK,GAAG,CAAC,MAAM,CAAC;AACtD,CAAC;AAED,0EAA0E;AAC1E,MAAM,UAAU,YAAY,CAAC,QAAgB;IAC3C,IAAI,CAAC,QAAQ,CAAC,UAAU,CAAC,OAAO,CAAC;QAAE,OAAO,KAAK,CAAC;IAChD,OAAO,CAAC,CAAC,QAAQ,CAAC,UAAU,CAAC,GAAG,SAAS,GAAG,CAAC,IAAI,QAAQ,CAAC,UAAU,CAAC,UAAU,CAAC,CAAC,CAAC;
|
|
1
|
+
{"version":3,"file":"guard.js","sourceRoot":"","sources":["../../src/runtime/guard.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,WAAW,CAAC;AAEtC,MAAM,CAAC,MAAM,UAAU,GAAG,cAAc,CAAC;AAEzC,MAAM,UAAU,GAAG,CAAC,mCAAmC,EAAE,qBAAqB,EAAE,YAAY,CAAC,CAAC;AAC9F,MAAM,MAAM,GAAG,CAAC,MAAM,EAAE,KAAK,EAAE,OAAO,EAAE,QAAQ,CAAC,CAAC;AAElD,2FAA2F;AAC3F,mEAAmE;AACnE,MAAM,UAAU,eAAe,CAAC,OAAgB,EAAE,GAAQ;IACxD,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,OAAO,CAAC,MAAM,CAAC;QAAE,OAAO,KAAK,CAAC;IACnD,MAAM,IAAI,GAAG,OAAO,CAAC,OAAO,CAAC,GAAG,CAAC,cAAc,CAAC,EAAE,KAAK,CAAC,GAAG,EAAE,CAAC,CAAC,CAAC,CAAC,CAAE,CAAC,IAAI,EAAE,CAAC,WAAW,EAAE,IAAI,EAAE,CAAC;IAC/F,IAAI,CAAC,UAAU,CAAC,QAAQ,CAAC,IAAI,CAAC;QAAE,OAAO,KAAK,CAAC;IAC7C,OAAO,OAAO,CAAC,OAAO,CAAC,GAAG,CAAC,QAAQ,CAAC,KAAK,GAAG,CAAC,MAAM,CAAC;AACtD,CAAC;AAED,0EAA0E;AAC1E,MAAM,UAAU,YAAY,CAAC,QAAgB;IAC3C,IAAI,CAAC,QAAQ,CAAC,UAAU,CAAC,OAAO,CAAC;QAAE,OAAO,KAAK,CAAC;IAChD,8FAA8F;IAC9F,OAAO,CAAC,CAAC,QAAQ,CAAC,UAAU,CAAC,GAAG,SAAS,GAAG,CAAC,IAAI,QAAQ,CAAC,UAAU,CAAC,UAAU,CAAC,IAAI,QAAQ,CAAC,UAAU,CAAC,YAAY,CAAC,CAAC,CAAC;AACzH,CAAC;AAMD,qEAAqE;AACrE,MAAM,OAAO,GAAmC;IAC9C,CAAC,GAAG,SAAS,gBAAgB,CAAC,EAAE,OAAO;IACvC,CAAC,GAAG,SAAS,yBAAyB,CAAC,EAAE,OAAO;IAChD,CAAC,GAAG,SAAS,iBAAiB,CAAC,EAAE,IAAI;IACrC,CAAC,GAAG,SAAS,gBAAgB,CAAC,EAAE,IAAI;CACrC,CAAC;AAEF,MAAM,CAAC,KAAK,UAAU,WAAW,CAAC,OAAgB,EAAE,QAAgB,EAAE,OAAgC;IACpG,MAAM,EAAE,GAAG,OAAO,CAAC,QAAQ,CAAC,CAAC;IAC7B,IAAI,CAAC,OAAO,IAAI,CAAC,EAAE,IAAI,OAAO,CAAC,MAAM,KAAK,MAAM;QAAE,OAAO,KAAK,CAAC;IAC/D,IAAI,OAAO,GAAG,OAAO,CAAC,OAAO,CAAC,GAAG,CAAC,kBAAkB,CAAC,IAAI,SAAS,CAAC;IACnE,IAAI,EAAE,KAAK,OAAO,EAAE,CAAC;QACnB,MAAM,IAAI,GAAG,CAAC,MAAM,OAAO,CAAC,KAAK,EAAE,CAAC,IAAI,EAAE,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC,CAAwB,CAAC;QACrF,IAAI,OAAO,IAAI,CAAC,KAAK,KAAK,QAAQ;YAAE,OAAO,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,EAAE,CAAC,WAAW,EAAE,CAAC;IAChF,CAAC;IACD,OAAO,CAAC,CAAC,MAAM,OAAO,CAAC,KAAK,CAAC,EAAE,GAAG,EAAE,GAAG,QAAQ,IAAI,OAAO,EAAE,EAAE,CAAC,CAAC,CAAC,OAAO,CAAC;AAC3E,CAAC"}
|
package/dist/runtime/index.d.ts
CHANGED
|
@@ -4,9 +4,13 @@ import { type Auth } from "./auth.js";
|
|
|
4
4
|
import { type Email, type EmailBindings } from "./email.js";
|
|
5
5
|
import { type Files, type FilesBindings } from "./files.js";
|
|
6
6
|
import { type RateLimiter } from "./guard.js";
|
|
7
|
+
import { type Live, type LiveNamespace } from "./live.js";
|
|
8
|
+
import type { LivePeer } from "./live-client.js";
|
|
7
9
|
export type { Auth } from "./auth.js";
|
|
8
10
|
export type { Email, EmailMessage } from "./email.js";
|
|
9
11
|
export type { FileEntry, Files, Folder, StoredObject } from "./files.js";
|
|
12
|
+
export type { Live } from "./live.js";
|
|
13
|
+
export type { LiveConnection, LiveHandlers, LivePeer } from "./live-client.js";
|
|
10
14
|
export interface PlatformBindings extends EmailBindings, FilesBindings {
|
|
11
15
|
DB?: {
|
|
12
16
|
connectionString: string;
|
|
@@ -16,6 +20,8 @@ export interface PlatformBindings extends EmailBindings, FilesBindings {
|
|
|
16
20
|
BETTER_AUTH_SECRET?: string;
|
|
17
21
|
AUTH_ORGANIZATIONS?: string;
|
|
18
22
|
AUTH_LIMIT?: RateLimiter;
|
|
23
|
+
LIVE?: LiveNamespace;
|
|
24
|
+
LIVE_ROOMS?: string;
|
|
19
25
|
}
|
|
20
26
|
export interface ExecutionContext {
|
|
21
27
|
waitUntil(promise: Promise<unknown>): void;
|
|
@@ -28,18 +34,26 @@ export interface AppContext<Env, Schema extends Record<string, unknown>> {
|
|
|
28
34
|
readonly email: Email;
|
|
29
35
|
readonly files: Files;
|
|
30
36
|
readonly auth: Auth;
|
|
37
|
+
readonly live: Live;
|
|
31
38
|
session(): Promise<Session | null>;
|
|
32
39
|
requireUser(): Promise<User>;
|
|
33
40
|
waitUntil(promise: Promise<unknown>): void;
|
|
34
41
|
}
|
|
35
42
|
export type Handler<Env, Schema extends Record<string, unknown>> = (request: Request, app: AppContext<Env, Schema>) => Response | Promise<Response>;
|
|
36
|
-
export interface
|
|
43
|
+
export interface LiveOptions<Env, Schema extends Record<string, unknown>> {
|
|
44
|
+
canJoin?(room: string, user: User | null, app: AppContext<Env, Schema>): boolean | Promise<boolean>;
|
|
45
|
+
canSend?(room: string, user: User | null, app: AppContext<Env, Schema>): boolean | Promise<boolean>;
|
|
46
|
+
onMessage?(room: string, message: unknown, from: LivePeer | null, app: AppContext<Env, Schema>): void | Promise<void>;
|
|
47
|
+
}
|
|
48
|
+
export interface AppOptions<Env, Schema extends Record<string, unknown>> {
|
|
37
49
|
schema?: Schema;
|
|
38
50
|
screens?: {
|
|
39
51
|
stylesheet?: string;
|
|
40
52
|
};
|
|
53
|
+
live?: LiveOptions<Env, Schema>;
|
|
41
54
|
pool?: (connectionString: string) => Pool;
|
|
42
55
|
}
|
|
43
|
-
export declare function defineApp<Secrets extends object = object, Schema extends Record<string, unknown> = Record<string, never>>(handler: Handler<Secrets & PlatformBindings, Schema>, options?: AppOptions<Schema>): {
|
|
56
|
+
export declare function defineApp<Secrets extends object = object, Schema extends Record<string, unknown> = Record<string, never>>(handler: Handler<Secrets & PlatformBindings, Schema>, options?: AppOptions<Secrets & PlatformBindings, Schema>): {
|
|
44
57
|
fetch(request: Request, env: Secrets & PlatformBindings, ctx: ExecutionContext): Promise<Response>;
|
|
58
|
+
LiveRoom: import("./live.js").LiveRoomClass;
|
|
45
59
|
};
|
package/dist/runtime/index.js
CHANGED
|
@@ -4,6 +4,7 @@ import { AUTH_PATH, createAuth } from "./auth.js";
|
|
|
4
4
|
import { createEmail } from "./email.js";
|
|
5
5
|
import { createFiles } from "./files.js";
|
|
6
6
|
import { isCrossSiteForm, needsSession, rateLimited } from "./guard.js";
|
|
7
|
+
import { CLIENT_PATH, clientScript, createLive, joinRoom, LIVE_PATH, liveRoom } from "./live.js";
|
|
7
8
|
import { isScreen, renderScreen } from "./screens.js";
|
|
8
9
|
const defaultPool = (connectionString) => new Pool({ connectionString, max: 5 });
|
|
9
10
|
const json = (body, status = 200) => Response.json(body, { status });
|
|
@@ -11,54 +12,17 @@ const json = (body, status = 200) => Response.json(body, { status });
|
|
|
11
12
|
// platform's own bindings are added to it. Pass the app's tables as `schema` for a typed `app.db`.
|
|
12
13
|
// A handler may throw a Response, as `requireUser` does, and it is sent as the answer.
|
|
13
14
|
export function defineApp(handler, options = {}) {
|
|
14
|
-
const
|
|
15
|
+
const onMessage = options.live?.onMessage;
|
|
15
16
|
return {
|
|
16
17
|
async fetch(request, env, ctx) {
|
|
17
18
|
const url = new URL(request.url);
|
|
18
|
-
|
|
19
|
-
let db;
|
|
20
|
-
let email;
|
|
21
|
-
let files;
|
|
22
|
-
let auth;
|
|
23
|
-
let session;
|
|
24
|
-
const app = {
|
|
25
|
-
env,
|
|
26
|
-
get db() {
|
|
27
|
-
if (!env.DB)
|
|
28
|
-
throw new Error("this app has no database; add `database` to platform.jsonc");
|
|
29
|
-
return (db ??= drizzle((pool ??= openPool(env.DB.connectionString)), { schema: options.schema ?? {} }));
|
|
30
|
-
},
|
|
31
|
-
get email() {
|
|
32
|
-
return (email ??= createEmail(env));
|
|
33
|
-
},
|
|
34
|
-
get files() {
|
|
35
|
-
return (files ??= createFiles(env));
|
|
36
|
-
},
|
|
37
|
-
get auth() {
|
|
38
|
-
if (!env.BETTER_AUTH_SECRET)
|
|
39
|
-
throw new Error("this app has no auth; set `auth: true` in platform.jsonc");
|
|
40
|
-
return (auth ??= createAuth({
|
|
41
|
-
db: app.db,
|
|
42
|
-
secret: env.BETTER_AUTH_SECRET,
|
|
43
|
-
baseURL: env.APP_URL ?? url.origin,
|
|
44
|
-
email: app.email,
|
|
45
|
-
requireVerification: env.EMAIL_MODE === "send",
|
|
46
|
-
}));
|
|
47
|
-
},
|
|
48
|
-
session() {
|
|
49
|
-
return (session ??= env.BETTER_AUTH_SECRET ? app.auth.api.getSession({ headers: request.headers }) : Promise.resolve(null));
|
|
50
|
-
},
|
|
51
|
-
async requireUser() {
|
|
52
|
-
const current = await app.session();
|
|
53
|
-
if (!current)
|
|
54
|
-
throw json({ error: "sign in first" }, 401);
|
|
55
|
-
return current.user;
|
|
56
|
-
},
|
|
57
|
-
waitUntil: (promise) => ctx.waitUntil(promise),
|
|
58
|
-
};
|
|
19
|
+
const { app, close } = createContext(request, env, ctx, options);
|
|
59
20
|
try {
|
|
60
21
|
if (isCrossSiteForm(request, url))
|
|
61
22
|
return json({ error: "cross-site form submissions are refused" }, 403);
|
|
23
|
+
const live = await liveRoute(request, url, env, app, options);
|
|
24
|
+
if (live)
|
|
25
|
+
return live;
|
|
62
26
|
if (env.BETTER_AUTH_SECRET) {
|
|
63
27
|
const platform = await platformRoute(request, url, env, app, options);
|
|
64
28
|
if (platform)
|
|
@@ -72,11 +36,90 @@ export function defineApp(handler, options = {}) {
|
|
|
72
36
|
throw thrown;
|
|
73
37
|
}
|
|
74
38
|
finally {
|
|
75
|
-
|
|
76
|
-
ctx.waitUntil(pool.end());
|
|
39
|
+
close();
|
|
77
40
|
}
|
|
78
41
|
},
|
|
42
|
+
// The Durable Object class behind live rooms, exported by the deploy's generated entry module.
|
|
43
|
+
// A browser's message reaches the app's onMessage with the same `app` a request gets.
|
|
44
|
+
LiveRoom: liveRoom((rawEnv) => {
|
|
45
|
+
if (!onMessage)
|
|
46
|
+
return undefined;
|
|
47
|
+
const env = rawEnv;
|
|
48
|
+
return async (room, message, from) => {
|
|
49
|
+
const pending = [];
|
|
50
|
+
const { app, close } = createContext(new Request(env.APP_URL ?? "https://app.invalid/"), env, { waitUntil: (p) => void pending.push(p) }, options);
|
|
51
|
+
try {
|
|
52
|
+
await onMessage(room, message, from, app);
|
|
53
|
+
await Promise.allSettled(pending);
|
|
54
|
+
}
|
|
55
|
+
finally {
|
|
56
|
+
close();
|
|
57
|
+
}
|
|
58
|
+
};
|
|
59
|
+
}),
|
|
60
|
+
};
|
|
61
|
+
}
|
|
62
|
+
function createContext(request, env, ctx, options) {
|
|
63
|
+
const openPool = options.pool ?? defaultPool;
|
|
64
|
+
let pool;
|
|
65
|
+
let db;
|
|
66
|
+
let email;
|
|
67
|
+
let files;
|
|
68
|
+
let auth;
|
|
69
|
+
let live;
|
|
70
|
+
let session;
|
|
71
|
+
const app = {
|
|
72
|
+
env,
|
|
73
|
+
get db() {
|
|
74
|
+
if (!env.DB)
|
|
75
|
+
throw new Error("this app has no database; add `database` to platform.jsonc");
|
|
76
|
+
return (db ??= drizzle((pool ??= openPool(env.DB.connectionString)), { schema: options.schema ?? {} }));
|
|
77
|
+
},
|
|
78
|
+
get email() {
|
|
79
|
+
return (email ??= createEmail(env));
|
|
80
|
+
},
|
|
81
|
+
get files() {
|
|
82
|
+
return (files ??= createFiles(env));
|
|
83
|
+
},
|
|
84
|
+
get auth() {
|
|
85
|
+
if (!env.BETTER_AUTH_SECRET)
|
|
86
|
+
throw new Error("this app has no auth; set `auth: true` in platform.jsonc");
|
|
87
|
+
return (auth ??= createAuth({
|
|
88
|
+
db: app.db,
|
|
89
|
+
secret: env.BETTER_AUTH_SECRET,
|
|
90
|
+
baseURL: env.APP_URL ?? new URL(request.url).origin,
|
|
91
|
+
email: app.email,
|
|
92
|
+
requireVerification: env.EMAIL_MODE === "send",
|
|
93
|
+
}));
|
|
94
|
+
},
|
|
95
|
+
get live() {
|
|
96
|
+
return (live ??= createLive(env.LIVE, env.LIVE_ROOMS === "on"));
|
|
97
|
+
},
|
|
98
|
+
session() {
|
|
99
|
+
return (session ??= env.BETTER_AUTH_SECRET ? app.auth.api.getSession({ headers: request.headers }) : Promise.resolve(null));
|
|
100
|
+
},
|
|
101
|
+
async requireUser() {
|
|
102
|
+
const current = await app.session();
|
|
103
|
+
if (!current)
|
|
104
|
+
throw json({ error: "sign in first" }, 401);
|
|
105
|
+
return current.user;
|
|
106
|
+
},
|
|
107
|
+
waitUntil: (promise) => ctx.waitUntil(promise),
|
|
79
108
|
};
|
|
109
|
+
return { app, close: () => void (pool && ctx.waitUntil(pool.end())) };
|
|
110
|
+
}
|
|
111
|
+
// Live rooms answer for themselves: the browser client, and joining a room once the app agrees.
|
|
112
|
+
async function liveRoute(request, url, env, app, options) {
|
|
113
|
+
if (!url.pathname.startsWith(LIVE_PATH) || env.LIVE_ROOMS !== "on" || !env.LIVE)
|
|
114
|
+
return undefined;
|
|
115
|
+
if (url.pathname === CLIENT_PATH)
|
|
116
|
+
return clientScript();
|
|
117
|
+
return joinRoom(request, url, env.LIVE, async (room) => {
|
|
118
|
+
const user = (await app.session())?.user ?? null;
|
|
119
|
+
const canJoin = (await options.live?.canJoin?.(room, user, app)) ?? false;
|
|
120
|
+
const canSend = canJoin && ((await options.live?.canSend?.(room, user, app)) ?? false);
|
|
121
|
+
return { user: user && { id: user.id, name: user.name }, canJoin, canSend };
|
|
122
|
+
});
|
|
80
123
|
}
|
|
81
124
|
// What the platform answers itself for an app with auth: screens, auth routes, and the sign-in
|
|
82
125
|
// check in front of every private /api route.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/runtime/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAuB,MAAM,2BAA2B,CAAC;AACzE,OAAO,EAAE,IAAI,EAAE,MAAM,IAAI,CAAC;AAC1B,OAAO,EAAE,SAAS,EAAE,UAAU,EAAa,MAAM,WAAW,CAAC;AAC7D,OAAO,EAAE,WAAW,EAAkC,MAAM,YAAY,CAAC;AACzE,OAAO,EAAE,WAAW,EAAkC,MAAM,YAAY,CAAC;AACzE,OAAO,EAAE,eAAe,EAAE,YAAY,EAAE,WAAW,EAAoB,MAAM,YAAY,CAAC;AAC1F,OAAO,EAAE,QAAQ,EAAE,YAAY,EAAE,MAAM,cAAc,CAAC;
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/runtime/index.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
export interface LivePeer {
|
|
2
|
+
id: string;
|
|
3
|
+
name: string;
|
|
4
|
+
}
|
|
5
|
+
export interface LiveHandlers {
|
|
6
|
+
onMessage?(data: unknown, meta: {
|
|
7
|
+
from: LivePeer | null;
|
|
8
|
+
seq: number;
|
|
9
|
+
}): void;
|
|
10
|
+
onPresence?(people: LivePeer[], anonymous: number): void;
|
|
11
|
+
onStatus?(status: "open" | "closed" | "refused"): void;
|
|
12
|
+
onError?(error: string): void;
|
|
13
|
+
onReload?(): void;
|
|
14
|
+
}
|
|
15
|
+
export interface LiveConnection {
|
|
16
|
+
send(data: unknown): boolean;
|
|
17
|
+
close(): void;
|
|
18
|
+
}
|
|
19
|
+
export declare function live(room: string, handlers?: LiveHandlers): LiveConnection;
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
// The browser side of live rooms. It has no imports and closes over nothing, so the runtime
|
|
2
|
+
// can also serve it as a script with `live.toString()`, for pages that have no bundler.
|
|
3
|
+
export function live(room, handlers = {}) {
|
|
4
|
+
let socket;
|
|
5
|
+
let last;
|
|
6
|
+
let stopped = false;
|
|
7
|
+
let attempts = 0;
|
|
8
|
+
const open = () => {
|
|
9
|
+
const url = new URL(`/api/live/${encodeURIComponent(room)}`, location.href);
|
|
10
|
+
url.protocol = url.protocol === "https:" ? "wss:" : "ws:";
|
|
11
|
+
if (last !== undefined)
|
|
12
|
+
url.searchParams.set("since", String(last));
|
|
13
|
+
const current = new WebSocket(url);
|
|
14
|
+
socket = current;
|
|
15
|
+
current.onopen = () => {
|
|
16
|
+
attempts = 0;
|
|
17
|
+
handlers.onStatus?.("open");
|
|
18
|
+
};
|
|
19
|
+
current.onmessage = (event) => {
|
|
20
|
+
const frame = JSON.parse(String(event.data));
|
|
21
|
+
if (frame.type === "hello") {
|
|
22
|
+
if (last === undefined)
|
|
23
|
+
last = frame.seq;
|
|
24
|
+
}
|
|
25
|
+
else if (frame.type === "message") {
|
|
26
|
+
last = frame.seq;
|
|
27
|
+
handlers.onMessage?.(frame.data, { from: frame.from, seq: frame.seq });
|
|
28
|
+
}
|
|
29
|
+
else if (frame.type === "ack") {
|
|
30
|
+
last = Math.max(last ?? 0, frame.seq);
|
|
31
|
+
}
|
|
32
|
+
else if (frame.type === "presence") {
|
|
33
|
+
handlers.onPresence?.(frame.people, frame.anonymous);
|
|
34
|
+
}
|
|
35
|
+
else if (frame.type === "reload") {
|
|
36
|
+
last = undefined;
|
|
37
|
+
if (handlers.onReload)
|
|
38
|
+
handlers.onReload();
|
|
39
|
+
else
|
|
40
|
+
location.reload();
|
|
41
|
+
}
|
|
42
|
+
else if (frame.type === "error") {
|
|
43
|
+
handlers.onError?.(frame.error);
|
|
44
|
+
}
|
|
45
|
+
};
|
|
46
|
+
current.onclose = (event) => {
|
|
47
|
+
if (socket !== current)
|
|
48
|
+
return;
|
|
49
|
+
// 4403 and 4404 mean the app refused this room; trying again would only be refused again.
|
|
50
|
+
if (event.code === 4403 || event.code === 4404) {
|
|
51
|
+
stopped = true;
|
|
52
|
+
handlers.onStatus?.("refused");
|
|
53
|
+
return;
|
|
54
|
+
}
|
|
55
|
+
handlers.onStatus?.("closed");
|
|
56
|
+
if (!stopped)
|
|
57
|
+
setTimeout(open, Math.min(15000, 500 * 2 ** attempts++));
|
|
58
|
+
};
|
|
59
|
+
};
|
|
60
|
+
open();
|
|
61
|
+
return {
|
|
62
|
+
send(data) {
|
|
63
|
+
if (socket?.readyState !== 1)
|
|
64
|
+
return false;
|
|
65
|
+
socket.send(JSON.stringify({ data }));
|
|
66
|
+
return true;
|
|
67
|
+
},
|
|
68
|
+
close() {
|
|
69
|
+
stopped = true;
|
|
70
|
+
socket?.close();
|
|
71
|
+
},
|
|
72
|
+
};
|
|
73
|
+
}
|
|
74
|
+
//# sourceMappingURL=live-client.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"live-client.js","sourceRoot":"","sources":["../../src/runtime/live-client.ts"],"names":[],"mappings":"AAAA,4FAA4F;AAC5F,wFAAwF;AAuBxF,MAAM,UAAU,IAAI,CAAC,IAAY,EAAE,QAAQ,GAAiB,EAAE;IAC5D,IAAI,MAA6B,CAAC;IAClC,IAAI,IAAwB,CAAC;IAC7B,IAAI,OAAO,GAAG,KAAK,CAAC;IACpB,IAAI,QAAQ,GAAG,CAAC,CAAC;IAEjB,MAAM,IAAI,GAAG,GAAG,EAAE;QAChB,MAAM,GAAG,GAAG,IAAI,GAAG,CAAC,aAAa,kBAAkB,CAAC,IAAI,CAAC,EAAE,EAAE,QAAQ,CAAC,IAAI,CAAC,CAAC;QAC5E,GAAG,CAAC,QAAQ,GAAG,GAAG,CAAC,QAAQ,KAAK,QAAQ,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,KAAK,CAAC;QAC1D,IAAI,IAAI,KAAK,SAAS;YAAE,GAAG,CAAC,YAAY,CAAC,GAAG,CAAC,OAAO,EAAE,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC;QACpE,MAAM,OAAO,GAAG,IAAI,SAAS,CAAC,GAAG,CAAC,CAAC;QACnC,MAAM,GAAG,OAAO,CAAC;QACjB,OAAO,CAAC,MAAM,GAAG,GAAG,EAAE;YACpB,QAAQ,GAAG,CAAC,CAAC;YACb,QAAQ,CAAC,QAAQ,EAAE,CAAC,MAAM,CAAC,CAAC;QAC9B,CAAC,CAAC;QACF,OAAO,CAAC,SAAS,GAAG,CAAC,KAAK,EAAE,EAAE;YAC5B,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC;YAC7C,IAAI,KAAK,CAAC,IAAI,KAAK,OAAO,EAAE,CAAC;gBAC3B,IAAI,IAAI,KAAK,SAAS;oBAAE,IAAI,GAAG,KAAK,CAAC,GAAG,CAAC;YAC3C,CAAC;iBAAM,IAAI,KAAK,CAAC,IAAI,KAAK,SAAS,EAAE,CAAC;gBACpC,IAAI,GAAG,KAAK,CAAC,GAAG,CAAC;gBACjB,QAAQ,CAAC,SAAS,EAAE,CAAC,KAAK,CAAC,IAAI,EAAE,EAAE,IAAI,EAAE,KAAK,CAAC,IAAI,EAAE,GAAG,EAAE,KAAK,CAAC,GAAG,EAAE,CAAC,CAAC;YACzE,CAAC;iBAAM,IAAI,KAAK,CAAC,IAAI,KAAK,KAAK,EAAE,CAAC;gBAChC,IAAI,GAAG,IAAI,CAAC,GAAG,CAAC,IAAI,IAAI,CAAC,EAAE,KAAK,CAAC,GAAG,CAAC,CAAC;YACxC,CAAC;iBAAM,IAAI,KAAK,CAAC,IAAI,KAAK,UAAU,EAAE,CAAC;gBACrC,QAAQ,CAAC,UAAU,EAAE,CAAC,KAAK,CAAC,MAAM,EAAE,KAAK,CAAC,SAAS,CAAC,CAAC;YACvD,CAAC;iBAAM,IAAI,KAAK,CAAC,IAAI,KAAK,QAAQ,EAAE,CAAC;gBACnC,IAAI,GAAG,SAAS,CAAC;gBACjB,IAAI,QAAQ,CAAC,QAAQ;oBAAE,QAAQ,CAAC,QAAQ,EAAE,CAAC;;oBACtC,QAAQ,CAAC,MAAM,EAAE,CAAC;YACzB,CAAC;iBAAM,IAAI,KAAK,CAAC,IAAI,KAAK,OAAO,EAAE,CAAC;gBAClC,QAAQ,CAAC,OAAO,EAAE,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC;YAClC,CAAC;QACH,CAAC,CAAC;QACF,OAAO,CAAC,OAAO,GAAG,CAAC,KAAK,EAAE,EAAE;YAC1B,IAAI,MAAM,KAAK,OAAO;gBAAE,OAAO;YAC/B,0FAA0F;YAC1F,IAAI,KAAK,CAAC,IAAI,KAAK,IAAI,IAAI,KAAK,CAAC,IAAI,KAAK,IAAI,EAAE,CAAC;gBAC/C,OAAO,GAAG,IAAI,CAAC;gBACf,QAAQ,CAAC,QAAQ,EAAE,CAAC,SAAS,CAAC,CAAC;gBAC/B,OAAO;YACT,CAAC;YACD,QAAQ,CAAC,QAAQ,EAAE,CAAC,QAAQ,CAAC,CAAC;YAC9B,IAAI,CAAC,OAAO;gBAAE,UAAU,CAAC,IAAI,EAAE,IAAI,CAAC,GAAG,CAAC,KAAK,EAAE,GAAG,GAAG,CAAC,IAAI,QAAQ,EAAE,CAAC,CAAC,CAAC;QACzE,CAAC,CAAC;IACJ,CAAC,CAAC;IAEF,IAAI,EAAE,CAAC;IACP,OAAO;QACL,IAAI,CAAC,IAAI;YACP,IAAI,MAAM,EAAE,UAAU,KAAK,CAAC;gBAAE,OAAO,KAAK,CAAC;YAC3C,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,SAAS,CAAC,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC;YACtC,OAAO,IAAI,CAAC;QACd,CAAC;QACD,KAAK;YACH,OAAO,GAAG,IAAI,CAAC;YACf,MAAM,EAAE,KAAK,EAAE,CAAC;QAClB,CAAC;KACF,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import type { LivePeer } from "./live-client.js";
|
|
2
|
+
export declare const LIVE_PATH = "/api/live/";
|
|
3
|
+
export declare const CLIENT_PATH = "/api/live/client.js";
|
|
4
|
+
export declare const MAX_MESSAGE: number;
|
|
5
|
+
export declare const KEPT_MESSAGES = 500;
|
|
6
|
+
export interface LiveNamespace {
|
|
7
|
+
idFromName(name: string): unknown;
|
|
8
|
+
get(id: unknown): {
|
|
9
|
+
fetch(request: Request): Promise<Response>;
|
|
10
|
+
};
|
|
11
|
+
}
|
|
12
|
+
export interface Live {
|
|
13
|
+
publish(room: string, message: unknown): Promise<void>;
|
|
14
|
+
}
|
|
15
|
+
export declare const clientScript: () => Response;
|
|
16
|
+
export declare function createLive(namespace: LiveNamespace | undefined, enabled: boolean): Live;
|
|
17
|
+
export interface JoinDecision {
|
|
18
|
+
user: LivePeer | null;
|
|
19
|
+
canJoin: boolean;
|
|
20
|
+
canSend: boolean;
|
|
21
|
+
}
|
|
22
|
+
export declare function joinRoom(request: Request, url: URL, namespace: LiveNamespace, decide: (room: string) => Promise<JoinDecision>): Promise<Response>;
|
|
23
|
+
export type OnMessage = (room: string, message: unknown, from: LivePeer | null) => Promise<void>;
|
|
24
|
+
export interface LiveRoomClass {
|
|
25
|
+
new (state: unknown, env: unknown): {
|
|
26
|
+
fetch(request: Request): Promise<Response>;
|
|
27
|
+
};
|
|
28
|
+
}
|
|
29
|
+
export declare function liveRoom(onMessage: (env: unknown) => OnMessage | undefined): LiveRoomClass;
|
|
@@ -0,0 +1,158 @@
|
|
|
1
|
+
import { live as client } from "./live-client.js";
|
|
2
|
+
// Live rooms: one Durable Object per room name, holding the open sockets, a numbered window of
|
|
3
|
+
// recent messages for catching up, and who is connected. Rooms carry messages only; what they
|
|
4
|
+
// mean and whether anything is saved is the app's business.
|
|
5
|
+
export const LIVE_PATH = "/api/live/";
|
|
6
|
+
export const CLIENT_PATH = `${LIVE_PATH}client.js`;
|
|
7
|
+
export const MAX_MESSAGE = 64 * 1024;
|
|
8
|
+
export const KEPT_MESSAGES = 500;
|
|
9
|
+
const ROOM_NAME = /^[A-Za-z0-9:_.-]{1,200}$/;
|
|
10
|
+
export const clientScript = () => new Response(`export ${client.toString()}\n`, { headers: { "content-type": "text/javascript; charset=utf-8", "cache-control": "public, max-age=300" } });
|
|
11
|
+
const roomStub = (namespace, room) => namespace.get(namespace.idFromName(room));
|
|
12
|
+
export function createLive(namespace, enabled) {
|
|
13
|
+
return {
|
|
14
|
+
async publish(room, message) {
|
|
15
|
+
if (!enabled || !namespace)
|
|
16
|
+
throw new Error("this app has no live rooms; set `live: true` in platform.jsonc");
|
|
17
|
+
if (!ROOM_NAME.test(room))
|
|
18
|
+
throw new Error(`invalid room name ${room}`);
|
|
19
|
+
const body = JSON.stringify(message);
|
|
20
|
+
if (body.length > MAX_MESSAGE)
|
|
21
|
+
throw new Error(`live messages are limited to ${MAX_MESSAGE} bytes`);
|
|
22
|
+
const response = await roomStub(namespace, room).fetch(new Request("https://room/publish", { method: "POST", headers: { "x-room": room }, body }));
|
|
23
|
+
if (!response.ok)
|
|
24
|
+
throw new Error(`publishing to ${room} failed: ${response.status}`);
|
|
25
|
+
},
|
|
26
|
+
};
|
|
27
|
+
}
|
|
28
|
+
// A refusal is sent as a closed socket with a reason, so the browser client knows to stop retrying.
|
|
29
|
+
function refuse(code, reason) {
|
|
30
|
+
const pair = new WebSocketPair();
|
|
31
|
+
const socket = pair[1];
|
|
32
|
+
socket.accept();
|
|
33
|
+
socket.close(code, reason);
|
|
34
|
+
return new Response(null, { status: 101, webSocket: pair[0] });
|
|
35
|
+
}
|
|
36
|
+
// The Worker decides who joins and who may send; the room trusts what it is told, since only
|
|
37
|
+
// the Worker can reach it.
|
|
38
|
+
export async function joinRoom(request, url, namespace, decide) {
|
|
39
|
+
if (request.headers.get("upgrade")?.toLowerCase() !== "websocket")
|
|
40
|
+
return new Response("expected a WebSocket", { status: 426 });
|
|
41
|
+
const room = decodeURIComponent(url.pathname.slice(LIVE_PATH.length));
|
|
42
|
+
if (!ROOM_NAME.test(room))
|
|
43
|
+
return refuse(4404, "no such room");
|
|
44
|
+
const { user, canJoin, canSend } = await decide(room);
|
|
45
|
+
if (!canJoin)
|
|
46
|
+
return refuse(4403, "not allowed to join");
|
|
47
|
+
const headers = new Headers(request.headers);
|
|
48
|
+
headers.set("x-room", room);
|
|
49
|
+
headers.set("x-attachment", JSON.stringify({ room, user, canSend }));
|
|
50
|
+
const since = url.searchParams.get("since");
|
|
51
|
+
return roomStub(namespace, room).fetch(new Request(`https://room/join${since ? `?since=${encodeURIComponent(since)}` : ""}`, { headers }));
|
|
52
|
+
}
|
|
53
|
+
export function liveRoom(onMessage) {
|
|
54
|
+
return class LiveRoom {
|
|
55
|
+
env;
|
|
56
|
+
state;
|
|
57
|
+
constructor(state, env) {
|
|
58
|
+
this.env = env;
|
|
59
|
+
this.state = state;
|
|
60
|
+
this.state.storage.sql.exec("create table if not exists messages (seq integer primary key autoincrement, body text not null, sender text not null)");
|
|
61
|
+
}
|
|
62
|
+
async fetch(request) {
|
|
63
|
+
const url = new URL(request.url);
|
|
64
|
+
if (url.pathname === "/publish") {
|
|
65
|
+
this.deliver(await request.text(), null);
|
|
66
|
+
return new Response(null, { status: 204 });
|
|
67
|
+
}
|
|
68
|
+
const attachment = JSON.parse(request.headers.get("x-attachment") ?? "null");
|
|
69
|
+
const pair = new WebSocketPair();
|
|
70
|
+
const socket = pair[1];
|
|
71
|
+
this.state.acceptWebSocket(socket);
|
|
72
|
+
socket.serializeAttachment(attachment);
|
|
73
|
+
socket.send(JSON.stringify({ type: "hello", seq: this.latest() }));
|
|
74
|
+
const since = url.searchParams.get("since");
|
|
75
|
+
if (since !== null)
|
|
76
|
+
this.catchUp(socket, Number(since));
|
|
77
|
+
this.presence();
|
|
78
|
+
return new Response(null, { status: 101, webSocket: pair[0] });
|
|
79
|
+
}
|
|
80
|
+
async webSocketMessage(socket, raw) {
|
|
81
|
+
const attachment = socket.deserializeAttachment();
|
|
82
|
+
if (!attachment.canSend)
|
|
83
|
+
return socket.send(JSON.stringify({ type: "error", error: "not allowed to send to this room" }));
|
|
84
|
+
if (typeof raw !== "string" || raw.length > MAX_MESSAGE)
|
|
85
|
+
return socket.send(JSON.stringify({ type: "error", error: `messages are text up to ${MAX_MESSAGE} bytes` }));
|
|
86
|
+
let data;
|
|
87
|
+
try {
|
|
88
|
+
data = JSON.parse(raw).data;
|
|
89
|
+
}
|
|
90
|
+
catch {
|
|
91
|
+
return socket.send(JSON.stringify({ type: "error", error: "messages are JSON" }));
|
|
92
|
+
}
|
|
93
|
+
const seq = this.deliver(JSON.stringify(data ?? null), attachment.user, socket);
|
|
94
|
+
socket.send(JSON.stringify({ type: "ack", seq }));
|
|
95
|
+
const hook = onMessage(this.env);
|
|
96
|
+
if (hook)
|
|
97
|
+
this.state.waitUntil(hook(attachment.room, data, attachment.user));
|
|
98
|
+
}
|
|
99
|
+
webSocketClose(socket, code, reason) {
|
|
100
|
+
try {
|
|
101
|
+
socket.close(code, reason);
|
|
102
|
+
}
|
|
103
|
+
catch {
|
|
104
|
+
// already closed
|
|
105
|
+
}
|
|
106
|
+
this.presence(socket);
|
|
107
|
+
}
|
|
108
|
+
webSocketError(socket) {
|
|
109
|
+
this.presence(socket);
|
|
110
|
+
}
|
|
111
|
+
latest() {
|
|
112
|
+
return Number(this.state.storage.sql.exec("select coalesce(max(seq), 0) as seq from messages").toArray()[0].seq);
|
|
113
|
+
}
|
|
114
|
+
// A browser gone longer than the kept window can only be told to reload.
|
|
115
|
+
catchUp(socket, since) {
|
|
116
|
+
const oldest = Number(this.state.storage.sql.exec("select coalesce(min(seq), 0) as seq from messages").toArray()[0].seq);
|
|
117
|
+
if (since + 1 < oldest)
|
|
118
|
+
return socket.send(JSON.stringify({ type: "reload" }));
|
|
119
|
+
for (const row of this.state.storage.sql.exec("select seq, body, sender from messages where seq > ? order by seq", since).toArray()) {
|
|
120
|
+
socket.send(`{"type":"message","seq":${row.seq},"from":${row.sender},"data":${row.body}}`);
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
deliver(body, from, except) {
|
|
124
|
+
const sender = JSON.stringify(from);
|
|
125
|
+
const seq = Number(this.state.storage.sql.exec("insert into messages (body, sender) values (?, ?) returning seq", body, sender).toArray()[0].seq);
|
|
126
|
+
this.state.storage.sql.exec("delete from messages where seq <= ?", seq - KEPT_MESSAGES);
|
|
127
|
+
const frame = `{"type":"message","seq":${seq},"from":${sender},"data":${body}}`;
|
|
128
|
+
for (const socket of this.state.getWebSockets())
|
|
129
|
+
if (socket !== except)
|
|
130
|
+
trySend(socket, frame);
|
|
131
|
+
return seq;
|
|
132
|
+
}
|
|
133
|
+
presence(leaving) {
|
|
134
|
+
const sockets = this.state.getWebSockets().filter((s) => s !== leaving);
|
|
135
|
+
const people = new Map();
|
|
136
|
+
let anonymous = 0;
|
|
137
|
+
for (const socket of sockets) {
|
|
138
|
+
const { user } = socket.deserializeAttachment();
|
|
139
|
+
if (user)
|
|
140
|
+
people.set(user.id, user);
|
|
141
|
+
else
|
|
142
|
+
anonymous++;
|
|
143
|
+
}
|
|
144
|
+
const frame = JSON.stringify({ type: "presence", people: [...people.values()], anonymous });
|
|
145
|
+
for (const socket of sockets)
|
|
146
|
+
trySend(socket, frame);
|
|
147
|
+
}
|
|
148
|
+
};
|
|
149
|
+
}
|
|
150
|
+
function trySend(socket, frame) {
|
|
151
|
+
try {
|
|
152
|
+
socket.send(frame);
|
|
153
|
+
}
|
|
154
|
+
catch {
|
|
155
|
+
// the socket closed between listing and sending; its close handler updates presence
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
//# sourceMappingURL=live.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"live.js","sourceRoot":"","sources":["../../src/runtime/live.ts"],"names":[],"mappings":"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"}
|
package/dist/target.d.ts
CHANGED
|
@@ -13,5 +13,6 @@ export interface Names {
|
|
|
13
13
|
filesPrefix: string;
|
|
14
14
|
}
|
|
15
15
|
export declare function names(config: Config, target: Target): Names;
|
|
16
|
-
export declare
|
|
16
|
+
export declare const previewPattern: (app: string) => RegExp;
|
|
17
|
+
export declare function previewHostname(pr: number, hostname: string): string;
|
|
17
18
|
export declare function originOf(connectionUri: string): string;
|
package/dist/target.js
CHANGED
|
@@ -1,19 +1,21 @@
|
|
|
1
|
-
//
|
|
1
|
+
// Every name is the app name, alone or followed by a suffix after `--`, which app names never
|
|
2
|
+
// contain. Prod gets its own bucket; previews share one, each under its PR's folder.
|
|
2
3
|
export function names(config, target) {
|
|
3
4
|
if (target.kind === "prod") {
|
|
4
|
-
return { worker: config.name, hyperdrive: config.name, neonBranch: undefined, bucket: `${config.name}
|
|
5
|
+
return { worker: config.name, hyperdrive: config.name, neonBranch: undefined, bucket: `${config.name}--files`, filesPrefix: "" };
|
|
5
6
|
}
|
|
6
7
|
const suffix = `pr-${target.pr}`;
|
|
7
8
|
return {
|
|
8
|
-
worker: `${config.name}
|
|
9
|
-
hyperdrive: `${config.name}
|
|
9
|
+
worker: `${config.name}--${suffix}`,
|
|
10
|
+
hyperdrive: `${config.name}--${suffix}`,
|
|
10
11
|
neonBranch: suffix,
|
|
11
|
-
bucket: `${config.name}
|
|
12
|
+
bucket: `${config.name}--previews`,
|
|
12
13
|
filesPrefix: `${suffix}/`,
|
|
13
14
|
};
|
|
14
15
|
}
|
|
15
|
-
export
|
|
16
|
-
|
|
16
|
+
export const previewPattern = (app) => new RegExp(`^${app}--pr-(\\d+)$`);
|
|
17
|
+
export function previewHostname(pr, hostname) {
|
|
18
|
+
return `pr-${pr}.${hostname}`;
|
|
17
19
|
}
|
|
18
20
|
export function originOf(connectionUri) {
|
|
19
21
|
const url = new URL(connectionUri);
|
package/dist/target.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"target.js","sourceRoot":"","sources":["../src/target.ts"],"names":[],"mappings":"AAYA,
|
|
1
|
+
{"version":3,"file":"target.js","sourceRoot":"","sources":["../src/target.ts"],"names":[],"mappings":"AAYA,8FAA8F;AAC9F,qFAAqF;AACrF,MAAM,UAAU,KAAK,CAAC,MAAc,EAAE,MAAc;IAClD,IAAI,MAAM,CAAC,IAAI,KAAK,MAAM,EAAE,CAAC;QAC3B,OAAO,EAAE,MAAM,EAAE,MAAM,CAAC,IAAI,EAAE,UAAU,EAAE,MAAM,CAAC,IAAI,EAAE,UAAU,EAAE,SAAS,EAAE,MAAM,EAAE,GAAG,MAAM,CAAC,IAAI,SAAS,EAAE,WAAW,EAAE,EAAE,EAAE,CAAC;IACnI,CAAC;IACD,MAAM,MAAM,GAAG,MAAM,MAAM,CAAC,EAAE,EAAE,CAAC;IACjC,OAAO;QACL,MAAM,EAAE,GAAG,MAAM,CAAC,IAAI,KAAK,MAAM,EAAE;QACnC,UAAU,EAAE,GAAG,MAAM,CAAC,IAAI,KAAK,MAAM,EAAE;QACvC,UAAU,EAAE,MAAM;QAClB,MAAM,EAAE,GAAG,MAAM,CAAC,IAAI,YAAY;QAClC,WAAW,EAAE,GAAG,MAAM,GAAG;KAC1B,CAAC;AACJ,CAAC;AAED,MAAM,CAAC,MAAM,cAAc,GAAG,CAAC,GAAW,EAAE,EAAE,CAAC,IAAI,MAAM,CAAC,IAAI,GAAG,cAAc,CAAC,CAAC;AAEjF,MAAM,UAAU,eAAe,CAAC,EAAU,EAAE,QAAgB;IAC1D,OAAO,MAAM,EAAE,IAAI,QAAQ,EAAE,CAAC;AAChC,CAAC;AAED,MAAM,UAAU,QAAQ,CAAC,aAAqB;IAC5C,MAAM,GAAG,GAAG,IAAI,GAAG,CAAC,aAAa,CAAC,CAAC;IACnC,OAAO,GAAG,GAAG,CAAC,QAAQ,IAAI,GAAG,CAAC,IAAI,GAAG,GAAG,CAAC,QAAQ,EAAE,CAAC;AACtD,CAAC"}
|
|
@@ -12,5 +12,7 @@ export declare const AUTH_LIMIT: {
|
|
|
12
12
|
readonly limit: 10;
|
|
13
13
|
readonly period: 60;
|
|
14
14
|
};
|
|
15
|
+
export declare const ENTRY_FILE = ".platform-entry.ts";
|
|
16
|
+
export declare function entryModule(worker: string): string;
|
|
15
17
|
export declare function wranglerConfig({ config, worker, hostname, accountId, hyperdriveId, vars, bucket }: WranglerInput): object;
|
|
16
18
|
export declare function namespaceId(worker: string): string;
|