rivet-design 0.28.1 → 0.28.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cli/commands/open.js +4 -2
- package/dist/cli/commands/serve.js +1 -0
- package/dist/jest.globalSetup.d.ts +3 -0
- package/dist/jest.globalSetup.js +19 -0
- package/dist/proxy-middleware/proxy-config.d.ts +0 -1
- package/dist/proxy-middleware/proxy-config.js +6 -34
- package/dist/routes/agentVariants.js +20 -173
- package/dist/routes/static.js +8 -2
- package/dist/server.d.ts +1 -1
- package/dist/server.js +13 -25
- package/dist/services/AuthService.js +7 -61
- package/dist/services/templates/viteReactTs.js +1 -1
- package/dist/types/rivet-page-types.d.ts +48 -0
- package/dist/types/rivet-page-types.js +6 -0
- package/dist/utils/rivetPage.d.ts +8 -0
- package/dist/utils/rivetPage.js +24 -0
- package/dist/utils/rivetPage.testHelpers.d.ts +6 -0
- package/dist/utils/rivetPage.testHelpers.js +18 -0
- package/dist/utils/rivetPageDocument.d.ts +7 -0
- package/dist/utils/rivetPageDocument.js +41 -0
- package/dist/utils/scriptJson.d.ts +2 -0
- package/dist/utils/scriptJson.js +9 -0
- package/dist/utils/uiDistPath.d.ts +2 -0
- package/dist/utils/uiDistPath.js +22 -0
- package/package.json +8 -5
- package/src/ui/dist/assets/LibraryEntry-B8-RtQpK.js +2 -0
- package/src/ui/dist/assets/google-g-CpxN0HWb.png +0 -0
- package/src/ui/dist/assets/main-11-ME6E3.css +1 -0
- package/src/ui/dist/assets/main-BGCGsyhl.js +204 -0
- package/src/ui/dist/index.html +3 -3
- package/src/ui/dist/pages/empty-project.html +53 -0
- package/src/ui/dist/pages/rivet-page.html +53 -0
- package/dist/routes/emptyStatePage.d.ts +0 -2
- package/dist/routes/emptyStatePage.js +0 -589
- package/src/ui/dist/assets/LibraryEntry-DS6Ce0sW.js +0 -112
- package/src/ui/dist/assets/logo-animation/clasp.png +0 -0
- package/src/ui/dist/assets/logo-animation/eraser.png +0 -0
- package/src/ui/dist/assets/logo-animation/playdough.png +0 -0
- package/src/ui/dist/assets/logo-animation/sea/bubblephone.png +0 -0
- package/src/ui/dist/assets/logo-animation/sea/cart.png +0 -0
- package/src/ui/dist/assets/logo-animation/sea/chair.png +0 -0
- package/src/ui/dist/assets/logo-animation/sea/desk.png +0 -0
- package/src/ui/dist/assets/logo-animation/sea/mug.png +0 -0
- package/src/ui/dist/assets/logo-animation/sea/pitcher.png +0 -0
- package/src/ui/dist/assets/logo-animation/sea/pot.png +0 -0
- package/src/ui/dist/assets/logo-animation/sea/startac.png +0 -0
- package/src/ui/dist/assets/logo-animation/sea/terracotta-1.png +0 -0
- package/src/ui/dist/assets/logo-animation/sea/terracotta-2.png +0 -0
- package/src/ui/dist/assets/logo-animation/sea/vhsplant.png +0 -0
- package/src/ui/dist/assets/main-CQSk-6km.css +0 -1
- package/src/ui/dist/assets/main-DkKRuatC.js +0 -218
|
@@ -70,6 +70,7 @@ const SERVER_START_TIMEOUT_ENV = 'RIVET_SERVER_START_TIMEOUT_MS';
|
|
|
70
70
|
const LOCK_WAIT_TIMEOUT_ENV = 'RIVET_LOCK_WAIT_TIMEOUT_MS';
|
|
71
71
|
const OPEN_RETRY_DELAY_MS = 1_000;
|
|
72
72
|
const APP_HEALTH_TIMEOUT_MS = 10_000;
|
|
73
|
+
const APP_HEALTH_TIMEOUT_ENV = 'RIVET_APP_HEALTH_TIMEOUT_MS';
|
|
73
74
|
const RETRY_OPEN_RECOVERY = {
|
|
74
75
|
isRecoverable: true,
|
|
75
76
|
nextAction: { action: 'retry', delayMs: OPEN_RETRY_DELAY_MS },
|
|
@@ -247,6 +248,7 @@ const ensureProjectRuntime = async (context, io, dependencies = {}) => {
|
|
|
247
248
|
const env = dependencies.env ?? process.env;
|
|
248
249
|
const serverStartTimeoutMs = timeoutFromEnv(env, SERVER_START_TIMEOUT_ENV, DEFAULT_SERVER_START_TIMEOUT_MS);
|
|
249
250
|
const lockWaitTimeoutMs = timeoutFromEnv(env, LOCK_WAIT_TIMEOUT_ENV, DEFAULT_LOCK_WAIT_TIMEOUT_MS);
|
|
251
|
+
const appHealthTimeoutMs = timeoutFromEnv(env, APP_HEALTH_TIMEOUT_ENV, Math.min(serverStartTimeoutMs, APP_HEALTH_TIMEOUT_MS));
|
|
250
252
|
const validation = await (0, exports.validateProjectOpen)({
|
|
251
253
|
context,
|
|
252
254
|
io,
|
|
@@ -292,7 +294,7 @@ const ensureProjectRuntime = async (context, io, dependencies = {}) => {
|
|
|
292
294
|
}, RETRY_OPEN_RECOVERY);
|
|
293
295
|
}
|
|
294
296
|
if (replacement.outcome === 'attach') {
|
|
295
|
-
const readinessError = await verifyRuntimeReadiness(existing,
|
|
297
|
+
const readinessError = await verifyRuntimeReadiness(existing, appHealthTimeoutMs);
|
|
296
298
|
if (!readinessError) {
|
|
297
299
|
return finishProjectOpen(await openedData(existing, true), io);
|
|
298
300
|
}
|
|
@@ -346,7 +348,7 @@ const ensureProjectRuntime = async (context, io, dependencies = {}) => {
|
|
|
346
348
|
...(0, serverVersion_1.versionEnvelopeFields)(attached.handshake),
|
|
347
349
|
});
|
|
348
350
|
}
|
|
349
|
-
const readinessError = await verifyRuntimeReadiness(attached,
|
|
351
|
+
const readinessError = await verifyRuntimeReadiness(attached, appHealthTimeoutMs);
|
|
350
352
|
if (readinessError)
|
|
351
353
|
return readinessError;
|
|
352
354
|
const data = await openedData(attached, false);
|
|
@@ -200,6 +200,7 @@ const handleServe = async (args, io) => {
|
|
|
200
200
|
previewPort,
|
|
201
201
|
agentApplyMode: 'external',
|
|
202
202
|
rivetPort,
|
|
203
|
+
resolveProjectName: (targetPath) => library.registry.findByPath(targetPath)?.name,
|
|
203
204
|
resolveLibraryOrigin: () => {
|
|
204
205
|
const hub = hubDiscovery.read();
|
|
205
206
|
return hub?.port && (0, pid_1.isPidAlive)(hub.pid)
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
const fs_1 = __importDefault(require("fs"));
|
|
7
|
+
const path_1 = __importDefault(require("path"));
|
|
8
|
+
const rivetPage_1 = require("./utils/rivetPage");
|
|
9
|
+
const ensureRivetPageShells = () => {
|
|
10
|
+
fs_1.default.mkdirSync(rivetPage_1.RIVET_PAGE_SHELL_DIRECTORY, { recursive: true });
|
|
11
|
+
for (const shellFile of rivetPage_1.RIVET_PAGE_SHELL_FILES) {
|
|
12
|
+
const builtShell = path_1.default.join(rivetPage_1.RIVET_PAGE_SHELL_DIRECTORY, shellFile);
|
|
13
|
+
if (!fs_1.default.existsSync(builtShell)) {
|
|
14
|
+
fs_1.default.copyFileSync(path_1.default.join(__dirname, 'ui', shellFile), builtShell);
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
};
|
|
18
|
+
exports.default = ensureRivetPageShells;
|
|
19
|
+
//# sourceMappingURL=jest.globalSetup.js.map
|
|
@@ -14,7 +14,6 @@ export declare const resolveTargetAddressedPreview: (args: {
|
|
|
14
14
|
resolveVariantPreviewPort?: ResolveVariantPreviewPort;
|
|
15
15
|
}) => TargetAddressedPreview | null;
|
|
16
16
|
export declare const markPreviewBridgeDocumentUncacheable: (proxyRes: IncomingMessage) => void;
|
|
17
|
-
export declare const buildPreviewHoldingPage: () => string;
|
|
18
17
|
export declare const createUserDevServerProxy: (userPort: number, userHost?: string, options?: {
|
|
19
18
|
isPreviewBridgeEnabled?: boolean;
|
|
20
19
|
expectedPreviewParentOrigin?: string;
|
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.createUserDevServerProxy = exports.
|
|
3
|
+
exports.createUserDevServerProxy = exports.markPreviewBridgeDocumentUncacheable = exports.resolveTargetAddressedPreview = void 0;
|
|
4
4
|
const http_proxy_middleware_1 = require("http-proxy-middleware");
|
|
5
5
|
const crypto_1 = require("crypto");
|
|
6
6
|
const logger_1 = require("../utils/logger");
|
|
7
|
+
const rivetPage_1 = require("../utils/rivetPage");
|
|
7
8
|
const htmlDocument_1 = require("../utils/htmlDocument");
|
|
8
9
|
const preview_connections_1 = require("./preview-connections");
|
|
9
10
|
const preview_bridge_1 = require("./preview-bridge");
|
|
@@ -74,36 +75,6 @@ const markPreviewBridgeDocumentUncacheable = (proxyRes) => {
|
|
|
74
75
|
proxyRes.headers['cache-control'] = 'no-cache, no-store';
|
|
75
76
|
};
|
|
76
77
|
exports.markPreviewBridgeDocumentUncacheable = markPreviewBridgeDocumentUncacheable;
|
|
77
|
-
const buildPreviewHoldingPage = () => `<!doctype html>
|
|
78
|
-
<html lang="en">
|
|
79
|
-
<head>
|
|
80
|
-
<meta charset="utf-8" />
|
|
81
|
-
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
|
82
|
-
<title>Preview — waiting for dev server</title>
|
|
83
|
-
<style>
|
|
84
|
-
html, body { height: 100%; margin: 0; }
|
|
85
|
-
body {
|
|
86
|
-
display: flex; align-items: center; justify-content: center;
|
|
87
|
-
background: #0f0f10; color: #a1a1aa;
|
|
88
|
-
font: 14px/1.5 ui-sans-serif, system-ui, -apple-system, sans-serif;
|
|
89
|
-
}
|
|
90
|
-
.wrap { display: flex; flex-direction: column; align-items: center; gap: 14px; padding: 24px; text-align: center; }
|
|
91
|
-
.spinner {
|
|
92
|
-
width: 22px; height: 22px; border: 2px solid #2a2a2e; border-top-color: #a1a1aa;
|
|
93
|
-
border-radius: 50%; animation: rivet-preview-spin 0.8s linear infinite;
|
|
94
|
-
}
|
|
95
|
-
@keyframes rivet-preview-spin { to { transform: rotate(360deg); } }
|
|
96
|
-
@media (prefers-reduced-motion: reduce) { .spinner { animation: none; } }
|
|
97
|
-
</style>
|
|
98
|
-
</head>
|
|
99
|
-
<body>
|
|
100
|
-
<div class="wrap">
|
|
101
|
-
<div class="spinner" aria-hidden="true"></div>
|
|
102
|
-
<div>Waiting for the preview dev server…</div>
|
|
103
|
-
</div>
|
|
104
|
-
</body>
|
|
105
|
-
</html>`;
|
|
106
|
-
exports.buildPreviewHoldingPage = buildPreviewHoldingPage;
|
|
107
78
|
const createUserDevServerProxy = (userPort, userHost = 'localhost', options = {}) => {
|
|
108
79
|
let variantTarget = null;
|
|
109
80
|
const requestTargets = new WeakMap();
|
|
@@ -311,9 +282,10 @@ const createUserDevServerProxy = (userPort, userHost = 'localhost', options = {}
|
|
|
311
282
|
if ('writeHead' in res && !res.headersSent) {
|
|
312
283
|
if (isPreviewBridgeEnabled && (0, preview_bridge_1.isHtmlDocumentRequest)(req)) {
|
|
313
284
|
log.debug(`Serving preview holding page — no upstream yet (userPort=${userPort}).`);
|
|
314
|
-
const body = (0, preview_bridge_1.injectPreviewBridge)((0,
|
|
315
|
-
|
|
316
|
-
|
|
285
|
+
const body = (0, preview_bridge_1.injectPreviewBridge)((0, rivetPage_1.renderRivetPage)({
|
|
286
|
+
page: { kind: 'preview-waiting' },
|
|
287
|
+
head: { title: 'Preview — waiting for dev server' },
|
|
288
|
+
}), { expectedParentOrigin: options.expectedPreviewParentOrigin });
|
|
317
289
|
res.writeHead(200, {
|
|
318
290
|
'Content-Type': 'text/html; charset=utf-8',
|
|
319
291
|
'Cache-Control': 'no-cache, no-store',
|
|
@@ -23,6 +23,7 @@ const express_1 = require("express");
|
|
|
23
23
|
const v3_1 = require("zod/v3");
|
|
24
24
|
const api_responses_1 = require("../types/api-responses");
|
|
25
25
|
const logger_1 = require("../utils/logger");
|
|
26
|
+
const rivetPage_1 = require("../utils/rivetPage");
|
|
26
27
|
const agent_variants_1 = require("../agent-variants");
|
|
27
28
|
const changeBatchClassification_1 = require("../mcp/changeBatchClassification");
|
|
28
29
|
const createAgentVariantsOrchestrator_1 = require("../services/createAgentVariantsOrchestrator");
|
|
@@ -167,22 +168,6 @@ const HISTORY_STATUSES = new Set([
|
|
|
167
168
|
]);
|
|
168
169
|
const VARIANT_SHARE_TITLE_FALLBACK = 'Prototype';
|
|
169
170
|
const CANVAS_SHARE_TITLE_FALLBACK = 'Prototype canvas';
|
|
170
|
-
const escapeHtml = (value) => value.replace(/[&<>"']/g, (char) => {
|
|
171
|
-
switch (char) {
|
|
172
|
-
case '&':
|
|
173
|
-
return '&';
|
|
174
|
-
case '<':
|
|
175
|
-
return '<';
|
|
176
|
-
case '>':
|
|
177
|
-
return '>';
|
|
178
|
-
case '"':
|
|
179
|
-
return '"';
|
|
180
|
-
case "'":
|
|
181
|
-
return ''';
|
|
182
|
-
default:
|
|
183
|
-
return char;
|
|
184
|
-
}
|
|
185
|
-
});
|
|
186
171
|
const getVariantShareTitle = (manifest) => {
|
|
187
172
|
const title = [manifest.label, manifest.brief, manifest.sessionPrompt].find((candidate) => candidate.trim().length > 0);
|
|
188
173
|
return (0, PrototypeDeployService_1.normalizePrototypeShareTitle)(title) ?? VARIANT_SHARE_TITLE_FALLBACK;
|
|
@@ -190,165 +175,27 @@ const getVariantShareTitle = (manifest) => {
|
|
|
190
175
|
const getCanvasShareTitle = (sessionPrompt) => {
|
|
191
176
|
return ((0, PrototypeDeployService_1.normalizePrototypeShareTitle)(sessionPrompt) ?? CANVAS_SHARE_TITLE_FALLBACK);
|
|
192
177
|
};
|
|
193
|
-
const CANVAS_IFRAME_SANDBOX = 'allow-scripts allow-forms allow-popups';
|
|
194
178
|
const RIVET_SOCIAL_IMAGE_URL = 'https://rivet.design/images/rivet-social.png';
|
|
195
179
|
const RIVET_DEFAULT_SHARE_DESCRIPTION = 'Built with Rivet — the visual editor for design';
|
|
196
180
|
const UNSUPPORTED_PROTOTYPE_DEPLOY_MESSAGE = "This prototype can't be deployed — only buildable app directions or static previews are supported.";
|
|
197
|
-
const
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
.
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
.join('\n');
|
|
216
|
-
const canvasTitle = `Rivet Canvas — ${args.variants.length} directions`;
|
|
217
|
-
const escapedTitle = escapeHtml(canvasTitle);
|
|
218
|
-
const escapedDesc = escapeHtml(RIVET_DEFAULT_SHARE_DESCRIPTION);
|
|
219
|
-
return `<!doctype html>
|
|
220
|
-
<html lang="en">
|
|
221
|
-
<head>
|
|
222
|
-
<meta charset="utf-8">
|
|
223
|
-
<meta name="viewport" content="width=device-width, initial-scale=1">
|
|
224
|
-
<title>${escapedTitle}</title>
|
|
225
|
-
<meta name="description" content="${escapedDesc}" />
|
|
226
|
-
<meta property="og:type" content="website" />
|
|
227
|
-
<meta property="og:title" content="${escapedTitle}" />
|
|
228
|
-
<meta property="og:description" content="${escapedDesc}" />
|
|
229
|
-
<meta property="og:image" content="${RIVET_SOCIAL_IMAGE_URL}" />
|
|
230
|
-
<meta name="twitter:card" content="summary_large_image" />
|
|
231
|
-
<meta name="twitter:title" content="${escapedTitle}" />
|
|
232
|
-
<meta name="twitter:description" content="${escapedDesc}" />
|
|
233
|
-
<meta name="twitter:image" content="${RIVET_SOCIAL_IMAGE_URL}" />
|
|
234
|
-
<style>
|
|
235
|
-
:root {
|
|
236
|
-
color-scheme: light;
|
|
237
|
-
--bg: #f6f4ef;
|
|
238
|
-
--card: #ffffff;
|
|
239
|
-
--ink: #161615;
|
|
240
|
-
--muted: #6f6a60;
|
|
241
|
-
--border: #ded8cc;
|
|
242
|
-
--accent: #ff5a1f;
|
|
243
|
-
}
|
|
244
|
-
* { box-sizing: border-box; }
|
|
245
|
-
body {
|
|
246
|
-
margin: 0;
|
|
247
|
-
background: var(--bg);
|
|
248
|
-
color: var(--ink);
|
|
249
|
-
font-family: Inter, ui-sans-serif, system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif;
|
|
250
|
-
}
|
|
251
|
-
main {
|
|
252
|
-
width: min(1440px, calc(100vw - 32px));
|
|
253
|
-
margin: 0 auto;
|
|
254
|
-
padding: 32px 0 48px;
|
|
255
|
-
}
|
|
256
|
-
.hero {
|
|
257
|
-
display: flex;
|
|
258
|
-
align-items: flex-end;
|
|
259
|
-
justify-content: space-between;
|
|
260
|
-
gap: 24px;
|
|
261
|
-
margin-bottom: 24px;
|
|
262
|
-
}
|
|
263
|
-
h1 {
|
|
264
|
-
margin: 0;
|
|
265
|
-
font-size: clamp(32px, 5vw, 64px);
|
|
266
|
-
letter-spacing: -0.06em;
|
|
267
|
-
line-height: 0.95;
|
|
268
|
-
}
|
|
269
|
-
.prompt {
|
|
270
|
-
max-width: 720px;
|
|
271
|
-
color: var(--muted);
|
|
272
|
-
font-size: 15px;
|
|
273
|
-
line-height: 1.5;
|
|
274
|
-
}
|
|
275
|
-
.grid {
|
|
276
|
-
display: grid;
|
|
277
|
-
grid-template-columns: repeat(auto-fit, minmax(420px, 1fr));
|
|
278
|
-
gap: 18px;
|
|
279
|
-
}
|
|
280
|
-
.variant-card {
|
|
281
|
-
overflow: hidden;
|
|
282
|
-
border: 1px solid var(--border);
|
|
283
|
-
border-radius: 18px;
|
|
284
|
-
background: var(--card);
|
|
285
|
-
box-shadow: 0 20px 60px rgba(22, 22, 21, 0.08);
|
|
286
|
-
}
|
|
287
|
-
.variant-card header {
|
|
288
|
-
display: flex;
|
|
289
|
-
align-items: flex-start;
|
|
290
|
-
justify-content: space-between;
|
|
291
|
-
gap: 16px;
|
|
292
|
-
padding: 18px 18px 0;
|
|
293
|
-
}
|
|
294
|
-
.eyebrow {
|
|
295
|
-
margin: 0 0 6px;
|
|
296
|
-
color: var(--accent);
|
|
297
|
-
font-size: 11px;
|
|
298
|
-
font-weight: 700;
|
|
299
|
-
letter-spacing: 0.12em;
|
|
300
|
-
text-transform: uppercase;
|
|
301
|
-
}
|
|
302
|
-
h2 {
|
|
303
|
-
margin: 0;
|
|
304
|
-
font-size: 20px;
|
|
305
|
-
letter-spacing: -0.03em;
|
|
306
|
-
}
|
|
307
|
-
a {
|
|
308
|
-
color: var(--ink);
|
|
309
|
-
font-size: 13px;
|
|
310
|
-
font-weight: 700;
|
|
311
|
-
text-decoration: none;
|
|
312
|
-
border-bottom: 1px solid currentColor;
|
|
313
|
-
}
|
|
314
|
-
.brief {
|
|
315
|
-
margin: 10px 18px 16px;
|
|
316
|
-
color: var(--muted);
|
|
317
|
-
font-size: 13px;
|
|
318
|
-
line-height: 1.45;
|
|
319
|
-
}
|
|
320
|
-
iframe {
|
|
321
|
-
display: block;
|
|
322
|
-
width: 100%;
|
|
323
|
-
height: 720px;
|
|
324
|
-
border: 0;
|
|
325
|
-
border-top: 1px solid var(--border);
|
|
326
|
-
background: white;
|
|
327
|
-
}
|
|
328
|
-
@media (max-width: 640px) {
|
|
329
|
-
main { width: min(100vw - 20px, 1440px); padding-top: 20px; }
|
|
330
|
-
.hero { display: block; }
|
|
331
|
-
.grid { grid-template-columns: 1fr; }
|
|
332
|
-
iframe { height: 560px; }
|
|
333
|
-
}
|
|
334
|
-
</style>
|
|
335
|
-
</head>
|
|
336
|
-
<body>
|
|
337
|
-
<main>
|
|
338
|
-
<section class="hero">
|
|
339
|
-
<div>
|
|
340
|
-
<p class="eyebrow">Rivet Canvas</p>
|
|
341
|
-
<h1>${args.variants.length} directions</h1>
|
|
342
|
-
</div>
|
|
343
|
-
${prompt ? `<p class="prompt">${escapeHtml(prompt)}</p>` : ''}
|
|
344
|
-
</section>
|
|
345
|
-
<section class="grid">
|
|
346
|
-
${variantCards}
|
|
347
|
-
</section>
|
|
348
|
-
</main>
|
|
349
|
-
</body>
|
|
350
|
-
</html>`;
|
|
351
|
-
};
|
|
181
|
+
const buildCanvasSharePage = (args) => (0, rivetPage_1.renderRivetPage)({
|
|
182
|
+
page: {
|
|
183
|
+
kind: 'canvas-share',
|
|
184
|
+
prompt: args.sessionPrompt.trim(),
|
|
185
|
+
directions: args.variants.map((variant, index) => ({
|
|
186
|
+
label: variant.label.trim() || `Direction ${index + 1}`,
|
|
187
|
+
brief: variant.brief.trim(),
|
|
188
|
+
shareUrl: variant.shareUrl,
|
|
189
|
+
})),
|
|
190
|
+
},
|
|
191
|
+
head: {
|
|
192
|
+
title: `Rivet Canvas — ${args.variants.length} directions`,
|
|
193
|
+
shareCard: {
|
|
194
|
+
description: RIVET_DEFAULT_SHARE_DESCRIPTION,
|
|
195
|
+
imageUrl: RIVET_SOCIAL_IMAGE_URL,
|
|
196
|
+
},
|
|
197
|
+
},
|
|
198
|
+
});
|
|
352
199
|
const generatedProjectWorkspaceRoot = (projectPath) => {
|
|
353
200
|
const normalized = path_1.default.normalize(projectPath);
|
|
354
201
|
const segments = normalized.split(path_1.default.sep);
|
|
@@ -1811,7 +1658,7 @@ const createAgentVariantsRouter = (orchestrator, bridge, telemetry, variantHisto
|
|
|
1811
1658
|
}
|
|
1812
1659
|
deployedVariants.push(deployed.variant);
|
|
1813
1660
|
}
|
|
1814
|
-
const html =
|
|
1661
|
+
const html = buildCanvasSharePage({
|
|
1815
1662
|
sessionPrompt,
|
|
1816
1663
|
variants: deployedVariants,
|
|
1817
1664
|
});
|
package/dist/routes/static.js
CHANGED
|
@@ -42,7 +42,7 @@ const path_1 = __importDefault(require("path"));
|
|
|
42
42
|
const fs_1 = __importDefault(require("fs"));
|
|
43
43
|
const logger_1 = require("../utils/logger");
|
|
44
44
|
const preview_bridge_1 = require("../proxy-middleware/preview-bridge");
|
|
45
|
-
const
|
|
45
|
+
const rivetPage_1 = require("../utils/rivetPage");
|
|
46
46
|
const log = (0, logger_1.createLogger)('StaticRoutes');
|
|
47
47
|
const createStaticRoutes = (staticService, _projectPath, options = {}) => {
|
|
48
48
|
const router = (0, express_1.Router)();
|
|
@@ -62,7 +62,13 @@ const createStaticRoutes = (staticService, _projectPath, options = {}) => {
|
|
|
62
62
|
res.sendFile(entryFileName, { root: basePath });
|
|
63
63
|
};
|
|
64
64
|
const sendEmptyState = (res) => {
|
|
65
|
-
res
|
|
65
|
+
res
|
|
66
|
+
.status(200)
|
|
67
|
+
.type('html')
|
|
68
|
+
.send((0, rivetPage_1.renderRivetPage)({
|
|
69
|
+
page: { kind: 'empty-project' },
|
|
70
|
+
head: { title: 'Empty project' },
|
|
71
|
+
}));
|
|
66
72
|
};
|
|
67
73
|
router.get('/static', (_req, res) => {
|
|
68
74
|
const entryPath = path_1.default.join(basePath, entryFileName);
|
package/dist/server.d.ts
CHANGED
|
@@ -7,7 +7,6 @@ import type { VariantRunService } from './services/VariantRunService';
|
|
|
7
7
|
import type { VariantsRuntime } from './services/VariantsRuntime';
|
|
8
8
|
export declare const INACTIVE_VARIANTS_EVENT_HEARTBEAT_MS = 30000;
|
|
9
9
|
export declare const RIVET_CORS_ALLOWED_HEADERS: string[];
|
|
10
|
-
export declare const DIST_UI_PATH: string;
|
|
11
10
|
type RivetUiBootstrap = {
|
|
12
11
|
agentApplyMode: 'embedded' | 'external' | null;
|
|
13
12
|
queueAccessToken: string | null;
|
|
@@ -58,6 +57,7 @@ export type ServerOptions = Omit<CLIOptions, 'help' | 'version' | 'debug'> & {
|
|
|
58
57
|
userHost?: string;
|
|
59
58
|
beforeShutdown?: () => Promise<void>;
|
|
60
59
|
resolveLibraryOrigin?: () => string | undefined;
|
|
60
|
+
resolveProjectName?: (projectPath: string) => string | undefined;
|
|
61
61
|
createLibraryViewUrl?: (view: 'projects' | 'references') => Promise<string | null>;
|
|
62
62
|
};
|
|
63
63
|
export type ServerHandle = {
|
package/dist/server.js
CHANGED
|
@@ -36,7 +36,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
36
36
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
37
37
|
};
|
|
38
38
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
39
|
-
exports.startServer = exports.runServerShutdownTasks = exports.isRivetCorsOriginAllowed = exports.isRivetUiStaticAssetPath = exports.isEmbeddedAgentUiHost = exports.resolveEmbeddedAgentUiOrigin = exports.resolveRivetListenHost = exports.sendInactiveVariantsEventStream = exports.readRivetUiIndexHtml = exports.injectRivetUiBootstrap = exports.
|
|
39
|
+
exports.startServer = exports.runServerShutdownTasks = exports.isRivetCorsOriginAllowed = exports.isRivetUiStaticAssetPath = exports.isEmbeddedAgentUiHost = exports.resolveEmbeddedAgentUiOrigin = exports.resolveRivetListenHost = exports.sendInactiveVariantsEventStream = exports.readRivetUiIndexHtml = exports.injectRivetUiBootstrap = exports.RIVET_CORS_ALLOWED_HEADERS = exports.INACTIVE_VARIANTS_EVENT_HEARTBEAT_MS = void 0;
|
|
40
40
|
const editorSession_1 = require("./cli/editorSession");
|
|
41
41
|
const editorAccess_1 = require("./routes/editorAccess");
|
|
42
42
|
const editorAccess_2 = require("./utils/editorAccess");
|
|
@@ -77,6 +77,8 @@ const VariantHistoryService_1 = require("./services/VariantHistoryService");
|
|
|
77
77
|
const RequestAuthContext_1 = require("./services/RequestAuthContext");
|
|
78
78
|
const middleware_1 = require("./routes/library/middleware");
|
|
79
79
|
const errorMessage_1 = require("./utils/errorMessage");
|
|
80
|
+
const scriptJson_1 = require("./utils/scriptJson");
|
|
81
|
+
const uiDistPath_1 = require("./utils/uiDistPath");
|
|
80
82
|
const pluginContext_1 = require("./hosts/pluginContext");
|
|
81
83
|
const log = (0, index_core_1.createLogger)('RivetServer');
|
|
82
84
|
const QUEUE_ACCESS_TOKEN_BYTES = 32;
|
|
@@ -93,36 +95,21 @@ exports.RIVET_CORS_ALLOWED_HEADERS = [
|
|
|
93
95
|
'x-rivet-queue-token',
|
|
94
96
|
editorAccess_2.EDITOR_ACCESS_TOKEN_HEADER,
|
|
95
97
|
];
|
|
96
|
-
const resolveUiPath = () => {
|
|
97
|
-
const bundledPath = path_1.default.join(__dirname, 'ui/dist');
|
|
98
|
-
const devPath = path_1.default.join(__dirname, '../src/ui/dist');
|
|
99
|
-
if (fs_1.default.existsSync(bundledPath)) {
|
|
100
|
-
log.debug(`Using bundled UI path: ${bundledPath}`);
|
|
101
|
-
return bundledPath;
|
|
102
|
-
}
|
|
103
|
-
log.debug(`Using development UI path: ${devPath}`);
|
|
104
|
-
return devPath;
|
|
105
|
-
};
|
|
106
|
-
exports.DIST_UI_PATH = resolveUiPath();
|
|
107
98
|
const NO_USER_DEV_SERVER_PORT = 0;
|
|
108
99
|
const setNoStoreHeaders = (res) => {
|
|
109
100
|
res.setHeader('Cache-Control', 'no-store, no-cache, must-revalidate, proxy-revalidate');
|
|
110
101
|
res.setHeader('Pragma', 'no-cache');
|
|
111
102
|
res.setHeader('Expires', '0');
|
|
112
103
|
};
|
|
113
|
-
const escapeScriptJson = (value) => JSON.stringify(value)
|
|
114
|
-
.replace(/</g, '\\u003c')
|
|
115
|
-
.replace(/\u2028/g, '\\u2028')
|
|
116
|
-
.replace(/\u2029/g, '\\u2029');
|
|
117
104
|
const injectRivetUiBootstrap = (html, bootstrap) => {
|
|
118
|
-
const script = `<script id="${RIVET_BOOTSTRAP_SCRIPT_ID}">window.__RIVET_BOOTSTRAP__=${escapeScriptJson(bootstrap)};</script>`;
|
|
105
|
+
const script = `<script id="${RIVET_BOOTSTRAP_SCRIPT_ID}">window.__RIVET_BOOTSTRAP__=${(0, scriptJson_1.escapeScriptJson)(bootstrap)};</script>`;
|
|
119
106
|
if (html.includes('</head>')) {
|
|
120
107
|
return html.replace('</head>', `${script}</head>`);
|
|
121
108
|
}
|
|
122
109
|
return `${script}${html}`;
|
|
123
110
|
};
|
|
124
111
|
exports.injectRivetUiBootstrap = injectRivetUiBootstrap;
|
|
125
|
-
const readRivetUiIndexHtml = () => fs_1.default.readFileSync(path_1.default.join(
|
|
112
|
+
const readRivetUiIndexHtml = () => fs_1.default.readFileSync(path_1.default.join(uiDistPath_1.DIST_UI_PATH, RIVET_UI_INDEX_FILENAME), 'utf8');
|
|
126
113
|
exports.readRivetUiIndexHtml = readRivetUiIndexHtml;
|
|
127
114
|
const sendInactiveVariantsEventStream = (req, res) => {
|
|
128
115
|
res.set({
|
|
@@ -366,15 +353,15 @@ const startServer = async (options) => {
|
|
|
366
353
|
const serve = express_1.default.static(directory, uiStaticOptions);
|
|
367
354
|
return (req, res, next) => isPreviewRequest(req) ? next() : serve(req, res, next);
|
|
368
355
|
};
|
|
369
|
-
app.use('/assets', serveEditorAssets(path_1.default.join(
|
|
370
|
-
app.use('/rivet/assets', serveEditorAssets(path_1.default.join(
|
|
371
|
-
app.use('/fonts', serveEditorAssets(path_1.default.join(
|
|
372
|
-
app.use('/rivet/fonts', serveEditorAssets(path_1.default.join(
|
|
356
|
+
app.use('/assets', serveEditorAssets(path_1.default.join(uiDistPath_1.DIST_UI_PATH, 'assets')));
|
|
357
|
+
app.use('/rivet/assets', serveEditorAssets(path_1.default.join(uiDistPath_1.DIST_UI_PATH, 'assets')));
|
|
358
|
+
app.use('/fonts', serveEditorAssets(path_1.default.join(uiDistPath_1.DIST_UI_PATH, 'fonts')));
|
|
359
|
+
app.use('/rivet/fonts', serveEditorAssets(path_1.default.join(uiDistPath_1.DIST_UI_PATH, 'fonts')));
|
|
373
360
|
app.get('/favicon.ico', (_req, res) => {
|
|
374
|
-
res.sendFile('favicon.ico', { root:
|
|
361
|
+
res.sendFile('favicon.ico', { root: uiDistPath_1.DIST_UI_PATH });
|
|
375
362
|
});
|
|
376
363
|
app.get('/rivet/favicon.ico', (_req, res) => {
|
|
377
|
-
res.sendFile('favicon.ico', { root:
|
|
364
|
+
res.sendFile('favicon.ico', { root: uiDistPath_1.DIST_UI_PATH });
|
|
378
365
|
});
|
|
379
366
|
app.get(/^\/rivet\/library(?:\/.*)?$/, (req, res) => {
|
|
380
367
|
const resolvedLibraryOrigin = options.resolveLibraryOrigin?.();
|
|
@@ -391,7 +378,7 @@ const startServer = async (options) => {
|
|
|
391
378
|
}
|
|
392
379
|
sendRivetUiIndex(req, res);
|
|
393
380
|
});
|
|
394
|
-
log.info(`Serving UI assets from: ${
|
|
381
|
+
log.info(`Serving UI assets from: ${uiDistPath_1.DIST_UI_PATH}`);
|
|
395
382
|
if (framework === 'static' && !hasUserDevServer) {
|
|
396
383
|
app.get('/', (req, res, next) => {
|
|
397
384
|
if (isPreviewRequest(req)) {
|
|
@@ -511,6 +498,7 @@ const startServer = async (options) => {
|
|
|
511
498
|
? (agentApplyMode ?? 'external')
|
|
512
499
|
: null,
|
|
513
500
|
projectPath: livePath,
|
|
501
|
+
projectName: options.resolveProjectName?.(livePath) ?? path_1.default.basename(livePath),
|
|
514
502
|
projectId: options.projectId ?? null,
|
|
515
503
|
libraryOrigin: options.resolveLibraryOrigin?.() ?? null,
|
|
516
504
|
});
|
|
@@ -36,6 +36,8 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
36
36
|
exports.AuthService = exports.validateAccessToken = void 0;
|
|
37
37
|
const zod_1 = require("zod");
|
|
38
38
|
const logger_1 = require("../utils/logger");
|
|
39
|
+
const rivetPage_1 = require("../utils/rivetPage");
|
|
40
|
+
const rivet_page_types_1 = require("../types/rivet-page-types");
|
|
39
41
|
const ConfigManager_1 = require("./ConfigManager");
|
|
40
42
|
const http_1 = require("http");
|
|
41
43
|
const accessTokenRefresh_1 = require("./accessTokenRefresh");
|
|
@@ -46,7 +48,6 @@ const proxy_1 = require("../config/proxy");
|
|
|
46
48
|
const log = (0, logger_1.createLogger)('AuthService');
|
|
47
49
|
const LOOPBACK_HOST = '127.0.0.1';
|
|
48
50
|
const LOOPBACK_PORT = 0;
|
|
49
|
-
const CALLBACK_COMPLETE_PATH = '/complete';
|
|
50
51
|
const OAUTH_CALLBACK_TIMEOUT_MS = 120_000;
|
|
51
52
|
const MAX_CALLBACK_BODY_BYTES = 64 * 1024;
|
|
52
53
|
const PROFILE_FETCH_TIMEOUT_MS = 10_000;
|
|
@@ -101,64 +102,6 @@ const readRequestBody = (request) => {
|
|
|
101
102
|
request.on('error', reject);
|
|
102
103
|
});
|
|
103
104
|
};
|
|
104
|
-
const getLoopbackCallbackHtml = () => {
|
|
105
|
-
return `<!doctype html>
|
|
106
|
-
<html>
|
|
107
|
-
<head>
|
|
108
|
-
<meta charset="utf-8" />
|
|
109
|
-
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
|
110
|
-
<title>Rivet authentication</title>
|
|
111
|
-
<style>
|
|
112
|
-
body {
|
|
113
|
-
margin: 0;
|
|
114
|
-
min-height: 100vh;
|
|
115
|
-
display: grid;
|
|
116
|
-
place-items: center;
|
|
117
|
-
font-family: system-ui, sans-serif;
|
|
118
|
-
background: #0b0b0f;
|
|
119
|
-
color: #fff;
|
|
120
|
-
}
|
|
121
|
-
main {
|
|
122
|
-
max-width: 420px;
|
|
123
|
-
padding: 32px;
|
|
124
|
-
text-align: center;
|
|
125
|
-
}
|
|
126
|
-
</style>
|
|
127
|
-
</head>
|
|
128
|
-
<body>
|
|
129
|
-
<main>
|
|
130
|
-
<h1>Finishing Rivet sign in...</h1>
|
|
131
|
-
<p>You can return to your editor after this page completes.</p>
|
|
132
|
-
</main>
|
|
133
|
-
<script>
|
|
134
|
-
const params = new URLSearchParams(window.location.search);
|
|
135
|
-
const hash = new URLSearchParams(window.location.hash.slice(1));
|
|
136
|
-
if (window.location.hash) {
|
|
137
|
-
window.history.replaceState(
|
|
138
|
-
null,
|
|
139
|
-
document.title,
|
|
140
|
-
window.location.pathname + window.location.search
|
|
141
|
-
);
|
|
142
|
-
}
|
|
143
|
-
fetch('/complete', {
|
|
144
|
-
method: 'POST',
|
|
145
|
-
headers: { 'Content-Type': 'application/json' },
|
|
146
|
-
body: JSON.stringify({
|
|
147
|
-
sessionId: params.get('session'),
|
|
148
|
-
accessToken: hash.get('access_token'),
|
|
149
|
-
refreshToken: hash.get('refresh_token')
|
|
150
|
-
})
|
|
151
|
-
}).then((response) => {
|
|
152
|
-
document.querySelector('h1').textContent = response.ok
|
|
153
|
-
? 'Rivet sign in complete'
|
|
154
|
-
: 'Rivet sign in failed';
|
|
155
|
-
}).catch(() => {
|
|
156
|
-
document.querySelector('h1').textContent = 'Rivet sign in failed';
|
|
157
|
-
});
|
|
158
|
-
</script>
|
|
159
|
-
</body>
|
|
160
|
-
</html>`;
|
|
161
|
-
};
|
|
162
105
|
const validateAccessToken = async (proxyUrl, accessToken) => {
|
|
163
106
|
const response = await fetch(`${proxyUrl.replace(/\/$/, '')}/api/user/profile`, {
|
|
164
107
|
method: 'GET',
|
|
@@ -204,11 +147,14 @@ const createLoopbackOAuthCallback = async () => {
|
|
|
204
147
|
const server = (0, http_1.createServer)((request, response) => {
|
|
205
148
|
const url = new URL(request.url ?? '/', `http://${LOOPBACK_HOST}`);
|
|
206
149
|
if (request.method === 'GET') {
|
|
207
|
-
sendTextResponse(response, 200,
|
|
150
|
+
sendTextResponse(response, 200, (0, rivetPage_1.renderRivetPage)({
|
|
151
|
+
page: { kind: 'sign-in-callback' },
|
|
152
|
+
head: { title: 'Rivet authentication' },
|
|
153
|
+
}));
|
|
208
154
|
return;
|
|
209
155
|
}
|
|
210
156
|
if (request.method !== 'POST' ||
|
|
211
|
-
url.pathname !==
|
|
157
|
+
url.pathname !== rivet_page_types_1.SIGN_IN_CALLBACK_COMPLETE_PATH) {
|
|
212
158
|
sendTextResponse(response, 404, 'Not found');
|
|
213
159
|
return;
|
|
214
160
|
}
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
export declare const RIVET_PAGE_DATA_ELEMENT_ID = "rivet-page";
|
|
2
|
+
export declare const SIGN_IN_CALLBACK_COMPLETE_PATH = "/complete";
|
|
3
|
+
export type CanvasShareDirection = {
|
|
4
|
+
label: string;
|
|
5
|
+
brief: string;
|
|
6
|
+
shareUrl: string;
|
|
7
|
+
};
|
|
8
|
+
export type SharedShellRivetPage = {
|
|
9
|
+
kind: 'preview-waiting';
|
|
10
|
+
} | {
|
|
11
|
+
kind: 'sign-in-callback';
|
|
12
|
+
} | {
|
|
13
|
+
kind: 'canvas-share';
|
|
14
|
+
prompt: string;
|
|
15
|
+
directions: CanvasShareDirection[];
|
|
16
|
+
};
|
|
17
|
+
export type RivetPage = {
|
|
18
|
+
kind: 'empty-project';
|
|
19
|
+
} | SharedShellRivetPage;
|
|
20
|
+
export type ConnectResultMessage = {
|
|
21
|
+
type: 'rivet:connect-result';
|
|
22
|
+
provider: string;
|
|
23
|
+
status: 'connected' | 'error';
|
|
24
|
+
message?: string;
|
|
25
|
+
};
|
|
26
|
+
export type ConnectResultClosePolicy = 'always' | 'after-notifying-opener';
|
|
27
|
+
export type HostedRivetPage = {
|
|
28
|
+
kind: 'google-sign-in';
|
|
29
|
+
initiator: string;
|
|
30
|
+
providerAuthUrl: string;
|
|
31
|
+
} | {
|
|
32
|
+
kind: 'sign-in-link-expired';
|
|
33
|
+
} | {
|
|
34
|
+
kind: 'connect-result';
|
|
35
|
+
result: ConnectResultMessage;
|
|
36
|
+
notice: string;
|
|
37
|
+
closePolicy: ConnectResultClosePolicy;
|
|
38
|
+
};
|
|
39
|
+
export type RivetPageShareCard = {
|
|
40
|
+
description: string;
|
|
41
|
+
imageUrl: string;
|
|
42
|
+
};
|
|
43
|
+
export type RivetPageHead = {
|
|
44
|
+
title: string;
|
|
45
|
+
shareCard?: RivetPageShareCard;
|
|
46
|
+
robots?: 'noindex';
|
|
47
|
+
};
|
|
48
|
+
//# sourceMappingURL=rivet-page-types.d.ts.map
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.SIGN_IN_CALLBACK_COMPLETE_PATH = exports.RIVET_PAGE_DATA_ELEMENT_ID = void 0;
|
|
4
|
+
exports.RIVET_PAGE_DATA_ELEMENT_ID = 'rivet-page';
|
|
5
|
+
exports.SIGN_IN_CALLBACK_COMPLETE_PATH = '/complete';
|
|
6
|
+
//# sourceMappingURL=rivet-page-types.js.map
|