@editframe/cli 0.8.0-beta.7 → 0.8.0-beta.8

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/VERSION.d.ts CHANGED
@@ -1 +1 @@
1
- export declare const VERSION = "0.8.0-beta.7";
1
+ export declare const VERSION = "0.8.0-beta.8";
package/dist/VERSION.js CHANGED
@@ -1,4 +1,4 @@
1
- const VERSION = "0.8.0-beta.7";
1
+ const VERSION = "0.8.0-beta.8";
2
2
  export {
3
3
  VERSION
4
4
  };
@@ -49,13 +49,27 @@ const syncAssetDirectory = async (projectDirectory) => {
49
49
  const assets = await fs.readdir(fullPath);
50
50
  process.stderr.write(`Syncing asset dir: ${fullPath}
51
51
  `);
52
- for (const asset of assets) {
53
- process.stderr.write(`Syncing asset: ${asset}
52
+ const errors = {};
53
+ const reportError = (path2, message) => {
54
+ errors[path2] ||= [];
55
+ errors[path2].push(message);
56
+ process.stderr.write(` 🚫 ${message}
57
+ `);
58
+ };
59
+ const reportSuccess = (_path, message) => {
60
+ process.stderr.write(` āœ… ${message}
61
+ `);
62
+ };
63
+ const reportInfo = (_path, message) => {
64
+ process.stderr.write(` ${message}
54
65
  `);
66
+ };
67
+ for (const asset of assets) {
68
+ reportInfo(asset, `Syncing asset: ${asset}`);
55
69
  const assetDir = path.join(fullPath, asset);
56
70
  const stat2 = await fs.stat(assetDir);
57
71
  if (!stat2.isDirectory()) {
58
- process.stderr.write("Invalid asset. Did not find asset directory.\n");
72
+ reportError(asset, "Invalid asset. Did not find asset directory.");
59
73
  return;
60
74
  }
61
75
  const subAssets = await fs.readdir(assetDir);
@@ -66,9 +80,9 @@ const syncAssetDirectory = async (projectDirectory) => {
66
80
  const subAssetPath = path.join(assetDir, subAsset);
67
81
  const syncStatus = new SyncStatus(subAssetPath);
68
82
  if (await syncStatus.isSynced()) {
69
- process.stderr.write(
70
- ` āœ” Sub-asset has already been synced: ${subAsset}
71
- `
83
+ reportInfo(
84
+ subAsset,
85
+ `āœ” Sub-asset has already been synced: ${subAsset}`
72
86
  );
73
87
  continue;
74
88
  }
@@ -78,20 +92,15 @@ const syncAssetDirectory = async (projectDirectory) => {
78
92
  const [videoProbe] = probeResult.videoStreams;
79
93
  const { format } = probeResult;
80
94
  if (!videoProbe) {
81
- process.stderr.write(
82
- `🚫 No video stream found in image: ${subAsset}
83
- `
84
- );
95
+ reportError(subAsset, `No media info found in image: ${subAsset}`);
85
96
  break;
86
97
  }
87
98
  const ext = path.extname(subAsset).slice(1);
88
99
  if (!(ext === "jpg" || ext === "jpeg" || ext === "png" || ext === "webp")) {
89
- process.stderr.write(`🚫 Invalid image format: ${subAsset}
90
- `);
100
+ reportError(subAsset, `Invalid image format: ${subAsset}`);
91
101
  break;
92
102
  }
93
- process.stderr.write(`šŸ–¼ļø Syncing image: ${subAsset}
94
- `);
103
+ reportInfo(subAsset, `šŸ–¼ļø Syncing image: ${subAsset}`);
95
104
  const created = await createImageFile(getClient(), {
96
105
  id: asset,
97
106
  filename: subAsset,
@@ -102,23 +111,29 @@ const syncAssetDirectory = async (projectDirectory) => {
102
111
  });
103
112
  if (created) {
104
113
  if (created.complete) {
105
- process.stderr.write(" āœ” Image has already been synced.\n");
114
+ reportInfo(subAsset, " āœ” Image has already been synced");
115
+ await syncStatus.markSynced();
106
116
  } else {
107
117
  await uploadImageFile(
108
118
  getClient(),
109
119
  created.id,
110
120
  createReadStream(subAssetPath),
111
121
  Number.parseInt(format.size || "0")
112
- );
113
- process.stderr.write(" āœ… Image has been synced.\n");
122
+ ).catch((error) => {
123
+ reportError(
124
+ subAsset,
125
+ `Error uploading image: ${error.message}`
126
+ );
127
+ }).then(() => {
128
+ reportSuccess(subAsset, "Image has been synced.");
129
+ return syncStatus.markSynced();
130
+ });
114
131
  }
115
- await syncStatus.markSynced();
116
132
  }
117
133
  break;
118
134
  }
119
135
  case trackMatch.test(subAsset): {
120
- process.stderr.write(`šŸ“¼ Syncing a/v track: ${subAsset}
121
- `);
136
+ reportInfo(subAsset, `šŸ“¼ Syncing a/v track: ${subAsset}`);
122
137
  const createdFile = await createISOBMFFFile(getClient(), {
123
138
  id: asset,
124
139
  filename: subAsset.replace(/\.track-[\d]+.mp4$/, "")
@@ -127,25 +142,19 @@ const syncAssetDirectory = async (projectDirectory) => {
127
142
  const probe = await Probe.probePath(subAssetPath);
128
143
  const trackId = subAsset.match(/track-([\d]+).mp4/)?.[1];
129
144
  if (!trackId) {
130
- process.stderr.write(
131
- `🚫 No track ID found for track: ${subAsset}
132
- `
133
- );
145
+ reportError(subAsset, `No track ID found for track: ${subAsset}`);
134
146
  break;
135
147
  }
136
148
  const [track] = probe.streams;
137
149
  if (!track) {
138
- process.stderr.write(
139
- `🚫 No track stream found in track: ${subAsset}
140
- `
150
+ reportError(
151
+ subAsset,
152
+ `No track stream found in track: ${subAsset}`
141
153
  );
142
154
  break;
143
155
  }
144
156
  if (track.duration === void 0) {
145
- process.stderr.write(
146
- `🚫 No duration found in track: ${subAsset}
147
- `
148
- );
157
+ reportError(subAsset, `No duration found in track: ${subAsset}`);
149
158
  break;
150
159
  }
151
160
  const stat3 = await fs.stat(subAssetPath);
@@ -172,7 +181,8 @@ const syncAssetDirectory = async (projectDirectory) => {
172
181
  );
173
182
  if (createdTrack) {
174
183
  if (createdTrack.next_byte === createdTrack.byte_size - 1) {
175
- process.stderr.write(" āœ” Track has already been synced.\n");
184
+ reportInfo(subAsset, "āœ” Track has already been synced.");
185
+ await syncStatus.markSynced();
176
186
  } else {
177
187
  await uploadISOBMFFTrack(
178
188
  getClient(),
@@ -180,26 +190,30 @@ const syncAssetDirectory = async (projectDirectory) => {
180
190
  Number(trackId),
181
191
  createReadStream(subAssetPath),
182
192
  createdTrack.byte_size
183
- );
184
- process.stderr.write(" āœ… Track has been synced.\n");
193
+ ).catch((error) => {
194
+ reportError(
195
+ subAsset,
196
+ `Error uploading track: ${error.message}`
197
+ );
198
+ }).then(() => {
199
+ reportSuccess(subAsset, "Track has been synced.");
200
+ return syncStatus.markSynced();
201
+ });
185
202
  }
186
- await syncStatus.markSynced();
187
203
  }
188
204
  }
189
205
  break;
190
206
  }
191
207
  case fragmentIndexMatch.test(subAsset): {
192
- process.stderr.write(`šŸ“‹ Syncing fragment index: ${subAsset}
193
- `);
208
+ reportInfo(subAsset, `šŸ“‹ Syncing fragment index: ${subAsset}`);
194
209
  const createdFile = await createISOBMFFFile(getClient(), {
195
210
  id: asset,
196
211
  filename: subAsset.replace(/\.tracks.json$/, "")
197
212
  });
198
213
  if (createdFile) {
199
214
  if (createdFile.fragment_index_complete) {
200
- process.stderr.write(
201
- " āœ” Fragment index has already been synced.\n"
202
- );
215
+ reportInfo(subAsset, "āœ” Fragment index has already been synced.");
216
+ await syncStatus.markSynced();
203
217
  } else {
204
218
  const stats = statSync(subAssetPath);
205
219
  const readStream = createReadStream(subAssetPath);
@@ -208,22 +222,27 @@ const syncAssetDirectory = async (projectDirectory) => {
208
222
  asset,
209
223
  readStream,
210
224
  stats.size
211
- );
212
- process.stderr.write(" āœ… Fragment index has been synced.\n");
225
+ ).catch((error) => {
226
+ reportError(
227
+ subAsset,
228
+ `Error uploading fragment index: ${error.message}`
229
+ );
230
+ }).then(() => {
231
+ reportSuccess(subAsset, "Fragment index has been synced.");
232
+ return syncStatus.markSynced();
233
+ });
213
234
  }
214
- await syncStatus.markSynced();
215
235
  } else {
216
- process.stderr.write(
217
- `🚫 No file found for fragment index: ${subAsset}
218
- `
236
+ reportError(
237
+ subAsset,
238
+ `No file found for fragment index: ${subAsset}`
219
239
  );
220
240
  break;
221
241
  }
222
242
  break;
223
243
  }
224
244
  case captionsMatch.test(subAsset): {
225
- process.stderr.write(`šŸ“ Syncing captions: ${subAsset}
226
- `);
245
+ reportInfo(subAsset, `šŸ“ Syncing captions: ${subAsset}`);
227
246
  const createdFile = await createCaptionFile(getClient(), {
228
247
  id: asset,
229
248
  filename: subAsset.replace(/\.captions.json$/, ""),
@@ -231,7 +250,8 @@ const syncAssetDirectory = async (projectDirectory) => {
231
250
  });
232
251
  if (createdFile) {
233
252
  if (createdFile.complete) {
234
- process.stderr.write(" āœ” Captions have already been synced.\n");
253
+ reportInfo(subAsset, "āœ” Captions have already been synced.");
254
+ await syncStatus.markSynced();
235
255
  } else {
236
256
  const readStream = createReadStream(subAssetPath);
237
257
  const stats = statSync(subAssetPath);
@@ -241,32 +261,41 @@ const syncAssetDirectory = async (projectDirectory) => {
241
261
  readStream,
242
262
  stats.size
243
263
  ).catch((error) => {
244
- process.stderr.write(
245
- `🚫 Error uploading captions: ${error.message}
246
- `
264
+ reportError(
265
+ subAsset,
266
+ `Error uploading captions: ${error.message}`
247
267
  );
248
268
  }).then(() => {
249
- process.stderr.write(" āœ… Captions have been synced.\n");
269
+ reportSuccess(subAsset, "Captions have been synced.");
270
+ return syncStatus.markSynced();
250
271
  });
251
272
  }
252
- await syncStatus.markSynced();
253
273
  } else {
254
- process.stderr.write(
255
- `🚫 No file found for captions: ${subAsset}
256
- `
257
- );
274
+ reportError(subAsset, `No file found for captions: ${subAsset}`);
258
275
  break;
259
276
  }
260
277
  break;
261
278
  }
262
279
  default: {
263
- process.stderr.write(`🚫 Unknown sub-asset: ${subAsset}
264
- `);
280
+ reportError(subAsset, `Unknown sub-asset: ${subAsset}`);
265
281
  break;
266
282
  }
267
283
  }
268
284
  }
269
285
  }
286
+ if (Object.keys(errors).length) {
287
+ process.stderr.write("\n\nāŒ Encountered errors while syncing assets:\n");
288
+ for (const [asset, messages] of Object.entries(errors)) {
289
+ process.stderr.write(`
290
+ 🚫 ${asset}
291
+ `);
292
+ for (const message of messages) {
293
+ process.stderr.write(` - ${message}
294
+ `);
295
+ }
296
+ }
297
+ throw new Error("Failed to sync assets");
298
+ }
270
299
  };
271
300
  export {
272
301
  syncAssetDirectory
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@editframe/cli",
3
- "version": "0.8.0-beta.7",
3
+ "version": "0.8.0-beta.8",
4
4
  "description": "Command line interface for EditFrame",
5
5
  "bin": {
6
6
  "editframe": "./dist/index.js"
@@ -23,10 +23,10 @@
23
23
  "vite-tsconfig-paths": "^4.3.2"
24
24
  },
25
25
  "dependencies": {
26
- "@editframe/api": "0.8.0-beta.7",
27
- "@editframe/assets": "0.8.0-beta.7",
28
- "@editframe/elements": "0.8.0-beta.7",
29
- "@editframe/vite-plugin": "0.8.0-beta.7",
26
+ "@editframe/api": "0.8.0-beta.8",
27
+ "@editframe/assets": "0.8.0-beta.8",
28
+ "@editframe/elements": "0.8.0-beta.8",
29
+ "@editframe/vite-plugin": "0.8.0-beta.8",
30
30
  "axios": "^1.6.8",
31
31
  "chalk": "^5.3.0",
32
32
  "commander": "^12.0.0",
@@ -63,6 +63,7 @@ export const syncAssetDirectory = async (
63
63
  }
64
64
  throw error;
65
65
  });
66
+
66
67
  if (!stat?.isDirectory()) {
67
68
  console.error(`No assets cache directory found at ${fullPath}`);
68
69
  return;
@@ -71,12 +72,28 @@ export const syncAssetDirectory = async (
71
72
 
72
73
  process.stderr.write(`Syncing asset dir: ${fullPath}\n`);
73
74
 
75
+ const errors: Record<string, string[]> = {};
76
+
77
+ const reportError = (path: string, message: string) => {
78
+ errors[path] ||= [];
79
+ errors[path].push(message);
80
+ process.stderr.write(` 🚫 ${message}\n`);
81
+ };
82
+
83
+ const reportSuccess = (_path: string, message: string) => {
84
+ process.stderr.write(` āœ… ${message}\n`);
85
+ };
86
+
87
+ const reportInfo = (_path: string, message: string) => {
88
+ process.stderr.write(` ${message}\n`);
89
+ };
90
+
74
91
  for (const asset of assets) {
75
- process.stderr.write(`Syncing asset: ${asset}\n`);
92
+ reportInfo(asset, `Syncing asset: ${asset}`);
76
93
  const assetDir = path.join(fullPath, asset);
77
94
  const stat = await fs.stat(assetDir);
78
95
  if (!stat.isDirectory()) {
79
- process.stderr.write("Invalid asset. Did not find asset directory.\n");
96
+ reportError(asset, "Invalid asset. Did not find asset directory.");
80
97
  return;
81
98
  }
82
99
  const subAssets = await fs.readdir(assetDir);
@@ -89,8 +106,9 @@ export const syncAssetDirectory = async (
89
106
  const subAssetPath = path.join(assetDir, subAsset);
90
107
  const syncStatus = new SyncStatus(subAssetPath);
91
108
  if (await syncStatus.isSynced()) {
92
- process.stderr.write(
93
- ` āœ” Sub-asset has already been synced: ${subAsset}\n`,
109
+ reportInfo(
110
+ subAsset,
111
+ `āœ” Sub-asset has already been synced: ${subAsset}`,
94
112
  );
95
113
  continue;
96
114
  }
@@ -100,9 +118,7 @@ export const syncAssetDirectory = async (
100
118
  const [videoProbe] = probeResult.videoStreams;
101
119
  const { format } = probeResult;
102
120
  if (!videoProbe) {
103
- process.stderr.write(
104
- `🚫 No video stream found in image: ${subAsset}\n`,
105
- );
121
+ reportError(subAsset, `No media info found in image: ${subAsset}`);
106
122
  break;
107
123
  }
108
124
  const ext = path.extname(subAsset).slice(1);
@@ -114,10 +130,10 @@ export const syncAssetDirectory = async (
114
130
  ext === "webp"
115
131
  )
116
132
  ) {
117
- process.stderr.write(`🚫 Invalid image format: ${subAsset}\n`);
133
+ reportError(subAsset, `Invalid image format: ${subAsset}`);
118
134
  break;
119
135
  }
120
- process.stderr.write(`šŸ–¼ļø Syncing image: ${subAsset}\n`);
136
+ reportInfo(subAsset, `šŸ–¼ļø Syncing image: ${subAsset}`);
121
137
  const created = await createImageFile(getClient(), {
122
138
  id: asset,
123
139
  filename: subAsset,
@@ -128,22 +144,31 @@ export const syncAssetDirectory = async (
128
144
  });
129
145
  if (created) {
130
146
  if (created.complete) {
131
- process.stderr.write(" āœ” Image has already been synced.\n");
147
+ reportInfo(subAsset, " āœ” Image has already been synced");
148
+ await syncStatus.markSynced();
132
149
  } else {
133
150
  await uploadImageFile(
134
151
  getClient(),
135
152
  created.id,
136
153
  createReadStream(subAssetPath),
137
154
  Number.parseInt(format.size || "0"),
138
- );
139
- process.stderr.write(" āœ… Image has been synced.\n");
155
+ )
156
+ .catch((error) => {
157
+ reportError(
158
+ subAsset,
159
+ `Error uploading image: ${error.message}`,
160
+ );
161
+ })
162
+ .then(() => {
163
+ reportSuccess(subAsset, "Image has been synced.");
164
+ return syncStatus.markSynced();
165
+ });
140
166
  }
141
- await syncStatus.markSynced();
142
167
  }
143
168
  break;
144
169
  }
145
170
  case trackMatch.test(subAsset): {
146
- process.stderr.write(`šŸ“¼ Syncing a/v track: ${subAsset}\n`);
171
+ reportInfo(subAsset, `šŸ“¼ Syncing a/v track: ${subAsset}`);
147
172
  const createdFile = await createISOBMFFFile(getClient(), {
148
173
  id: asset,
149
174
  filename: subAsset.replace(/\.track-[\d]+.mp4$/, ""),
@@ -152,22 +177,19 @@ export const syncAssetDirectory = async (
152
177
  const probe = await Probe.probePath(subAssetPath);
153
178
  const trackId = subAsset.match(/track-([\d]+).mp4/)?.[1];
154
179
  if (!trackId) {
155
- process.stderr.write(
156
- `🚫 No track ID found for track: ${subAsset}\n`,
157
- );
180
+ reportError(subAsset, `No track ID found for track: ${subAsset}`);
158
181
  break;
159
182
  }
160
183
  const [track] = probe.streams;
161
184
  if (!track) {
162
- process.stderr.write(
163
- `🚫 No track stream found in track: ${subAsset}\n`,
185
+ reportError(
186
+ subAsset,
187
+ `No track stream found in track: ${subAsset}`,
164
188
  );
165
189
  break;
166
190
  }
167
191
  if (track.duration === undefined) {
168
- process.stderr.write(
169
- `🚫 No duration found in track: ${subAsset}\n`,
170
- );
192
+ reportError(subAsset, `No duration found in track: ${subAsset}`);
171
193
  break;
172
194
  }
173
195
 
@@ -206,7 +228,8 @@ export const syncAssetDirectory = async (
206
228
 
207
229
  if (createdTrack) {
208
230
  if (createdTrack.next_byte === createdTrack.byte_size - 1) {
209
- process.stderr.write(" āœ” Track has already been synced.\n");
231
+ reportInfo(subAsset, "āœ” Track has already been synced.");
232
+ await syncStatus.markSynced();
210
233
  } else {
211
234
  await uploadISOBMFFTrack(
212
235
  getClient(),
@@ -214,26 +237,33 @@ export const syncAssetDirectory = async (
214
237
  Number(trackId),
215
238
  createReadStream(subAssetPath),
216
239
  createdTrack.byte_size,
217
- );
218
- process.stderr.write(" āœ… Track has been synced.\n");
240
+ )
241
+ .catch((error) => {
242
+ reportError(
243
+ subAsset,
244
+ `Error uploading track: ${error.message}`,
245
+ );
246
+ })
247
+ .then(() => {
248
+ reportSuccess(subAsset, "Track has been synced.");
249
+ return syncStatus.markSynced();
250
+ });
219
251
  }
220
- await syncStatus.markSynced();
221
252
  }
222
253
  }
223
254
 
224
255
  break;
225
256
  }
226
257
  case fragmentIndexMatch.test(subAsset): {
227
- process.stderr.write(`šŸ“‹ Syncing fragment index: ${subAsset}\n`);
258
+ reportInfo(subAsset, `šŸ“‹ Syncing fragment index: ${subAsset}`);
228
259
  const createdFile = await createISOBMFFFile(getClient(), {
229
260
  id: asset,
230
261
  filename: subAsset.replace(/\.tracks.json$/, ""),
231
262
  });
232
263
  if (createdFile) {
233
264
  if (createdFile.fragment_index_complete) {
234
- process.stderr.write(
235
- " āœ” Fragment index has already been synced.\n",
236
- );
265
+ reportInfo(subAsset, "āœ” Fragment index has already been synced.");
266
+ await syncStatus.markSynced();
237
267
  } else {
238
268
  const stats = statSync(subAssetPath);
239
269
  const readStream = createReadStream(subAssetPath);
@@ -242,20 +272,29 @@ export const syncAssetDirectory = async (
242
272
  asset,
243
273
  readStream,
244
274
  stats.size,
245
- );
246
- process.stderr.write(" āœ… Fragment index has been synced.\n");
275
+ )
276
+ .catch((error) => {
277
+ reportError(
278
+ subAsset,
279
+ `Error uploading fragment index: ${error.message}`,
280
+ );
281
+ })
282
+ .then(() => {
283
+ reportSuccess(subAsset, "Fragment index has been synced.");
284
+ return syncStatus.markSynced();
285
+ });
247
286
  }
248
- await syncStatus.markSynced();
249
287
  } else {
250
- process.stderr.write(
251
- `🚫 No file found for fragment index: ${subAsset}\n`,
288
+ reportError(
289
+ subAsset,
290
+ `No file found for fragment index: ${subAsset}`,
252
291
  );
253
292
  break;
254
293
  }
255
294
  break;
256
295
  }
257
296
  case captionsMatch.test(subAsset): {
258
- process.stderr.write(`šŸ“ Syncing captions: ${subAsset}\n`);
297
+ reportInfo(subAsset, `šŸ“ Syncing captions: ${subAsset}`);
259
298
  const createdFile = await createCaptionFile(getClient(), {
260
299
  id: asset,
261
300
  filename: subAsset.replace(/\.captions.json$/, ""),
@@ -263,7 +302,8 @@ export const syncAssetDirectory = async (
263
302
  });
264
303
  if (createdFile) {
265
304
  if (createdFile.complete) {
266
- process.stderr.write(" āœ” Captions have already been synced.\n");
305
+ reportInfo(subAsset, "āœ” Captions have already been synced.");
306
+ await syncStatus.markSynced();
267
307
  } else {
268
308
  const readStream = createReadStream(subAssetPath);
269
309
  const stats = statSync(subAssetPath);
@@ -274,28 +314,39 @@ export const syncAssetDirectory = async (
274
314
  stats.size,
275
315
  )
276
316
  .catch((error) => {
277
- process.stderr.write(
278
- `🚫 Error uploading captions: ${error.message}\n`,
317
+ reportError(
318
+ subAsset,
319
+ `Error uploading captions: ${error.message}`,
279
320
  );
280
321
  })
281
322
  .then(() => {
282
- process.stderr.write(" āœ… Captions have been synced.\n");
323
+ reportSuccess(subAsset, "Captions have been synced.");
324
+ return syncStatus.markSynced();
283
325
  });
284
326
  }
285
- await syncStatus.markSynced();
286
327
  } else {
287
- process.stderr.write(
288
- `🚫 No file found for captions: ${subAsset}\n`,
289
- );
328
+ reportError(subAsset, `No file found for captions: ${subAsset}`);
290
329
  break;
291
330
  }
292
331
  break;
293
332
  }
294
333
  default: {
295
- process.stderr.write(`🚫 Unknown sub-asset: ${subAsset}\n`);
334
+ reportError(subAsset, `Unknown sub-asset: ${subAsset}`);
296
335
  break;
297
336
  }
298
337
  }
299
338
  }
300
339
  }
340
+
341
+ if (Object.keys(errors).length) {
342
+ process.stderr.write("\n\nāŒ Encountered errors while syncing assets:\n");
343
+ for (const [asset, messages] of Object.entries(errors)) {
344
+ process.stderr.write(`\n🚫 ${asset}\n`);
345
+ for (const message of messages) {
346
+ process.stderr.write(` - ${message}\n`);
347
+ }
348
+ }
349
+
350
+ throw new Error("Failed to sync assets");
351
+ }
301
352
  };