skystream-cli 1.1.0 → 1.2.4
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 +68 -10
- package/dist/index.js +48 -48
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# SkyStream CLI
|
|
2
2
|
|
|
3
|
-
The official command-line toolkit for
|
|
3
|
+
The official command-line toolkit for deploying, testing, and managing SkyStream (Gen 2) plugin repositories.
|
|
4
4
|
|
|
5
5
|
## 🚀 Quick Start
|
|
6
6
|
|
|
@@ -23,21 +23,79 @@ cd my-universe
|
|
|
23
23
|
skystream add "New Provider"
|
|
24
24
|
```
|
|
25
25
|
|
|
26
|
-
###
|
|
26
|
+
### Deploy for Distribution
|
|
27
27
|
|
|
28
28
|
```bash
|
|
29
|
-
skystream
|
|
29
|
+
skystream deploy -u https://my-cdn.com/repo
|
|
30
30
|
```
|
|
31
31
|
|
|
32
32
|
## 🛠 Commands
|
|
33
33
|
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
34
|
+
### `init`
|
|
35
|
+
Initialize a new Sky Gen 2 Repository project.
|
|
36
|
+
|
|
37
|
+
**Usage:**
|
|
38
|
+
```bash
|
|
39
|
+
skystream init <project-name> --package-name <id> --plugin-name <name> [options]
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
**Options:**
|
|
43
|
+
- `-p, --package-name <id>`: **(Required)** Unique Repository ID (e.g., `com.dev.stars`).
|
|
44
|
+
- `-n, --plugin-name <name>`: **(Required)** First plugin name (e.g., `YTS`).
|
|
45
|
+
- `-d, --description <desc>`: Repository description (Default: `SkyStream plugins repository`).
|
|
46
|
+
- `-a, --author <author>`: Author name (Default: `Developer`).
|
|
47
|
+
|
|
48
|
+
---
|
|
49
|
+
|
|
50
|
+
### `add`
|
|
51
|
+
Add a new Sky Gen 2 plugin to an existing repository.
|
|
52
|
+
|
|
53
|
+
**Usage:**
|
|
54
|
+
```bash
|
|
55
|
+
skystream add <plugin-name> [options]
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
**Options:**
|
|
59
|
+
- `-d, --description <desc>`: Plugin description.
|
|
60
|
+
- `-a, --author <author>`: Author name.
|
|
61
|
+
|
|
62
|
+
---
|
|
63
|
+
|
|
64
|
+
### `validate`
|
|
65
|
+
Validate all plugins in the repository (manifests and logic exports).
|
|
66
|
+
|
|
67
|
+
**Usage:**
|
|
68
|
+
```bash
|
|
69
|
+
skystream validate
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
---
|
|
73
|
+
|
|
74
|
+
### `test`
|
|
75
|
+
Test a specific plugin in a mock runtime.
|
|
76
|
+
|
|
77
|
+
**Usage:**
|
|
78
|
+
```bash
|
|
79
|
+
skystream test [options]
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
**Options:**
|
|
83
|
+
- `-p, --path <path>`: Path to plugin folder (Default: `.`).
|
|
84
|
+
- `-f, --function <name>`: Function to test (Default: `getHome`).
|
|
85
|
+
- `-q, --query <query>`: Query string for functions like `search`.
|
|
86
|
+
|
|
87
|
+
---
|
|
88
|
+
|
|
89
|
+
### `deploy`
|
|
90
|
+
Bundle all plugins and generate the `repo.json` index.
|
|
91
|
+
|
|
92
|
+
**Usage:**
|
|
93
|
+
```bash
|
|
94
|
+
skystream deploy --url <url>
|
|
95
|
+
```
|
|
96
|
+
|
|
97
|
+
**Options:**
|
|
98
|
+
- `-u, --url <url>`: **(Required)** Base hosting URL where the `.sky` files will be served (e.g., `https://raw.githubusercontent.com/USER/REPO/main`).
|
|
41
99
|
|
|
42
100
|
## 📖 Learn More
|
|
43
101
|
Visit the [SkyStream Repository Specification](https://github.com/akashdh11/skystream) for more details.
|
package/dist/index.js
CHANGED
|
@@ -9,21 +9,21 @@ const program = new Command();
|
|
|
9
9
|
program
|
|
10
10
|
.name('skystream')
|
|
11
11
|
.description('SkyStream Plugin Development Kit CLI (Sky Gen 2)')
|
|
12
|
-
.version('1.2.
|
|
12
|
+
.version('1.2.4');
|
|
13
13
|
// Schemas
|
|
14
14
|
const pluginSchema = z.object({
|
|
15
|
-
|
|
15
|
+
packageName: z.string().min(5).regex(/^[a-z0-9._-]+$/),
|
|
16
16
|
name: z.string().min(1),
|
|
17
|
-
internalName: z.string().min(1).regex(/^[A-Z0-9]+$/),
|
|
18
17
|
version: z.number().int().positive(),
|
|
19
18
|
description: z.string().min(1),
|
|
19
|
+
baseUrl: z.string().url(),
|
|
20
20
|
authors: z.array(z.string()).min(1),
|
|
21
21
|
languages: z.array(z.string()).min(1),
|
|
22
22
|
categories: z.array(z.string()).min(1),
|
|
23
23
|
});
|
|
24
24
|
const repoSchema = z.object({
|
|
25
25
|
name: z.string().min(1),
|
|
26
|
-
|
|
26
|
+
packageName: z.string().min(3).regex(/^[a-z0-9._-]+$/),
|
|
27
27
|
description: z.string().min(1),
|
|
28
28
|
manifestVersion: z.number().int().positive(),
|
|
29
29
|
pluginLists: z.array(z.string().url()),
|
|
@@ -55,12 +55,12 @@ const JS_TEMPLATE = `(function() {
|
|
|
55
55
|
"Trending": [
|
|
56
56
|
new MultimediaItem({
|
|
57
57
|
title: "Example Movie",
|
|
58
|
-
url:
|
|
59
|
-
posterUrl:
|
|
58
|
+
url: \`\${manifest.baseUrl}/movie\`,
|
|
59
|
+
posterUrl: \`\${manifest.baseUrl}/poster.jpg\`,
|
|
60
60
|
type: "movie", // Valid types: movie, series, anime, livestream
|
|
61
|
-
bannerUrl:
|
|
61
|
+
bannerUrl: \`\${manifest.baseUrl}/banner.jpg\`, // (optional)
|
|
62
62
|
description: "Plot summary here...", // (optional)
|
|
63
|
-
headers: { "Referer":
|
|
63
|
+
headers: { "Referer": \`\${manifest.baseUrl}\` } // (optional)
|
|
64
64
|
})
|
|
65
65
|
]
|
|
66
66
|
}
|
|
@@ -81,15 +81,15 @@ const JS_TEMPLATE = `(function() {
|
|
|
81
81
|
cb({
|
|
82
82
|
success: true,
|
|
83
83
|
data: [
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
84
|
+
new MultimediaItem({
|
|
85
|
+
title: "Example Movie",
|
|
86
|
+
url: \`\${manifest.baseUrl}/movie\`,
|
|
87
|
+
posterUrl: \`\${manifest.baseUrl}/poster.jpg\`,
|
|
88
|
+
type: "movie", // Valid types: movie, series, anime, livestream
|
|
89
|
+
bannerUrl: \`\${manifest.baseUrl}/banner.jpg\`, // (optional)
|
|
90
|
+
description: "Plot summary here...", // (optional)
|
|
91
|
+
headers: { "Referer": \`\${manifest.baseUrl}\` } // (optional)
|
|
92
|
+
})
|
|
93
93
|
]
|
|
94
94
|
});
|
|
95
95
|
} catch (e) {
|
|
@@ -110,20 +110,20 @@ const JS_TEMPLATE = `(function() {
|
|
|
110
110
|
data: new MultimediaItem({
|
|
111
111
|
title: "Example Movie Full Details",
|
|
112
112
|
url: url,
|
|
113
|
-
posterUrl:
|
|
113
|
+
posterUrl: \`\${manifest.baseUrl}/poster.jpg\`,
|
|
114
114
|
type: "movie", // Valid types: movie, series, anime, livestream
|
|
115
|
-
bannerUrl:
|
|
115
|
+
bannerUrl: \`\${manifest.baseUrl}/banner.jpg\`, // (optional)
|
|
116
116
|
description: "This is a detailed description of the movie.", // (optional)
|
|
117
|
-
headers: { "Referer":
|
|
117
|
+
headers: { "Referer": \`\${manifest.baseUrl}\` }, // (optional)
|
|
118
118
|
episodes: [
|
|
119
119
|
new Episode({
|
|
120
120
|
name: "Episode 1",
|
|
121
|
-
url:
|
|
121
|
+
url: \`\${manifest.baseUrl}/watch/1\`,
|
|
122
122
|
season: 1, // (optional)
|
|
123
123
|
episode: 1, // (optional)
|
|
124
124
|
description: "Episode summary...", // (optional)
|
|
125
|
-
posterUrl:
|
|
126
|
-
headers: { "Referer":
|
|
125
|
+
posterUrl: \`\${manifest.baseUrl}/ep-poster.jpg\`, // (optional)
|
|
126
|
+
headers: { "Referer": \`\${manifest.baseUrl}\` } // (optional)
|
|
127
127
|
})
|
|
128
128
|
]
|
|
129
129
|
})
|
|
@@ -147,9 +147,9 @@ const JS_TEMPLATE = `(function() {
|
|
|
147
147
|
new StreamResult({
|
|
148
148
|
url: "https://test-streams.mux.dev/x36xhzz/x36xhzz.m3u8",
|
|
149
149
|
quality: "1080p", // (optional)
|
|
150
|
-
headers: { "Referer":
|
|
150
|
+
headers: { "Referer": \`\${manifest.baseUrl}\` }, // (optional)
|
|
151
151
|
subtitles: [
|
|
152
|
-
{ url:
|
|
152
|
+
{ url: \`\${manifest.baseUrl}/sub.vtt\`, label: "English", lang: "en" } // (optional)
|
|
153
153
|
],
|
|
154
154
|
drmKid: "kid_value", // (optional)
|
|
155
155
|
drmKey: "key_value", // (optional)
|
|
@@ -228,21 +228,21 @@ jobs:
|
|
|
228
228
|
with:
|
|
229
229
|
node-version: '20'
|
|
230
230
|
|
|
231
|
-
- name:
|
|
231
|
+
- name: Deploy Repository
|
|
232
232
|
run: |
|
|
233
233
|
npm install -g skystream-cli
|
|
234
|
-
skystream
|
|
234
|
+
skystream deploy -u https://raw.githubusercontent.com/\${{ github.repository }}/main
|
|
235
235
|
|
|
236
236
|
- name: Commit and Push changes
|
|
237
237
|
run: |
|
|
238
238
|
git config --global user.name "github-actions[bot]"
|
|
239
239
|
git config --global user.email "github-actions[bot]@users.noreply.github.com"
|
|
240
240
|
git add .
|
|
241
|
-
git commit -m "chore: automated
|
|
241
|
+
git commit -m "chore: automated deploy [skip ci]" || echo "No changes to commit"
|
|
242
242
|
git push
|
|
243
243
|
`;
|
|
244
244
|
async function updatePluginsJson(rootDir) {
|
|
245
|
-
// Logic removed:
|
|
245
|
+
// Logic removed: deploy command now handles dynamic generation in dist/
|
|
246
246
|
}
|
|
247
247
|
program.command('init')
|
|
248
248
|
.description('Initialize a Sky Gen 2 Repository project')
|
|
@@ -262,11 +262,11 @@ program.command('init')
|
|
|
262
262
|
const projectSlug = projectName.toLowerCase().replace(/\s+/g, '-').replace(/[^a-z0-9-]/g, '');
|
|
263
263
|
const repo = {
|
|
264
264
|
name: projectName,
|
|
265
|
-
|
|
265
|
+
packageName: options.packageName,
|
|
266
266
|
description: options.description,
|
|
267
267
|
manifestVersion: 1,
|
|
268
268
|
pluginLists: [
|
|
269
|
-
`
|
|
269
|
+
`https://raw.githubusercontent.com/USER_NAME/REPO_NAME/main/dist/plugins.json`
|
|
270
270
|
]
|
|
271
271
|
};
|
|
272
272
|
await fs.writeJson(path.join(rootDir, 'repo.json'), repo, { spaces: 2 });
|
|
@@ -282,10 +282,10 @@ program.command('init')
|
|
|
282
282
|
const pluginDir = path.join(rootDir, pluginSlug);
|
|
283
283
|
await fs.ensureDir(pluginDir);
|
|
284
284
|
const pluginManifest = {
|
|
285
|
-
|
|
285
|
+
packageName: `${packageName}.${pluginSlug}`,
|
|
286
286
|
name: pluginName,
|
|
287
|
-
internalName: pluginName.toUpperCase().replace(/\s+/g, ''),
|
|
288
287
|
version: 1,
|
|
288
|
+
baseUrl: "https://example.com",
|
|
289
289
|
description: `${pluginName} plugin (Sky Gen 2)`,
|
|
290
290
|
authors: [options.author],
|
|
291
291
|
languages: ["en"],
|
|
@@ -295,7 +295,7 @@ program.command('init')
|
|
|
295
295
|
await fs.writeFile(path.join(pluginDir, 'plugin.js'), JS_TEMPLATE);
|
|
296
296
|
console.log('\nSky Gen 2 Repository successfully initialized!');
|
|
297
297
|
console.log(`Project Directory: ${rootDir}`);
|
|
298
|
-
console.log(`First Plugin
|
|
298
|
+
console.log(`First Plugin Package Name: ${pluginManifest.packageName}`);
|
|
299
299
|
});
|
|
300
300
|
program.command('add')
|
|
301
301
|
.description('Add a new Sky Gen 2 plugin to the repository')
|
|
@@ -317,12 +317,12 @@ program.command('add')
|
|
|
317
317
|
process.exit(1);
|
|
318
318
|
}
|
|
319
319
|
// Guess package-name from repo id
|
|
320
|
-
const packageName = repo.
|
|
320
|
+
const packageName = repo.packageName;
|
|
321
321
|
const pluginManifest = {
|
|
322
|
-
|
|
322
|
+
packageName: `${packageName}.${pluginSlug}`,
|
|
323
323
|
name: pluginName,
|
|
324
|
-
internalName: pluginName.toUpperCase().replace(/\s+/g, ''),
|
|
325
324
|
version: 1,
|
|
325
|
+
baseUrl: "https://example.com",
|
|
326
326
|
description: options.description || `${pluginName} plugin for ${repo.name}`,
|
|
327
327
|
authors: [options.author || repo.author || "Developer"],
|
|
328
328
|
languages: ["en"],
|
|
@@ -331,7 +331,7 @@ program.command('add')
|
|
|
331
331
|
await fs.ensureDir(pluginDir);
|
|
332
332
|
await fs.writeJson(path.join(pluginDir, 'plugin.json'), pluginManifest, { spaces: 2 });
|
|
333
333
|
await fs.writeFile(path.join(pluginDir, 'plugin.js'), JS_TEMPLATE);
|
|
334
|
-
console.log(`✓ Added Plugin: ${pluginName} (
|
|
334
|
+
console.log(`✓ Added Plugin: ${pluginName} (Package: ${pluginManifest.packageName})`);
|
|
335
335
|
});
|
|
336
336
|
program.command('validate')
|
|
337
337
|
.description('Validate all plugins in the repo')
|
|
@@ -346,13 +346,13 @@ program.command('validate')
|
|
|
346
346
|
try {
|
|
347
347
|
const manifest = await fs.readJson(manifestPath);
|
|
348
348
|
pluginSchema.parse(manifest);
|
|
349
|
-
console.log(`✓ ${manifest.
|
|
349
|
+
console.log(`✓ ${manifest.packageName}: Manifest OK`);
|
|
350
350
|
const js = await fs.readFile(path.join(itemPath, 'plugin.js'), 'utf8');
|
|
351
351
|
if (js.includes('globalThis.getHome = getHome')) {
|
|
352
|
-
console.log(`✓ ${manifest.
|
|
352
|
+
console.log(`✓ ${manifest.packageName}: Logic OK`);
|
|
353
353
|
}
|
|
354
354
|
else {
|
|
355
|
-
console.warn(`! ${manifest.
|
|
355
|
+
console.warn(`! ${manifest.packageName}: Missing exports`);
|
|
356
356
|
}
|
|
357
357
|
count++;
|
|
358
358
|
}
|
|
@@ -377,7 +377,7 @@ program.command('test')
|
|
|
377
377
|
const jsPath = path.join(pluginDir, 'plugin.js');
|
|
378
378
|
const manifest = await fs.readJson(manifestPath);
|
|
379
379
|
const jsContent = await fs.readFile(jsPath, 'utf8');
|
|
380
|
-
console.log(`\n--- Testing ${manifest.
|
|
380
|
+
console.log(`\n--- Testing ${manifest.packageName} -> ${options.function} ---`);
|
|
381
381
|
const context = {
|
|
382
382
|
manifest,
|
|
383
383
|
console: { log: (...args) => console.log(' [JS]:', ...args), error: (...args) => console.error(' [JS ERR]:', ...args) },
|
|
@@ -416,8 +416,8 @@ program.command('test')
|
|
|
416
416
|
else
|
|
417
417
|
await fn(options.query, callback);
|
|
418
418
|
});
|
|
419
|
-
program.command('
|
|
420
|
-
.description('
|
|
419
|
+
program.command('deploy')
|
|
420
|
+
.description('Deploy all plugins and repository index')
|
|
421
421
|
.requiredOption('-u, --url <url>', 'Base hosting URL for .sky files')
|
|
422
422
|
.action(async (options) => {
|
|
423
423
|
const rootDir = process.cwd();
|
|
@@ -438,7 +438,8 @@ program.command('build')
|
|
|
438
438
|
const mPath = path.join(itemPath, 'plugin.json');
|
|
439
439
|
if (await fs.pathExists(mPath) && (await fs.stat(itemPath)).isDirectory()) {
|
|
440
440
|
const manifest = await fs.readJson(mPath);
|
|
441
|
-
const
|
|
441
|
+
const packageName = manifest.packageName || manifest.id || item;
|
|
442
|
+
const bundleName = `${packageName}.sky`;
|
|
442
443
|
const outPath = path.join(distDir, bundleName);
|
|
443
444
|
const arch = archiver('zip', { zlib: { level: 9 } });
|
|
444
445
|
arch.pipe(fs.createWriteStream(outPath));
|
|
@@ -446,12 +447,11 @@ program.command('build')
|
|
|
446
447
|
arch.file(path.join(itemPath, 'plugin.js'), { name: 'plugin.js' });
|
|
447
448
|
await arch.finalize();
|
|
448
449
|
catalog.push({ ...manifest, url: `${distUrl}/${bundleName}` });
|
|
449
|
-
console.log(`✓ Bundled ${manifest.
|
|
450
|
+
console.log(`✓ Bundled ${manifest.packageName}`);
|
|
450
451
|
}
|
|
451
452
|
}
|
|
452
453
|
const finalRepo = {
|
|
453
454
|
...repo,
|
|
454
|
-
updatedAt: new Date().toISOString(),
|
|
455
455
|
pluginLists: [`${distUrl}/plugins.json`]
|
|
456
456
|
};
|
|
457
457
|
await fs.writeJson(repoPath, finalRepo, { spaces: 2 });
|
|
@@ -468,7 +468,7 @@ program.command('build')
|
|
|
468
468
|
console.log(`✓ Updated README.md with live URL`);
|
|
469
469
|
}
|
|
470
470
|
}
|
|
471
|
-
console.log(`\
|
|
471
|
+
console.log(`\nDeployment Complete. Assets generated in dist/`);
|
|
472
472
|
console.log(`\nYour Repo Link for the app:`);
|
|
473
473
|
console.log(`> ${baseRaw}/repo.json`);
|
|
474
474
|
});
|