demo-reel 0.1.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.
- package/LICENSE +21 -0
- package/README.md +158 -0
- package/dist/cli.d.ts +3 -0
- package/dist/cli.d.ts.map +1 -0
- package/dist/cli.js +124 -0
- package/dist/cli.js.map +1 -0
- package/dist/config-loader.d.ts +11 -0
- package/dist/config-loader.d.ts.map +1 -0
- package/dist/config-loader.js +107 -0
- package/dist/config-loader.js.map +1 -0
- package/dist/index.d.ts +7 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +9 -0
- package/dist/index.js.map +1 -0
- package/dist/runner.d.ts +4 -0
- package/dist/runner.d.ts.map +1 -0
- package/dist/runner.js +465 -0
- package/dist/runner.js.map +1 -0
- package/dist/schemas.d.ts +2706 -0
- package/dist/schemas.d.ts.map +1 -0
- package/dist/schemas.js +223 -0
- package/dist/schemas.js.map +1 -0
- package/dist/types.d.ts +2 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +2 -0
- package/dist/types.js.map +1 -0
- package/dist/video-handler.d.ts +15 -0
- package/dist/video-handler.d.ts.map +1 -0
- package/dist/video-handler.js +77 -0
- package/dist/video-handler.js.map +1 -0
- package/package.json +50 -0
- package/templates/demo-reel.config.ts +94 -0
- package/templates/scenario.demo.ts +70 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2024
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,158 @@
|
|
|
1
|
+
# Demo Reel
|
|
2
|
+
|
|
3
|
+
Create beautiful demo videos from web apps using Playwright. Perfect for showcasing features, creating onboarding tutorials, or documenting workflows.
|
|
4
|
+
|
|
5
|
+
## Installation
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
npm install -D demo-reel playwright
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
Or use without installing:
|
|
12
|
+
|
|
13
|
+
```bash
|
|
14
|
+
npx demo-reel --config ./my-demo.ts
|
|
15
|
+
```
|
|
16
|
+
|
|
17
|
+
## Quick Start
|
|
18
|
+
|
|
19
|
+
1. Create a config file `demo-reel.config.ts`:
|
|
20
|
+
|
|
21
|
+
```typescript
|
|
22
|
+
import { defineConfig } from 'demo-reel';
|
|
23
|
+
|
|
24
|
+
export default defineConfig({
|
|
25
|
+
viewport: { width: 1920, height: 1080 },
|
|
26
|
+
video: {
|
|
27
|
+
enabled: true,
|
|
28
|
+
size: { width: 1920, height: 1080 },
|
|
29
|
+
},
|
|
30
|
+
name: 'my-demo',
|
|
31
|
+
steps: [
|
|
32
|
+
{ action: 'goto', url: 'https://example.com' },
|
|
33
|
+
{ action: 'wait', ms: 2000 },
|
|
34
|
+
],
|
|
35
|
+
});
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
2. Run it:
|
|
39
|
+
|
|
40
|
+
```bash
|
|
41
|
+
npx demo-reel
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
## CLI Usage
|
|
45
|
+
|
|
46
|
+
```bash
|
|
47
|
+
# Run default config (demo-reel.config.ts)
|
|
48
|
+
npx demo-reel
|
|
49
|
+
|
|
50
|
+
# Run a specific scenario
|
|
51
|
+
npx demo-reel onboarding
|
|
52
|
+
|
|
53
|
+
# Run all scenarios
|
|
54
|
+
npx demo-reel --all
|
|
55
|
+
|
|
56
|
+
# Dry run (validate config)
|
|
57
|
+
npx demo-reel --dry-run
|
|
58
|
+
|
|
59
|
+
# Show browser window (non-headless)
|
|
60
|
+
npx demo-reel --headed
|
|
61
|
+
|
|
62
|
+
# Override output directory
|
|
63
|
+
npx demo-reel --output-dir ./public/videos
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
## Configuration
|
|
67
|
+
|
|
68
|
+
### Config File Discovery
|
|
69
|
+
|
|
70
|
+
The CLI looks for configs in this order:
|
|
71
|
+
1. `demo-reel.config.ts` (default)
|
|
72
|
+
2. `<scenario>.demo.ts` (when specifying a scenario name)
|
|
73
|
+
3. All `*.demo.ts` files (with `--all` flag)
|
|
74
|
+
|
|
75
|
+
### Output Naming
|
|
76
|
+
|
|
77
|
+
Videos are named based on this priority:
|
|
78
|
+
1. `outputPath` in config (full path)
|
|
79
|
+
2. `name` + `outputDir` in config
|
|
80
|
+
3. Config filename (e.g., `onboarding.demo.ts` → `onboarding.webm`)
|
|
81
|
+
4. Default: `demo-reel.webm`
|
|
82
|
+
|
|
83
|
+
### Available Steps
|
|
84
|
+
|
|
85
|
+
- `goto` - Navigate to URL
|
|
86
|
+
- `click` - Click an element
|
|
87
|
+
- `hover` - Hover over element
|
|
88
|
+
- `type` - Type text into input
|
|
89
|
+
- `press` - Press a key
|
|
90
|
+
- `scroll` - Scroll element
|
|
91
|
+
- `select` - Select option(s)
|
|
92
|
+
- `check` - Check/uncheck checkbox
|
|
93
|
+
- `upload` - Upload file(s)
|
|
94
|
+
- `drag` - Drag element to target
|
|
95
|
+
- `wait` - Wait for duration
|
|
96
|
+
- `waitFor` - Wait for condition (selector, URL, loadState, request, response, function)
|
|
97
|
+
|
|
98
|
+
### Selector Strategies
|
|
99
|
+
|
|
100
|
+
```typescript
|
|
101
|
+
// By test ID (data-testid attribute)
|
|
102
|
+
{ strategy: 'testId', value: 'submit-button' }
|
|
103
|
+
|
|
104
|
+
// By ID (without #)
|
|
105
|
+
{ strategy: 'id', value: 'username' }
|
|
106
|
+
|
|
107
|
+
// By class (without .)
|
|
108
|
+
{ strategy: 'class', value: 'btn-primary' }
|
|
109
|
+
|
|
110
|
+
// By href
|
|
111
|
+
{ strategy: 'href', value: '/dashboard' }
|
|
112
|
+
```
|
|
113
|
+
|
|
114
|
+
## CI/CD Integration
|
|
115
|
+
|
|
116
|
+
Example GitHub Actions workflow:
|
|
117
|
+
|
|
118
|
+
```yaml
|
|
119
|
+
name: Generate Demo Videos
|
|
120
|
+
|
|
121
|
+
on: push
|
|
122
|
+
|
|
123
|
+
jobs:
|
|
124
|
+
demos:
|
|
125
|
+
runs-on: ubuntu-latest
|
|
126
|
+
steps:
|
|
127
|
+
- uses: actions/checkout@v4
|
|
128
|
+
- uses: actions/setup-node@v4
|
|
129
|
+
with:
|
|
130
|
+
node-version: '20'
|
|
131
|
+
- run: npm ci
|
|
132
|
+
- run: npx playwright install chromium
|
|
133
|
+
- run: npx demo-reel --all
|
|
134
|
+
- uses: actions/upload-artifact@v4
|
|
135
|
+
with:
|
|
136
|
+
name: demo-videos
|
|
137
|
+
path: ./videos/*.webm
|
|
138
|
+
```
|
|
139
|
+
|
|
140
|
+
## Features
|
|
141
|
+
|
|
142
|
+
### Human-Like Cursor Movement
|
|
143
|
+
- Smooth Bezier curve paths with ease-in/out timing
|
|
144
|
+
- Configurable speed, curve offset, and step count
|
|
145
|
+
- Visual cursor overlay (SVG or dot style)
|
|
146
|
+
|
|
147
|
+
### Natural Typing
|
|
148
|
+
- Variable delays based on character type
|
|
149
|
+
- Longer pauses for spaces, punctuation, and newlines
|
|
150
|
+
|
|
151
|
+
### Smart Delays
|
|
152
|
+
- Built-in delays after page navigation
|
|
153
|
+
- Per-step delays before/after actions
|
|
154
|
+
- Final delay to keep video open
|
|
155
|
+
|
|
156
|
+
## License
|
|
157
|
+
|
|
158
|
+
MIT
|
package/dist/cli.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cli.d.ts","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":""}
|
package/dist/cli.js
ADDED
|
@@ -0,0 +1,124 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import { loadConfig, findConfig, loadScenario, findScenarioFiles } from './config-loader.js';
|
|
3
|
+
import { runVideoScenario } from './video-handler.js';
|
|
4
|
+
function parseArgs() {
|
|
5
|
+
const args = process.argv.slice(2);
|
|
6
|
+
const options = {
|
|
7
|
+
verbose: false,
|
|
8
|
+
dryRun: false,
|
|
9
|
+
all: false,
|
|
10
|
+
};
|
|
11
|
+
let scenario;
|
|
12
|
+
for (let i = 0; i < args.length; i++) {
|
|
13
|
+
const arg = args[i];
|
|
14
|
+
if (arg === '--verbose' || arg === '-v') {
|
|
15
|
+
options.verbose = true;
|
|
16
|
+
}
|
|
17
|
+
else if (arg === '--dry-run') {
|
|
18
|
+
options.dryRun = true;
|
|
19
|
+
}
|
|
20
|
+
else if (arg === '--all') {
|
|
21
|
+
options.all = true;
|
|
22
|
+
}
|
|
23
|
+
else if (arg === '--output-dir' || arg === '-o') {
|
|
24
|
+
options.outputDir = args[++i];
|
|
25
|
+
}
|
|
26
|
+
else if (arg === '--headed') {
|
|
27
|
+
options.headed = true;
|
|
28
|
+
}
|
|
29
|
+
else if (arg === '--help' || arg === '-h') {
|
|
30
|
+
showHelp();
|
|
31
|
+
process.exit(0);
|
|
32
|
+
}
|
|
33
|
+
else if (!arg.startsWith('-')) {
|
|
34
|
+
scenario = arg;
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
return { scenario, options };
|
|
38
|
+
}
|
|
39
|
+
function showHelp() {
|
|
40
|
+
console.log(`
|
|
41
|
+
demo-reel - Create demo videos from web apps
|
|
42
|
+
|
|
43
|
+
Usage:
|
|
44
|
+
demo-reel [scenario] [options]
|
|
45
|
+
|
|
46
|
+
Arguments:
|
|
47
|
+
scenario Name of scenario to run (e.g., "onboarding")
|
|
48
|
+
Looks for: <scenario>.demo.ts or <scenario>.config.ts
|
|
49
|
+
|
|
50
|
+
Options:
|
|
51
|
+
--all Run all *.demo.ts files in the project
|
|
52
|
+
--output-dir, -o <dir> Override output directory for videos
|
|
53
|
+
--dry-run Validate config without recording
|
|
54
|
+
--headed Show browser window (non-headless)
|
|
55
|
+
--verbose, -v Show detailed output
|
|
56
|
+
--help, -h Show this help message
|
|
57
|
+
|
|
58
|
+
Examples:
|
|
59
|
+
demo-reel # Run demo-reel.config.ts
|
|
60
|
+
demo-reel onboarding # Run onboarding.demo.ts
|
|
61
|
+
demo-reel --all # Run all *.demo.ts files
|
|
62
|
+
demo-reel --dry-run # Validate config without recording
|
|
63
|
+
demo-reel -o ./public/videos # Override output directory
|
|
64
|
+
`);
|
|
65
|
+
}
|
|
66
|
+
async function main() {
|
|
67
|
+
const { scenario, options } = parseArgs();
|
|
68
|
+
try {
|
|
69
|
+
if (options.all) {
|
|
70
|
+
// Run all demo scenarios
|
|
71
|
+
const files = await findScenarioFiles();
|
|
72
|
+
if (files.length === 0) {
|
|
73
|
+
console.error('No *.demo.ts files found');
|
|
74
|
+
process.exit(1);
|
|
75
|
+
}
|
|
76
|
+
console.log(`Found ${files.length} scenario(s)`);
|
|
77
|
+
for (const file of files) {
|
|
78
|
+
console.log(`\n▶ ${file}`);
|
|
79
|
+
const loaded = await loadConfig(file, options.outputDir);
|
|
80
|
+
await runVideoScenario(loaded.config, loaded.outputPath, options);
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
else if (scenario) {
|
|
84
|
+
// Run specific scenario
|
|
85
|
+
const configPath = await loadScenario(scenario);
|
|
86
|
+
if (!configPath) {
|
|
87
|
+
console.error(`Scenario not found: ${scenario}`);
|
|
88
|
+
console.error('Looked for:');
|
|
89
|
+
console.error(` - ${scenario}.demo.ts`);
|
|
90
|
+
console.error(` - ${scenario}.config.ts`);
|
|
91
|
+
process.exit(1);
|
|
92
|
+
}
|
|
93
|
+
const loaded = await loadConfig(configPath, options.outputDir);
|
|
94
|
+
await runVideoScenario(loaded.config, loaded.outputPath, options);
|
|
95
|
+
}
|
|
96
|
+
else {
|
|
97
|
+
// Run default config
|
|
98
|
+
const configPath = await findConfig();
|
|
99
|
+
if (!configPath) {
|
|
100
|
+
console.error('No config file found. Looked for:');
|
|
101
|
+
console.error(' - demo-reel.config.ts');
|
|
102
|
+
console.error(' - demo-reel.config.js');
|
|
103
|
+
console.error(' - demo-reel.config.mjs');
|
|
104
|
+
console.error(' - demo-reel.config.json');
|
|
105
|
+
console.error('\nRun with --help for more options.');
|
|
106
|
+
process.exit(1);
|
|
107
|
+
}
|
|
108
|
+
const loaded = await loadConfig(configPath, options.outputDir);
|
|
109
|
+
await runVideoScenario(loaded.config, loaded.outputPath, options);
|
|
110
|
+
}
|
|
111
|
+
process.exit(0);
|
|
112
|
+
}
|
|
113
|
+
catch (error) {
|
|
114
|
+
if (options.verbose) {
|
|
115
|
+
console.error(error);
|
|
116
|
+
}
|
|
117
|
+
else {
|
|
118
|
+
console.error(`Error: ${error instanceof Error ? error.message : String(error)}`);
|
|
119
|
+
}
|
|
120
|
+
process.exit(1);
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
main();
|
|
124
|
+
//# sourceMappingURL=cli.js.map
|
package/dist/cli.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cli.js","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { type DemoReelConfig } from './schemas.js';
|
|
2
|
+
export interface LoadedConfig {
|
|
3
|
+
config: DemoReelConfig;
|
|
4
|
+
configPath: string;
|
|
5
|
+
outputPath: string;
|
|
6
|
+
}
|
|
7
|
+
export declare function loadConfig(configPath: string, cliOutputDir?: string): Promise<LoadedConfig>;
|
|
8
|
+
export declare function findConfig(cwd?: string): Promise<string | null>;
|
|
9
|
+
export declare function findScenarioFiles(cwd?: string, pattern?: string): Promise<string[]>;
|
|
10
|
+
export declare function loadScenario(name: string, cwd?: string): Promise<string | null>;
|
|
11
|
+
//# sourceMappingURL=config-loader.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"config-loader.d.ts","sourceRoot":"","sources":["../src/config-loader.ts"],"names":[],"mappings":"AAGA,OAAO,EAAwB,KAAK,cAAc,EAAE,MAAM,cAAc,CAAC;AAEzE,MAAM,WAAW,YAAY;IAC3B,MAAM,EAAE,cAAc,CAAC;IACvB,UAAU,EAAE,MAAM,CAAC;IACnB,UAAU,EAAE,MAAM,CAAC;CACpB;AA+DD,wBAAsB,UAAU,CAC9B,UAAU,EAAE,MAAM,EAClB,YAAY,CAAC,EAAE,MAAM,GACpB,OAAO,CAAC,YAAY,CAAC,CAavB;AAED,wBAAsB,UAAU,CAAC,GAAG,GAAE,MAAsB,GAAG,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAgBpF;AAED,wBAAsB,iBAAiB,CACrC,GAAG,GAAE,MAAsB,EAC3B,OAAO,GAAE,MAAuB,GAC/B,OAAO,CAAC,MAAM,EAAE,CAAC,CAQnB;AAED,wBAAsB,YAAY,CAChC,IAAI,EAAE,MAAM,EACZ,GAAG,GAAE,MAAsB,GAC1B,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAkBxB"}
|
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
import { promises as fs } from 'fs';
|
|
2
|
+
import { join, dirname, resolve, extname, basename } from 'path';
|
|
3
|
+
import { pathToFileURL } from 'url';
|
|
4
|
+
import { demoReelConfigSchema } from './schemas.js';
|
|
5
|
+
async function fileExists(path) {
|
|
6
|
+
try {
|
|
7
|
+
await fs.access(path);
|
|
8
|
+
return true;
|
|
9
|
+
}
|
|
10
|
+
catch {
|
|
11
|
+
return false;
|
|
12
|
+
}
|
|
13
|
+
}
|
|
14
|
+
async function loadConfigFile(configPath) {
|
|
15
|
+
const ext = extname(configPath);
|
|
16
|
+
if (ext === '.ts') {
|
|
17
|
+
// For TypeScript files, we'll try to use dynamic import with tsx
|
|
18
|
+
// In a real implementation, we'd need to handle this better
|
|
19
|
+
// For now, we'll throw an error suggesting the build process
|
|
20
|
+
const module = await import(pathToFileURL(configPath).href);
|
|
21
|
+
const config = module.default || module;
|
|
22
|
+
return demoReelConfigSchema.parse(config);
|
|
23
|
+
}
|
|
24
|
+
if (ext === '.js' || ext === '.mjs') {
|
|
25
|
+
const module = await import(pathToFileURL(configPath).href);
|
|
26
|
+
const config = module.default || module;
|
|
27
|
+
return demoReelConfigSchema.parse(config);
|
|
28
|
+
}
|
|
29
|
+
if (ext === '.json') {
|
|
30
|
+
const content = await fs.readFile(configPath, 'utf-8');
|
|
31
|
+
const config = JSON.parse(content);
|
|
32
|
+
return demoReelConfigSchema.parse(config);
|
|
33
|
+
}
|
|
34
|
+
throw new Error(`Unsupported config file extension: ${ext}`);
|
|
35
|
+
}
|
|
36
|
+
function resolveOutputPath(config, configPath, cliOutputDir) {
|
|
37
|
+
// Priority 1: outputPath from config
|
|
38
|
+
if (config.outputPath) {
|
|
39
|
+
if (config.outputPath.startsWith('/')) {
|
|
40
|
+
return config.outputPath;
|
|
41
|
+
}
|
|
42
|
+
return resolve(dirname(configPath), config.outputPath);
|
|
43
|
+
}
|
|
44
|
+
// Priority 2: name + outputDir (or CLI override)
|
|
45
|
+
const outputDir = cliOutputDir || config.outputDir || dirname(configPath);
|
|
46
|
+
const baseName = config.name || getBaseNameFromConfig(configPath);
|
|
47
|
+
return join(resolve(outputDir), `${baseName}.webm`);
|
|
48
|
+
}
|
|
49
|
+
function getBaseNameFromConfig(configPath) {
|
|
50
|
+
const base = basename(configPath, extname(configPath));
|
|
51
|
+
// Remove .demo or .config suffix if present
|
|
52
|
+
return base.replace(/\.(demo|config)$/, '');
|
|
53
|
+
}
|
|
54
|
+
export async function loadConfig(configPath, cliOutputDir) {
|
|
55
|
+
if (!await fileExists(configPath)) {
|
|
56
|
+
throw new Error(`Config file not found: ${configPath}`);
|
|
57
|
+
}
|
|
58
|
+
const config = await loadConfigFile(configPath);
|
|
59
|
+
const outputPath = resolveOutputPath(config, configPath, cliOutputDir);
|
|
60
|
+
return {
|
|
61
|
+
config,
|
|
62
|
+
configPath,
|
|
63
|
+
outputPath,
|
|
64
|
+
};
|
|
65
|
+
}
|
|
66
|
+
export async function findConfig(cwd = process.cwd()) {
|
|
67
|
+
const candidates = [
|
|
68
|
+
'demo-reel.config.ts',
|
|
69
|
+
'demo-reel.config.js',
|
|
70
|
+
'demo-reel.config.mjs',
|
|
71
|
+
'demo-reel.config.json',
|
|
72
|
+
];
|
|
73
|
+
for (const candidate of candidates) {
|
|
74
|
+
const fullPath = join(cwd, candidate);
|
|
75
|
+
if (await fileExists(fullPath)) {
|
|
76
|
+
return fullPath;
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
return null;
|
|
80
|
+
}
|
|
81
|
+
export async function findScenarioFiles(cwd = process.cwd(), pattern = '**/*.demo.ts') {
|
|
82
|
+
const { glob } = await import('glob');
|
|
83
|
+
const files = await glob(pattern, {
|
|
84
|
+
cwd,
|
|
85
|
+
absolute: true,
|
|
86
|
+
ignore: ['node_modules/**', 'dist/**', 'test-results/**'],
|
|
87
|
+
});
|
|
88
|
+
return files.sort();
|
|
89
|
+
}
|
|
90
|
+
export async function loadScenario(name, cwd = process.cwd()) {
|
|
91
|
+
const candidates = [
|
|
92
|
+
`${name}.demo.ts`,
|
|
93
|
+
`${name}.demo.js`,
|
|
94
|
+
`${name}.demo.mjs`,
|
|
95
|
+
`${name}.config.ts`,
|
|
96
|
+
`${name}.config.js`,
|
|
97
|
+
`${name}.config.mjs`,
|
|
98
|
+
];
|
|
99
|
+
for (const candidate of candidates) {
|
|
100
|
+
const fullPath = join(cwd, candidate);
|
|
101
|
+
if (await fileExists(fullPath)) {
|
|
102
|
+
return fullPath;
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
return null;
|
|
106
|
+
}
|
|
107
|
+
//# sourceMappingURL=config-loader.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"config-loader.js","sourceRoot":"","sources":["../src/config-loader.ts"],"names":[],"mappings":"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"}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import { demoReelConfigSchema, type DemoReelConfig } from './schemas.js';
|
|
2
|
+
export declare function defineConfig(config: DemoReelConfig): DemoReelConfig;
|
|
3
|
+
export declare function validateConfig(config: unknown): DemoReelConfig;
|
|
4
|
+
export { demoReelConfigSchema };
|
|
5
|
+
export type { DemoReelConfig } from './schemas.js';
|
|
6
|
+
export type * from './types.js';
|
|
7
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,oBAAoB,EAAE,KAAK,cAAc,EAAE,MAAM,cAAc,CAAC;AAEzE,wBAAgB,YAAY,CAAC,MAAM,EAAE,cAAc,GAAG,cAAc,CAEnE;AAED,wBAAgB,cAAc,CAAC,MAAM,EAAE,OAAO,GAAG,cAAc,CAE9D;AAED,OAAO,EAAE,oBAAoB,EAAE,CAAC;AAChC,YAAY,EAAE,cAAc,EAAE,MAAM,cAAc,CAAC;AACnD,mBAAmB,YAAY,CAAC"}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { demoReelConfigSchema } from './schemas.js';
|
|
2
|
+
export function defineConfig(config) {
|
|
3
|
+
return config;
|
|
4
|
+
}
|
|
5
|
+
export function validateConfig(config) {
|
|
6
|
+
return demoReelConfigSchema.parse(config);
|
|
7
|
+
}
|
|
8
|
+
export { demoReelConfigSchema };
|
|
9
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,oBAAoB,EAAuB,MAAM,cAAc,CAAC;AAEzE,MAAM,UAAU,YAAY,CAAC,MAAsB;IACjD,OAAO,MAAM,CAAC;AAChB,CAAC;AAED,MAAM,UAAU,cAAc,CAAC,MAAe;IAC5C,OAAO,oBAAoB,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC;AAC5C,CAAC;AAED,OAAO,EAAE,oBAAoB,EAAE,CAAC"}
|
package/dist/runner.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"runner.d.ts","sourceRoot":"","sources":["../src/runner.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAW,IAAI,EAAE,MAAM,YAAY,CAAC;AAChD,OAAO,KAAK,EAEV,cAAc,EAMf,MAAM,cAAc,CAAC;AAooBtB,eAAO,MAAM,OAAO,GAAU,MAAM,IAAI,EAAE,QAAQ,cAAc,kBAsB/D,CAAC"}
|