@hyperframes/studio-server 0.7.16 → 0.7.18
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/index.d.ts +40 -1
- package/dist/index.js +99 -0
- package/dist/index.js.map +1 -1
- package/package.json +3 -3
package/dist/index.d.ts
CHANGED
|
@@ -32,6 +32,45 @@ interface LintResult {
|
|
|
32
32
|
fixHint?: string;
|
|
33
33
|
}>;
|
|
34
34
|
}
|
|
35
|
+
interface StudioSelectionTextField {
|
|
36
|
+
key: string;
|
|
37
|
+
label: string;
|
|
38
|
+
value: string;
|
|
39
|
+
tagName: string;
|
|
40
|
+
source: "self" | "child" | "text-node";
|
|
41
|
+
}
|
|
42
|
+
interface StudioSelectionSnapshot {
|
|
43
|
+
schemaVersion: 1;
|
|
44
|
+
projectId: string;
|
|
45
|
+
compositionPath: string;
|
|
46
|
+
sourceFile: string;
|
|
47
|
+
currentTime: number;
|
|
48
|
+
target: {
|
|
49
|
+
id?: string | null;
|
|
50
|
+
hfId?: string;
|
|
51
|
+
selector?: string;
|
|
52
|
+
selectorIndex?: number;
|
|
53
|
+
};
|
|
54
|
+
label: string;
|
|
55
|
+
tagName: string;
|
|
56
|
+
boundingBox: {
|
|
57
|
+
x: number;
|
|
58
|
+
y: number;
|
|
59
|
+
width: number;
|
|
60
|
+
height: number;
|
|
61
|
+
};
|
|
62
|
+
textContent: string | null;
|
|
63
|
+
dataAttributes: Record<string, string>;
|
|
64
|
+
inlineStyles: Record<string, string>;
|
|
65
|
+
computedStyles: Record<string, string>;
|
|
66
|
+
textFields: StudioSelectionTextField[];
|
|
67
|
+
capabilities: Record<string, boolean | string | undefined>;
|
|
68
|
+
thumbnailUrl: string;
|
|
69
|
+
}
|
|
70
|
+
interface StudioSelectionResponse {
|
|
71
|
+
selection: StudioSelectionSnapshot | null;
|
|
72
|
+
updatedAt: string | null;
|
|
73
|
+
}
|
|
35
74
|
/**
|
|
36
75
|
* Adapter interface — injected by each consumer to handle host-specific behavior.
|
|
37
76
|
* The shared API module calls these methods; each host (vite dev, CLI embedded)
|
|
@@ -164,4 +203,4 @@ declare function getMimeType(path: string): string;
|
|
|
164
203
|
*/
|
|
165
204
|
declare function buildSubCompositionHtml(projectDir: string, compPath: string, runtimeUrl: string, baseHref?: string): string | null;
|
|
166
205
|
|
|
167
|
-
export { type LintResult, MIME_TYPES, type RenderJobState, type ResolvedProject, type StudioApiAdapter, buildSubCompositionHtml, createProjectSignature, createStudioApi, getMimeType, walkDir };
|
|
206
|
+
export { type LintResult, MIME_TYPES, type RenderJobState, type ResolvedProject, type StudioApiAdapter, type StudioSelectionResponse, type StudioSelectionSnapshot, type StudioSelectionTextField, buildSubCompositionHtml, createProjectSignature, createStudioApi, getMimeType, walkDir };
|
package/dist/index.js
CHANGED
|
@@ -4114,6 +4114,104 @@ function registerRegistryRoutes(api, adapter) {
|
|
|
4114
4114
|
});
|
|
4115
4115
|
}
|
|
4116
4116
|
|
|
4117
|
+
// src/routes/selection.ts
|
|
4118
|
+
function isRecord2(value) {
|
|
4119
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
4120
|
+
}
|
|
4121
|
+
function isFiniteNumber(value) {
|
|
4122
|
+
return typeof value === "number" && Number.isFinite(value);
|
|
4123
|
+
}
|
|
4124
|
+
function isStringRecord(value) {
|
|
4125
|
+
return isRecord2(value) && Object.values(value).every((v) => typeof v === "string");
|
|
4126
|
+
}
|
|
4127
|
+
function hasString(value, key) {
|
|
4128
|
+
return typeof value[key] === "string";
|
|
4129
|
+
}
|
|
4130
|
+
function hasRequiredStrings(value, keys) {
|
|
4131
|
+
return keys.every((key) => hasString(value, key));
|
|
4132
|
+
}
|
|
4133
|
+
function hasOptionalString(value, key) {
|
|
4134
|
+
return value[key] === void 0 || typeof value[key] === "string";
|
|
4135
|
+
}
|
|
4136
|
+
function hasOptionalNullableString(value, key) {
|
|
4137
|
+
return value[key] == null || typeof value[key] === "string";
|
|
4138
|
+
}
|
|
4139
|
+
function hasOptionalNumber(value, key) {
|
|
4140
|
+
return value[key] === void 0 || isFiniteNumber(value[key]);
|
|
4141
|
+
}
|
|
4142
|
+
function isBoundingBox(value) {
|
|
4143
|
+
return isRecord2(value) && ["x", "y", "width", "height"].every((key) => isFiniteNumber(value[key]));
|
|
4144
|
+
}
|
|
4145
|
+
function isTarget(value) {
|
|
4146
|
+
if (!isRecord2(value)) return false;
|
|
4147
|
+
return hasOptionalNullableString(value, "id") && hasOptionalString(value, "hfId") && hasOptionalString(value, "selector") && hasOptionalNumber(value, "selectorIndex");
|
|
4148
|
+
}
|
|
4149
|
+
function isTextField(value) {
|
|
4150
|
+
return isRecord2(value) && hasRequiredStrings(value, ["key", "label", "value", "tagName"]) && ["self", "child", "text-node"].includes(value.source);
|
|
4151
|
+
}
|
|
4152
|
+
function isTextFields(value) {
|
|
4153
|
+
return Array.isArray(value) && value.every(isTextField);
|
|
4154
|
+
}
|
|
4155
|
+
function isSelectionSnapshot(value) {
|
|
4156
|
+
if (!isRecord2(value)) return false;
|
|
4157
|
+
const checks = [
|
|
4158
|
+
value.schemaVersion === 1 && hasRequiredStrings(value, [
|
|
4159
|
+
"projectId",
|
|
4160
|
+
"compositionPath",
|
|
4161
|
+
"sourceFile",
|
|
4162
|
+
"label",
|
|
4163
|
+
"tagName",
|
|
4164
|
+
"thumbnailUrl"
|
|
4165
|
+
]),
|
|
4166
|
+
isFiniteNumber(value.currentTime),
|
|
4167
|
+
isTarget(value.target),
|
|
4168
|
+
isBoundingBox(value.boundingBox),
|
|
4169
|
+
value.textContent === null || typeof value.textContent === "string",
|
|
4170
|
+
isStringRecord(value.dataAttributes),
|
|
4171
|
+
isStringRecord(value.inlineStyles),
|
|
4172
|
+
isStringRecord(value.computedStyles),
|
|
4173
|
+
isTextFields(value.textFields),
|
|
4174
|
+
isRecord2(value.capabilities)
|
|
4175
|
+
];
|
|
4176
|
+
return checks.every(Boolean);
|
|
4177
|
+
}
|
|
4178
|
+
function registerSelectionRoutes(api, adapter) {
|
|
4179
|
+
const selections = /* @__PURE__ */ new Map();
|
|
4180
|
+
api.get("/projects/:id/selection", async (c) => {
|
|
4181
|
+
const project = await adapter.resolveProject(c.req.param("id"));
|
|
4182
|
+
if (!project) return c.json({ error: "not found" }, 404);
|
|
4183
|
+
const stored = selections.get(project.id);
|
|
4184
|
+
return c.json({
|
|
4185
|
+
selection: stored?.selection ?? null,
|
|
4186
|
+
updatedAt: stored?.updatedAt ?? null
|
|
4187
|
+
});
|
|
4188
|
+
});
|
|
4189
|
+
api.put("/projects/:id/selection", async (c) => {
|
|
4190
|
+
const project = await adapter.resolveProject(c.req.param("id"));
|
|
4191
|
+
if (!project) return c.json({ error: "not found" }, 404);
|
|
4192
|
+
let body;
|
|
4193
|
+
try {
|
|
4194
|
+
body = await c.req.json();
|
|
4195
|
+
} catch {
|
|
4196
|
+
return c.json({ error: "invalid json" }, 400);
|
|
4197
|
+
}
|
|
4198
|
+
if (!isRecord2(body) || !("selection" in body)) {
|
|
4199
|
+
return c.json({ error: "missing selection" }, 400);
|
|
4200
|
+
}
|
|
4201
|
+
if (body.selection === null) {
|
|
4202
|
+
selections.delete(project.id);
|
|
4203
|
+
return c.json({ ok: true, selection: null, updatedAt: null });
|
|
4204
|
+
}
|
|
4205
|
+
if (!isSelectionSnapshot(body.selection)) {
|
|
4206
|
+
return c.json({ error: "invalid selection" }, 400);
|
|
4207
|
+
}
|
|
4208
|
+
const selection = { ...body.selection, projectId: project.id };
|
|
4209
|
+
const updatedAt = (/* @__PURE__ */ new Date()).toISOString();
|
|
4210
|
+
selections.set(project.id, { selection, updatedAt });
|
|
4211
|
+
return c.json({ ok: true, selection, updatedAt });
|
|
4212
|
+
});
|
|
4213
|
+
}
|
|
4214
|
+
|
|
4117
4215
|
// src/createStudioApi.ts
|
|
4118
4216
|
function createStudioApi(adapter) {
|
|
4119
4217
|
const api = new Hono();
|
|
@@ -4124,6 +4222,7 @@ function createStudioApi(adapter) {
|
|
|
4124
4222
|
registerLintRoutes(api, adapter);
|
|
4125
4223
|
registerRenderRoutes(api, adapter);
|
|
4126
4224
|
registerThumbnailRoutes(api, adapter);
|
|
4225
|
+
registerSelectionRoutes(api, adapter);
|
|
4127
4226
|
registerWaveformRoutes(api, adapter);
|
|
4128
4227
|
registerFontRoutes(api);
|
|
4129
4228
|
registerRegistryRoutes(api, adapter);
|