@orxataguy/tyr 1.0.41 → 1.0.42
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 +2 -2
- package/package.json +1 -1
- package/src/core/Kernel.ts +1 -1
- package/src/core/sys/config.ts +10 -0
- package/src/core/sys/modules.ts +23 -8
package/README.md
CHANGED
|
@@ -184,7 +184,7 @@ Third parties can distribute commands as a `manifest.json` — a flat JSON map o
|
|
|
184
184
|
}
|
|
185
185
|
```
|
|
186
186
|
|
|
187
|
-
Register one with `tyr --add`, which validates the manifest, records it in `~/.tyr/imported_modules.
|
|
187
|
+
Register one with `tyr --add`, which validates the manifest, records it in `~/.tyr/imported_modules.yaml`, and immediately downloads whatever commands are missing:
|
|
188
188
|
|
|
189
189
|
```bash
|
|
190
190
|
tyr --add https://raw.githubusercontent.com/someuser/tyr-modules/main/manifest.json my-module
|
|
@@ -200,7 +200,7 @@ Rules worth knowing:
|
|
|
200
200
|
|
|
201
201
|
- A command name that already exists locally is never overwritten by a plain sync — only `tyr --update` (or `tyr --modules sync --force`) refreshes commands that were themselves installed by an import.
|
|
202
202
|
- Hand-written commands are never touched, even if a manifest later defines a command with the same name.
|
|
203
|
-
- If two modules define the same command name, the one processed last (last entry in `imported_modules.
|
|
203
|
+
- If two modules define the same command name, the one processed last (last entry in `imported_modules.yaml`) wins.
|
|
204
204
|
- Only `https://` URLs are accepted, both for manifests and for the command files they point to.
|
|
205
205
|
|
|
206
206
|
Which commands came from which module is tracked in `~/.tyr/imported_modules.lock.yml`, generated automatically — you shouldn't need to edit it by hand.
|
package/package.json
CHANGED
package/src/core/Kernel.ts
CHANGED
|
@@ -110,7 +110,7 @@ export class Kernel {
|
|
|
110
110
|
console.log('Run: tyr --config --repo <url> to link it.');
|
|
111
111
|
}
|
|
112
112
|
|
|
113
|
-
const modulesPath = path.join(this.userRoot, 'imported_modules.
|
|
113
|
+
const modulesPath = path.join(this.userRoot, 'imported_modules.yaml');
|
|
114
114
|
if (fs.existsSync(modulesPath)) {
|
|
115
115
|
console.log('\nUpdating imported modules...');
|
|
116
116
|
const updateContext = {
|
package/src/core/sys/config.ts
CHANGED
|
@@ -284,6 +284,10 @@ export default function config({ logger, fs: tyrFs, frameworkRoot, shell }: TyrC
|
|
|
284
284
|
await tyrFs.write(mapPath, 'commands: {}\n');
|
|
285
285
|
logger.success(`File created: ${mapPath}`);
|
|
286
286
|
|
|
287
|
+
const importedModulesPath = path.join(userRoot, 'imported_modules.yaml');
|
|
288
|
+
await tyrFs.write(importedModulesPath, 'modules: {}\n');
|
|
289
|
+
logger.success(`File created: ${importedModulesPath}`);
|
|
290
|
+
|
|
287
291
|
const envPath = path.join(userRoot, '.env.example');
|
|
288
292
|
if (!tyrFs.exists(envPath)) {
|
|
289
293
|
await tyrFs.write(envPath, ENV_TEMPLATE);
|
|
@@ -331,6 +335,12 @@ export default function config({ logger, fs: tyrFs, frameworkRoot, shell }: TyrC
|
|
|
331
335
|
}
|
|
332
336
|
}
|
|
333
337
|
|
|
338
|
+
const importedModulesPath = path.join(userRoot, 'imported_modules.yaml');
|
|
339
|
+
if (!tyrFs.exists(importedModulesPath)) {
|
|
340
|
+
await tyrFs.write(importedModulesPath, 'modules: {}\n');
|
|
341
|
+
logger.success(`File created: ${importedModulesPath}`);
|
|
342
|
+
}
|
|
343
|
+
|
|
334
344
|
const packageJsonPath = path.join(userRoot, 'package.json');
|
|
335
345
|
const tsconfigPath = path.join(userRoot, 'tsconfig.json');
|
|
336
346
|
let needsInstall = false;
|
package/src/core/sys/modules.ts
CHANGED
|
@@ -29,7 +29,7 @@ export interface SyncSummary {
|
|
|
29
29
|
failed: { command: string; reason: string }[];
|
|
30
30
|
}
|
|
31
31
|
|
|
32
|
-
const IMPORTED_MODULES_FILE = 'imported_modules.
|
|
32
|
+
const IMPORTED_MODULES_FILE = 'imported_modules.yaml';
|
|
33
33
|
const LOCK_FILE = 'imported_modules.lock.yml';
|
|
34
34
|
|
|
35
35
|
function isValidHttpsUrl(value: string): boolean {
|
|
@@ -101,7 +101,7 @@ async function fetchManifest(web: any, manifestUrl: string): Promise<Record<stri
|
|
|
101
101
|
}
|
|
102
102
|
|
|
103
103
|
/**
|
|
104
|
-
* Reconciles ~/.tyr/imported_modules.
|
|
104
|
+
* Reconciles ~/.tyr/imported_modules.yaml against ~/.tyr/map.yml.
|
|
105
105
|
*
|
|
106
106
|
* - A command that doesn't exist yet in map.yml is installed.
|
|
107
107
|
* - A command that already exists and isn't tracked in the lockfile is left
|
|
@@ -111,7 +111,7 @@ async function fetchManifest(web: any, manifestUrl: string): Promise<Record<stri
|
|
|
111
111
|
* silently.
|
|
112
112
|
* - If two modules define the same command name, the last one processed
|
|
113
113
|
* wins (modules are processed in the order they appear in
|
|
114
|
-
* imported_modules.
|
|
114
|
+
* imported_modules.yaml).
|
|
115
115
|
*/
|
|
116
116
|
export async function syncModules(context: TyrContext, options: { force?: boolean } = {}): Promise<SyncSummary> {
|
|
117
117
|
const { logger, fs, web, userRoot } = context as any;
|
|
@@ -155,6 +155,9 @@ export async function syncModules(context: TyrContext, options: { force?: boolea
|
|
|
155
155
|
} catch (e) {
|
|
156
156
|
const reason = e instanceof Error ? e.message : String(e);
|
|
157
157
|
logger.error(`Could not read manifest for module '${moduleName}': ${reason}`);
|
|
158
|
+
// logger.error() is silenced unless --debug is passed, so mirror it via
|
|
159
|
+
// logger.info() too — otherwise this failure would be entirely invisible.
|
|
160
|
+
logger.info(`Skipped module '${moduleName}': ${reason}`);
|
|
158
161
|
summary.failed.push({ command: moduleName, reason });
|
|
159
162
|
continue;
|
|
160
163
|
}
|
|
@@ -202,6 +205,7 @@ export async function syncModules(context: TyrContext, options: { force?: boolea
|
|
|
202
205
|
} catch (e) {
|
|
203
206
|
const reason = e instanceof Error ? e.message : String(e);
|
|
204
207
|
logger.error(`Could not download '${commandName}' from '${fileUrl}': ${reason}`);
|
|
208
|
+
logger.info(`Skipped '${commandName}': ${reason}`);
|
|
205
209
|
summary.failed.push({ command: commandName, reason });
|
|
206
210
|
}
|
|
207
211
|
}
|
|
@@ -215,11 +219,18 @@ export async function syncModules(context: TyrContext, options: { force?: boolea
|
|
|
215
219
|
`skipped: ${summary.skipped.length}, failed: ${summary.failed.length}.`
|
|
216
220
|
);
|
|
217
221
|
|
|
222
|
+
if (summary.failed.length > 0) {
|
|
223
|
+
logger.info('Failures:');
|
|
224
|
+
for (const { command, reason } of summary.failed) {
|
|
225
|
+
logger.info(` - ${command}: ${reason}`);
|
|
226
|
+
}
|
|
227
|
+
}
|
|
228
|
+
|
|
218
229
|
return summary;
|
|
219
230
|
}
|
|
220
231
|
|
|
221
232
|
/**
|
|
222
|
-
* Registers a manifest URL under a module name in imported_modules.
|
|
233
|
+
* Registers a manifest URL under a module name in imported_modules.yaml and
|
|
223
234
|
* immediately syncs it (downloads whatever commands are missing).
|
|
224
235
|
*/
|
|
225
236
|
export async function addModule(context: TyrContext, manifestUrl: string, name?: string): Promise<void> {
|
|
@@ -233,6 +244,7 @@ export async function addModule(context: TyrContext, manifestUrl: string, name?:
|
|
|
233
244
|
|
|
234
245
|
if (!isValidHttpsUrl(manifestUrl)) {
|
|
235
246
|
logger.error('Manifest URL must be a valid https:// URL.');
|
|
247
|
+
logger.info(`Could not add module: '${manifestUrl}' is not a valid https:// URL.`);
|
|
236
248
|
return;
|
|
237
249
|
}
|
|
238
250
|
|
|
@@ -242,6 +254,7 @@ export async function addModule(context: TyrContext, manifestUrl: string, name?:
|
|
|
242
254
|
} catch (e) {
|
|
243
255
|
const reason = e instanceof Error ? e.message : String(e);
|
|
244
256
|
logger.error(`Could not add module: ${reason}`);
|
|
257
|
+
logger.info(`Could not add module: ${reason}`);
|
|
245
258
|
return;
|
|
246
259
|
}
|
|
247
260
|
|
|
@@ -313,12 +326,14 @@ export async function generateManifest(context: TyrContext): Promise<void> {
|
|
|
313
326
|
remoteUrl = await shell.exec('git remote get-url origin');
|
|
314
327
|
} catch {
|
|
315
328
|
logger.error("~/.tyr's repository has no 'origin' remote configured. Cannot generate manifest.json.");
|
|
329
|
+
logger.info("Cannot generate manifest.json: ~/.tyr's repository has no 'origin' remote configured.");
|
|
316
330
|
return;
|
|
317
331
|
}
|
|
318
332
|
|
|
319
333
|
const repoInfo = parseGithubRemote(remoteUrl);
|
|
320
334
|
if (!repoInfo) {
|
|
321
335
|
logger.error(`Cannot generate manifest.json: only GitHub repositories are supported (raw.githubusercontent.com). Remote was: ${remoteUrl}`);
|
|
336
|
+
logger.info(`Cannot generate manifest.json: only GitHub repositories are supported. Remote was: ${remoteUrl}`);
|
|
322
337
|
return;
|
|
323
338
|
}
|
|
324
339
|
|
|
@@ -328,10 +343,10 @@ export async function generateManifest(context: TyrContext): Promise<void> {
|
|
|
328
343
|
if (currentBranch && currentBranch !== 'HEAD') {
|
|
329
344
|
branch = currentBranch;
|
|
330
345
|
} else {
|
|
331
|
-
logger.
|
|
346
|
+
logger.info(`Could not determine the current branch (detached HEAD?). Falling back to '${branch}'.`);
|
|
332
347
|
}
|
|
333
348
|
} catch {
|
|
334
|
-
logger.
|
|
349
|
+
logger.info(`Could not determine the current branch. Falling back to '${branch}'.`);
|
|
335
350
|
}
|
|
336
351
|
|
|
337
352
|
const mapPath = path.join(userRoot, 'map.yml');
|
|
@@ -347,7 +362,7 @@ export async function generateManifest(context: TyrContext): Promise<void> {
|
|
|
347
362
|
: scriptPath.replace(/^\.[/\\]/, '');
|
|
348
363
|
|
|
349
364
|
if (repoRelativePath.startsWith('..')) {
|
|
350
|
-
logger.
|
|
365
|
+
logger.info(`Skipping '${name}': its file lives outside ~/.tyr and can't be published.`);
|
|
351
366
|
skipped.push(name);
|
|
352
367
|
continue;
|
|
353
368
|
}
|
|
@@ -357,7 +372,7 @@ export async function generateManifest(context: TyrContext): Promise<void> {
|
|
|
357
372
|
}
|
|
358
373
|
|
|
359
374
|
if (Object.keys(manifest).length === 0) {
|
|
360
|
-
logger.
|
|
375
|
+
logger.info('No commands to include in manifest.json.');
|
|
361
376
|
}
|
|
362
377
|
|
|
363
378
|
const manifestPath = path.join(userRoot, 'manifest.json');
|