framer-dalton 0.0.11 → 0.0.13
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.js +84 -48
- package/dist/start-relay-server.js +7 -3
- package/package.json +1 -1
package/dist/cli.js
CHANGED
|
@@ -10,7 +10,7 @@ import { z } from 'zod';
|
|
|
10
10
|
import { fileURLToPath } from 'url';
|
|
11
11
|
import { createTRPCClient, httpLink } from '@trpc/client';
|
|
12
12
|
|
|
13
|
-
/* @framer/ai CLI v0.0.
|
|
13
|
+
/* @framer/ai CLI v0.0.13 */
|
|
14
14
|
var __defProp = Object.defineProperty;
|
|
15
15
|
var __name = (target, value) => __defProp(target, "name", { value, configurable: true });
|
|
16
16
|
function openUrl(url) {
|
|
@@ -134,11 +134,10 @@ function extractProjectId(input) {
|
|
|
134
134
|
if (/^[a-zA-Z0-9]+$/.test(input)) {
|
|
135
135
|
return input;
|
|
136
136
|
}
|
|
137
|
-
const
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
const slugMatch = input.match(/^(?:.+--)?([a-zA-Z0-9]+)(?:-[a-zA-Z0-9]+)?$/);
|
|
137
|
+
const candidate = input.match(/\/projects\/([^/?#]+)/)?.[1] ?? input;
|
|
138
|
+
const slugMatch = candidate.match(
|
|
139
|
+
/^(?:.+--)?([a-zA-Z0-9]+)(?:-[a-zA-Z0-9]+)?$/
|
|
140
|
+
);
|
|
142
141
|
if (slugMatch) {
|
|
143
142
|
return slugMatch[1];
|
|
144
143
|
}
|
|
@@ -204,6 +203,16 @@ __name(printError, "printError");
|
|
|
204
203
|
|
|
205
204
|
// src/auth-callback.ts
|
|
206
205
|
var TIMEOUT_MS = 3e5;
|
|
206
|
+
var codeMessages = {
|
|
207
|
+
"user.denied": "Authorization denied by user.",
|
|
208
|
+
"project.access_denied": "You don\u2019t have access to this project.",
|
|
209
|
+
"project.not_found": "Project not found. Check that the project ID is correct.",
|
|
210
|
+
"project.unauthorized": "Not logged in to Framer.",
|
|
211
|
+
"api_key.access_denied": "You don\u2019t have permission to create API keys for this project.",
|
|
212
|
+
"api_key.unauthorized": "Session expired.",
|
|
213
|
+
connection_error: "Could not connect to Framer.",
|
|
214
|
+
unknown: "Authorization failed."
|
|
215
|
+
};
|
|
207
216
|
var themes = {
|
|
208
217
|
dark: {
|
|
209
218
|
pageBackground: "rgb(17, 17, 17)",
|
|
@@ -271,15 +280,6 @@ function successHtml(theme) {
|
|
|
271
280
|
});
|
|
272
281
|
}
|
|
273
282
|
__name(successHtml, "successHtml");
|
|
274
|
-
function deniedHtml(theme) {
|
|
275
|
-
return htmlPage({
|
|
276
|
-
title: "Framer \u2014 Authorization Denied",
|
|
277
|
-
heading: "Authorization Denied",
|
|
278
|
-
message: "Agent access was denied. You can close this tab.",
|
|
279
|
-
theme
|
|
280
|
-
});
|
|
281
|
-
}
|
|
282
|
-
__name(deniedHtml, "deniedHtml");
|
|
283
283
|
function errorHtml(theme) {
|
|
284
284
|
return htmlPage({
|
|
285
285
|
title: "Framer \u2014 Authorization Failed",
|
|
@@ -289,27 +289,53 @@ function errorHtml(theme) {
|
|
|
289
289
|
});
|
|
290
290
|
}
|
|
291
291
|
__name(errorHtml, "errorHtml");
|
|
292
|
+
function codeHtml(code, theme) {
|
|
293
|
+
const heading = code === "user.denied" ? "Authorization Denied" : "Authorization Failed";
|
|
294
|
+
return htmlPage({
|
|
295
|
+
title: `Framer \u2014 ${heading}`,
|
|
296
|
+
heading,
|
|
297
|
+
message: codeMessages[code],
|
|
298
|
+
theme
|
|
299
|
+
});
|
|
300
|
+
}
|
|
301
|
+
__name(codeHtml, "codeHtml");
|
|
292
302
|
function parseTheme(value) {
|
|
293
303
|
return value === "light" ? "light" : "dark";
|
|
294
304
|
}
|
|
295
305
|
__name(parseTheme, "parseTheme");
|
|
306
|
+
var validCodes = new Set(Object.keys(codeMessages));
|
|
307
|
+
function parseCode(value) {
|
|
308
|
+
if (value !== null && validCodes.has(value)) return value;
|
|
309
|
+
return null;
|
|
310
|
+
}
|
|
311
|
+
__name(parseCode, "parseCode");
|
|
296
312
|
async function acquireKeyFromBrowser(projectId) {
|
|
297
313
|
const state = crypto.randomBytes(16).toString("hex");
|
|
298
314
|
return new Promise((resolve, reject) => {
|
|
299
|
-
let
|
|
315
|
+
let settled = false;
|
|
316
|
+
let pendingApiKey = null;
|
|
317
|
+
function settle(fn) {
|
|
318
|
+
if (settled) return;
|
|
319
|
+
settled = true;
|
|
320
|
+
cleanup();
|
|
321
|
+
fn();
|
|
322
|
+
}
|
|
323
|
+
__name(settle, "settle");
|
|
300
324
|
const server = http.createServer((req, res) => {
|
|
301
325
|
const url = new URL(req.url ?? "/", `http://127.0.0.1`);
|
|
302
326
|
if (url.pathname === "/done") {
|
|
303
327
|
const theme2 = parseTheme(url.searchParams.get("theme"));
|
|
304
328
|
res.writeHead(200, { "Content-Type": "text/html" });
|
|
305
|
-
res.end(successHtml(theme2))
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
329
|
+
res.end(successHtml(theme2), () => {
|
|
330
|
+
if (pendingApiKey) {
|
|
331
|
+
const apiKey2 = pendingApiKey;
|
|
332
|
+
pendingApiKey = null;
|
|
333
|
+
settle(() => {
|
|
334
|
+
print("\u2713 Agent authorized");
|
|
335
|
+
resolve(apiKey2);
|
|
336
|
+
});
|
|
337
|
+
}
|
|
338
|
+
});
|
|
313
339
|
return;
|
|
314
340
|
}
|
|
315
341
|
if (url.pathname === "/error") {
|
|
@@ -324,12 +350,14 @@ async function acquireKeyFromBrowser(projectId) {
|
|
|
324
350
|
return;
|
|
325
351
|
}
|
|
326
352
|
const theme = parseTheme(url.searchParams.get("theme"));
|
|
327
|
-
const
|
|
328
|
-
|
|
353
|
+
const legacyError = url.searchParams.get("error");
|
|
354
|
+
const legacyCode = legacyError === "denied" ? "user.denied" : legacyError === "failed" ? "project.unauthorized" : null;
|
|
355
|
+
const code = parseCode(url.searchParams.get("code")) ?? legacyCode;
|
|
356
|
+
if (code !== null) {
|
|
329
357
|
res.writeHead(200, { "Content-Type": "text/html" });
|
|
330
|
-
res.end(
|
|
331
|
-
|
|
332
|
-
|
|
358
|
+
res.end(codeHtml(code, theme), () => {
|
|
359
|
+
settle(() => reject(new Error(codeMessages[code])));
|
|
360
|
+
});
|
|
333
361
|
return;
|
|
334
362
|
}
|
|
335
363
|
const apiKey = url.searchParams.get("apiKey");
|
|
@@ -339,7 +367,7 @@ async function acquireKeyFromBrowser(projectId) {
|
|
|
339
367
|
res.end();
|
|
340
368
|
return;
|
|
341
369
|
}
|
|
342
|
-
|
|
370
|
+
pendingApiKey = apiKey;
|
|
343
371
|
res.writeHead(302, { Location: `/done?theme=${theme}` });
|
|
344
372
|
res.end();
|
|
345
373
|
});
|
|
@@ -347,9 +375,10 @@ async function acquireKeyFromBrowser(projectId) {
|
|
|
347
375
|
const pollTimer = setInterval(() => {
|
|
348
376
|
const apiKey = getApiKey(projectId);
|
|
349
377
|
if (apiKey) {
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
378
|
+
settle(() => {
|
|
379
|
+
print("\u2713 API key detected from config");
|
|
380
|
+
resolve(apiKey);
|
|
381
|
+
});
|
|
353
382
|
}
|
|
354
383
|
}, POLL_INTERVAL_MS);
|
|
355
384
|
const HINT_MS = 55e3;
|
|
@@ -366,25 +395,31 @@ async function acquireKeyFromBrowser(projectId) {
|
|
|
366
395
|
print("Waiting for authorization in browser...");
|
|
367
396
|
}, HINT_MS);
|
|
368
397
|
const timer = setTimeout(() => {
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
398
|
+
settle(
|
|
399
|
+
() => reject(
|
|
400
|
+
new Error(
|
|
401
|
+
"Browser authorization timed out. Use `framer project auth <projectUrlOrId> <apiKey>` instead."
|
|
402
|
+
)
|
|
373
403
|
)
|
|
374
404
|
);
|
|
375
405
|
}, TIMEOUT_MS);
|
|
406
|
+
let cleaned = false;
|
|
376
407
|
function cleanup() {
|
|
408
|
+
if (cleaned) return;
|
|
409
|
+
cleaned = true;
|
|
377
410
|
clearTimeout(timer);
|
|
378
411
|
clearTimeout(hintTimer);
|
|
379
412
|
clearInterval(pollTimer);
|
|
380
413
|
server.close();
|
|
414
|
+
server.closeAllConnections();
|
|
381
415
|
}
|
|
382
416
|
__name(cleanup, "cleanup");
|
|
383
|
-
server.
|
|
417
|
+
server.keepAliveTimeout = 0;
|
|
418
|
+
server.unref();
|
|
419
|
+
server.listen(0, "127.0.0.1", () => {
|
|
384
420
|
const addr = server.address();
|
|
385
421
|
if (!addr || typeof addr === "string") {
|
|
386
|
-
|
|
387
|
-
reject(new Error("Failed to start callback server."));
|
|
422
|
+
settle(() => reject(new Error("Failed to start callback server.")));
|
|
388
423
|
return;
|
|
389
424
|
}
|
|
390
425
|
const callbackUrl = `http://127.0.0.1:${addr.port}/callback`;
|
|
@@ -393,13 +428,14 @@ async function acquireKeyFromBrowser(projectId) {
|
|
|
393
428
|
deeplink.searchParams.set("state", state);
|
|
394
429
|
deeplink.searchParams.set("projectId", projectId);
|
|
395
430
|
const deeplinkStr = deeplink.toString();
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
431
|
+
openUrl(deeplinkStr).then((opened) => {
|
|
432
|
+
if (opened) {
|
|
433
|
+
print("Waiting for authorization in browser...");
|
|
434
|
+
} else {
|
|
435
|
+
printError("Could not open browser. Open this URL manually:");
|
|
436
|
+
printError(deeplinkStr);
|
|
437
|
+
}
|
|
438
|
+
});
|
|
403
439
|
});
|
|
404
440
|
});
|
|
405
441
|
}
|
|
@@ -14910,7 +14946,7 @@ ${typeDef}`);
|
|
|
14910
14946
|
__name(renderDocs, "renderDocs");
|
|
14911
14947
|
var __filename$1 = fileURLToPath(import.meta.url);
|
|
14912
14948
|
var __dirname$1 = path4.dirname(__filename$1);
|
|
14913
|
-
var VERSION = "0.0.
|
|
14949
|
+
var VERSION = "0.0.13" ;
|
|
14914
14950
|
var RELAY_PORT = Number(process.env.FRAMER_CLI_PORT) || 19988;
|
|
14915
14951
|
var client = createTRPCClient({
|
|
14916
14952
|
links: [
|
|
@@ -13,7 +13,7 @@ import { createRequire } from 'module';
|
|
|
13
13
|
import * as vm from 'vm';
|
|
14
14
|
import { connect } from 'framer-api';
|
|
15
15
|
|
|
16
|
-
/* @framer/ai relay server v0.0.
|
|
16
|
+
/* @framer/ai relay server v0.0.13 */
|
|
17
17
|
var __defProp = Object.defineProperty;
|
|
18
18
|
var __knownSymbol = (name, symbol) => (symbol = Symbol[name]) ? symbol : /* @__PURE__ */ Symbol.for("Symbol." + name);
|
|
19
19
|
var __typeError = (msg) => {
|
|
@@ -91,7 +91,7 @@ function log(message) {
|
|
|
91
91
|
__name(log, "log");
|
|
92
92
|
var __filename$1 = fileURLToPath(import.meta.url);
|
|
93
93
|
path.dirname(__filename$1);
|
|
94
|
-
var VERSION = "0.0.
|
|
94
|
+
var VERSION = "0.0.13" ;
|
|
95
95
|
var RELAY_PORT = Number(process.env.FRAMER_CLI_PORT) || 19988;
|
|
96
96
|
createTRPCClient({
|
|
97
97
|
links: [
|
|
@@ -796,6 +796,7 @@ var appRouter = t.router({
|
|
|
796
796
|
error: "Failed to get connection for session"
|
|
797
797
|
};
|
|
798
798
|
}
|
|
799
|
+
const start = performance.now();
|
|
799
800
|
const result = await executeWithReconnect(
|
|
800
801
|
session,
|
|
801
802
|
framer,
|
|
@@ -804,8 +805,11 @@ var appRouter = t.router({
|
|
|
804
805
|
() => sessionManager.reconnect(session),
|
|
805
806
|
execId
|
|
806
807
|
);
|
|
808
|
+
const elapsed = (performance.now() - start).toFixed(0);
|
|
807
809
|
if (result.error) {
|
|
808
|
-
log(`exec.error ${tag} error="${result.error}"`);
|
|
810
|
+
log(`exec.error ${tag} ${elapsed}ms error="${result.error}"`);
|
|
811
|
+
} else {
|
|
812
|
+
log(`exec.done ${tag} ${elapsed}ms`);
|
|
809
813
|
}
|
|
810
814
|
return result;
|
|
811
815
|
} catch (_) {
|