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.
Files changed (3) hide show
  1. package/README.md +68 -10
  2. package/dist/index.js +48 -48
  3. 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 building, testing, and managing SkyStream (Gen 2) plugin repositories.
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
- ### Build for Distribution
26
+ ### Deploy for Distribution
27
27
 
28
28
  ```bash
29
- skystream build -u https://my-cdn.com/repo
29
+ skystream deploy -u https://my-cdn.com/repo
30
30
  ```
31
31
 
32
32
  ## 🛠 Commands
33
33
 
34
- | Command | Description |
35
- | --- | --- |
36
- | `init` | Initialize a Sky Gen 2 Repository project |
37
- | `add` | Add a new plugin to the repository |
38
- | `validate` | Validate all plugins in the repo |
39
- | `test` | Test a specific plugin in a mock runtime |
40
- | `build` | Bundle plugins and generate `repo.json` |
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.1');
12
+ .version('1.2.4');
13
13
  // Schemas
14
14
  const pluginSchema = z.object({
15
- id: z.string().min(5).regex(/^[a-z0-9._-]+$/),
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
- id: z.string().min(3).regex(/^[a-z0-9._-]+$/),
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: "https://site.com/movie",
59
- posterUrl: "https://site.com/poster.jpg",
58
+ url: \`\${manifest.baseUrl}/movie\`,
59
+ posterUrl: \`\${manifest.baseUrl}/poster.jpg\`,
60
60
  type: "movie", // Valid types: movie, series, anime, livestream
61
- bannerUrl: "https://site.com/banner.jpg", // (optional)
61
+ bannerUrl: \`\${manifest.baseUrl}/banner.jpg\`, // (optional)
62
62
  description: "Plot summary here...", // (optional)
63
- headers: { "Referer": "https://site.com" } // (optional)
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
- new MultimediaItem({
85
- title: "Example Movie",
86
- url: "https://site.com/movie",
87
- posterUrl: "https://site.com/poster.jpg",
88
- type: "movie", // Valid types: movie, series, anime, livestream
89
- bannerUrl: "https://site.com/banner.jpg", // (optional)
90
- description: "Plot summary here...", // (optional)
91
- headers: { "Referer": "https://site.com" } // (optional)
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: "https://site.com/poster.jpg",
113
+ posterUrl: \`\${manifest.baseUrl}/poster.jpg\`,
114
114
  type: "movie", // Valid types: movie, series, anime, livestream
115
- bannerUrl: "https://site.com/banner.jpg", // (optional)
115
+ bannerUrl: \`\${manifest.baseUrl}/banner.jpg\`, // (optional)
116
116
  description: "This is a detailed description of the movie.", // (optional)
117
- headers: { "Referer": "https://site.com" }, // (optional)
117
+ headers: { "Referer": \`\${manifest.baseUrl}\` }, // (optional)
118
118
  episodes: [
119
119
  new Episode({
120
120
  name: "Episode 1",
121
- url: "https://site.com/watch/1",
121
+ url: \`\${manifest.baseUrl}/watch/1\`,
122
122
  season: 1, // (optional)
123
123
  episode: 1, // (optional)
124
124
  description: "Episode summary...", // (optional)
125
- posterUrl: "https://site.com/ep-poster.jpg", // (optional)
126
- headers: { "Referer": "https://site.com" } // (optional)
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": "https://site.com" }, // (optional)
150
+ headers: { "Referer": \`\${manifest.baseUrl}\` }, // (optional)
151
151
  subtitles: [
152
- { url: "https://site.com/sub.vtt", label: "English", lang: "en" } // (optional)
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: Build Repository
231
+ - name: Deploy Repository
232
232
  run: |
233
233
  npm install -g skystream-cli
234
- skystream build -u https://raw.githubusercontent.com/\${{ github.repository }}
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 build [skip ci]" || echo "No changes to commit"
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: build command now handles dynamic generation in dist/
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
- id: options.packageName,
265
+ packageName: options.packageName,
266
266
  description: options.description,
267
267
  manifestVersion: 1,
268
268
  pluginLists: [
269
- `REPLACE_WITH_BASE_URL/plugins.json` // Placeholder for user to update
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
- id: `${packageName}.${pluginSlug}`,
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 ID: ${pluginManifest.id}`);
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.id;
320
+ const packageName = repo.packageName;
321
321
  const pluginManifest = {
322
- id: `${packageName}.${pluginSlug}`,
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} (ID: ${pluginManifest.id})`);
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.id}: Manifest OK`);
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.id}: Logic OK`);
352
+ console.log(`✓ ${manifest.packageName}: Logic OK`);
353
353
  }
354
354
  else {
355
- console.warn(`! ${manifest.id}: Missing exports`);
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.id} -> ${options.function} ---`);
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('build')
420
- .description('Build all plugins and repository index')
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 bundleName = `${manifest.id}.sky`;
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.id}`);
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(`\nBuild Complete. Assets generated in dist/`);
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
  });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "skystream-cli",
3
- "version": "1.1.0",
3
+ "version": "1.2.4",
4
4
  "type": "module",
5
5
  "description": "SkyStream Plugin Development Kit & Repository Manager",
6
6
  "main": "dist/index.js",