@agent-native/core 0.84.32 → 0.84.34
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/corpus/README.md +1 -1
- package/corpus/core/CHANGELOG.md +12 -0
- package/corpus/core/package.json +1 -1
- package/corpus/core/src/client/use-action.ts +5 -1
- package/corpus/core/src/server/ssr-handler.ts +12 -0
- package/corpus/core/src/vite/action-types-plugin.ts +6 -2
- package/corpus/core/src/vite/client.ts +152 -17
- package/corpus/templates/design/actions/import-design-source.ts +158 -0
- package/corpus/templates/design/actions/navigate.ts +3 -2
- package/corpus/templates/design/actions/view-screen.ts +1 -1
- package/corpus/templates/design/app/components/design/DesignImportPanel.tsx +519 -0
- package/corpus/templates/design/app/hooks/use-navigation-state.ts +28 -5
- package/corpus/templates/design/app/i18n/zh-TW.ts +40 -0
- package/corpus/templates/design/app/i18n-data.ts +508 -0
- package/corpus/templates/design/app/pages/DesignEditor.tsx +27 -0
- package/corpus/templates/design/changelog/2026-07-01-design-can-import-figma-paste-fig-files-and-standalone-html.md +6 -0
- package/corpus/templates/design/package.json +3 -0
- package/corpus/templates/design/server/handlers/import-design-file.ts +168 -0
- package/corpus/templates/design/server/lib/figma-import/clipboard.ts +122 -0
- package/corpus/templates/design/server/lib/figma-import/decode.ts +455 -0
- package/corpus/templates/design/server/lib/figma-import/processor.ts +116 -0
- package/corpus/templates/design/server/lib/figma-import/render-html.ts +397 -0
- package/corpus/templates/design/server/lib/figma-import/types.ts +60 -0
- package/corpus/templates/design/server/lib/import-design-files.ts +314 -0
- package/corpus/templates/design/server/routes/api/import-design-file.post.ts +1 -0
- package/dist/client/use-action.d.ts +5 -1
- package/dist/client/use-action.d.ts.map +1 -1
- package/dist/client/use-action.js.map +1 -1
- package/dist/collab/awareness.d.ts +2 -2
- package/dist/collab/awareness.d.ts.map +1 -1
- package/dist/collab/routes.d.ts +1 -1
- package/dist/notifications/routes.d.ts +3 -3
- package/dist/observability/routes.d.ts +3 -3
- package/dist/resources/handlers.d.ts +2 -2
- package/dist/server/agent-engine-api-key-route.d.ts +1 -1
- package/dist/server/ssr-handler.d.ts.map +1 -1
- package/dist/server/ssr-handler.js +7 -0
- package/dist/server/ssr-handler.js.map +1 -1
- package/dist/vite/action-types-plugin.d.ts.map +1 -1
- package/dist/vite/action-types-plugin.js +6 -2
- package/dist/vite/action-types-plugin.js.map +1 -1
- package/dist/vite/client.d.ts.map +1 -1
- package/dist/vite/client.js +132 -11
- package/dist/vite/client.js.map +1 -1
- package/package.json +1 -1
|
@@ -0,0 +1,314 @@
|
|
|
1
|
+
import { readAppStateForCurrentTab } from "@agent-native/core/application-state";
|
|
2
|
+
import {
|
|
3
|
+
applyText,
|
|
4
|
+
hasCollabState,
|
|
5
|
+
seedFromText,
|
|
6
|
+
} from "@agent-native/core/collab";
|
|
7
|
+
import { assertAccess } from "@agent-native/core/sharing";
|
|
8
|
+
import { eq } from "drizzle-orm";
|
|
9
|
+
import { nanoid } from "nanoid";
|
|
10
|
+
|
|
11
|
+
import {
|
|
12
|
+
mergeCanvasFramePlacements,
|
|
13
|
+
type CanvasFramePlacement,
|
|
14
|
+
} from "../../shared/canvas-frames.js";
|
|
15
|
+
import { getDb, schema } from "../db/index.js";
|
|
16
|
+
|
|
17
|
+
const DEFAULT_FRAME_WIDTH = 1440;
|
|
18
|
+
const DEFAULT_FRAME_HEIGHT = 900;
|
|
19
|
+
const FRAME_GAP = 96;
|
|
20
|
+
|
|
21
|
+
export interface ImportedDesignFile {
|
|
22
|
+
filename: string;
|
|
23
|
+
fileType: "html" | "css" | "jsx" | "asset";
|
|
24
|
+
content: string;
|
|
25
|
+
source?: Record<string, unknown>;
|
|
26
|
+
preferredFrame?: {
|
|
27
|
+
title?: string;
|
|
28
|
+
width?: number;
|
|
29
|
+
height?: number;
|
|
30
|
+
x?: number;
|
|
31
|
+
y?: number;
|
|
32
|
+
};
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
export interface SaveImportedDesignFilesInput {
|
|
36
|
+
designId?: string;
|
|
37
|
+
files: ImportedDesignFile[];
|
|
38
|
+
sourceType: string;
|
|
39
|
+
warnings?: string[];
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
export interface SavedImportedDesignFile {
|
|
43
|
+
id: string;
|
|
44
|
+
filename: string;
|
|
45
|
+
fileType: string;
|
|
46
|
+
source?: Record<string, unknown>;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
function isRecord(value: unknown): value is Record<string, unknown> {
|
|
50
|
+
return value !== null && typeof value === "object" && !Array.isArray(value);
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
function stringFromState(value: unknown, key: string): string | undefined {
|
|
54
|
+
return isRecord(value) && typeof value[key] === "string"
|
|
55
|
+
? (value[key] as string)
|
|
56
|
+
: undefined;
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
export async function resolveImportDesignId(
|
|
60
|
+
explicitDesignId?: string,
|
|
61
|
+
): Promise<string> {
|
|
62
|
+
if (explicitDesignId?.trim()) return explicitDesignId.trim();
|
|
63
|
+
const navigation = await readAppStateForCurrentTab("navigation").catch(
|
|
64
|
+
() => null,
|
|
65
|
+
);
|
|
66
|
+
const designId = stringFromState(navigation, "designId");
|
|
67
|
+
if (!designId) {
|
|
68
|
+
throw new Error(
|
|
69
|
+
"No designId was provided and no active design was found in the current editor.",
|
|
70
|
+
);
|
|
71
|
+
}
|
|
72
|
+
return designId;
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
function parseJson(value: string | null | undefined): Record<string, unknown> {
|
|
76
|
+
if (!value) return {};
|
|
77
|
+
try {
|
|
78
|
+
const parsed = JSON.parse(value);
|
|
79
|
+
return isRecord(parsed) ? parsed : {};
|
|
80
|
+
} catch {
|
|
81
|
+
return {};
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
export function sanitizeImportedFilename(filename: string): string {
|
|
86
|
+
const trimmed = filename.trim();
|
|
87
|
+
if (!trimmed || trimmed.includes("..") || /[\\/]/.test(trimmed)) {
|
|
88
|
+
throw new Error("Imported filename is invalid.");
|
|
89
|
+
}
|
|
90
|
+
const cleaned = trimmed
|
|
91
|
+
.replace(/[^\w. -]+/g, "-")
|
|
92
|
+
.replace(/\s+/g, "-")
|
|
93
|
+
.replace(/-+/g, "-")
|
|
94
|
+
.replace(/^-+|-+$/g, "");
|
|
95
|
+
if (!cleaned) throw new Error("Imported filename is invalid.");
|
|
96
|
+
return cleaned;
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
function ensureExtension(
|
|
100
|
+
filename: string,
|
|
101
|
+
fileType: ImportedDesignFile["fileType"],
|
|
102
|
+
) {
|
|
103
|
+
if (/\.[A-Za-z0-9]+$/.test(filename)) return filename;
|
|
104
|
+
if (fileType === "css") return `${filename}.css`;
|
|
105
|
+
if (fileType === "jsx") return `${filename}.jsx`;
|
|
106
|
+
if (fileType === "asset") return filename;
|
|
107
|
+
return `${filename}.html`;
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
function uniqueFilename(filename: string, used: Set<string>): string {
|
|
111
|
+
if (!used.has(filename)) {
|
|
112
|
+
used.add(filename);
|
|
113
|
+
return filename;
|
|
114
|
+
}
|
|
115
|
+
const dot = filename.lastIndexOf(".");
|
|
116
|
+
const base = dot > 0 ? filename.slice(0, dot) : filename;
|
|
117
|
+
const ext = dot > 0 ? filename.slice(dot) : "";
|
|
118
|
+
let index = 2;
|
|
119
|
+
while (used.has(`${base}-${index}${ext}`)) index += 1;
|
|
120
|
+
const next = `${base}-${index}${ext}`;
|
|
121
|
+
used.add(next);
|
|
122
|
+
return next;
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
function positiveDimension(value: unknown, fallback: number): number {
|
|
126
|
+
return typeof value === "number" && Number.isFinite(value) && value > 0
|
|
127
|
+
? Math.round(value)
|
|
128
|
+
: fallback;
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
function sanitizeImportedHtml(content: string): string {
|
|
132
|
+
return content
|
|
133
|
+
.replace(/<\s*script\b[^>]*>[\s\S]*?<\s*\/\s*script\s*>/gi, "")
|
|
134
|
+
.replace(/<\s*script\b[^>]*\/?\s*>/gi, "")
|
|
135
|
+
.replace(/<\s*(iframe|object|embed)\b[^>]*>[\s\S]*?<\s*\/\s*\1\s*>/gi, "")
|
|
136
|
+
.replace(/<\s*(iframe|object|embed)\b[^>]*\/?\s*>/gi, "")
|
|
137
|
+
.replace(/\s+on[a-z][\w:-]*\s*=\s*(?:"[^"]*"|'[^']*'|[^\s>]+)/gi, "")
|
|
138
|
+
.replace(/\s+srcdoc\s*=\s*(?:"[^"]*"|'[^']*'|[^\s>]+)/gi, "")
|
|
139
|
+
.replace(
|
|
140
|
+
/\s+(href|src|xlink:href|action|formaction)\s*=\s*"[\s]*(?:javascript|vbscript):[^"]*"/gi,
|
|
141
|
+
"",
|
|
142
|
+
)
|
|
143
|
+
.replace(
|
|
144
|
+
/\s+(href|src|xlink:href|action|formaction)\s*=\s*'[\s]*(?:javascript|vbscript):[^']*'/gi,
|
|
145
|
+
"",
|
|
146
|
+
)
|
|
147
|
+
.replace(
|
|
148
|
+
/\s+(href|src|xlink:href|action|formaction)\s*=\s*(?:javascript|vbscript):[^\s>]*/gi,
|
|
149
|
+
"",
|
|
150
|
+
)
|
|
151
|
+
.replace(
|
|
152
|
+
/\s+style\s*=\s*(["'])(?:(?!\1).)*(?:expression\s*\(|javascript:)(?:(?!\1).)*\1/gi,
|
|
153
|
+
"",
|
|
154
|
+
);
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
export function normalizeImportedHtmlDocument(
|
|
158
|
+
content: string,
|
|
159
|
+
sourceLabel: string,
|
|
160
|
+
): string {
|
|
161
|
+
const normalized = sanitizeImportedHtml(content.replace(/\0/g, "")).trim();
|
|
162
|
+
if (!normalized) throw new Error("HTML import content is empty.");
|
|
163
|
+
const safeSourceLabel = sourceLabel.replace(/--+/g, "-").replace(/[<>]/g, "");
|
|
164
|
+
const comment = `<!-- Imported into Design from ${safeSourceLabel}. -->`;
|
|
165
|
+
if (/<html[\s>]/i.test(normalized)) {
|
|
166
|
+
return normalized.replace(
|
|
167
|
+
/<head(\s[^>]*)?>/i,
|
|
168
|
+
(match) => `${match}\n ${comment}`,
|
|
169
|
+
);
|
|
170
|
+
}
|
|
171
|
+
return `<!doctype html>
|
|
172
|
+
<html>
|
|
173
|
+
<head>
|
|
174
|
+
<meta charset="utf-8" />
|
|
175
|
+
${comment}
|
|
176
|
+
</head>
|
|
177
|
+
<body>
|
|
178
|
+
${normalized}
|
|
179
|
+
</body>
|
|
180
|
+
</html>`;
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
export async function saveImportedDesignFiles(
|
|
184
|
+
input: SaveImportedDesignFilesInput,
|
|
185
|
+
) {
|
|
186
|
+
if (input.files.length === 0) {
|
|
187
|
+
throw new Error("No files were produced by the import.");
|
|
188
|
+
}
|
|
189
|
+
const designId = await resolveImportDesignId(input.designId);
|
|
190
|
+
await assertAccess("design", designId, "editor");
|
|
191
|
+
|
|
192
|
+
const db = getDb();
|
|
193
|
+
const now = new Date().toISOString();
|
|
194
|
+
const savedFiles: SavedImportedDesignFile[] = [];
|
|
195
|
+
const seedRecords: Array<{ id: string; content: string }> = [];
|
|
196
|
+
let placedFrames:
|
|
197
|
+
| Array<{
|
|
198
|
+
fileId: string;
|
|
199
|
+
filename?: string;
|
|
200
|
+
frame: CanvasFramePlacement;
|
|
201
|
+
}>
|
|
202
|
+
| undefined;
|
|
203
|
+
|
|
204
|
+
await db.transaction(async (tx) => {
|
|
205
|
+
const [design] = await tx
|
|
206
|
+
.select()
|
|
207
|
+
.from(schema.designs)
|
|
208
|
+
.where(eq(schema.designs.id, designId))
|
|
209
|
+
.limit(1);
|
|
210
|
+
if (!design) throw new Error(`Design ${designId} was not found.`);
|
|
211
|
+
|
|
212
|
+
const existingFiles = await tx
|
|
213
|
+
.select()
|
|
214
|
+
.from(schema.designFiles)
|
|
215
|
+
.where(eq(schema.designFiles.designId, designId));
|
|
216
|
+
const usedFilenames = new Set(existingFiles.map((file) => file.filename));
|
|
217
|
+
const prevData = parseJson(design.data);
|
|
218
|
+
const previousMetadata = isRecord(prevData.screenMetadata)
|
|
219
|
+
? { ...prevData.screenMetadata }
|
|
220
|
+
: {};
|
|
221
|
+
const placements: CanvasFramePlacement[] = [];
|
|
222
|
+
let nextFrameX = 0;
|
|
223
|
+
|
|
224
|
+
for (let index = 0; index < input.files.length; index += 1) {
|
|
225
|
+
const file = input.files[index]!;
|
|
226
|
+
const filename = uniqueFilename(
|
|
227
|
+
ensureExtension(sanitizeImportedFilename(file.filename), file.fileType),
|
|
228
|
+
usedFilenames,
|
|
229
|
+
);
|
|
230
|
+
const fileId = nanoid();
|
|
231
|
+
await tx.insert(schema.designFiles).values({
|
|
232
|
+
id: fileId,
|
|
233
|
+
designId,
|
|
234
|
+
filename,
|
|
235
|
+
fileType: file.fileType,
|
|
236
|
+
content: file.content,
|
|
237
|
+
createdAt: now,
|
|
238
|
+
updatedAt: now,
|
|
239
|
+
});
|
|
240
|
+
seedRecords.push({ id: fileId, content: file.content });
|
|
241
|
+
|
|
242
|
+
const width = positiveDimension(
|
|
243
|
+
file.preferredFrame?.width,
|
|
244
|
+
DEFAULT_FRAME_WIDTH,
|
|
245
|
+
);
|
|
246
|
+
const height = positiveDimension(
|
|
247
|
+
file.preferredFrame?.height,
|
|
248
|
+
DEFAULT_FRAME_HEIGHT,
|
|
249
|
+
);
|
|
250
|
+
placements.push({
|
|
251
|
+
fileId,
|
|
252
|
+
filename,
|
|
253
|
+
x: file.preferredFrame?.x ?? nextFrameX,
|
|
254
|
+
y: file.preferredFrame?.y ?? 0,
|
|
255
|
+
width,
|
|
256
|
+
height,
|
|
257
|
+
z: index,
|
|
258
|
+
});
|
|
259
|
+
nextFrameX += width + FRAME_GAP;
|
|
260
|
+
const source = {
|
|
261
|
+
sourceType: input.sourceType,
|
|
262
|
+
previewState: "static",
|
|
263
|
+
title: file.preferredFrame?.title ?? filename.replace(/\.[^.]+$/, ""),
|
|
264
|
+
width,
|
|
265
|
+
height,
|
|
266
|
+
...file.source,
|
|
267
|
+
};
|
|
268
|
+
previousMetadata[fileId] = source;
|
|
269
|
+
savedFiles.push({
|
|
270
|
+
id: fileId,
|
|
271
|
+
filename,
|
|
272
|
+
fileType: file.fileType,
|
|
273
|
+
source,
|
|
274
|
+
});
|
|
275
|
+
}
|
|
276
|
+
|
|
277
|
+
const mergedFrames = mergeCanvasFramePlacements({
|
|
278
|
+
existing: prevData.canvasFrames,
|
|
279
|
+
placements,
|
|
280
|
+
resolveFileId: (placement) => placement.fileId,
|
|
281
|
+
});
|
|
282
|
+
placedFrames = mergedFrames.placedFrames;
|
|
283
|
+
await tx
|
|
284
|
+
.update(schema.designs)
|
|
285
|
+
.set({
|
|
286
|
+
data: JSON.stringify({
|
|
287
|
+
...prevData,
|
|
288
|
+
sourceMode: "import",
|
|
289
|
+
canvasFrames: mergedFrames.canvasFrames,
|
|
290
|
+
screenMetadata: previousMetadata,
|
|
291
|
+
updatedAt: now,
|
|
292
|
+
}),
|
|
293
|
+
updatedAt: now,
|
|
294
|
+
})
|
|
295
|
+
.where(eq(schema.designs.id, designId));
|
|
296
|
+
});
|
|
297
|
+
|
|
298
|
+
for (const record of seedRecords) {
|
|
299
|
+
if (await hasCollabState(record.id)) {
|
|
300
|
+
await applyText(record.id, record.content, "content", "agent");
|
|
301
|
+
} else {
|
|
302
|
+
await seedFromText(record.id, record.content);
|
|
303
|
+
}
|
|
304
|
+
}
|
|
305
|
+
|
|
306
|
+
return {
|
|
307
|
+
designId,
|
|
308
|
+
files: savedFiles,
|
|
309
|
+
warnings: input.warnings ?? [],
|
|
310
|
+
placedFrames: placedFrames ?? [],
|
|
311
|
+
overview: true,
|
|
312
|
+
urlPath: `/design/${designId}`,
|
|
313
|
+
};
|
|
314
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { importDesignFile as default } from "../../handlers/import-design-file.js";
|
|
@@ -5,7 +5,11 @@ import type { UseQueryOptions, UseMutationOptions } from "@tanstack/react-query"
|
|
|
5
5
|
* it maps action names to their parameter and return types, enabling
|
|
6
6
|
* end-to-end type safety for `useActionQuery` and `useActionMutation`.
|
|
7
7
|
*/
|
|
8
|
-
|
|
8
|
+
declare global {
|
|
9
|
+
interface AgentNativeActionRegistry {
|
|
10
|
+
}
|
|
11
|
+
}
|
|
12
|
+
export interface ActionRegistry extends AgentNativeActionRegistry {
|
|
9
13
|
}
|
|
10
14
|
/** Resolves to the union of registered action names, or `string` if no registry exists. */
|
|
11
15
|
type ActionName = keyof ActionRegistry extends never ? string : (keyof ActionRegistry & string) | (string & {});
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"use-action.d.ts","sourceRoot":"","sources":["../../src/client/use-action.ts"],"names":[],"mappings":"AAwBA,OAAO,KAAK,EACV,eAAe,EACf,kBAAkB,EACnB,MAAM,uBAAuB,CAAC;AA6B/B;;;;;GAKG;AACH,MAAM,WAAW,
|
|
1
|
+
{"version":3,"file":"use-action.d.ts","sourceRoot":"","sources":["../../src/client/use-action.ts"],"names":[],"mappings":"AAwBA,OAAO,KAAK,EACV,eAAe,EACf,kBAAkB,EACnB,MAAM,uBAAuB,CAAC;AA6B/B;;;;;GAKG;AACH,OAAO,CAAC,MAAM,CAAC;IACb,UAAU,yBAAyB;KAAG;CACvC;AAED,MAAM,WAAW,cAAe,SAAQ,yBAAyB;CAAG;AAEpE,2FAA2F;AAC3F,KAAK,UAAU,GAAG,MAAM,cAAc,SAAS,KAAK,GAChD,MAAM,GACN,CAAC,MAAM,cAAc,GAAG,MAAM,CAAC,GAAG,CAAC,MAAM,GAAG,EAAE,CAAC,CAAC;AAEpD,8EAA8E;AAC9E,KAAK,YAAY,CAAC,CAAC,SAAS,MAAM,IAAI,CAAC,SAAS,MAAM,cAAc,GAChE,cAAc,CAAC,CAAC,CAAC,SAAS;IAAE,MAAM,EAAE,MAAM,CAAC,CAAA;CAAE,GAC3C,CAAC,GACD,GAAG,GACL,GAAG,CAAC;AAER,iGAAiG;AACjG,KAAK,YAAY,CAAC,CAAC,SAAS,MAAM,IAAI,CAAC,SAAS,MAAM,cAAc,GAChE,cAAc,CAAC,CAAC,CAAC,SAAS;IAAE,MAAM,EAAE,MAAM,CAAC,CAAA;CAAE,GAC3C,CAAC,GACD,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,GACrB,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;AAExB,MAAM,MAAM,kBAAkB,GAAG,KAAK,GAAG,MAAM,GAAG,KAAK,GAAG,QAAQ,CAAC;AAEnE,MAAM,WAAW,uBAAuB;IACtC,MAAM,CAAC,EAAE,kBAAkB,CAAC;CAC7B;AAmBD,wBAAgB,0BAA0B,CACxC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,GAC1B,MAAM,CAMR;AAsID;;;;;;GAMG;AACH,wBAAgB,UAAU,CACxB,OAAO,GAAG,SAAS,EACnB,KAAK,SAAS,UAAU,GAAG,UAAU,EAErC,UAAU,EAAE,KAAK,EACjB,MAAM,CAAC,EAAE,YAAY,CAAC,KAAK,CAAC,EAC5B,OAAO,GAAE,uBAA4B,GACpC,OAAO,CAAC,OAAO,SAAS,SAAS,GAAG,YAAY,CAAC,KAAK,CAAC,GAAG,OAAO,CAAC,CAGpE;AAMD;;;;;;;;;;;;;GAaG;AACH,wBAAgB,cAAc,CAC5B,OAAO,GAAG,SAAS,EACnB,KAAK,SAAS,UAAU,GAAG,UAAU,EAErC,UAAU,EAAE,KAAK,EACjB,MAAM,CAAC,EAAE,YAAY,CAAC,KAAK,CAAC,EAC5B,OAAO,CAAC,EAAE,IAAI,CACZ,eAAe,CAAC,OAAO,SAAS,SAAS,GAAG,YAAY,CAAC,KAAK,CAAC,GAAG,OAAO,CAAC,EAC1E,UAAU,GAAG,SAAS,CACvB,6HASF;AAMD;;;;;;;;;;;GAWG;AACH,wBAAgB,iBAAiB,CAC/B,KAAK,GAAG,SAAS,EACjB,UAAU,GAAG,SAAS,EACtB,KAAK,SAAS,UAAU,GAAG,UAAU,EAErC,UAAU,EAAE,KAAK,EACjB,OAAO,CAAC,EAAE,IAAI,CACZ,kBAAkB,CAChB,KAAK,SAAS,SAAS,GAAG,YAAY,CAAC,KAAK,CAAC,GAAG,KAAK,EACrD,KAAK,EACL,UAAU,SAAS,SAAS,GAAG,YAAY,CAAC,KAAK,CAAC,GAAG,UAAU,CAChE,EACD,YAAY,CACb,GAAG;IACF,MAAM,CAAC,EAAE,MAAM,GAAG,KAAK,GAAG,QAAQ,CAAC;CACpC,6LAuBF"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"use-action.js","sourceRoot":"","sources":["../../src/client/use-action.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Client helpers for calling actions through the framework transport.\n *\n * Components should prefer `useActionQuery` / `useActionMutation`; use\n * `callAction` for imperative cases such as debounced search, prefetching, or\n * event handlers that do not fit a hook.\n *\n * ## End-to-end type safety\n *\n * When the action type registry is generated (via the Vite plugin or CLI),\n * `useActionQuery` and `useActionMutation` automatically infer the correct\n * return type and parameter types from the action definitions — no manual\n * type annotations needed.\n *\n * ```ts\n * // Fully typed — return type and params inferred from the action's defineAction()\n * const { data } = useActionQuery(\"list-forms\", { status: \"published\" });\n * // ^? Form[] (inferred from the action's run() return type)\n * ```\n *\n * Without the registry, the hooks fall back to `any` types for backward\n * compatibility.\n */\nimport { useQuery, useMutation, useQueryClient } from \"@tanstack/react-query\";\nimport type {\n UseQueryOptions,\n UseMutationOptions,\n} from \"@tanstack/react-query\";\n\nimport { agentNativePath } from \"./api-path.js\";\nimport { ensureEmbedAuthFetchInterceptor } from \"./embed-auth.js\";\n\nconst ACTION_PREFIX = agentNativePath(\"/_agent-native/actions\");\n\nfunction isAuthFailure(error: unknown): boolean {\n return (\n !!error &&\n typeof error === \"object\" &&\n \"status\" in error &&\n ((error as { status?: unknown }).status === 401 ||\n (error as { status?: unknown }).status === 403)\n );\n}\n\nfunction defaultActionQueryRetry(\n failureCount: number,\n error: unknown,\n): boolean {\n if (isAuthFailure(error)) return false;\n return failureCount < 3;\n}\n\n// ---------------------------------------------------------------------------\n// Action type registry — augmented by generated code\n// ---------------------------------------------------------------------------\n\n/**\n * Action type registry. This interface is empty by default and gets augmented\n * by the auto-generated `.generated/action-types.d.ts` file. When augmented,\n * it maps action names to their parameter and return types, enabling\n * end-to-end type safety for `useActionQuery` and `useActionMutation`.\n */\nexport interface ActionRegistry {}\n\n/** Resolves to the union of registered action names, or `string` if no registry exists. */\ntype ActionName = keyof ActionRegistry extends never\n ? string\n : (keyof ActionRegistry & string) | (string & {});\n\n/** Resolves the return type of an action, or `any` if not in the registry. */\ntype ActionResult<T extends string> = T extends keyof ActionRegistry\n ? ActionRegistry[T] extends { result: infer R }\n ? R\n : any\n : any;\n\n/** Resolves the parameter type of an action, or `Record<string, any>` if not in the registry. */\ntype ActionParams<T extends string> = T extends keyof ActionRegistry\n ? ActionRegistry[T] extends { params: infer P }\n ? P\n : Record<string, any>\n : Record<string, any>;\n\nexport type ClientActionMethod = \"GET\" | \"POST\" | \"PUT\" | \"DELETE\";\n\nexport interface ClientActionCallOptions {\n method?: ClientActionMethod;\n}\n\n// ---------------------------------------------------------------------------\n// Fetch helper\n// ---------------------------------------------------------------------------\n\n/**\n * Resolve the browser's IANA timezone (e.g. \"America/Los_Angeles\"). This is\n * sent on every action request as `x-user-timezone` so server-side defaults\n * like \"today\" honor the user's local day rather than the server's UTC clock.\n */\nfunction resolveUserTimezone(): string | undefined {\n try {\n return Intl.DateTimeFormat().resolvedOptions().timeZone || undefined;\n } catch {\n return undefined;\n }\n}\n\nexport function serializeActionQueryParams(\n params: Record<string, any>,\n): string {\n const qs = new URLSearchParams();\n for (const [key, value] of Object.entries(params)) {\n appendActionQueryParam(qs, key, value);\n }\n return qs.toString();\n}\n\nfunction appendActionQueryParam(\n qs: URLSearchParams,\n key: string,\n value: unknown,\n) {\n if (value === null || value === undefined) return;\n if (Array.isArray(value)) {\n // Use bracket keys so a one-item array still arrives as an array after the\n // server parses URLSearchParams. Repeated bare keys lose that distinction.\n for (const item of value) {\n appendActionQueryParam(qs, `${key}[]`, item);\n }\n return;\n }\n qs.append(key, String(value));\n}\n\nasync function actionFetch<T>(\n name: string,\n method: string,\n params?: Record<string, any>,\n): Promise<T> {\n ensureEmbedAuthFetchInterceptor();\n let url = `${ACTION_PREFIX}/${name}`;\n const headers: Record<string, string> = {\n \"Content-Type\": \"application/json\",\n // Tag browser-originated action calls so the server can set\n // `ctx.caller = \"frontend\"` (vs a bare programmatic `\"http\"` POST).\n // Mirrors the X-Agent-Native-Tool-Bridge: 1 convention. The header is\n // safe to expose: CORS allows it (see action-routes.ts) and it carries\n // no auth weight — it only narrows the caller tag.\n \"X-Agent-Native-Frontend\": \"1\",\n };\n const tz = resolveUserTimezone();\n if (tz) headers[\"x-user-timezone\"] = tz;\n const init: RequestInit = {\n method,\n headers,\n cache: \"no-store\",\n };\n\n if (method === \"GET\" && params && Object.keys(params).length > 0) {\n // Skip null/undefined so optional filters don't turn into literal \"null\"\n // strings in the query string (e.g. `?folderId=null`).\n const qs = serializeActionQueryParams(params);\n if (qs) url += `?${qs}`;\n } else if (method !== \"GET\" && params) {\n init.body = JSON.stringify(params);\n }\n\n let res: Response;\n try {\n res = await fetch(url, init);\n } catch (err) {\n // Network failures, CORS, server unreachable, etc. — give the caller a\n // useful message instead of the opaque \"Failed to fetch\".\n const cause = err instanceof Error ? err.message : String(err);\n throw new Error(`Action ${name} failed: ${cause}`);\n }\n\n // 204 No Content — nothing to parse.\n if (res.status === 204) return null as T;\n\n // Read the body as text first so we can:\n // - tolerate empty bodies (avoids \"Unexpected end of JSON input\")\n // - surface non-JSON error responses (HTML 401/404 pages, plain text, etc.)\n // - preserve the original HTTP status in the thrown error\n // Track read failures separately from \"no body\" — a stream interruption /\n // decode failure on a 2xx response should error rather than silently\n // succeed with `null`.\n let raw = \"\";\n let readFailed = false;\n let readError: unknown;\n try {\n raw = await res.text();\n } catch (err) {\n readFailed = true;\n readError = err;\n }\n\n let data: any = undefined;\n let parseFailed = false;\n if (raw.length > 0) {\n try {\n data = JSON.parse(raw);\n } catch {\n // Body wasn't JSON — keep `data` undefined and use the raw text below.\n parseFailed = true;\n }\n }\n\n if (!res.ok) {\n const message =\n (data && (data.error || data.message)) ||\n // Truncate non-JSON bodies so we don't dump entire HTML pages into the\n // console, but still give the developer a hint as to what came back.\n (raw && raw.slice(0, 200)) ||\n res.statusText ||\n `HTTP ${res.status}`;\n const error = new Error(`Action ${name} failed: ${message}`);\n (error as any).status = res.status;\n throw error;\n }\n\n // 2xx but the body couldn't even be read (mid-stream abort, decode failure,\n // etc.). Don't silently treat that as a `null` success.\n if (readFailed) {\n const cause =\n readError instanceof Error ? readError.message : String(readError);\n const error = new Error(\n `Action ${name} returned ${res.status} but the body could not be read: ${cause}`,\n );\n (error as any).status = res.status;\n throw error;\n }\n\n // 2xx with a non-empty, non-JSON body. Action callers expect typed data, so\n // returning `null` here would silently mask a real server bug (e.g. a proxy\n // returning HTML 200 instead of JSON). Throw instead — empty bodies (handled\n // above by the `raw.length > 0` guard and the 204 short-circuit) still\n // correctly resolve to `null`.\n if (parseFailed) {\n const error = new Error(\n `Action ${name} returned a non-JSON ${res.status} response: ${raw.slice(0, 200)}`,\n );\n (error as any).status = res.status;\n throw error;\n }\n\n return (data ?? (null as unknown)) as T;\n}\n\n/**\n * Imperatively call an action from browser/client code.\n *\n * Prefer `useActionQuery` / `useActionMutation` in React render flows. Use this\n * helper when a hook is not ergonomic; do not hand-write fetch calls to\n * `/_agent-native/actions/*` in components.\n */\nexport function callAction<\n TResult = undefined,\n TName extends ActionName = ActionName,\n>(\n actionName: TName,\n params?: ActionParams<TName>,\n options: ClientActionCallOptions = {},\n): Promise<TResult extends undefined ? ActionResult<TName> : TResult> {\n type R = TResult extends undefined ? ActionResult<TName> : TResult;\n return actionFetch<R>(actionName, options.method ?? \"POST\", params);\n}\n\n// ---------------------------------------------------------------------------\n// Query hook\n// ---------------------------------------------------------------------------\n\n/**\n * Query an action exposed as GET.\n *\n * When the action type registry is generated, the return type and parameter\n * types are inferred automatically from the action's `defineAction()` call.\n *\n * ```ts\n * // Type-safe — no manual generic needed\n * const { data } = useActionQuery(\"list-meals\", { date: \"2025-01-01\" });\n *\n * // Manual override still works when needed\n * const { data } = useActionQuery<CustomType>(\"list-meals\");\n * ```\n */\nexport function useActionQuery<\n TResult = undefined,\n TName extends ActionName = ActionName,\n>(\n actionName: TName,\n params?: ActionParams<TName>,\n options?: Omit<\n UseQueryOptions<TResult extends undefined ? ActionResult<TName> : TResult>,\n \"queryKey\" | \"queryFn\"\n >,\n) {\n type R = TResult extends undefined ? ActionResult<TName> : TResult;\n return useQuery<R>({\n queryKey: [\"action\", actionName, params],\n queryFn: () => actionFetch<R>(actionName, \"GET\", params),\n retry: defaultActionQueryRetry,\n ...options,\n });\n}\n\n// ---------------------------------------------------------------------------\n// Mutation hook\n// ---------------------------------------------------------------------------\n\n/**\n * Mutate via an action exposed as POST (default), PUT, or DELETE.\n *\n * When the action type registry is generated, the return type and parameter\n * types are inferred automatically.\n *\n * ```ts\n * // Type-safe\n * const { mutate } = useActionMutation(\"log-meal\");\n * mutate({ name: \"Salad\", calories: 350 });\n * ```\n */\nexport function useActionMutation<\n TData = undefined,\n TVariables = undefined,\n TName extends ActionName = ActionName,\n>(\n actionName: TName,\n options?: Omit<\n UseMutationOptions<\n TData extends undefined ? ActionResult<TName> : TData,\n Error,\n TVariables extends undefined ? ActionParams<TName> : TVariables\n >,\n \"mutationFn\"\n > & {\n method?: \"POST\" | \"PUT\" | \"DELETE\";\n },\n) {\n const queryClient = useQueryClient();\n const {\n method: methodOpt,\n onSuccess,\n ...restOptions\n } = options ?? ({} as any);\n const method = methodOpt ?? \"POST\";\n\n type D = TData extends undefined ? ActionResult<TName> : TData;\n type V = TVariables extends undefined ? ActionParams<TName> : TVariables;\n\n return useMutation<D, Error, V>({\n ...restOptions,\n mutationFn: (params) =>\n actionFetch<D>(actionName, method, params as Record<string, any>),\n onSuccess: (...args: [any, any, any]) => {\n // Invalidate related action queries\n queryClient.invalidateQueries({ queryKey: [\"action\"] });\n (onSuccess as Function)?.(...args);\n },\n });\n}\n"]}
|
|
1
|
+
{"version":3,"file":"use-action.js","sourceRoot":"","sources":["../../src/client/use-action.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;GAsBG;AACH,OAAO,EAAE,QAAQ,EAAE,WAAW,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;AAM9E,OAAO,EAAE,eAAe,EAAE,MAAM,eAAe,CAAC;AAChD,OAAO,EAAE,+BAA+B,EAAE,MAAM,iBAAiB,CAAC;AAElE,MAAM,aAAa,GAAG,eAAe,CAAC,wBAAwB,CAAC,CAAC;AAEhE,SAAS,aAAa,CAAC,KAAc;IACnC,OAAO,CACL,CAAC,CAAC,KAAK;QACP,OAAO,KAAK,KAAK,QAAQ;QACzB,QAAQ,IAAI,KAAK;QACjB,CAAE,KAA8B,CAAC,MAAM,KAAK,GAAG;YAC5C,KAA8B,CAAC,MAAM,KAAK,GAAG,CAAC,CAClD,CAAC;AACJ,CAAC;AAED,SAAS,uBAAuB,CAC9B,YAAoB,EACpB,KAAc;IAEd,IAAI,aAAa,CAAC,KAAK,CAAC;QAAE,OAAO,KAAK,CAAC;IACvC,OAAO,YAAY,GAAG,CAAC,CAAC;AAC1B,CAAC;AA2CD,8EAA8E;AAC9E,eAAe;AACf,8EAA8E;AAE9E;;;;GAIG;AACH,SAAS,mBAAmB;IAC1B,IAAI,CAAC;QACH,OAAO,IAAI,CAAC,cAAc,EAAE,CAAC,eAAe,EAAE,CAAC,QAAQ,IAAI,SAAS,CAAC;IACvE,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,SAAS,CAAC;IACnB,CAAC;AACH,CAAC;AAED,MAAM,UAAU,0BAA0B,CACxC,MAA2B;IAE3B,MAAM,EAAE,GAAG,IAAI,eAAe,EAAE,CAAC;IACjC,KAAK,MAAM,CAAC,GAAG,EAAE,KAAK,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,MAAM,CAAC,EAAE,CAAC;QAClD,sBAAsB,CAAC,EAAE,EAAE,GAAG,EAAE,KAAK,CAAC,CAAC;IACzC,CAAC;IACD,OAAO,EAAE,CAAC,QAAQ,EAAE,CAAC;AACvB,CAAC;AAED,SAAS,sBAAsB,CAC7B,EAAmB,EACnB,GAAW,EACX,KAAc;IAEd,IAAI,KAAK,KAAK,IAAI,IAAI,KAAK,KAAK,SAAS;QAAE,OAAO;IAClD,IAAI,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,EAAE,CAAC;QACzB,2EAA2E;QAC3E,2EAA2E;QAC3E,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;YACzB,sBAAsB,CAAC,EAAE,EAAE,GAAG,GAAG,IAAI,EAAE,IAAI,CAAC,CAAC;QAC/C,CAAC;QACD,OAAO;IACT,CAAC;IACD,EAAE,CAAC,MAAM,CAAC,GAAG,EAAE,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC;AAChC,CAAC;AAED,KAAK,UAAU,WAAW,CACxB,IAAY,EACZ,MAAc,EACd,MAA4B;IAE5B,+BAA+B,EAAE,CAAC;IAClC,IAAI,GAAG,GAAG,GAAG,aAAa,IAAI,IAAI,EAAE,CAAC;IACrC,MAAM,OAAO,GAA2B;QACtC,cAAc,EAAE,kBAAkB;QAClC,4DAA4D;QAC5D,oEAAoE;QACpE,sEAAsE;QACtE,uEAAuE;QACvE,mDAAmD;QACnD,yBAAyB,EAAE,GAAG;KAC/B,CAAC;IACF,MAAM,EAAE,GAAG,mBAAmB,EAAE,CAAC;IACjC,IAAI,EAAE;QAAE,OAAO,CAAC,iBAAiB,CAAC,GAAG,EAAE,CAAC;IACxC,MAAM,IAAI,GAAgB;QACxB,MAAM;QACN,OAAO;QACP,KAAK,EAAE,UAAU;KAClB,CAAC;IAEF,IAAI,MAAM,KAAK,KAAK,IAAI,MAAM,IAAI,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QACjE,yEAAyE;QACzE,uDAAuD;QACvD,MAAM,EAAE,GAAG,0BAA0B,CAAC,MAAM,CAAC,CAAC;QAC9C,IAAI,EAAE;YAAE,GAAG,IAAI,IAAI,EAAE,EAAE,CAAC;IAC1B,CAAC;SAAM,IAAI,MAAM,KAAK,KAAK,IAAI,MAAM,EAAE,CAAC;QACtC,IAAI,CAAC,IAAI,GAAG,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC,CAAC;IACrC,CAAC;IAED,IAAI,GAAa,CAAC;IAClB,IAAI,CAAC;QACH,GAAG,GAAG,MAAM,KAAK,CAAC,GAAG,EAAE,IAAI,CAAC,CAAC;IAC/B,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,uEAAuE;QACvE,0DAA0D;QAC1D,MAAM,KAAK,GAAG,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;QAC/D,MAAM,IAAI,KAAK,CAAC,UAAU,IAAI,YAAY,KAAK,EAAE,CAAC,CAAC;IACrD,CAAC;IAED,qCAAqC;IACrC,IAAI,GAAG,CAAC,MAAM,KAAK,GAAG;QAAE,OAAO,IAAS,CAAC;IAEzC,yCAAyC;IACzC,oEAAoE;IACpE,8EAA8E;IAC9E,4DAA4D;IAC5D,0EAA0E;IAC1E,qEAAqE;IACrE,uBAAuB;IACvB,IAAI,GAAG,GAAG,EAAE,CAAC;IACb,IAAI,UAAU,GAAG,KAAK,CAAC;IACvB,IAAI,SAAkB,CAAC;IACvB,IAAI,CAAC;QACH,GAAG,GAAG,MAAM,GAAG,CAAC,IAAI,EAAE,CAAC;IACzB,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,UAAU,GAAG,IAAI,CAAC;QAClB,SAAS,GAAG,GAAG,CAAC;IAClB,CAAC;IAED,IAAI,IAAI,GAAQ,SAAS,CAAC;IAC1B,IAAI,WAAW,GAAG,KAAK,CAAC;IACxB,IAAI,GAAG,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QACnB,IAAI,CAAC;YACH,IAAI,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;QACzB,CAAC;QAAC,MAAM,CAAC;YACP,uEAAuE;YACvE,WAAW,GAAG,IAAI,CAAC;QACrB,CAAC;IACH,CAAC;IAED,IAAI,CAAC,GAAG,CAAC,EAAE,EAAE,CAAC;QACZ,MAAM,OAAO,GACX,CAAC,IAAI,IAAI,CAAC,IAAI,CAAC,KAAK,IAAI,IAAI,CAAC,OAAO,CAAC,CAAC;YACtC,uEAAuE;YACvE,qEAAqE;YACrE,CAAC,GAAG,IAAI,GAAG,CAAC,KAAK,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC;YAC1B,GAAG,CAAC,UAAU;YACd,QAAQ,GAAG,CAAC,MAAM,EAAE,CAAC;QACvB,MAAM,KAAK,GAAG,IAAI,KAAK,CAAC,UAAU,IAAI,YAAY,OAAO,EAAE,CAAC,CAAC;QAC5D,KAAa,CAAC,MAAM,GAAG,GAAG,CAAC,MAAM,CAAC;QACnC,MAAM,KAAK,CAAC;IACd,CAAC;IAED,4EAA4E;IAC5E,wDAAwD;IACxD,IAAI,UAAU,EAAE,CAAC;QACf,MAAM,KAAK,GACT,SAAS,YAAY,KAAK,CAAC,CAAC,CAAC,SAAS,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,SAAS,CAAC,CAAC;QACrE,MAAM,KAAK,GAAG,IAAI,KAAK,CACrB,UAAU,IAAI,aAAa,GAAG,CAAC,MAAM,oCAAoC,KAAK,EAAE,CACjF,CAAC;QACD,KAAa,CAAC,MAAM,GAAG,GAAG,CAAC,MAAM,CAAC;QACnC,MAAM,KAAK,CAAC;IACd,CAAC;IAED,4EAA4E;IAC5E,4EAA4E;IAC5E,6EAA6E;IAC7E,uEAAuE;IACvE,+BAA+B;IAC/B,IAAI,WAAW,EAAE,CAAC;QAChB,MAAM,KAAK,GAAG,IAAI,KAAK,CACrB,UAAU,IAAI,wBAAwB,GAAG,CAAC,MAAM,cAAc,GAAG,CAAC,KAAK,CAAC,CAAC,EAAE,GAAG,CAAC,EAAE,CAClF,CAAC;QACD,KAAa,CAAC,MAAM,GAAG,GAAG,CAAC,MAAM,CAAC;QACnC,MAAM,KAAK,CAAC;IACd,CAAC;IAED,OAAO,CAAC,IAAI,IAAK,IAAgB,CAAM,CAAC;AAC1C,CAAC;AAED;;;;;;GAMG;AACH,MAAM,UAAU,UAAU,CAIxB,UAAiB,EACjB,MAA4B,EAC5B,OAAO,GAA4B,EAAE;IAGrC,OAAO,WAAW,CAAI,UAAU,EAAE,OAAO,CAAC,MAAM,IAAI,MAAM,EAAE,MAAM,CAAC,CAAC;AACtE,CAAC;AAED,8EAA8E;AAC9E,aAAa;AACb,8EAA8E;AAE9E;;;;;;;;;;;;;GAaG;AACH,MAAM,UAAU,cAAc,CAI5B,UAAiB,EACjB,MAA4B,EAC5B,OAGC;IAGD,OAAO,QAAQ,CAAI;QACjB,QAAQ,EAAE,CAAC,QAAQ,EAAE,UAAU,EAAE,MAAM,CAAC;QACxC,OAAO,EAAE,GAAG,EAAE,CAAC,WAAW,CAAI,UAAU,EAAE,KAAK,EAAE,MAAM,CAAC;QACxD,KAAK,EAAE,uBAAuB;QAC9B,GAAG,OAAO;KACX,CAAC,CAAC;AACL,CAAC;AAED,8EAA8E;AAC9E,gBAAgB;AAChB,8EAA8E;AAE9E;;;;;;;;;;;GAWG;AACH,MAAM,UAAU,iBAAiB,CAK/B,UAAiB,EACjB,OASC;IAED,MAAM,WAAW,GAAG,cAAc,EAAE,CAAC;IACrC,MAAM,EACJ,MAAM,EAAE,SAAS,EACjB,SAAS,EACT,GAAG,WAAW,EACf,GAAG,OAAO,IAAK,EAAU,CAAC;IAC3B,MAAM,MAAM,GAAG,SAAS,IAAI,MAAM,CAAC;IAKnC,OAAO,WAAW,CAAc;QAC9B,GAAG,WAAW;QACd,UAAU,EAAE,CAAC,MAAM,EAAE,EAAE,CACrB,WAAW,CAAI,UAAU,EAAE,MAAM,EAAE,MAA6B,CAAC;QACnE,SAAS,EAAE,CAAC,GAAG,IAAqB,EAAE,EAAE;YACtC,oCAAoC;YACpC,WAAW,CAAC,iBAAiB,CAAC,EAAE,QAAQ,EAAE,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC;YACvD,SAAsB,EAAE,CAAC,GAAG,IAAI,CAAC,CAAC;QACrC,CAAC;KACF,CAAC,CAAC;AACL,CAAC","sourcesContent":["/**\n * Client helpers for calling actions through the framework transport.\n *\n * Components should prefer `useActionQuery` / `useActionMutation`; use\n * `callAction` for imperative cases such as debounced search, prefetching, or\n * event handlers that do not fit a hook.\n *\n * ## End-to-end type safety\n *\n * When the action type registry is generated (via the Vite plugin or CLI),\n * `useActionQuery` and `useActionMutation` automatically infer the correct\n * return type and parameter types from the action definitions — no manual\n * type annotations needed.\n *\n * ```ts\n * // Fully typed — return type and params inferred from the action's defineAction()\n * const { data } = useActionQuery(\"list-forms\", { status: \"published\" });\n * // ^? Form[] (inferred from the action's run() return type)\n * ```\n *\n * Without the registry, the hooks fall back to `any` types for backward\n * compatibility.\n */\nimport { useQuery, useMutation, useQueryClient } from \"@tanstack/react-query\";\nimport type {\n UseQueryOptions,\n UseMutationOptions,\n} from \"@tanstack/react-query\";\n\nimport { agentNativePath } from \"./api-path.js\";\nimport { ensureEmbedAuthFetchInterceptor } from \"./embed-auth.js\";\n\nconst ACTION_PREFIX = agentNativePath(\"/_agent-native/actions\");\n\nfunction isAuthFailure(error: unknown): boolean {\n return (\n !!error &&\n typeof error === \"object\" &&\n \"status\" in error &&\n ((error as { status?: unknown }).status === 401 ||\n (error as { status?: unknown }).status === 403)\n );\n}\n\nfunction defaultActionQueryRetry(\n failureCount: number,\n error: unknown,\n): boolean {\n if (isAuthFailure(error)) return false;\n return failureCount < 3;\n}\n\n// ---------------------------------------------------------------------------\n// Action type registry — augmented by generated code\n// ---------------------------------------------------------------------------\n\n/**\n * Action type registry. This interface is empty by default and gets augmented\n * by the auto-generated `.generated/action-types.d.ts` file. When augmented,\n * it maps action names to their parameter and return types, enabling\n * end-to-end type safety for `useActionQuery` and `useActionMutation`.\n */\ndeclare global {\n interface AgentNativeActionRegistry {}\n}\n\nexport interface ActionRegistry extends AgentNativeActionRegistry {}\n\n/** Resolves to the union of registered action names, or `string` if no registry exists. */\ntype ActionName = keyof ActionRegistry extends never\n ? string\n : (keyof ActionRegistry & string) | (string & {});\n\n/** Resolves the return type of an action, or `any` if not in the registry. */\ntype ActionResult<T extends string> = T extends keyof ActionRegistry\n ? ActionRegistry[T] extends { result: infer R }\n ? R\n : any\n : any;\n\n/** Resolves the parameter type of an action, or `Record<string, any>` if not in the registry. */\ntype ActionParams<T extends string> = T extends keyof ActionRegistry\n ? ActionRegistry[T] extends { params: infer P }\n ? P\n : Record<string, any>\n : Record<string, any>;\n\nexport type ClientActionMethod = \"GET\" | \"POST\" | \"PUT\" | \"DELETE\";\n\nexport interface ClientActionCallOptions {\n method?: ClientActionMethod;\n}\n\n// ---------------------------------------------------------------------------\n// Fetch helper\n// ---------------------------------------------------------------------------\n\n/**\n * Resolve the browser's IANA timezone (e.g. \"America/Los_Angeles\"). This is\n * sent on every action request as `x-user-timezone` so server-side defaults\n * like \"today\" honor the user's local day rather than the server's UTC clock.\n */\nfunction resolveUserTimezone(): string | undefined {\n try {\n return Intl.DateTimeFormat().resolvedOptions().timeZone || undefined;\n } catch {\n return undefined;\n }\n}\n\nexport function serializeActionQueryParams(\n params: Record<string, any>,\n): string {\n const qs = new URLSearchParams();\n for (const [key, value] of Object.entries(params)) {\n appendActionQueryParam(qs, key, value);\n }\n return qs.toString();\n}\n\nfunction appendActionQueryParam(\n qs: URLSearchParams,\n key: string,\n value: unknown,\n) {\n if (value === null || value === undefined) return;\n if (Array.isArray(value)) {\n // Use bracket keys so a one-item array still arrives as an array after the\n // server parses URLSearchParams. Repeated bare keys lose that distinction.\n for (const item of value) {\n appendActionQueryParam(qs, `${key}[]`, item);\n }\n return;\n }\n qs.append(key, String(value));\n}\n\nasync function actionFetch<T>(\n name: string,\n method: string,\n params?: Record<string, any>,\n): Promise<T> {\n ensureEmbedAuthFetchInterceptor();\n let url = `${ACTION_PREFIX}/${name}`;\n const headers: Record<string, string> = {\n \"Content-Type\": \"application/json\",\n // Tag browser-originated action calls so the server can set\n // `ctx.caller = \"frontend\"` (vs a bare programmatic `\"http\"` POST).\n // Mirrors the X-Agent-Native-Tool-Bridge: 1 convention. The header is\n // safe to expose: CORS allows it (see action-routes.ts) and it carries\n // no auth weight — it only narrows the caller tag.\n \"X-Agent-Native-Frontend\": \"1\",\n };\n const tz = resolveUserTimezone();\n if (tz) headers[\"x-user-timezone\"] = tz;\n const init: RequestInit = {\n method,\n headers,\n cache: \"no-store\",\n };\n\n if (method === \"GET\" && params && Object.keys(params).length > 0) {\n // Skip null/undefined so optional filters don't turn into literal \"null\"\n // strings in the query string (e.g. `?folderId=null`).\n const qs = serializeActionQueryParams(params);\n if (qs) url += `?${qs}`;\n } else if (method !== \"GET\" && params) {\n init.body = JSON.stringify(params);\n }\n\n let res: Response;\n try {\n res = await fetch(url, init);\n } catch (err) {\n // Network failures, CORS, server unreachable, etc. — give the caller a\n // useful message instead of the opaque \"Failed to fetch\".\n const cause = err instanceof Error ? err.message : String(err);\n throw new Error(`Action ${name} failed: ${cause}`);\n }\n\n // 204 No Content — nothing to parse.\n if (res.status === 204) return null as T;\n\n // Read the body as text first so we can:\n // - tolerate empty bodies (avoids \"Unexpected end of JSON input\")\n // - surface non-JSON error responses (HTML 401/404 pages, plain text, etc.)\n // - preserve the original HTTP status in the thrown error\n // Track read failures separately from \"no body\" — a stream interruption /\n // decode failure on a 2xx response should error rather than silently\n // succeed with `null`.\n let raw = \"\";\n let readFailed = false;\n let readError: unknown;\n try {\n raw = await res.text();\n } catch (err) {\n readFailed = true;\n readError = err;\n }\n\n let data: any = undefined;\n let parseFailed = false;\n if (raw.length > 0) {\n try {\n data = JSON.parse(raw);\n } catch {\n // Body wasn't JSON — keep `data` undefined and use the raw text below.\n parseFailed = true;\n }\n }\n\n if (!res.ok) {\n const message =\n (data && (data.error || data.message)) ||\n // Truncate non-JSON bodies so we don't dump entire HTML pages into the\n // console, but still give the developer a hint as to what came back.\n (raw && raw.slice(0, 200)) ||\n res.statusText ||\n `HTTP ${res.status}`;\n const error = new Error(`Action ${name} failed: ${message}`);\n (error as any).status = res.status;\n throw error;\n }\n\n // 2xx but the body couldn't even be read (mid-stream abort, decode failure,\n // etc.). Don't silently treat that as a `null` success.\n if (readFailed) {\n const cause =\n readError instanceof Error ? readError.message : String(readError);\n const error = new Error(\n `Action ${name} returned ${res.status} but the body could not be read: ${cause}`,\n );\n (error as any).status = res.status;\n throw error;\n }\n\n // 2xx with a non-empty, non-JSON body. Action callers expect typed data, so\n // returning `null` here would silently mask a real server bug (e.g. a proxy\n // returning HTML 200 instead of JSON). Throw instead — empty bodies (handled\n // above by the `raw.length > 0` guard and the 204 short-circuit) still\n // correctly resolve to `null`.\n if (parseFailed) {\n const error = new Error(\n `Action ${name} returned a non-JSON ${res.status} response: ${raw.slice(0, 200)}`,\n );\n (error as any).status = res.status;\n throw error;\n }\n\n return (data ?? (null as unknown)) as T;\n}\n\n/**\n * Imperatively call an action from browser/client code.\n *\n * Prefer `useActionQuery` / `useActionMutation` in React render flows. Use this\n * helper when a hook is not ergonomic; do not hand-write fetch calls to\n * `/_agent-native/actions/*` in components.\n */\nexport function callAction<\n TResult = undefined,\n TName extends ActionName = ActionName,\n>(\n actionName: TName,\n params?: ActionParams<TName>,\n options: ClientActionCallOptions = {},\n): Promise<TResult extends undefined ? ActionResult<TName> : TResult> {\n type R = TResult extends undefined ? ActionResult<TName> : TResult;\n return actionFetch<R>(actionName, options.method ?? \"POST\", params);\n}\n\n// ---------------------------------------------------------------------------\n// Query hook\n// ---------------------------------------------------------------------------\n\n/**\n * Query an action exposed as GET.\n *\n * When the action type registry is generated, the return type and parameter\n * types are inferred automatically from the action's `defineAction()` call.\n *\n * ```ts\n * // Type-safe — no manual generic needed\n * const { data } = useActionQuery(\"list-meals\", { date: \"2025-01-01\" });\n *\n * // Manual override still works when needed\n * const { data } = useActionQuery<CustomType>(\"list-meals\");\n * ```\n */\nexport function useActionQuery<\n TResult = undefined,\n TName extends ActionName = ActionName,\n>(\n actionName: TName,\n params?: ActionParams<TName>,\n options?: Omit<\n UseQueryOptions<TResult extends undefined ? ActionResult<TName> : TResult>,\n \"queryKey\" | \"queryFn\"\n >,\n) {\n type R = TResult extends undefined ? ActionResult<TName> : TResult;\n return useQuery<R>({\n queryKey: [\"action\", actionName, params],\n queryFn: () => actionFetch<R>(actionName, \"GET\", params),\n retry: defaultActionQueryRetry,\n ...options,\n });\n}\n\n// ---------------------------------------------------------------------------\n// Mutation hook\n// ---------------------------------------------------------------------------\n\n/**\n * Mutate via an action exposed as POST (default), PUT, or DELETE.\n *\n * When the action type registry is generated, the return type and parameter\n * types are inferred automatically.\n *\n * ```ts\n * // Type-safe\n * const { mutate } = useActionMutation(\"log-meal\");\n * mutate({ name: \"Salad\", calories: 350 });\n * ```\n */\nexport function useActionMutation<\n TData = undefined,\n TVariables = undefined,\n TName extends ActionName = ActionName,\n>(\n actionName: TName,\n options?: Omit<\n UseMutationOptions<\n TData extends undefined ? ActionResult<TName> : TData,\n Error,\n TVariables extends undefined ? ActionParams<TName> : TVariables\n >,\n \"mutationFn\"\n > & {\n method?: \"POST\" | \"PUT\" | \"DELETE\";\n },\n) {\n const queryClient = useQueryClient();\n const {\n method: methodOpt,\n onSuccess,\n ...restOptions\n } = options ?? ({} as any);\n const method = methodOpt ?? \"POST\";\n\n type D = TData extends undefined ? ActionResult<TName> : TData;\n type V = TVariables extends undefined ? ActionParams<TName> : TVariables;\n\n return useMutation<D, Error, V>({\n ...restOptions,\n mutationFn: (params) =>\n actionFetch<D>(actionName, method, params as Record<string, any>),\n onSuccess: (...args: [any, any, any]) => {\n // Invalidate related action queries\n queryClient.invalidateQueries({ queryKey: [\"action\"] });\n (onSuccess as Function)?.(...args);\n },\n });\n}\n"]}
|
|
@@ -49,11 +49,11 @@ export declare const postAwareness: import("h3").EventHandlerWithFetch<import("h
|
|
|
49
49
|
error: string;
|
|
50
50
|
states?: undefined;
|
|
51
51
|
} | {
|
|
52
|
+
error?: undefined;
|
|
52
53
|
states: {
|
|
53
54
|
clientId: number;
|
|
54
55
|
state: string;
|
|
55
56
|
}[];
|
|
56
|
-
error?: undefined;
|
|
57
57
|
}>>;
|
|
58
58
|
/**
|
|
59
59
|
* GET /_agent-native/collab/:docId/users
|
|
@@ -64,10 +64,10 @@ export declare const getActiveUsers: import("h3").EventHandlerWithFetch<import("
|
|
|
64
64
|
error: string;
|
|
65
65
|
users?: undefined;
|
|
66
66
|
} | {
|
|
67
|
+
error?: undefined;
|
|
67
68
|
users: {
|
|
68
69
|
clientId: number;
|
|
69
70
|
lastSeen: number;
|
|
70
71
|
}[];
|
|
71
|
-
error?: undefined;
|
|
72
72
|
}>>;
|
|
73
73
|
//# sourceMappingURL=awareness.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"awareness.d.ts","sourceRoot":"","sources":["../../src/collab/awareness.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAEH,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAS3C,MAAM,WAAW,cAAc;IAC7B,QAAQ,EAAE,MAAM,CAAC;IACjB,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,EAAE,MAAM,CAAC;CAClB;AAOD,eAAO,MAAM,sBAAsB,EAAG,kBAA2B,CAAC;AAElE,MAAM,WAAW,oBAAoB;IACnC,MAAM,EAAE,WAAW,CAAC;IACpB,IAAI,EAAE,kBAAkB,CAAC;IACzB,KAAK,EAAE,MAAM,CAAC;IACd,2EAA2E;IAC3E,MAAM,EAAE,KAAK,CAAC;QAAE,QAAQ,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IACnD,gFAAgF;IAChF,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,sCAAsC;IACtC,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAKD,wBAAgB,mBAAmB,IAAI,YAAY,CAElD;AAED,wBAAgB,mBAAmB,CACjC,KAAK,EAAE,MAAM,EACb,MAAM,EAAE,KAAK,CAAC;IAAE,QAAQ,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE,CAAC,EAClD,KAAK,CAAC,EAAE,MAAM,EACd,KAAK,CAAC,EAAE,MAAM,GACb,IAAI,CAUN;AAKD,wBAAgB,eAAe,CAAC,KAAK,EAAE,MAAM,GAAG,GAAG,CAAC,MAAM,EAAE,cAAc,CAAC,CAO1E;AAED,wBAAgB,YAAY,CAAC,GAAG,EAAE,GAAG,CAAC,MAAM,EAAE,cAAc,CAAC,GAAG,IAAI,CAOnE;AAUD;;;;;;;GAOG;AACH,eAAO,MAAM,aAAa
|
|
1
|
+
{"version":3,"file":"awareness.d.ts","sourceRoot":"","sources":["../../src/collab/awareness.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAEH,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAS3C,MAAM,WAAW,cAAc;IAC7B,QAAQ,EAAE,MAAM,CAAC;IACjB,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,EAAE,MAAM,CAAC;CAClB;AAOD,eAAO,MAAM,sBAAsB,EAAG,kBAA2B,CAAC;AAElE,MAAM,WAAW,oBAAoB;IACnC,MAAM,EAAE,WAAW,CAAC;IACpB,IAAI,EAAE,kBAAkB,CAAC;IACzB,KAAK,EAAE,MAAM,CAAC;IACd,2EAA2E;IAC3E,MAAM,EAAE,KAAK,CAAC;QAAE,QAAQ,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IACnD,gFAAgF;IAChF,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,sCAAsC;IACtC,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAKD,wBAAgB,mBAAmB,IAAI,YAAY,CAElD;AAED,wBAAgB,mBAAmB,CACjC,KAAK,EAAE,MAAM,EACb,MAAM,EAAE,KAAK,CAAC;IAAE,QAAQ,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE,CAAC,EAClD,KAAK,CAAC,EAAE,MAAM,EACd,KAAK,CAAC,EAAE,MAAM,GACb,IAAI,CAUN;AAKD,wBAAgB,eAAe,CAAC,KAAK,EAAE,MAAM,GAAG,GAAG,CAAC,MAAM,EAAE,cAAc,CAAC,CAO1E;AAED,wBAAgB,YAAY,CAAC,GAAG,EAAE,GAAG,CAAC,MAAM,EAAE,cAAc,CAAC,GAAG,IAAI,CAOnE;AAUD;;;;;;;GAOG;AACH,eAAO,MAAM,aAAa;;;;;;kBAuCa,MAAM;eAAS,MAAM;;GAa1D,CAAC;AAEH;;;;GAIG;AACH,eAAO,MAAM,cAAc;;;;;;kBAWM,MAAM;kBAAY,MAAM;;GAMvD,CAAC"}
|
package/dist/collab/routes.d.ts
CHANGED
|
@@ -26,8 +26,8 @@ export declare const getCollabState: import("h3").EventHandlerWithFetch<import("
|
|
|
26
26
|
* Body: { update: string (base64), requestSource?: string }
|
|
27
27
|
*/
|
|
28
28
|
export declare const postCollabUpdate: import("h3").EventHandlerWithFetch<import("h3").EventHandlerRequest, Promise<{
|
|
29
|
-
ok?: undefined;
|
|
30
29
|
error: string;
|
|
30
|
+
ok?: undefined;
|
|
31
31
|
} | {
|
|
32
32
|
error?: undefined;
|
|
33
33
|
ok: boolean;
|
|
@@ -11,14 +11,14 @@
|
|
|
11
11
|
* DELETE /_agent-native/notifications/:id — delete
|
|
12
12
|
*/
|
|
13
13
|
export declare function createNotificationsHandler(): import("h3").EventHandlerWithFetch<import("h3").EventHandlerRequest, Promise<"" | import("./types.js").Notification[] | {
|
|
14
|
+
error?: undefined;
|
|
14
15
|
count: number;
|
|
15
16
|
updated?: undefined;
|
|
16
|
-
error?: undefined;
|
|
17
17
|
ok?: undefined;
|
|
18
18
|
} | {
|
|
19
|
+
error?: undefined;
|
|
19
20
|
count?: undefined;
|
|
20
21
|
updated: number;
|
|
21
|
-
error?: undefined;
|
|
22
22
|
ok?: undefined;
|
|
23
23
|
} | {
|
|
24
24
|
count?: undefined;
|
|
@@ -26,9 +26,9 @@ export declare function createNotificationsHandler(): import("h3").EventHandlerW
|
|
|
26
26
|
error: string;
|
|
27
27
|
ok?: undefined;
|
|
28
28
|
} | {
|
|
29
|
+
error?: undefined;
|
|
29
30
|
count?: undefined;
|
|
30
31
|
updated?: undefined;
|
|
31
32
|
ok: boolean;
|
|
32
|
-
error?: undefined;
|
|
33
33
|
}>>;
|
|
34
34
|
//# sourceMappingURL=routes.d.ts.map
|
|
@@ -41,16 +41,16 @@ export declare function createObservabilityHandler(): import("h3").EventHandlerW
|
|
|
41
41
|
thumbsUpRate: number;
|
|
42
42
|
avgEvalScore: number;
|
|
43
43
|
} | {
|
|
44
|
+
error?: undefined;
|
|
44
45
|
summary: import("./types.js").TraceSummary;
|
|
45
46
|
spans: import("./types.js").TraceSpan[];
|
|
46
47
|
id?: undefined;
|
|
47
|
-
error?: undefined;
|
|
48
48
|
ok?: undefined;
|
|
49
49
|
} | {
|
|
50
|
+
error?: undefined;
|
|
50
51
|
summary?: undefined;
|
|
51
52
|
spans?: undefined;
|
|
52
53
|
id: string;
|
|
53
|
-
error?: undefined;
|
|
54
54
|
ok?: undefined;
|
|
55
55
|
} | {
|
|
56
56
|
summary?: undefined;
|
|
@@ -59,10 +59,10 @@ export declare function createObservabilityHandler(): import("h3").EventHandlerW
|
|
|
59
59
|
error: any;
|
|
60
60
|
ok?: undefined;
|
|
61
61
|
} | {
|
|
62
|
+
error?: undefined;
|
|
62
63
|
summary?: undefined;
|
|
63
64
|
spans?: undefined;
|
|
64
65
|
id?: undefined;
|
|
65
|
-
error?: undefined;
|
|
66
66
|
ok: boolean;
|
|
67
67
|
}>>;
|
|
68
68
|
//# sourceMappingURL=routes.d.ts.map
|
|
@@ -52,8 +52,8 @@ export declare function handleDeleteResource(event: any): Promise<{
|
|
|
52
52
|
error: string;
|
|
53
53
|
ok?: undefined;
|
|
54
54
|
} | {
|
|
55
|
-
error?: undefined;
|
|
56
55
|
ok: boolean;
|
|
56
|
+
error?: undefined;
|
|
57
57
|
}>;
|
|
58
58
|
/** POST /_agent-native/resources/upload — upload a file as a resource */
|
|
59
59
|
export declare function handleUploadResource(event: any): Promise<import("./store.js").Resource | {
|
|
@@ -73,9 +73,9 @@ export declare function handleUploadResource(event: any): Promise<import("./stor
|
|
|
73
73
|
runId: string | null;
|
|
74
74
|
expiresAt: number | null;
|
|
75
75
|
metadata: string | null;
|
|
76
|
-
error?: undefined;
|
|
77
76
|
url: string;
|
|
78
77
|
provider: string;
|
|
78
|
+
error?: undefined;
|
|
79
79
|
}>;
|
|
80
80
|
export {};
|
|
81
81
|
//# sourceMappingURL=handlers.d.ts.map
|
|
@@ -27,11 +27,11 @@ export declare function resolveAgentEngineApiKeyWriteTarget(event: H3Event, scop
|
|
|
27
27
|
export declare function createAgentEngineApiKeyHandler(): import("h3").EventHandlerWithFetch<import("h3").EventHandlerRequest, Promise<{
|
|
28
28
|
error: any;
|
|
29
29
|
} | {
|
|
30
|
+
error?: undefined;
|
|
30
31
|
ok: boolean;
|
|
31
32
|
key: string;
|
|
32
33
|
baseUrlKey?: string;
|
|
33
34
|
scope: AgentEngineApiKeyScope;
|
|
34
|
-
error?: undefined;
|
|
35
35
|
}>>;
|
|
36
36
|
export {};
|
|
37
37
|
//# sourceMappingURL=agent-engine-api-key-route.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ssr-handler.d.ts","sourceRoot":"","sources":["../../src/server/ssr-handler.ts"],"names":[],"mappings":"AA8CA,OAAO,EACL,yBAAyB,EACzB,gCAAgC,EAChC,yBAAyB,GAC1B,MAAM,4BAA4B,CAAC;
|
|
1
|
+
{"version":3,"file":"ssr-handler.d.ts","sourceRoot":"","sources":["../../src/server/ssr-handler.ts"],"names":[],"mappings":"AA8CA,OAAO,EACL,yBAAyB,EACzB,gCAAgC,EAChC,yBAAyB,GAC1B,MAAM,4BAA4B,CAAC;AAsoBpC;;;GAGG;AACH,wBAAgB,kBAAkB,CAAC,QAAQ,EAAE,MAAM,OAAO,CAAC,OAAO,CAAC,GAAG,OAAO,2FAgE5E"}
|
|
@@ -310,6 +310,11 @@ function appendToExistingCspDirective(directives, name, additions) {
|
|
|
310
310
|
return;
|
|
311
311
|
existing.tokens = appendCspTokens(existing.tokens, additions);
|
|
312
312
|
}
|
|
313
|
+
function ensureCspDirective(directives, name, tokens) {
|
|
314
|
+
if (findCspDirective(directives, name))
|
|
315
|
+
return;
|
|
316
|
+
directives.push({ name, tokens: [...tokens] });
|
|
317
|
+
}
|
|
313
318
|
function hasStrictNonceScriptPolicy(tokens) {
|
|
314
319
|
return tokens.some((token) => token === "'strict-dynamic'" || token.startsWith("'nonce-"));
|
|
315
320
|
}
|
|
@@ -358,6 +363,8 @@ function augmentExistingEnforcedCspForFrameworkScripts(policy, options) {
|
|
|
358
363
|
appendToExistingOrDefaultCspDirective(directives, "img-src", GA_CSP_IMG_HOSTS);
|
|
359
364
|
}
|
|
360
365
|
}
|
|
366
|
+
ensureCspDirective(directives, "object-src", ["'none'"]);
|
|
367
|
+
ensureCspDirective(directives, "base-uri", ["'self'"]);
|
|
361
368
|
return serializeCsp(directives);
|
|
362
369
|
}
|
|
363
370
|
function augmentExistingReportOnlyCspForFrameworkScripts(policy, options) {
|