@orxataguy/tyr 1.0.44 → 1.0.46

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 CHANGED
@@ -185,7 +185,7 @@ Third parties can distribute commands as a `manifest.json` — a flat JSON map o
185
185
  }
186
186
  ```
187
187
 
188
- `$env` is optional and reserved (`$` can never appear in a command name, so it never collides with one). If present, it's downloaded as `~/.tyr/<module-name>.env.example` — a template of whatever environment variables that module's commands expect. It follows the exact same install/skip/force-update rules as commands below, and `tyr --del <module-name>` removes it along with everything else that module owns.
188
+ `$env` is optional and reserved (`$` can never appear in a command name, so it never collides with one). If present, it's downloaded as `~/.tyr/.env.<module-name>.example` — a template of whatever environment variables that module's commands expect. It follows the exact same install/skip/force-update rules as commands below, and `tyr --del <module-name>` removes it along with everything else that module owns.
189
189
 
190
190
  Register one with `tyr --add`, which validates the manifest, records it in `~/.tyr/imported_modules.yaml`, and immediately downloads whatever commands (and `$env`, if present) are missing:
191
191
 
@@ -193,6 +193,8 @@ Register one with `tyr --add`, which validates the manifest, records it in `~/.t
193
193
  tyr --add https://raw.githubusercontent.com/someuser/tyr-modules/main/manifest.json my-module
194
194
  ```
195
195
 
196
+ The module name is optional. If you omit it and the manifest URL is a `raw.githubusercontent.com` link, the repository name is used (`tyr-modules` for the URL above). For any other host, it falls back to a slug of the manifest file's own name.
197
+
196
198
  ```bash
197
199
  tyr --modules # list registered modules
198
200
  tyr --modules sync # re-check all registered manifests and install anything missing
