@remix-run/cli 0.1.0 → 0.2.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 +0 -3
- package/bootstrap/.agents/skills/remix/SKILL.md +501 -0
- package/bootstrap/.agents/skills/remix/references/animate-elements.md +195 -0
- package/bootstrap/.agents/skills/remix/references/assets-and-browser-modules.md +122 -0
- package/bootstrap/.agents/skills/remix/references/auth-and-sessions.md +420 -0
- package/bootstrap/.agents/skills/remix/references/component-model.md +282 -0
- package/bootstrap/.agents/skills/remix/references/create-mixins.md +158 -0
- package/bootstrap/.agents/skills/remix/references/data-and-validation.md +363 -0
- package/bootstrap/.agents/skills/remix/references/hydration-frames-navigation.md +297 -0
- package/bootstrap/.agents/skills/remix/references/middleware-and-server.md +243 -0
- package/bootstrap/.agents/skills/remix/references/mixins-styling-events.md +213 -0
- package/bootstrap/.agents/skills/remix/references/routing-and-controllers.md +324 -0
- package/bootstrap/.agents/skills/remix/references/testing-patterns.md +156 -0
- package/bootstrap/AGENTS.md +4 -0
- package/bootstrap/app/assets/entry.ts +19 -0
- package/bootstrap/app/assets.ts +18 -0
- package/bootstrap/app/controllers/auth.tsx +2 -2
- package/bootstrap/app/controllers/home.tsx +3 -18
- package/bootstrap/app/router.ts +6 -0
- package/bootstrap/app/routes.ts +2 -1
- package/bootstrap/app/ui/document.tsx +6 -1
- package/bootstrap/app/ui/prompt-button.tsx +162 -0
- package/bootstrap/app/ui/scaffold-home-page.tsx +526 -0
- package/bootstrap/app/utils/render.tsx +22 -3
- package/bootstrap/server.ts +13 -13
- package/bootstrap/tsconfig.json +0 -1
- package/dist/lib/cli.d.ts.map +1 -1
- package/dist/lib/cli.js +7 -10
- package/dist/lib/commands/help.d.ts.map +1 -1
- package/dist/lib/commands/help.js +9 -33
- package/dist/lib/commands/test.d.ts +1 -1
- package/dist/lib/commands/test.d.ts.map +1 -1
- package/dist/lib/commands/test.js +8 -4
- package/dist/lib/completion.d.ts.map +1 -1
- package/dist/lib/completion.js +3 -101
- package/dist/lib/errors.d.ts +0 -6
- package/dist/lib/errors.d.ts.map +1 -1
- package/dist/lib/errors.js +0 -11
- package/package.json +3 -4
- package/src/lib/cli.ts +7 -11
- package/src/lib/commands/help.ts +9 -43
- package/src/lib/commands/test.ts +10 -4
- package/src/lib/completion.ts +3 -146
- package/src/lib/errors.ts +0 -12
- package/dist/lib/commands/skills.d.ts +0 -6
- package/dist/lib/commands/skills.d.ts.map +0 -1
- package/dist/lib/commands/skills.js +0 -222
- package/dist/lib/skills-cache.d.ts +0 -19
- package/dist/lib/skills-cache.d.ts.map +0 -1
- package/dist/lib/skills-cache.js +0 -89
- package/dist/lib/skills.d.ts +0 -30
- package/dist/lib/skills.d.ts.map +0 -1
- package/dist/lib/skills.js +0 -441
- package/src/lib/commands/skills.ts +0 -306
- package/src/lib/skills-cache.ts +0 -140
- package/src/lib/skills.ts +0 -706
package/src/lib/completion.ts
CHANGED
|
@@ -4,27 +4,8 @@ export interface CompletionResult {
|
|
|
4
4
|
}
|
|
5
5
|
|
|
6
6
|
const COMPLETION_SHELLS = ['bash', 'zsh'] as const
|
|
7
|
-
const HELP_COMMANDS = [
|
|
8
|
-
|
|
9
|
-
'doctor',
|
|
10
|
-
'help',
|
|
11
|
-
'new',
|
|
12
|
-
'routes',
|
|
13
|
-
'skills',
|
|
14
|
-
'test',
|
|
15
|
-
'version',
|
|
16
|
-
] as const
|
|
17
|
-
const ROOT_COMMANDS = [
|
|
18
|
-
'completion',
|
|
19
|
-
'doctor',
|
|
20
|
-
'help',
|
|
21
|
-
'new',
|
|
22
|
-
'routes',
|
|
23
|
-
'skills',
|
|
24
|
-
'test',
|
|
25
|
-
'version',
|
|
26
|
-
] as const
|
|
27
|
-
const SKILLS_COMMANDS = ['install', 'list'] as const
|
|
7
|
+
const HELP_COMMANDS = ['completion', 'doctor', 'help', 'new', 'routes', 'test', 'version'] as const
|
|
8
|
+
const ROOT_COMMANDS = ['completion', 'doctor', 'help', 'new', 'routes', 'test', 'version'] as const
|
|
28
9
|
|
|
29
10
|
export type CompletionShell = (typeof COMPLETION_SHELLS)[number]
|
|
30
11
|
|
|
@@ -183,10 +164,6 @@ function completeCommand(
|
|
|
183
164
|
return completeRoutes(tokens, currentWord, usedGlobalFlags)
|
|
184
165
|
}
|
|
185
166
|
|
|
186
|
-
if (command === 'skills') {
|
|
187
|
-
return completeSkills(tokens, currentWord, usedGlobalFlags)
|
|
188
|
-
}
|
|
189
|
-
|
|
190
167
|
if (command === 'version') {
|
|
191
168
|
return completeSimpleFlags(tokens, currentWord, usedGlobalFlags, [])
|
|
192
169
|
}
|
|
@@ -220,12 +197,8 @@ function completeHelp(
|
|
|
220
197
|
return completeValues(withHelpFlags([...HELP_COMMANDS], usedGlobalFlags), currentWord)
|
|
221
198
|
}
|
|
222
199
|
|
|
223
|
-
let [
|
|
200
|
+
let [, ...rest] = filteredTokens
|
|
224
201
|
if (rest.length === 0) {
|
|
225
|
-
if (topic === 'skills') {
|
|
226
|
-
return completeValues(withHelpFlags([...SKILLS_COMMANDS], usedGlobalFlags), currentWord)
|
|
227
|
-
}
|
|
228
|
-
|
|
229
202
|
return completeValues([], currentWord)
|
|
230
203
|
}
|
|
231
204
|
|
|
@@ -344,122 +317,6 @@ function completeRoutes(
|
|
|
344
317
|
return completeValues(flags, currentWord)
|
|
345
318
|
}
|
|
346
319
|
|
|
347
|
-
function completeSkills(
|
|
348
|
-
tokens: string[],
|
|
349
|
-
currentWord: string,
|
|
350
|
-
usedGlobalFlags: Set<string>,
|
|
351
|
-
): CompletionResult {
|
|
352
|
-
let filteredTokens = filterGlobalCommandTokens(tokens, usedGlobalFlags)
|
|
353
|
-
if (filteredTokens == null) {
|
|
354
|
-
return completeValues([], currentWord)
|
|
355
|
-
}
|
|
356
|
-
|
|
357
|
-
if (filteredTokens.length === 0) {
|
|
358
|
-
return completeValues(withHelpFlags([...SKILLS_COMMANDS], usedGlobalFlags), currentWord)
|
|
359
|
-
}
|
|
360
|
-
|
|
361
|
-
let [subcommand, ...rest] = filteredTokens
|
|
362
|
-
if (subcommand === 'install') {
|
|
363
|
-
return completeSkillsInstall(rest, currentWord, usedGlobalFlags)
|
|
364
|
-
}
|
|
365
|
-
|
|
366
|
-
if (subcommand === 'list') {
|
|
367
|
-
return completeSkillsList(rest, currentWord, usedGlobalFlags)
|
|
368
|
-
}
|
|
369
|
-
|
|
370
|
-
return completeValues([], currentWord)
|
|
371
|
-
}
|
|
372
|
-
|
|
373
|
-
function completeSkillsInstall(
|
|
374
|
-
tokens: string[],
|
|
375
|
-
currentWord: string,
|
|
376
|
-
usedGlobalFlags: Set<string>,
|
|
377
|
-
): CompletionResult {
|
|
378
|
-
let filteredTokens = filterGlobalCommandTokens(tokens, usedGlobalFlags)
|
|
379
|
-
if (filteredTokens == null) {
|
|
380
|
-
return completeValues([], currentWord)
|
|
381
|
-
}
|
|
382
|
-
|
|
383
|
-
let hasDir = false
|
|
384
|
-
let expectsDir = false
|
|
385
|
-
|
|
386
|
-
for (let token of filteredTokens) {
|
|
387
|
-
if (expectsDir) {
|
|
388
|
-
expectsDir = false
|
|
389
|
-
continue
|
|
390
|
-
}
|
|
391
|
-
|
|
392
|
-
if (token === '--dir') {
|
|
393
|
-
hasDir = true
|
|
394
|
-
expectsDir = true
|
|
395
|
-
continue
|
|
396
|
-
}
|
|
397
|
-
|
|
398
|
-
return completeValues([], currentWord)
|
|
399
|
-
}
|
|
400
|
-
|
|
401
|
-
if (expectsDir) {
|
|
402
|
-
return { mode: 'files' }
|
|
403
|
-
}
|
|
404
|
-
|
|
405
|
-
return completeValues(withHelpFlags(!hasDir ? ['--dir'] : [], usedGlobalFlags), currentWord)
|
|
406
|
-
}
|
|
407
|
-
|
|
408
|
-
function completeSkillsList(
|
|
409
|
-
tokens: string[],
|
|
410
|
-
currentWord: string,
|
|
411
|
-
usedGlobalFlags: Set<string>,
|
|
412
|
-
): CompletionResult {
|
|
413
|
-
return completeSkillsDirectoryCommand(tokens, currentWord, usedGlobalFlags)
|
|
414
|
-
}
|
|
415
|
-
|
|
416
|
-
function completeSkillsDirectoryCommand(
|
|
417
|
-
tokens: string[],
|
|
418
|
-
currentWord: string,
|
|
419
|
-
usedGlobalFlags: Set<string>,
|
|
420
|
-
): CompletionResult {
|
|
421
|
-
let filteredTokens = filterGlobalCommandTokens(tokens, usedGlobalFlags)
|
|
422
|
-
if (filteredTokens == null) {
|
|
423
|
-
return completeValues([], currentWord)
|
|
424
|
-
}
|
|
425
|
-
|
|
426
|
-
let hasDir = false
|
|
427
|
-
let hasJson = false
|
|
428
|
-
let expectsDir = false
|
|
429
|
-
|
|
430
|
-
for (let token of filteredTokens) {
|
|
431
|
-
if (expectsDir) {
|
|
432
|
-
expectsDir = false
|
|
433
|
-
continue
|
|
434
|
-
}
|
|
435
|
-
|
|
436
|
-
if (token === '--dir') {
|
|
437
|
-
hasDir = true
|
|
438
|
-
expectsDir = true
|
|
439
|
-
continue
|
|
440
|
-
}
|
|
441
|
-
|
|
442
|
-
if (token === '--json') {
|
|
443
|
-
hasJson = true
|
|
444
|
-
continue
|
|
445
|
-
}
|
|
446
|
-
|
|
447
|
-
return completeValues([], currentWord)
|
|
448
|
-
}
|
|
449
|
-
|
|
450
|
-
if (expectsDir) {
|
|
451
|
-
return { mode: 'files' }
|
|
452
|
-
}
|
|
453
|
-
|
|
454
|
-
return completeValues(
|
|
455
|
-
withHelpFlags(
|
|
456
|
-
[...(!hasDir ? ['--dir'] : []), ...(!hasJson ? ['--json'] : [])],
|
|
457
|
-
usedGlobalFlags,
|
|
458
|
-
),
|
|
459
|
-
currentWord,
|
|
460
|
-
)
|
|
461
|
-
}
|
|
462
|
-
|
|
463
320
|
function completeCompletionCommand(
|
|
464
321
|
tokens: string[],
|
|
465
322
|
currentWord: string,
|
package/src/lib/errors.ts
CHANGED
|
@@ -133,11 +133,6 @@ export const CLI_ERROR_DEFINITIONS = {
|
|
|
133
133
|
title: 'Unknown help topic',
|
|
134
134
|
fix: 'Run `remix help` to see available commands and help topics.',
|
|
135
135
|
},
|
|
136
|
-
unknownSkillsCommand: {
|
|
137
|
-
code: 'RMX_UNKNOWN_SKILLS_COMMAND',
|
|
138
|
-
title: 'Unknown skills command',
|
|
139
|
-
fix: 'Run `remix skills --help` to see available skills commands.',
|
|
140
|
-
},
|
|
141
136
|
} satisfies Record<string, CliErrorDefinition>
|
|
142
137
|
|
|
143
138
|
export class CliError extends Error {
|
|
@@ -321,13 +316,6 @@ export function unknownHelpTopic(topic: string): UsageError {
|
|
|
321
316
|
})
|
|
322
317
|
}
|
|
323
318
|
|
|
324
|
-
export function unknownSkillsCommand(command: string): UsageError {
|
|
325
|
-
return createUsageError(CLI_ERROR_DEFINITIONS.unknownSkillsCommand, {
|
|
326
|
-
context: { command },
|
|
327
|
-
message: `Unknown skills command: ${command}`,
|
|
328
|
-
})
|
|
329
|
-
}
|
|
330
|
-
|
|
331
319
|
export function unexpectedExtraArgument(argument: string): UsageError {
|
|
332
320
|
return createUsageError(CLI_ERROR_DEFINITIONS.unexpectedExtraArgument, {
|
|
333
321
|
context: { argument },
|
|
@@ -1,6 +0,0 @@
|
|
|
1
|
-
import type { CliContext } from '../cli-context.ts';
|
|
2
|
-
export declare function runSkillsCommand(argv: string[], context: CliContext): Promise<number>;
|
|
3
|
-
export declare function getSkillsCommandHelpText(target?: NodeJS.WriteStream): string;
|
|
4
|
-
export declare function getSkillsInstallCommandHelpText(target?: NodeJS.WriteStream): string;
|
|
5
|
-
export declare function getSkillsListCommandHelpText(target?: NodeJS.WriteStream): string;
|
|
6
|
-
//# sourceMappingURL=skills.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"skills.d.ts","sourceRoot":"","sources":["../../../src/lib/commands/skills.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,mBAAmB,CAAA;AAsBnD,wBAAsB,gBAAgB,CAAC,IAAI,EAAE,MAAM,EAAE,EAAE,OAAO,EAAE,UAAU,GAAG,OAAO,CAAC,MAAM,CAAC,CAwB3F;AAED,wBAAgB,wBAAwB,CAAC,MAAM,GAAE,MAAM,CAAC,WAA4B,GAAG,MAAM,CAwB5F;AAED,wBAAgB,+BAA+B,CAC7C,MAAM,GAAE,MAAM,CAAC,WAA4B,GAC1C,MAAM,CAeR;AAED,wBAAgB,4BAA4B,CAAC,MAAM,GAAE,MAAM,CAAC,WAA4B,GAAG,MAAM,CAqBhG"}
|
|
@@ -1,222 +0,0 @@
|
|
|
1
|
-
import * as process from 'node:process';
|
|
2
|
-
import { getDisplayPath } from "../display-path.js";
|
|
3
|
-
import { renderCliError, toCliError, unknownSkillsCommand } from "../errors.js";
|
|
4
|
-
import { formatHelpText } from "../help-text.js";
|
|
5
|
-
import { parseArgs } from "../parse-args.js";
|
|
6
|
-
import { getSkillsOverview, installRemixSkills } from "../skills.js";
|
|
7
|
-
import { createCommandReporter, createStepProgressReporter, } from "../reporter.js";
|
|
8
|
-
const SKILLS_PROGRESS_LABELS = {
|
|
9
|
-
'compare-local-skills': 'Compare local skills',
|
|
10
|
-
'download-remix-skills-archive': 'Download Remix skills archive',
|
|
11
|
-
'fetch-remix-skills-metadata': 'Fetch Remix skills metadata from GitHub',
|
|
12
|
-
'read-local-skills-cache': 'Read local skills cache',
|
|
13
|
-
'resolve-project-root': 'Resolve project root',
|
|
14
|
-
'write-updated-skills': 'Write updated skills',
|
|
15
|
-
};
|
|
16
|
-
export async function runSkillsCommand(argv, context) {
|
|
17
|
-
if (argv.length === 0 || argv[0] === '-h' || argv[0] === '--help') {
|
|
18
|
-
process.stdout.write(getSkillsCommandHelpText());
|
|
19
|
-
return 0;
|
|
20
|
-
}
|
|
21
|
-
let [subcommand, ...rest] = argv;
|
|
22
|
-
try {
|
|
23
|
-
if (subcommand === 'install') {
|
|
24
|
-
return await runSkillsInstallCommand(rest, context);
|
|
25
|
-
}
|
|
26
|
-
if (subcommand === 'list') {
|
|
27
|
-
return await runSkillsListCommand(rest, context);
|
|
28
|
-
}
|
|
29
|
-
throw unknownSkillsCommand(subcommand);
|
|
30
|
-
}
|
|
31
|
-
catch (error) {
|
|
32
|
-
process.stderr.write(renderCliError(toCliError(error), { helpText: getSkillsCommandHelpText(process.stderr) }));
|
|
33
|
-
return 1;
|
|
34
|
-
}
|
|
35
|
-
}
|
|
36
|
-
export function getSkillsCommandHelpText(target = process.stdout) {
|
|
37
|
-
return formatHelpText({
|
|
38
|
-
commands: [
|
|
39
|
-
{
|
|
40
|
-
description: 'Install Remix skills into a local directory',
|
|
41
|
-
label: 'install [--dir <path>]',
|
|
42
|
-
},
|
|
43
|
-
{
|
|
44
|
-
description: 'List Remix skills and local status',
|
|
45
|
-
label: 'list [--dir <path>] [--json]',
|
|
46
|
-
},
|
|
47
|
-
],
|
|
48
|
-
description: 'Manage Remix skills for the current project.',
|
|
49
|
-
examples: [
|
|
50
|
-
'remix skills install',
|
|
51
|
-
'remix skills install --dir custom/skills',
|
|
52
|
-
'remix skills list --dir custom/skills',
|
|
53
|
-
'remix skills list --json',
|
|
54
|
-
],
|
|
55
|
-
usage: ['remix skills <command>'],
|
|
56
|
-
}, target);
|
|
57
|
-
}
|
|
58
|
-
export function getSkillsInstallCommandHelpText(target = process.stdout) {
|
|
59
|
-
return formatHelpText({
|
|
60
|
-
description: 'Install or refresh Remix skills in .agents/skills for the current project.',
|
|
61
|
-
examples: ['remix skills install', 'remix skills install --dir custom/skills'],
|
|
62
|
-
options: [
|
|
63
|
-
{
|
|
64
|
-
description: 'Install skills into a custom directory relative to the project root',
|
|
65
|
-
label: '--dir <path>',
|
|
66
|
-
},
|
|
67
|
-
],
|
|
68
|
-
usage: ['remix skills install [--dir <path>]'],
|
|
69
|
-
}, target);
|
|
70
|
-
}
|
|
71
|
-
export function getSkillsListCommandHelpText(target = process.stdout) {
|
|
72
|
-
return formatHelpText({
|
|
73
|
-
description: 'List Remix skills and show whether each one is installed, outdated, or missing locally.',
|
|
74
|
-
examples: [
|
|
75
|
-
'remix skills list',
|
|
76
|
-
'remix skills list --dir custom/skills',
|
|
77
|
-
'remix skills list --json',
|
|
78
|
-
],
|
|
79
|
-
options: [
|
|
80
|
-
{
|
|
81
|
-
description: 'Read local skills from a custom directory relative to the project root',
|
|
82
|
-
label: '--dir <path>',
|
|
83
|
-
},
|
|
84
|
-
{ description: 'Print skill state as JSON', label: '--json' },
|
|
85
|
-
],
|
|
86
|
-
usage: ['remix skills list [--dir <path>] [--json]'],
|
|
87
|
-
}, target);
|
|
88
|
-
}
|
|
89
|
-
async function runSkillsInstallCommand(argv, context) {
|
|
90
|
-
if (argv.includes('-h') || argv.includes('--help')) {
|
|
91
|
-
process.stdout.write(getSkillsInstallCommandHelpText());
|
|
92
|
-
return 0;
|
|
93
|
-
}
|
|
94
|
-
let reporter = null;
|
|
95
|
-
let progress = null;
|
|
96
|
-
try {
|
|
97
|
-
let options = parseSkillsInstallCommandArgs(argv);
|
|
98
|
-
reporter = createCommandReporter({ remixVersion: context.remixVersion });
|
|
99
|
-
progress = createSkillsProgressReporter(reporter);
|
|
100
|
-
let cwd = context.cwd;
|
|
101
|
-
await reporter.status.commandHeader('skills install');
|
|
102
|
-
let result = await installRemixSkills(cwd, globalThis.fetch, {
|
|
103
|
-
progress,
|
|
104
|
-
skillsDir: options.dir ?? undefined,
|
|
105
|
-
});
|
|
106
|
-
let skillsDir = getDisplayPath(result.skillsDir, cwd);
|
|
107
|
-
progress.writeSummaryGap();
|
|
108
|
-
if (result.appliedChanges.length === 0) {
|
|
109
|
-
reporter.out.line(`No changes. ${skillsDir} is up to date.`);
|
|
110
|
-
reporter.finish();
|
|
111
|
-
return 0;
|
|
112
|
-
}
|
|
113
|
-
reporter.out.line(`Synced Remix skills into ${skillsDir}:`);
|
|
114
|
-
reporter.out.bullets(formatAppliedChanges(result.appliedChanges));
|
|
115
|
-
reporter.finish();
|
|
116
|
-
return 0;
|
|
117
|
-
}
|
|
118
|
-
catch (error) {
|
|
119
|
-
progress?.writeSummaryGap();
|
|
120
|
-
process.stderr.write(renderCliError(toCliError(error), {
|
|
121
|
-
helpText: getSkillsInstallCommandHelpText(process.stderr),
|
|
122
|
-
}));
|
|
123
|
-
reporter?.finish();
|
|
124
|
-
return 1;
|
|
125
|
-
}
|
|
126
|
-
}
|
|
127
|
-
async function runSkillsListCommand(argv, context) {
|
|
128
|
-
if (argv.includes('-h') || argv.includes('--help')) {
|
|
129
|
-
process.stdout.write(getSkillsListCommandHelpText());
|
|
130
|
-
return 0;
|
|
131
|
-
}
|
|
132
|
-
let reporter = null;
|
|
133
|
-
let progress = null;
|
|
134
|
-
try {
|
|
135
|
-
let options = parseSkillsDirArgs(argv, { allowJson: true });
|
|
136
|
-
let cwd = context.cwd;
|
|
137
|
-
reporter = options.json ? null : createCommandReporter({ remixVersion: context.remixVersion });
|
|
138
|
-
if (reporter != null) {
|
|
139
|
-
progress = createSkillsProgressReporter(reporter);
|
|
140
|
-
await reporter.status.commandHeader('skills list');
|
|
141
|
-
}
|
|
142
|
-
let result = await getSkillsOverview(cwd, globalThis.fetch, {
|
|
143
|
-
progress: progress ?? undefined,
|
|
144
|
-
skillsDir: options.dir ?? undefined,
|
|
145
|
-
});
|
|
146
|
-
if (options.json) {
|
|
147
|
-
process.stdout.write(`${JSON.stringify({
|
|
148
|
-
entries: result.entries,
|
|
149
|
-
projectRoot: result.projectRoot,
|
|
150
|
-
skillsDir: result.skillsDir,
|
|
151
|
-
}, null, 2)}\n`);
|
|
152
|
-
return 0;
|
|
153
|
-
}
|
|
154
|
-
progress?.writeSummaryGap();
|
|
155
|
-
if (reporter == null) {
|
|
156
|
-
return 0;
|
|
157
|
-
}
|
|
158
|
-
let listReporter = reporter;
|
|
159
|
-
listReporter.out.line(formatSkillsListSummary(result.entries, getDisplayPath(result.skillsDir, cwd)));
|
|
160
|
-
listReporter.out.bullets(result.entries.map((entry) => formatSkillListEntry(listReporter, entry)));
|
|
161
|
-
listReporter.finish();
|
|
162
|
-
return 0;
|
|
163
|
-
}
|
|
164
|
-
catch (error) {
|
|
165
|
-
progress?.writeSummaryGap();
|
|
166
|
-
process.stderr.write(renderCliError(toCliError(error), { helpText: getSkillsListCommandHelpText(process.stderr) }));
|
|
167
|
-
reporter?.finish();
|
|
168
|
-
return 1;
|
|
169
|
-
}
|
|
170
|
-
}
|
|
171
|
-
function createSkillsProgressReporter(reporter) {
|
|
172
|
-
return createStepProgressReporter(reporter.status, SKILLS_PROGRESS_LABELS);
|
|
173
|
-
}
|
|
174
|
-
function formatAppliedChanges(changes) {
|
|
175
|
-
let showAction = changes.some((change) => change.action !== 'add');
|
|
176
|
-
return changes.map((change) => showAction ? `${toPastTense(change.action)} ${change.name}` : change.name);
|
|
177
|
-
}
|
|
178
|
-
function formatSkillListEntry(reporter, entry) {
|
|
179
|
-
if (entry.state === 'installed') {
|
|
180
|
-
return entry.name;
|
|
181
|
-
}
|
|
182
|
-
let tone = entry.state === 'missing' ? 'error' : 'warn';
|
|
183
|
-
return `${entry.name} ${reporter.out.label(entry.state, '', { tone })}`;
|
|
184
|
-
}
|
|
185
|
-
function formatSkillsListSummary(entries, skillsDir) {
|
|
186
|
-
let installedCount = entries.filter((entry) => entry.state === 'installed').length;
|
|
187
|
-
let outdatedCount = entries.filter((entry) => entry.state === 'outdated').length;
|
|
188
|
-
let missingCount = entries.filter((entry) => entry.state === 'missing').length;
|
|
189
|
-
let detailParts = [
|
|
190
|
-
installedCount > 0 ? `${installedCount} installed` : null,
|
|
191
|
-
outdatedCount > 0 ? `${outdatedCount} outdated` : null,
|
|
192
|
-
missingCount > 0 ? `${missingCount} missing` : null,
|
|
193
|
-
].filter((part) => part != null);
|
|
194
|
-
let detail = detailParts.length === 0 ? '0 installed' : detailParts.join(', ');
|
|
195
|
-
return `Checked Remix skills against ${skillsDir}: ${detail}.`;
|
|
196
|
-
}
|
|
197
|
-
function parseSkillsInstallCommandArgs(argv) {
|
|
198
|
-
let { dir } = parseSkillsDirArgs(argv);
|
|
199
|
-
return { dir };
|
|
200
|
-
}
|
|
201
|
-
function parseSkillsDirArgs(argv, options = {}) {
|
|
202
|
-
if (options.allowJson) {
|
|
203
|
-
let parsed = parseArgs(argv, {
|
|
204
|
-
dir: { flag: '--dir', type: 'string' },
|
|
205
|
-
json: { flag: '--json', type: 'boolean' },
|
|
206
|
-
}, { maxPositionals: 0 });
|
|
207
|
-
return {
|
|
208
|
-
dir: parsed.options.dir ?? null,
|
|
209
|
-
json: parsed.options.json,
|
|
210
|
-
};
|
|
211
|
-
}
|
|
212
|
-
let parsed = parseArgs(argv, {
|
|
213
|
-
dir: { flag: '--dir', type: 'string' },
|
|
214
|
-
}, { maxPositionals: 0 });
|
|
215
|
-
return {
|
|
216
|
-
dir: parsed.options.dir ?? null,
|
|
217
|
-
json: false,
|
|
218
|
-
};
|
|
219
|
-
}
|
|
220
|
-
function toPastTense(action) {
|
|
221
|
-
return action === 'add' ? 'added' : 'replaced';
|
|
222
|
-
}
|
|
@@ -1,19 +0,0 @@
|
|
|
1
|
-
export interface SkillsCacheFileEntry {
|
|
2
|
-
localHash: string;
|
|
3
|
-
remoteSha: string;
|
|
4
|
-
}
|
|
5
|
-
export interface SkillsCacheSkillEntry {
|
|
6
|
-
files: Record<string, SkillsCacheFileEntry>;
|
|
7
|
-
}
|
|
8
|
-
export interface SkillsCacheManifest {
|
|
9
|
-
ref: string;
|
|
10
|
-
repo: string;
|
|
11
|
-
skills: Record<string, SkillsCacheSkillEntry>;
|
|
12
|
-
skillsDir: string;
|
|
13
|
-
version: number;
|
|
14
|
-
}
|
|
15
|
-
export declare function createSkillsCacheManifest(skillsDir: string, skills: Record<string, SkillsCacheSkillEntry>): SkillsCacheManifest;
|
|
16
|
-
export declare function getSkillsCacheFilePath(skillsDir: string): string;
|
|
17
|
-
export declare function readSkillsCache(skillsDir: string): Promise<SkillsCacheManifest | null>;
|
|
18
|
-
export declare function writeSkillsCache(skillsDir: string, manifest: SkillsCacheManifest): Promise<void>;
|
|
19
|
-
//# sourceMappingURL=skills-cache.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"skills-cache.d.ts","sourceRoot":"","sources":["../../src/lib/skills-cache.ts"],"names":[],"mappings":"AAUA,MAAM,WAAW,oBAAoB;IACnC,SAAS,EAAE,MAAM,CAAA;IACjB,SAAS,EAAE,MAAM,CAAA;CAClB;AAED,MAAM,WAAW,qBAAqB;IACpC,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,oBAAoB,CAAC,CAAA;CAC5C;AAED,MAAM,WAAW,mBAAmB;IAClC,GAAG,EAAE,MAAM,CAAA;IACX,IAAI,EAAE,MAAM,CAAA;IACZ,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,qBAAqB,CAAC,CAAA;IAC7C,SAAS,EAAE,MAAM,CAAA;IACjB,OAAO,EAAE,MAAM,CAAA;CAChB;AAED,wBAAgB,yBAAyB,CACvC,SAAS,EAAE,MAAM,EACjB,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,qBAAqB,CAAC,GAC5C,mBAAmB,CAQrB;AAED,wBAAgB,sBAAsB,CAAC,SAAS,EAAE,MAAM,GAAG,MAAM,CAGhE;AAED,wBAAsB,eAAe,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,mBAAmB,GAAG,IAAI,CAAC,CAiB5F;AAED,wBAAsB,gBAAgB,CACpC,SAAS,EAAE,MAAM,EACjB,QAAQ,EAAE,mBAAmB,GAC5B,OAAO,CAAC,IAAI,CAAC,CAOf"}
|
package/dist/lib/skills-cache.js
DELETED
|
@@ -1,89 +0,0 @@
|
|
|
1
|
-
import * as crypto from 'node:crypto';
|
|
2
|
-
import * as fs from 'node:fs/promises';
|
|
3
|
-
import * as os from 'node:os';
|
|
4
|
-
import * as path from 'node:path';
|
|
5
|
-
import * as process from 'node:process';
|
|
6
|
-
const REMIX_SKILLS_CACHE_VERSION = 1;
|
|
7
|
-
const REMIX_SKILLS_CACHE_REPO = 'remix-run/remix';
|
|
8
|
-
const REMIX_SKILLS_CACHE_REF = 'main';
|
|
9
|
-
export function createSkillsCacheManifest(skillsDir, skills) {
|
|
10
|
-
return {
|
|
11
|
-
ref: REMIX_SKILLS_CACHE_REF,
|
|
12
|
-
repo: REMIX_SKILLS_CACHE_REPO,
|
|
13
|
-
skills,
|
|
14
|
-
skillsDir: path.resolve(skillsDir),
|
|
15
|
-
version: REMIX_SKILLS_CACHE_VERSION,
|
|
16
|
-
};
|
|
17
|
-
}
|
|
18
|
-
export function getSkillsCacheFilePath(skillsDir) {
|
|
19
|
-
let cacheKey = crypto.createHash('sha256').update(path.resolve(skillsDir)).digest('hex');
|
|
20
|
-
return path.join(getSkillsCacheDir(), `${cacheKey}.json`);
|
|
21
|
-
}
|
|
22
|
-
export async function readSkillsCache(skillsDir) {
|
|
23
|
-
try {
|
|
24
|
-
let filePath = getSkillsCacheFilePath(skillsDir);
|
|
25
|
-
let raw = JSON.parse(await fs.readFile(filePath, 'utf8'));
|
|
26
|
-
return isSkillsCacheManifest(raw, skillsDir) ? raw : null;
|
|
27
|
-
}
|
|
28
|
-
catch (error) {
|
|
29
|
-
if (error instanceof SyntaxError) {
|
|
30
|
-
return null;
|
|
31
|
-
}
|
|
32
|
-
let nodeError = error;
|
|
33
|
-
if (nodeError.code === 'ENOENT') {
|
|
34
|
-
return null;
|
|
35
|
-
}
|
|
36
|
-
throw error;
|
|
37
|
-
}
|
|
38
|
-
}
|
|
39
|
-
export async function writeSkillsCache(skillsDir, manifest) {
|
|
40
|
-
let filePath = getSkillsCacheFilePath(skillsDir);
|
|
41
|
-
let tempPath = `${filePath}.${process.pid}.${Date.now()}.tmp`;
|
|
42
|
-
await fs.mkdir(path.dirname(filePath), { recursive: true });
|
|
43
|
-
await fs.writeFile(tempPath, `${JSON.stringify(manifest, null, 2)}\n`, 'utf8');
|
|
44
|
-
await fs.rename(tempPath, filePath);
|
|
45
|
-
}
|
|
46
|
-
function getSkillsCacheDir() {
|
|
47
|
-
if (process.platform === 'win32') {
|
|
48
|
-
let localAppData = process.env.LOCALAPPDATA ?? path.join(os.homedir(), 'AppData', 'Local');
|
|
49
|
-
return path.join(localAppData, 'remix', 'Cache', 'skills');
|
|
50
|
-
}
|
|
51
|
-
if (process.platform === 'darwin') {
|
|
52
|
-
return path.join(process.env.HOME ?? os.homedir(), 'Library', 'Caches', 'remix', 'cli', 'skills');
|
|
53
|
-
}
|
|
54
|
-
let xdgCacheHome = process.env.XDG_CACHE_HOME ?? path.join(os.homedir(), '.cache');
|
|
55
|
-
return path.join(xdgCacheHome, 'remix', 'cli', 'skills');
|
|
56
|
-
}
|
|
57
|
-
function isSkillsCacheManifest(value, skillsDir) {
|
|
58
|
-
if (typeof value !== 'object' || value == null) {
|
|
59
|
-
return false;
|
|
60
|
-
}
|
|
61
|
-
if (Reflect.get(value, 'version') !== REMIX_SKILLS_CACHE_VERSION ||
|
|
62
|
-
Reflect.get(value, 'repo') !== REMIX_SKILLS_CACHE_REPO ||
|
|
63
|
-
Reflect.get(value, 'ref') !== REMIX_SKILLS_CACHE_REF ||
|
|
64
|
-
Reflect.get(value, 'skillsDir') !== path.resolve(skillsDir)) {
|
|
65
|
-
return false;
|
|
66
|
-
}
|
|
67
|
-
let skills = Reflect.get(value, 'skills');
|
|
68
|
-
if (typeof skills !== 'object' || skills == null) {
|
|
69
|
-
return false;
|
|
70
|
-
}
|
|
71
|
-
for (let skillEntry of Object.values(skills)) {
|
|
72
|
-
if (typeof skillEntry !== 'object' || skillEntry == null) {
|
|
73
|
-
return false;
|
|
74
|
-
}
|
|
75
|
-
let files = Reflect.get(skillEntry, 'files');
|
|
76
|
-
if (typeof files !== 'object' || files == null) {
|
|
77
|
-
return false;
|
|
78
|
-
}
|
|
79
|
-
for (let fileEntry of Object.values(files)) {
|
|
80
|
-
if (typeof fileEntry !== 'object' ||
|
|
81
|
-
fileEntry == null ||
|
|
82
|
-
typeof Reflect.get(fileEntry, 'localHash') !== 'string' ||
|
|
83
|
-
typeof Reflect.get(fileEntry, 'remoteSha') !== 'string') {
|
|
84
|
-
return false;
|
|
85
|
-
}
|
|
86
|
-
}
|
|
87
|
-
}
|
|
88
|
-
return true;
|
|
89
|
-
}
|
package/dist/lib/skills.d.ts
DELETED
|
@@ -1,30 +0,0 @@
|
|
|
1
|
-
import { type StepProgressReporter } from './reporter.ts';
|
|
2
|
-
export interface SkillChange {
|
|
3
|
-
action: 'add' | 'replace';
|
|
4
|
-
name: string;
|
|
5
|
-
}
|
|
6
|
-
export interface SkillStatusEntry {
|
|
7
|
-
name: string;
|
|
8
|
-
state: 'installed' | 'missing' | 'outdated';
|
|
9
|
-
}
|
|
10
|
-
interface SkillsResult {
|
|
11
|
-
entries: SkillStatusEntry[];
|
|
12
|
-
projectRoot: string;
|
|
13
|
-
skillsDir: string;
|
|
14
|
-
}
|
|
15
|
-
export interface SkillsOverview extends SkillsResult {
|
|
16
|
-
}
|
|
17
|
-
export interface SkillsInstallResult extends SkillsResult {
|
|
18
|
-
appliedChanges: SkillChange[];
|
|
19
|
-
}
|
|
20
|
-
export interface SkillsOptions {
|
|
21
|
-
progress?: SkillsProgressReporter;
|
|
22
|
-
skillsDir?: string;
|
|
23
|
-
}
|
|
24
|
-
export type SkillsInstallPhase = 'resolve-project-root' | 'fetch-remix-skills-metadata' | 'read-local-skills-cache' | 'compare-local-skills' | 'download-remix-skills-archive' | 'write-updated-skills';
|
|
25
|
-
export type SkillsProgressReporter = StepProgressReporter<SkillsInstallPhase>;
|
|
26
|
-
type FetchImpl = typeof fetch;
|
|
27
|
-
export declare function getSkillsOverview(cwd?: string, fetchImpl?: FetchImpl, options?: SkillsOptions): Promise<SkillsOverview>;
|
|
28
|
-
export declare function installRemixSkills(cwd?: string, fetchImpl?: FetchImpl, options?: SkillsOptions): Promise<SkillsInstallResult>;
|
|
29
|
-
export {};
|
|
30
|
-
//# sourceMappingURL=skills.d.ts.map
|
package/dist/lib/skills.d.ts.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"skills.d.ts","sourceRoot":"","sources":["../../src/lib/skills.ts"],"names":[],"mappings":"AASA,OAAO,EAAmB,KAAK,oBAAoB,EAAE,MAAM,eAAe,CAAA;AAe1E,MAAM,WAAW,WAAW;IAC1B,MAAM,EAAE,KAAK,GAAG,SAAS,CAAA;IACzB,IAAI,EAAE,MAAM,CAAA;CACb;AAED,MAAM,WAAW,gBAAgB;IAC/B,IAAI,EAAE,MAAM,CAAA;IACZ,KAAK,EAAE,WAAW,GAAG,SAAS,GAAG,UAAU,CAAA;CAC5C;AAED,UAAU,YAAY;IACpB,OAAO,EAAE,gBAAgB,EAAE,CAAA;IAC3B,WAAW,EAAE,MAAM,CAAA;IACnB,SAAS,EAAE,MAAM,CAAA;CAClB;AAED,MAAM,WAAW,cAAe,SAAQ,YAAY;CAAG;AAEvD,MAAM,WAAW,mBAAoB,SAAQ,YAAY;IACvD,cAAc,EAAE,WAAW,EAAE,CAAA;CAC9B;AAED,MAAM,WAAW,aAAa;IAC5B,QAAQ,CAAC,EAAE,sBAAsB,CAAA;IACjC,SAAS,CAAC,EAAE,MAAM,CAAA;CACnB;AAED,MAAM,MAAM,kBAAkB,GAC1B,sBAAsB,GACtB,6BAA6B,GAC7B,yBAAyB,GACzB,sBAAsB,GACtB,+BAA+B,GAC/B,sBAAsB,CAAA;AAE1B,MAAM,MAAM,sBAAsB,GAAG,oBAAoB,CAAC,kBAAkB,CAAC,CAAA;AA4C7E,KAAK,SAAS,GAAG,OAAO,KAAK,CAAA;AAE7B,wBAAsB,iBAAiB,CACrC,GAAG,GAAE,MAAsB,EAC3B,SAAS,GAAE,SAA4B,EACvC,OAAO,GAAE,aAAkB,GAC1B,OAAO,CAAC,cAAc,CAAC,CAOzB;AAED,wBAAsB,kBAAkB,CACtC,GAAG,GAAE,MAAsB,EAC3B,SAAS,GAAE,SAA4B,EACvC,OAAO,GAAE,aAAkB,GAC1B,OAAO,CAAC,mBAAmB,CAAC,CA4C9B"}
|