@effectnode/media 0.5.0 → 0.7.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -8,6 +8,9 @@ export type QueueTaskType =
8
8
  | "render-assets"
9
9
  | "render-videos"
10
10
  | "render-scene-images"
11
+ | "render-asset"
12
+ | "render-scene-image"
13
+ | "render-video"
11
14
  | "regenerate-asset"
12
15
  | "regenerate-video"
13
16
  | "regenerate-scene-image";
@@ -33,6 +36,8 @@ export interface QueueTask {
33
36
  createdAt: number;
34
37
  startedAt: number | null;
35
38
  completedAt: number | null;
39
+ /** Only present in the "all projects" view — the task's owning project. */
40
+ projectId?: string;
36
41
  }
37
42
 
38
43
  interface QueueStore {
@@ -41,10 +46,14 @@ interface QueueStore {
41
46
  projectId: string | null;
42
47
  paused: boolean;
43
48
  logs: string;
49
+ showAll: boolean;
50
+ allTasks: QueueTask[];
44
51
  refresh: (projectId: string) => Promise<void>;
45
52
  refreshLogs: (projectId: string) => Promise<void>;
53
+ refreshAll: () => Promise<void>;
46
54
  startStreaming: (projectId: string) => void;
47
55
  stopStreaming: () => void;
56
+ setShowAll: (show: boolean) => void;
48
57
  cancel: (projectId: string, taskId: string) => Promise<void>;
49
58
  cancelActive: (projectId: string) => Promise<void>;
50
59
  clearFinished: (projectId: string) => Promise<void>;
@@ -53,6 +62,7 @@ interface QueueStore {
53
62
  }
54
63
 
55
64
  let eventSource: EventSource | null = null;
65
+ let allEventSource: EventSource | null = null;
56
66
 
57
67
  /** Upsert a task into the list, replacing any existing entry with the same id. */
58
68
  function upsertTask(tasks: QueueTask[], task: QueueTask): QueueTask[] {
@@ -69,6 +79,8 @@ export const useQueueStore = create<QueueStore>((set, get) => ({
69
79
  projectId: null,
70
80
  paused: false,
71
81
  logs: "",
82
+ showAll: false,
83
+ allTasks: [],
72
84
 
73
85
  refresh: async (projectId) => {
74
86
  try {
@@ -101,6 +113,19 @@ export const useQueueStore = create<QueueStore>((set, get) => ({
101
113
  }
102
114
  },
103
115
 
116
+ refreshAll: async () => {
117
+ try {
118
+ const res = await fetch(`${API_BASE}/api/queue/all`);
119
+ if (!res.ok) return;
120
+ const data = (await res.json()) as { tasks: QueueTask[] };
121
+ const tasks = Array.isArray(data.tasks) ? data.tasks : [];
122
+ tasks.sort((a, b) => a.createdAt - b.createdAt);
123
+ set({ allTasks: tasks });
124
+ } catch {
125
+ // ignore fetch failures
126
+ }
127
+ },
128
+
104
129
  startStreaming: (projectId) => {
105
130
  get().stopStreaming();
106
131
  set({ projectId, loading: true });
@@ -144,7 +169,47 @@ export const useQueueStore = create<QueueStore>((set, get) => ({
144
169
  eventSource.close();
145
170
  eventSource = null;
146
171
  }
147
- set({ tasks: [], projectId: null, loading: false, paused: false, logs: "" });
172
+ if (allEventSource) {
173
+ allEventSource.close();
174
+ allEventSource = null;
175
+ }
176
+ set({
177
+ tasks: [],
178
+ allTasks: [],
179
+ projectId: null,
180
+ loading: false,
181
+ paused: false,
182
+ logs: "",
183
+ showAll: false,
184
+ });
185
+ },
186
+
187
+ setShowAll: (show) => {
188
+ if (show) {
189
+ if (allEventSource) allEventSource.close();
190
+ set({ showAll: true });
191
+ void get().refreshAll();
192
+
193
+ const es = new EventSource(`${API_BASE}/api/events?projectId=*`);
194
+ allEventSource = es;
195
+ es.addEventListener("task", (event) => {
196
+ try {
197
+ const task = JSON.parse((event as MessageEvent).data) as QueueTask;
198
+ set((s) => ({ allTasks: upsertTask(s.allTasks, task) }));
199
+ } catch {
200
+ // ignore malformed events
201
+ }
202
+ });
203
+ es.onopen = () => {
204
+ void get().refreshAll();
205
+ };
206
+ } else {
207
+ if (allEventSource) {
208
+ allEventSource.close();
209
+ allEventSource = null;
210
+ }
211
+ set({ showAll: false, allTasks: [] });
212
+ }
148
213
  },
149
214
 
150
215
  cancel: async (projectId, taskId) => {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@effectnode/media",
3
- "version": "0.5.0",
3
+ "version": "0.7.0",
4
4
  "description": "Start a full-stack media app: Vite + React + TypeScript frontend, Express backend with REST + WebSocket API",
5
5
  "license": "MIT",
6
6
  "author": "",
@@ -19,7 +19,7 @@
19
19
  "scripts": {
20
20
  "deploy": "npm run build; npm version minor; npm publish --access public",
21
21
  "build": "tsc && node -e \"const fs=require('node:fs');fs.cpSync('src/backend/movie-backend/agent/prompt','dist/backend/movie-backend/agent/prompt',{recursive:true})\"",
22
- "dev": "concurrently -k -n backend,frontend -c blue,green \"bun run dev:backend\" \"bun run dev:frontend\"",
22
+ "dev": "open http://localhost:5177; concurrently -k -n backend,frontend -c blue,green \"bun run dev:backend\" \"bun run dev:frontend\";",
23
23
  "dev:backend": "nodemon",
24
24
  "dev:frontend": "vite",
25
25
  "start": "node bin/effectnode-media"