@aspects-ai/workspace-cli 0.1.7 → 0.1.10
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/README.md +41 -0
- package/dist/index.js +118 -15
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -98,6 +98,47 @@ This command will:
|
|
|
98
98
|
4. Update `workspace.config.json` with the new version and commit hash
|
|
99
99
|
5. Update dependencies in `package.json` if they changed
|
|
100
100
|
|
|
101
|
+
### `create-remotion-entry`
|
|
102
|
+
|
|
103
|
+
Generate a `remotion-entry.tsx` file for server-side rendering of Remotion compositions.
|
|
104
|
+
|
|
105
|
+
```bash
|
|
106
|
+
workspace-cli create-remotion-entry
|
|
107
|
+
```
|
|
108
|
+
|
|
109
|
+
Options:
|
|
110
|
+
- `-o, --output <path>` - Output path for remotion-entry.tsx (default: `remotion-entry.tsx`)
|
|
111
|
+
- `-f, --frames-dir <path>` - Path to frames directory (default: `frames`)
|
|
112
|
+
|
|
113
|
+
This command will:
|
|
114
|
+
1. Scan the frames directory for all frame subdirectories
|
|
115
|
+
2. Validate that each frame has a `main.tsx` file
|
|
116
|
+
3. Generate a `remotion-entry.tsx` file with all frames imported and registered
|
|
117
|
+
4. Display the list of registered frames
|
|
118
|
+
|
|
119
|
+
Example output:
|
|
120
|
+
```
|
|
121
|
+
[INFO] Scanning frames in: frames
|
|
122
|
+
[SUCCESS] Created remotion entry file: /path/to/remotion-entry.tsx
|
|
123
|
+
|
|
124
|
+
Registered 3 frame(s):
|
|
125
|
+
• example
|
|
126
|
+
• healthee
|
|
127
|
+
• peregrine
|
|
128
|
+
|
|
129
|
+
Next steps:
|
|
130
|
+
Render a frame: ANIMATION_SSR_MODE=true npx remotion render remotion-entry.tsx <frame-id> output.mp4
|
|
131
|
+
```
|
|
132
|
+
|
|
133
|
+
The generated file can be used with Remotion CLI for server-side rendering:
|
|
134
|
+
```bash
|
|
135
|
+
# Render a specific frame
|
|
136
|
+
ANIMATION_SSR_MODE=true npx remotion render remotion-entry.tsx example output.mp4
|
|
137
|
+
|
|
138
|
+
# List available compositions
|
|
139
|
+
ANIMATION_SSR_MODE=true npx remotion compositions remotion-entry.tsx
|
|
140
|
+
```
|
|
141
|
+
|
|
101
142
|
## Usage Examples
|
|
102
143
|
|
|
103
144
|
### Basic Workflow
|
package/dist/index.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
|
|
3
3
|
// src/index.ts
|
|
4
|
-
import { Command as
|
|
4
|
+
import { Command as Command8 } from "commander";
|
|
5
5
|
|
|
6
6
|
// src/commands/init.ts
|
|
7
7
|
import { Command } from "commander";
|
|
@@ -436,6 +436,9 @@ import chalk5 from "chalk";
|
|
|
436
436
|
import { Command as Command5 } from "commander";
|
|
437
437
|
import fs5 from "fs-extra";
|
|
438
438
|
import path5 from "path";
|
|
439
|
+
function generateId() {
|
|
440
|
+
return Math.floor(Math.random() * Number.MAX_SAFE_INTEGER).toString();
|
|
441
|
+
}
|
|
439
442
|
function parseManifestOption(manifestStr) {
|
|
440
443
|
try {
|
|
441
444
|
return JSON.parse(manifestStr);
|
|
@@ -446,7 +449,8 @@ function parseManifestOption(manifestStr) {
|
|
|
446
449
|
function validateAndFixManifest(manifest, toolName, frameName) {
|
|
447
450
|
const now = (/* @__PURE__ */ new Date()).toISOString();
|
|
448
451
|
const validatedManifest = {
|
|
449
|
-
id:
|
|
452
|
+
id: frameName,
|
|
453
|
+
// Always match the directory name
|
|
450
454
|
projectId: manifest.projectId || "default-project",
|
|
451
455
|
title: manifest.title || frameName.split("-").map((w) => w.charAt(0).toUpperCase() + w.slice(1)).join(" "),
|
|
452
456
|
description: manifest.description || `Frame for ${toolName}`,
|
|
@@ -459,17 +463,20 @@ function validateAndFixManifest(manifest, toolName, frameName) {
|
|
|
459
463
|
}
|
|
460
464
|
return validatedManifest;
|
|
461
465
|
}
|
|
462
|
-
async function getNextFrameName(framesDir,
|
|
463
|
-
|
|
464
|
-
|
|
466
|
+
async function getNextFrameName(framesDir, customName) {
|
|
467
|
+
let frameName;
|
|
468
|
+
if (customName) {
|
|
469
|
+
const truncatedName = customName.slice(0, 20);
|
|
470
|
+
const uniqueId = generateId();
|
|
471
|
+
frameName = `${truncatedName}-${uniqueId}`;
|
|
472
|
+
} else {
|
|
473
|
+
frameName = generateId();
|
|
465
474
|
}
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
counter++;
|
|
470
|
-
nextName = `${baseName}-${counter}`;
|
|
475
|
+
while (await fs5.pathExists(path5.join(framesDir, frameName))) {
|
|
476
|
+
const uniqueId = generateId();
|
|
477
|
+
frameName = customName ? `${customName.slice(0, 20)}-${uniqueId}` : uniqueId;
|
|
471
478
|
}
|
|
472
|
-
return
|
|
479
|
+
return frameName;
|
|
473
480
|
}
|
|
474
481
|
async function fetchExampleFrame(toolName, targetPath) {
|
|
475
482
|
const library = await getLibrary(toolName);
|
|
@@ -490,8 +497,8 @@ function createCreateFrameCommand() {
|
|
|
490
497
|
const workspaceRoot = await ensureWorkspaceRoot();
|
|
491
498
|
const framesDir = path5.join(workspaceRoot, "frames");
|
|
492
499
|
await fs5.ensureDir(framesDir);
|
|
493
|
-
const
|
|
494
|
-
const frameName = await getNextFrameName(framesDir,
|
|
500
|
+
const customName = options.name && options.name !== "new-frame" ? options.name : void 0;
|
|
501
|
+
const frameName = await getNextFrameName(framesDir, customName);
|
|
495
502
|
const frameDir = path5.join(framesDir, frameName);
|
|
496
503
|
logger.info(`Creating frame: ${chalk5.cyan(frameName)} for ${chalk5.cyan(toolName)}`);
|
|
497
504
|
await fetchExampleFrame(toolName, frameDir);
|
|
@@ -588,10 +595,105 @@ async function fetchFileFromGit(options) {
|
|
|
588
595
|
}
|
|
589
596
|
}
|
|
590
597
|
|
|
598
|
+
// src/commands/create-remotion-entry.ts
|
|
599
|
+
import chalk7 from "chalk";
|
|
600
|
+
import { Command as Command7 } from "commander";
|
|
601
|
+
import fs7 from "fs-extra";
|
|
602
|
+
import path7 from "path";
|
|
603
|
+
async function createRemotionEntry(framesDir, outputPath) {
|
|
604
|
+
if (!await fs7.pathExists(framesDir)) {
|
|
605
|
+
throw new Error(`Frames directory not found: ${framesDir}`);
|
|
606
|
+
}
|
|
607
|
+
const entries = await fs7.readdir(framesDir, { withFileTypes: true });
|
|
608
|
+
const frameDirs = entries.filter((entry) => entry.isDirectory()).map((entry) => entry.name);
|
|
609
|
+
if (frameDirs.length === 0) {
|
|
610
|
+
throw new Error(`No frame directories found in ${framesDir}`);
|
|
611
|
+
}
|
|
612
|
+
const validFrames = [];
|
|
613
|
+
for (const frameDir of frameDirs) {
|
|
614
|
+
const mainPath = path7.join(framesDir, frameDir, "main.tsx");
|
|
615
|
+
if (await fs7.pathExists(mainPath)) {
|
|
616
|
+
validFrames.push(frameDir);
|
|
617
|
+
} else {
|
|
618
|
+
logger.warn(`Skipping ${frameDir}: main.tsx not found`);
|
|
619
|
+
}
|
|
620
|
+
}
|
|
621
|
+
if (validFrames.length === 0) {
|
|
622
|
+
throw new Error("No valid frames found (frames must contain main.tsx)");
|
|
623
|
+
}
|
|
624
|
+
const imports = validFrames.map((frameDir, index) => {
|
|
625
|
+
const varName = `Frame${index}`;
|
|
626
|
+
const defName = `frame${index}Def`;
|
|
627
|
+
return {
|
|
628
|
+
frameDir,
|
|
629
|
+
varName,
|
|
630
|
+
defName,
|
|
631
|
+
statement: `import ${varName}, { compositionDefinition as ${defName} } from './frames/${frameDir}/main';`
|
|
632
|
+
};
|
|
633
|
+
});
|
|
634
|
+
const framesObject = imports.map(({ frameDir, varName, defName }) => {
|
|
635
|
+
return ` '${frameDir}': { component: ${varName}, compositionDefinition: ${defName} },`;
|
|
636
|
+
}).join("\n");
|
|
637
|
+
const content = `/**
|
|
638
|
+
* Auto-generated Remotion SSR Entry Point
|
|
639
|
+
*
|
|
640
|
+
* Generated by: @aspects-ai/workspace-cli create-remotion-entry
|
|
641
|
+
* DO NOT EDIT THIS FILE MANUALLY - it will be overwritten
|
|
642
|
+
*
|
|
643
|
+
* This file serves as the entry point for server-side rendering with Remotion.
|
|
644
|
+
* It automatically registers all frames in the ./frames directory.
|
|
645
|
+
*
|
|
646
|
+
* Usage:
|
|
647
|
+
* ANIMATION_SSR_MODE=true npx remotion render remotion-entry.tsx <frame-id> output.mp4
|
|
648
|
+
*
|
|
649
|
+
* To regenerate this file:
|
|
650
|
+
* npx @aspects-ai/workspace-cli create-remotion-entry
|
|
651
|
+
*/
|
|
652
|
+
|
|
653
|
+
import { registerRoot } from 'remotion';
|
|
654
|
+
import { createRemotionRoot } from '@aspects-ai/noodle-animate-core/remotion';
|
|
655
|
+
|
|
656
|
+
// Frame imports
|
|
657
|
+
${imports.map((i) => i.statement).join("\n")}
|
|
658
|
+
|
|
659
|
+
// Register all frames with Remotion
|
|
660
|
+
const Root = createRemotionRoot({
|
|
661
|
+
${framesObject}
|
|
662
|
+
});
|
|
663
|
+
|
|
664
|
+
registerRoot(Root);
|
|
665
|
+
`;
|
|
666
|
+
await fs7.writeFile(outputPath, content, "utf-8");
|
|
667
|
+
logger.success(`Created remotion entry file: ${chalk7.green(outputPath)}`);
|
|
668
|
+
logger.log("");
|
|
669
|
+
logger.log(chalk7.bold(`Registered ${validFrames.length} frame(s):`));
|
|
670
|
+
validFrames.forEach((frame) => {
|
|
671
|
+
logger.log(` ${chalk7.cyan("\u2022")} ${frame}`);
|
|
672
|
+
});
|
|
673
|
+
logger.log("");
|
|
674
|
+
logger.log(chalk7.bold("Next steps:"));
|
|
675
|
+
logger.log(` ${chalk7.gray("Render a frame:")} ANIMATION_SSR_MODE=true npx remotion render remotion-entry.tsx <frame-id> output.mp4`);
|
|
676
|
+
logger.log("");
|
|
677
|
+
}
|
|
678
|
+
function createCreateRemotionEntryCommand() {
|
|
679
|
+
return new Command7("create-remotion-entry").description("Create a remotion-entry.tsx file for server-side rendering").option("-o, --output <path>", "Output path for remotion-entry.tsx", "remotion-entry.tsx").option("-f, --frames-dir <path>", "Path to frames directory", "frames").action(async (options) => {
|
|
680
|
+
try {
|
|
681
|
+
const workspaceRoot = await ensureWorkspaceRoot();
|
|
682
|
+
const framesDir = path7.resolve(workspaceRoot, options.framesDir || "frames");
|
|
683
|
+
const outputPath = path7.resolve(workspaceRoot, options.output || "remotion-entry.tsx");
|
|
684
|
+
logger.info(`Scanning frames in: ${chalk7.cyan(path7.relative(workspaceRoot, framesDir))}`);
|
|
685
|
+
await createRemotionEntry(framesDir, outputPath);
|
|
686
|
+
} catch (error) {
|
|
687
|
+
logger.error(error.message);
|
|
688
|
+
process.exit(1);
|
|
689
|
+
}
|
|
690
|
+
});
|
|
691
|
+
}
|
|
692
|
+
|
|
591
693
|
// package.json
|
|
592
694
|
var package_default = {
|
|
593
695
|
name: "@aspects-ai/workspace-cli",
|
|
594
|
-
version: "0.1.
|
|
696
|
+
version: "0.1.9",
|
|
595
697
|
private: false,
|
|
596
698
|
description: "Lightweight CLI for installing libraries into workspaces",
|
|
597
699
|
type: "module",
|
|
@@ -627,7 +729,7 @@ var package_default = {
|
|
|
627
729
|
};
|
|
628
730
|
|
|
629
731
|
// src/index.ts
|
|
630
|
-
var program = new
|
|
732
|
+
var program = new Command8();
|
|
631
733
|
program.name("workspace-cli").description("Lightweight CLI for installing libraries into workspaces").version(package_default.version);
|
|
632
734
|
program.addCommand(createInitCommand());
|
|
633
735
|
program.addCommand(createListCommand());
|
|
@@ -635,4 +737,5 @@ program.addCommand(createAddCommand());
|
|
|
635
737
|
program.addCommand(createUpdateCommand());
|
|
636
738
|
program.addCommand(createCreateFrameCommand());
|
|
637
739
|
program.addCommand(createUpdateTemplateCommand());
|
|
740
|
+
program.addCommand(createCreateRemotionEntryCommand());
|
|
638
741
|
program.parse(process.argv);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@aspects-ai/workspace-cli",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.10",
|
|
4
4
|
"private": false,
|
|
5
5
|
"description": "Lightweight CLI for installing libraries into workspaces",
|
|
6
6
|
"type": "module",
|
|
@@ -33,4 +33,4 @@
|
|
|
33
33
|
"engines": {
|
|
34
34
|
"node": ">=18.0.0"
|
|
35
35
|
}
|
|
36
|
-
}
|
|
36
|
+
}
|