skystream-cli 1.0.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/README.md +43 -0
- package/dist/index.d.ts +3 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +407 -0
- package/dist/index.js.map +1 -0
- package/package.json +46 -0
package/README.md
ADDED
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
# SkyStream CLI
|
|
2
|
+
|
|
3
|
+
The official command-line toolkit for building, testing, and managing SkyStream (Gen 2) plugin repositories.
|
|
4
|
+
|
|
5
|
+
## 🚀 Quick Start
|
|
6
|
+
|
|
7
|
+
### Installation
|
|
8
|
+
|
|
9
|
+
```bash
|
|
10
|
+
npm install -g skystream-cli
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
### Initialize a new Repository
|
|
14
|
+
|
|
15
|
+
```bash
|
|
16
|
+
skystream init "My Universe" --package-name com.example.repo --plugin-name "Provider 1"
|
|
17
|
+
```
|
|
18
|
+
|
|
19
|
+
### Add a new Plugin
|
|
20
|
+
|
|
21
|
+
```bash
|
|
22
|
+
cd my-universe
|
|
23
|
+
skystream add "New Provider"
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
### Build for Distribution
|
|
27
|
+
|
|
28
|
+
```bash
|
|
29
|
+
skystream build -u https://my-cdn.com/repo
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
## 🛠Commands
|
|
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` |
|
|
41
|
+
|
|
42
|
+
## 📖 Learn More
|
|
43
|
+
Visit the [SkyStream Repository Specification](https://github.com/akashdh11/skystream) for more details.
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":""}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,407 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import { Command } from 'commander';
|
|
3
|
+
import * as path from 'path';
|
|
4
|
+
import fs from 'fs-extra';
|
|
5
|
+
import { z } from 'zod';
|
|
6
|
+
import archiver from 'archiver';
|
|
7
|
+
import axios from 'axios';
|
|
8
|
+
const program = new Command();
|
|
9
|
+
program
|
|
10
|
+
.name('skystream')
|
|
11
|
+
.description('SkyStream Plugin Development Kit CLI (Sky Gen 2)')
|
|
12
|
+
.version('1.2.1');
|
|
13
|
+
// Schemas
|
|
14
|
+
const pluginSchema = z.object({
|
|
15
|
+
id: z.string().min(5).regex(/^[a-z0-9._-]+$/),
|
|
16
|
+
name: z.string().min(1),
|
|
17
|
+
internalName: z.string().min(1).regex(/^[A-Z0-9]+$/),
|
|
18
|
+
version: z.number().int().positive(),
|
|
19
|
+
description: z.string().min(1),
|
|
20
|
+
authors: z.array(z.string()).min(1),
|
|
21
|
+
languages: z.array(z.string()).min(1),
|
|
22
|
+
categories: z.array(z.string()).min(1),
|
|
23
|
+
});
|
|
24
|
+
const repoSchema = z.object({
|
|
25
|
+
name: z.string().min(1),
|
|
26
|
+
id: z.string().min(3).regex(/^[a-z0-9._-]+$/),
|
|
27
|
+
description: z.string().min(1),
|
|
28
|
+
manifestVersion: z.number().int().positive(),
|
|
29
|
+
pluginLists: z.array(z.string().url()),
|
|
30
|
+
});
|
|
31
|
+
const JS_TEMPLATE = `(function() {
|
|
32
|
+
/**
|
|
33
|
+
* @typedef {Object} Response
|
|
34
|
+
* @property {boolean} success
|
|
35
|
+
* @property {any} [data]
|
|
36
|
+
* @property {string} [errorCode]
|
|
37
|
+
* @property {string} [message]
|
|
38
|
+
*/
|
|
39
|
+
|
|
40
|
+
/**
|
|
41
|
+
* @type {import('@skystream/sdk').Manifest}
|
|
42
|
+
*/
|
|
43
|
+
const pluginManifest = manifest;
|
|
44
|
+
|
|
45
|
+
/**
|
|
46
|
+
* Loads the home screen categories.
|
|
47
|
+
* @param {(res: Response) => void} cb
|
|
48
|
+
*/
|
|
49
|
+
async function getHome(cb) {
|
|
50
|
+
try {
|
|
51
|
+
// Example data structure: { "Trending": [mediaItem1, ...] }
|
|
52
|
+
cb({ success: true, data: {} });
|
|
53
|
+
} catch (e) {
|
|
54
|
+
cb({ success: false, errorCode: "PARSE_ERROR", message: (e instanceof Error) ? e.message : String(e) });
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
/**
|
|
59
|
+
* Searches for media items.
|
|
60
|
+
* @param {string} query
|
|
61
|
+
* @param {(res: Response) => void} cb
|
|
62
|
+
*/
|
|
63
|
+
async function search(query, cb) {
|
|
64
|
+
try {
|
|
65
|
+
cb({ success: true, data: [] });
|
|
66
|
+
} catch (e) {
|
|
67
|
+
cb({ success: false, errorCode: "SEARCH_ERROR", message: (e instanceof Error) ? e.message : String(e) });
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
/**
|
|
72
|
+
* Loads details for a specific media item.
|
|
73
|
+
* @param {string} url
|
|
74
|
+
* @param {(res: Response) => void} cb
|
|
75
|
+
*/
|
|
76
|
+
function load(url, cb) {
|
|
77
|
+
try {
|
|
78
|
+
cb({ success: true, data: { title: "Item", url, isFolder: false, episodes: [] } });
|
|
79
|
+
} catch (e) {
|
|
80
|
+
cb({ success: false, errorCode: "LOAD_ERROR", message: (e instanceof Error) ? e.message : String(e) });
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
/**
|
|
85
|
+
* Resolves streams for a specific media item or episode.
|
|
86
|
+
* @param {string} url
|
|
87
|
+
* @param {(res: Response) => void} cb
|
|
88
|
+
*/
|
|
89
|
+
async function loadStreams(url, cb) {
|
|
90
|
+
try {
|
|
91
|
+
cb({ success: true, data: [] });
|
|
92
|
+
} catch (e) {
|
|
93
|
+
cb({ success: false, errorCode: "STREAM_ERROR", message: (e instanceof Error) ? e.message : String(e) });
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
// Export to global scope for namespaced IIFE capture
|
|
98
|
+
globalThis.getHome = getHome;
|
|
99
|
+
globalThis.search = search;
|
|
100
|
+
globalThis.load = load;
|
|
101
|
+
globalThis.loadStreams = loadStreams;
|
|
102
|
+
})();
|
|
103
|
+
`;
|
|
104
|
+
const README_TEMPLATE = (name, slug) => `# 🌌 ${name}
|
|
105
|
+
${name} is an extension repo for [SkyStream](https://github.com/akashdh11/skystream). Follow the guide below to get started and set up your providers.
|
|
106
|
+
|
|
107
|
+
## 🚀 Getting Started
|
|
108
|
+
|
|
109
|
+
### 1. Installation
|
|
110
|
+
To install SkyStream on your device, follow these steps:
|
|
111
|
+
|
|
112
|
+
* **Download:** Navigate to the [SkyStream releases page](https://github.com/akashdh11/skystream/releases/) and download the latest release for your platform.
|
|
113
|
+
* **Install:** Open the downloaded file and follow your system's installation prompts.
|
|
114
|
+
* **Launch:** Once installed, open the **SkyStream** app.
|
|
115
|
+
|
|
116
|
+
---
|
|
117
|
+
|
|
118
|
+
## 🛠Setting Up Extensions
|
|
119
|
+
SkyStream uses a repository system to fetch plugins. Follow these steps to activate the app's content:
|
|
120
|
+
|
|
121
|
+
1. Open the app and navigate to **Settings**.
|
|
122
|
+
2. Select the **Manage Extensions** menu.
|
|
123
|
+
3. Click on the **Add Repository** button.
|
|
124
|
+
4. Enter the following Repository URL:
|
|
125
|
+
> **Repository URL:** \`https://raw.githubusercontent.com/USER_NAME/REPO_NAME/main/repo.json\`
|
|
126
|
+
5. Tap **Add**.
|
|
127
|
+
6. Wait for the list to populate, then **download** the desired plugins.
|
|
128
|
+
|
|
129
|
+
---
|
|
130
|
+
|
|
131
|
+
## 📺 Using the App
|
|
132
|
+
After you have installed your plugins, you need to toggle the providers to see content on your dashboard:
|
|
133
|
+
|
|
134
|
+
1. Return to the **Home Screen**.
|
|
135
|
+
2. Change **Provider** (bottom right floating action button).
|
|
136
|
+
3. Switch to your newly installed providers to begin browsing.
|
|
137
|
+
`;
|
|
138
|
+
const GITHUB_ACTION_TEMPLATE = `name: Build and Deploy Repository
|
|
139
|
+
|
|
140
|
+
on:
|
|
141
|
+
push:
|
|
142
|
+
branches: [ main ]
|
|
143
|
+
paths-ignore:
|
|
144
|
+
- 'dist/**'
|
|
145
|
+
- 'README.md'
|
|
146
|
+
|
|
147
|
+
permissions:
|
|
148
|
+
contents: write
|
|
149
|
+
|
|
150
|
+
jobs:
|
|
151
|
+
build:
|
|
152
|
+
runs-on: ubuntu-latest
|
|
153
|
+
steps:
|
|
154
|
+
- uses: actions/checkout@v4
|
|
155
|
+
with:
|
|
156
|
+
fetch-depth: 0
|
|
157
|
+
|
|
158
|
+
- name: Setup Node.js
|
|
159
|
+
uses: actions/setup-node@v4
|
|
160
|
+
with:
|
|
161
|
+
node-version: '20'
|
|
162
|
+
|
|
163
|
+
- name: Build Repository
|
|
164
|
+
run: |
|
|
165
|
+
npm install -g skystream-cli
|
|
166
|
+
skystream build -u https://raw.githubusercontent.com/\${{ github.repository }}
|
|
167
|
+
|
|
168
|
+
- name: Commit and Push changes
|
|
169
|
+
run: |
|
|
170
|
+
git config --global user.name "github-actions[bot]"
|
|
171
|
+
git config --global user.email "github-actions[bot]@users.noreply.github.com"
|
|
172
|
+
git add .
|
|
173
|
+
git commit -m "chore: automated build [skip ci]" || echo "No changes to commit"
|
|
174
|
+
git push
|
|
175
|
+
`;
|
|
176
|
+
async function updatePluginsJson(rootDir) {
|
|
177
|
+
// Logic removed: build command now handles dynamic generation in dist/
|
|
178
|
+
}
|
|
179
|
+
program.command('init')
|
|
180
|
+
.description('Initialize a Sky Gen 2 Repository project')
|
|
181
|
+
.argument('<project-name>', 'Display name of the project')
|
|
182
|
+
.requiredOption('-p, --package-name <id>', 'Unique Repository ID (e.g. dev.akash.stars)')
|
|
183
|
+
.requiredOption('-n, --plugin-name <name>', 'First plugin name (e.g. "AYNA 2")')
|
|
184
|
+
.option('-d, --description <desc>', 'Repository description', 'SkyStream plugins repository')
|
|
185
|
+
.option('-a, --author <author>', 'Author name', 'Developer')
|
|
186
|
+
.action(async (projectName, options) => {
|
|
187
|
+
const rootDir = path.resolve(projectName.toLowerCase().replace(/\s+/g, '-'));
|
|
188
|
+
if (await fs.pathExists(rootDir)) {
|
|
189
|
+
console.error(`Error: Directory ${rootDir} already exists`);
|
|
190
|
+
process.exit(1);
|
|
191
|
+
}
|
|
192
|
+
await fs.ensureDir(rootDir);
|
|
193
|
+
console.log(`Initializing Repository: ${projectName} (${options.packageName})`);
|
|
194
|
+
const projectSlug = projectName.toLowerCase().replace(/\s+/g, '-').replace(/[^a-z0-9-]/g, '');
|
|
195
|
+
const repo = {
|
|
196
|
+
name: projectName,
|
|
197
|
+
id: options.packageName,
|
|
198
|
+
description: options.description,
|
|
199
|
+
manifestVersion: 1,
|
|
200
|
+
pluginLists: [
|
|
201
|
+
`REPLACE_WITH_BASE_URL/plugins.json` // Placeholder for user to update
|
|
202
|
+
]
|
|
203
|
+
};
|
|
204
|
+
await fs.writeJson(path.join(rootDir, 'repo.json'), repo, { spaces: 2 });
|
|
205
|
+
await fs.writeFile(path.join(rootDir, 'README.md'), README_TEMPLATE(projectName, projectSlug));
|
|
206
|
+
// GitHub Action
|
|
207
|
+
const githubWorkflowsDir = path.join(rootDir, '.github', 'workflows');
|
|
208
|
+
await fs.ensureDir(githubWorkflowsDir);
|
|
209
|
+
await fs.writeFile(path.join(githubWorkflowsDir, 'build.yml'), GITHUB_ACTION_TEMPLATE);
|
|
210
|
+
// First Plugin
|
|
211
|
+
const pluginName = options.pluginName;
|
|
212
|
+
const packageName = options.packageName;
|
|
213
|
+
const pluginSlug = pluginName.toLowerCase().replace(/\s+/g, '').replace(/[^a-z0-9]/g, '');
|
|
214
|
+
const pluginDir = path.join(rootDir, pluginSlug);
|
|
215
|
+
await fs.ensureDir(pluginDir);
|
|
216
|
+
const pluginManifest = {
|
|
217
|
+
id: `${packageName}.${pluginSlug}`,
|
|
218
|
+
name: pluginName,
|
|
219
|
+
internalName: pluginName.toUpperCase().replace(/\s+/g, ''),
|
|
220
|
+
version: 1,
|
|
221
|
+
description: `${pluginName} plugin (Sky Gen 2)`,
|
|
222
|
+
authors: [options.author],
|
|
223
|
+
languages: ["en"],
|
|
224
|
+
categories: ["Others"]
|
|
225
|
+
};
|
|
226
|
+
await fs.writeJson(path.join(pluginDir, 'plugin.json'), pluginManifest, { spaces: 2 });
|
|
227
|
+
await fs.writeFile(path.join(pluginDir, 'plugin.js'), JS_TEMPLATE);
|
|
228
|
+
console.log('\nSky Gen 2 Repository successfully initialized!');
|
|
229
|
+
console.log(`Project Directory: ${rootDir}`);
|
|
230
|
+
console.log(`First Plugin ID: ${pluginManifest.id}`);
|
|
231
|
+
});
|
|
232
|
+
program.command('add')
|
|
233
|
+
.description('Add a new Sky Gen 2 plugin to the repository')
|
|
234
|
+
.argument('<plugin-name>', 'Name of the plugin (e.g. "Yflix")')
|
|
235
|
+
.option('-d, --description <desc>', 'Plugin description')
|
|
236
|
+
.option('-a, --author <author>', 'Author name')
|
|
237
|
+
.action(async (pluginName, options) => {
|
|
238
|
+
const rootDir = process.cwd();
|
|
239
|
+
const repoPath = path.join(rootDir, 'repo.json');
|
|
240
|
+
if (!await fs.pathExists(repoPath)) {
|
|
241
|
+
console.error('Error: Not in a SkyStream repository (repo.json missing)');
|
|
242
|
+
process.exit(1);
|
|
243
|
+
}
|
|
244
|
+
const repo = await fs.readJson(repoPath);
|
|
245
|
+
const pluginSlug = pluginName.toLowerCase().replace(/\s+/g, '').replace(/[^a-z0-9]/g, '');
|
|
246
|
+
const pluginDir = path.join(rootDir, pluginSlug);
|
|
247
|
+
if (await fs.pathExists(pluginDir)) {
|
|
248
|
+
console.error(`Error: Plugin ${pluginName} already exists at ${pluginSlug}`);
|
|
249
|
+
process.exit(1);
|
|
250
|
+
}
|
|
251
|
+
// Guess package-name from repo id
|
|
252
|
+
const packageName = repo.id;
|
|
253
|
+
const pluginManifest = {
|
|
254
|
+
id: `${packageName}.${pluginSlug}`,
|
|
255
|
+
name: pluginName,
|
|
256
|
+
internalName: pluginName.toUpperCase().replace(/\s+/g, ''),
|
|
257
|
+
version: 1,
|
|
258
|
+
description: options.description || `${pluginName} plugin for ${repo.name}`,
|
|
259
|
+
authors: [options.author || repo.author || "Developer"],
|
|
260
|
+
languages: ["en"],
|
|
261
|
+
categories: ["Others"]
|
|
262
|
+
};
|
|
263
|
+
await fs.ensureDir(pluginDir);
|
|
264
|
+
await fs.writeJson(path.join(pluginDir, 'plugin.json'), pluginManifest, { spaces: 2 });
|
|
265
|
+
await fs.writeFile(path.join(pluginDir, 'plugin.js'), JS_TEMPLATE);
|
|
266
|
+
console.log(`✓ Added Plugin: ${pluginName} (ID: ${pluginManifest.id})`);
|
|
267
|
+
});
|
|
268
|
+
program.command('validate')
|
|
269
|
+
.description('Validate all plugins in the repo')
|
|
270
|
+
.action(async () => {
|
|
271
|
+
const rootDir = process.cwd();
|
|
272
|
+
const items = await fs.readdir(rootDir);
|
|
273
|
+
let count = 0;
|
|
274
|
+
for (const item of items) {
|
|
275
|
+
const itemPath = path.join(rootDir, item);
|
|
276
|
+
const manifestPath = path.join(itemPath, 'plugin.json');
|
|
277
|
+
if (await fs.pathExists(manifestPath) && (await fs.stat(itemPath)).isDirectory()) {
|
|
278
|
+
try {
|
|
279
|
+
const manifest = await fs.readJson(manifestPath);
|
|
280
|
+
pluginSchema.parse(manifest);
|
|
281
|
+
console.log(`✓ ${manifest.id}: Manifest OK`);
|
|
282
|
+
const js = await fs.readFile(path.join(itemPath, 'plugin.js'), 'utf8');
|
|
283
|
+
if (js.includes('globalThis.getHome = getHome')) {
|
|
284
|
+
console.log(`✓ ${manifest.id}: Logic OK`);
|
|
285
|
+
}
|
|
286
|
+
else {
|
|
287
|
+
console.warn(`! ${manifest.id}: Missing exports`);
|
|
288
|
+
}
|
|
289
|
+
count++;
|
|
290
|
+
}
|
|
291
|
+
catch (e) {
|
|
292
|
+
console.error(`✗ ${item} invalid: ${e.message}`);
|
|
293
|
+
if (e instanceof z.ZodError) {
|
|
294
|
+
console.error(JSON.stringify(e.format(), null, 2));
|
|
295
|
+
}
|
|
296
|
+
}
|
|
297
|
+
}
|
|
298
|
+
}
|
|
299
|
+
console.log(`\nValidation complete. Validated ${count} plugins.`);
|
|
300
|
+
});
|
|
301
|
+
program.command('test')
|
|
302
|
+
.description('Test a specific plugin')
|
|
303
|
+
.option('-p, --path <path>', 'Path to plugin folder', '.')
|
|
304
|
+
.option('-f, --function <function>', 'Function to test', 'getHome')
|
|
305
|
+
.option('-q, --query <query>', 'Query for function', '')
|
|
306
|
+
.action(async (options) => {
|
|
307
|
+
const pluginDir = path.resolve(options.path);
|
|
308
|
+
const manifestPath = path.join(pluginDir, 'plugin.json');
|
|
309
|
+
const jsPath = path.join(pluginDir, 'plugin.js');
|
|
310
|
+
const manifest = await fs.readJson(manifestPath);
|
|
311
|
+
const jsContent = await fs.readFile(jsPath, 'utf8');
|
|
312
|
+
console.log(`\n--- Testing ${manifest.id} -> ${options.function} ---`);
|
|
313
|
+
const context = {
|
|
314
|
+
manifest,
|
|
315
|
+
console: { log: (...args) => console.log(' [JS]:', ...args), error: (...args) => console.error(' [JS ERR]:', ...args) },
|
|
316
|
+
http_get: async (url, headers, cb) => {
|
|
317
|
+
try {
|
|
318
|
+
const res = await axios.get(url, { headers });
|
|
319
|
+
const result = { status: res.status, body: res.data, headers: res.headers };
|
|
320
|
+
if (cb)
|
|
321
|
+
cb(result);
|
|
322
|
+
return result;
|
|
323
|
+
}
|
|
324
|
+
catch (e) {
|
|
325
|
+
const res = { status: 500, body: e.message, headers: {} };
|
|
326
|
+
if (cb)
|
|
327
|
+
cb(res);
|
|
328
|
+
return res;
|
|
329
|
+
}
|
|
330
|
+
},
|
|
331
|
+
btoa: (s) => Buffer.from(s).toString('base64'),
|
|
332
|
+
atob: (s) => Buffer.from(s, 'base64').toString('utf8'),
|
|
333
|
+
globalThis: {},
|
|
334
|
+
};
|
|
335
|
+
const runtime = new Function('manifest', 'console', 'http_get', 'btoa', 'atob', 'globalThis', jsContent);
|
|
336
|
+
runtime(context.manifest, context.console, context.http_get, context.btoa, context.atob, context.globalThis);
|
|
337
|
+
const fn = context.globalThis[options.function];
|
|
338
|
+
if (typeof fn !== 'function') {
|
|
339
|
+
console.error('Error: exported function not found');
|
|
340
|
+
process.exit(1);
|
|
341
|
+
}
|
|
342
|
+
const callback = (res) => {
|
|
343
|
+
console.log('\n--- Result ---');
|
|
344
|
+
console.log(JSON.stringify(res, null, 2));
|
|
345
|
+
};
|
|
346
|
+
if (options.function === 'getHome')
|
|
347
|
+
await fn(callback);
|
|
348
|
+
else
|
|
349
|
+
await fn(options.query, callback);
|
|
350
|
+
});
|
|
351
|
+
program.command('build')
|
|
352
|
+
.description('Build all plugins and repository index')
|
|
353
|
+
.requiredOption('-u, --url <url>', 'Base hosting URL for .sky files')
|
|
354
|
+
.action(async (options) => {
|
|
355
|
+
const rootDir = process.cwd();
|
|
356
|
+
const repoPath = path.join(rootDir, 'repo.json');
|
|
357
|
+
if (!await fs.pathExists(repoPath)) {
|
|
358
|
+
process.exit(1);
|
|
359
|
+
}
|
|
360
|
+
const distDir = path.join(rootDir, 'dist');
|
|
361
|
+
await fs.ensureDir(distDir);
|
|
362
|
+
const repo = await fs.readJson(repoPath);
|
|
363
|
+
const items = await fs.readdir(rootDir);
|
|
364
|
+
const catalog = [];
|
|
365
|
+
// Standardize URL: Append /dist automatically
|
|
366
|
+
const baseRaw = options.url.endsWith('/') ? options.url.slice(0, -1) : options.url;
|
|
367
|
+
const distUrl = `${baseRaw}/dist`;
|
|
368
|
+
for (const item of items) {
|
|
369
|
+
const itemPath = path.join(rootDir, item);
|
|
370
|
+
const mPath = path.join(itemPath, 'plugin.json');
|
|
371
|
+
if (await fs.pathExists(mPath) && (await fs.stat(itemPath)).isDirectory()) {
|
|
372
|
+
const manifest = await fs.readJson(mPath);
|
|
373
|
+
const bundleName = `${manifest.id}.sky`;
|
|
374
|
+
const outPath = path.join(distDir, bundleName);
|
|
375
|
+
const arch = archiver('zip', { zlib: { level: 9 } });
|
|
376
|
+
arch.pipe(fs.createWriteStream(outPath));
|
|
377
|
+
arch.file(mPath, { name: 'plugin.json' });
|
|
378
|
+
arch.file(path.join(itemPath, 'plugin.js'), { name: 'plugin.js' });
|
|
379
|
+
await arch.finalize();
|
|
380
|
+
catalog.push({ ...manifest, url: `${distUrl}/${bundleName}` });
|
|
381
|
+
console.log(`✓ Bundled ${manifest.id}`);
|
|
382
|
+
}
|
|
383
|
+
}
|
|
384
|
+
const finalRepo = {
|
|
385
|
+
...repo,
|
|
386
|
+
updatedAt: new Date().toISOString(),
|
|
387
|
+
pluginLists: [`${distUrl}/plugins.json`]
|
|
388
|
+
};
|
|
389
|
+
await fs.writeJson(repoPath, finalRepo, { spaces: 2 });
|
|
390
|
+
await fs.writeJson(path.join(distDir, 'plugins.json'), catalog, { spaces: 2 });
|
|
391
|
+
// Update README.md with the live URL
|
|
392
|
+
const readmePath = path.join(rootDir, 'README.md');
|
|
393
|
+
if (await fs.pathExists(readmePath)) {
|
|
394
|
+
let readme = await fs.readFile(readmePath, 'utf8');
|
|
395
|
+
const placeholder = 'https://raw.githubusercontent.com/USER_NAME/REPO_NAME/main/repo.json';
|
|
396
|
+
const liveUrl = `${baseRaw}/repo.json`;
|
|
397
|
+
if (readme.includes(placeholder)) {
|
|
398
|
+
readme = readme.replace(placeholder, liveUrl);
|
|
399
|
+
await fs.writeFile(readmePath, readme);
|
|
400
|
+
console.log(`✓ Updated README.md with live URL`);
|
|
401
|
+
}
|
|
402
|
+
}
|
|
403
|
+
console.log(`\nBuild Complete. Assets generated in dist/`);
|
|
404
|
+
console.log(`\nYour Repo Link for the app:`);
|
|
405
|
+
console.log(`> ${baseRaw}/repo.json`);
|
|
406
|
+
});
|
|
407
|
+
program.parse();
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
|
package/package.json
ADDED
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "skystream-cli",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"type": "module",
|
|
5
|
+
"description": "SkyStream Plugin Development Kit & Repository Manager",
|
|
6
|
+
"main": "dist/index.js",
|
|
7
|
+
"bin": {
|
|
8
|
+
"skystream": "dist/index.js"
|
|
9
|
+
},
|
|
10
|
+
"files": [
|
|
11
|
+
"dist",
|
|
12
|
+
"README.md"
|
|
13
|
+
],
|
|
14
|
+
"scripts": {
|
|
15
|
+
"build": "tsc",
|
|
16
|
+
"prepublishOnly": "npm run build",
|
|
17
|
+
"start": "node dist/index.js",
|
|
18
|
+
"test": "echo \"Error: no test specified\" && exit 1"
|
|
19
|
+
},
|
|
20
|
+
"keywords": [
|
|
21
|
+
"skystream",
|
|
22
|
+
"plugins",
|
|
23
|
+
"extensions",
|
|
24
|
+
"cli"
|
|
25
|
+
],
|
|
26
|
+
"author": "Akash",
|
|
27
|
+
"license": "MIT",
|
|
28
|
+
"dependencies": {
|
|
29
|
+
"adm-zip": "^0.5.16",
|
|
30
|
+
"archiver": "^7.0.1",
|
|
31
|
+
"axios": "^1.13.6",
|
|
32
|
+
"commander": "^14.0.3",
|
|
33
|
+
"esbuild": "^0.27.3",
|
|
34
|
+
"fs-extra": "^11.3.4",
|
|
35
|
+
"inquirer": "^12.11.1",
|
|
36
|
+
"zod": "^4.3.6"
|
|
37
|
+
},
|
|
38
|
+
"devDependencies": {
|
|
39
|
+
"@types/adm-zip": "^0.5.7",
|
|
40
|
+
"@types/archiver": "^7.0.0",
|
|
41
|
+
"@types/fs-extra": "^11.0.4",
|
|
42
|
+
"@types/inquirer": "^9.0.9",
|
|
43
|
+
"@types/node": "^25.4.0",
|
|
44
|
+
"typescript": "^5.9.3"
|
|
45
|
+
}
|
|
46
|
+
}
|