@@ -225,7 +227,7 @@ Commit and push it, and anyone can install your commands with `tyr --add <raw-ur
225
227
  - Requires a GitHub remote named `origin` — other hosts aren't supported, since the URLs only resolve through `raw.githubusercontent.com`.
226
228
  - If `~/.tyr` isn't a git repository (or has no `origin` remote), `--manifest` refuses and tells you why instead of generating a broken file.
227
229
  - Commands whose file lives outside `~/.tyr` (an absolute path elsewhere on disk) are skipped, since they can't be resolved to a URL in the repo.
228
- - If `~/.tyr/.env.example` exists, it's automatically included as `$env`, so whoever runs `tyr --add` on your manifest gets it as `<module-name>.env.example`.
230
+ - If `~/.tyr/.env.example` exists, it's automatically included as `$env`, so whoever runs `tyr --add` on your manifest gets it as `.env.<module-name>.example`.
229
231
 
230
232
  ### `tyr chat [directory] [--port <n>] [--split <0-1>]`
231
233
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@orxataguy/tyr",
3
- "version": "1.0.44",
3
+ "version": "1.0.46",
4
4
  "type": "module",
5
5
  "bin": {
6
6
  "tyr": "./bin/tyr.js"
@@ -55,11 +55,11 @@ export function createLogger(isDebug: boolean): Logger {
55
55
  writeToFile('SUCCESS', msg);
56
56
  },
57
57
  error: (msg) => {
58
- if (isDebug) console.error(chalk.red('✖'), msg);
58
+ console.error(chalk.red('✖'), msg);
59
59
  writeToFile('ERROR', msg);
60
60
  },
61
61
  warn: (msg) => {
62
- if (isDebug) console.warn(chalk.yellow('⚠'), msg);
62
+ console.warn(chalk.yellow('⚠'), msg);
63
63
  writeToFile('WARN', msg);
64
64
  },
65
65
  };
@@ -34,7 +34,7 @@ export class TyrError extends Error {
34
34
  logger.error('Oops! An error occurred.');
35
35
  logger.error(`↳ ${this.message}`);
36
36
 
37
- if (this.originalError) {
37
+ if (this.originalError && isDebug) {
38
38
  logger.error(` ↳ Caused by: ${this.extractErrorMessage(this.originalError)}`);
39
39
  }
40
40
 
@@ -63,13 +63,31 @@ function toSafeFilename(commandName: string): string {
63
63
  return commandName.replace(/:/g, '-');
64
64
  }
65
65
 
66
- function slugFromUrl(url: string): string {
66
+ function sanitizeSlug(value: string): string {
67
+ const slug = value.toLowerCase().replace(/[^a-z0-9_-]+/g, '-').replace(/^-+|-+$/g, '');
68
+ return slug || 'module';
69
+ }
70
+
71
+ /**
72
+ * Default module name when `tyr --add <url>` is called without one.
73
+ * For a raw.githubusercontent.com URL (the expected shape:
74
+ * raw.githubusercontent.com/<owner>/<repo>/<branch>/<path>) this uses the
75
+ * repository name, since that's what identifies where the module comes from.
76
+ * For any other host — a manifest can be served from anywhere, as long as
77
+ * it's https — falls back to a slug of the manifest file's own name.
78
+ */
79
+ function defaultModuleNameFromUrl(url: string): string {
67
80
  try {
68
81
  const parsed = new URL(url);
69
- const base = parsed.pathname.split('/').filter(Boolean).pop() ?? 'module';
82
+ const segments = parsed.pathname.split('/').filter(Boolean);
83
+
84
+ if (parsed.hostname === 'raw.githubusercontent.com' && segments.length >= 2) {
85
+ return sanitizeSlug(segments[1]);
86
+ }
87
+
88
+ const base = segments.pop() ?? 'module';
70
89
  const withoutExt = base.replace(/\.json$/i, '').replace(/\.manifest$/i, '');
71
- const slug = withoutExt.toLowerCase().replace(/[^a-z0-9_-]+/g, '-').replace(/^-+|-+$/g, '');
72
- return slug || 'module';
90
+ return sanitizeSlug(withoutExt);
73
91
  } catch {
74
92
  return 'module';
75
93
  }
@@ -257,7 +275,7 @@ export async function syncModules(context: TyrContext, options: { force?: boolea
257
275
  }
258
276
 
259
277
  if (envUrl) {
260
- const envFileName = `${moduleName}.env.example`;
278
+ const envFileName = `.env.${toSafeFilename(moduleName)}.example`;
261
279
  const envDestPath = path.join(userRoot, envFileName);
262
280
  const envManaged = lock.env![moduleName];
263
281
 
@@ -337,7 +355,7 @@ export async function addModule(context: TyrContext, manifestUrl: string, name?:
337
355
  return;
338
356
  }
339
357
 
340
- const moduleName = name && isValidCommandName(name) ? name : slugFromUrl(manifestUrl);
358
+ const moduleName = name && isValidCommandName(name) ? name : defaultModuleNameFromUrl(manifestUrl);
341
359
 
342
360
  const modulesPath = path.join(userRoot, IMPORTED_MODULES_FILE);
343
361
  const modulesFile = await loadYaml<ImportedModulesFile>(fs, modulesPath, { modules: {} });
@@ -358,7 +376,7 @@ export async function addModule(context: TyrContext, manifestUrl: string, name?:
358
376
  * Unregisters a module: removes it from imported_modules.yaml, deletes every
359
377
  * command file it's tracked as owning in the lockfile, drops those commands
360
378
  * (and any aliases pointing at them) from map.yml, deletes its
361
- * `<module>.env.example` if one was imported, and clears their lockfile
379
+ * `.env.<module>.example` if one was imported, and clears their lockfile
362
380
  * entries. The counterpart to `tyr --add` — closes the loop.
363
381
  */
364
382
  export async function removeModule(context: TyrContext, moduleName: string): Promise<void> {
@@ -484,7 +502,7 @@ function parseGithubRemote(remoteUrl: string): GithubRepoInfo | null {
484
502
  * handed to someone else, who registers it with `tyr --add <url>`.
485
503
  *
486
504
  * If ~/.tyr/.env.example exists, its raw URL is also included under the
487
- * reserved `$env` key, so `tyr --add` downloads it as `<module>.env.example`
505
+ * reserved `$env` key, so `tyr --add` downloads it as `.env.<module>.example`
488
506
  * for whoever installs this manifest.
489
507
  *
490
508
  * Requires ~/.tyr to be a git repository linked to a GitHub remote — there's
@@ -558,7 +576,7 @@ export async function generateManifest(context: TyrContext): Promise<void> {
558
576
  }
559
577
 
560
578
  // If ~/.tyr has a .env.example, publish it too — tyr --add downloads it as
561
- // <module>.env.example so whoever installs this manifest knows which
579
+ // .env.<module>.example so whoever installs this manifest knows which
562
580
  // environment variables these commands expect.
563
581
  const envExamplePath = path.join(userRoot, '.env.example');
564
582
  let includedEnv = false;