@ontrails/trails 1.0.0-beta.12 → 1.0.0-beta.14
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/.turbo/turbo-lint.log +1 -1
- package/CHANGELOG.md +40 -12
- package/__tests__/examples.test.ts +14 -0
- package/dist/src/app.d.ts.map +1 -1
- package/dist/src/app.js +13 -2
- package/dist/src/app.js.map +1 -1
- package/dist/src/clack.d.ts +1 -1
- package/dist/src/clack.js +1 -1
- package/dist/src/cli.js +2 -2
- package/dist/src/cli.js.map +1 -1
- package/dist/src/trails/add-trail.js +13 -13
- package/dist/src/trails/add-trail.js.map +1 -1
- package/dist/src/trails/add-trailhead.d.ts +13 -0
- package/dist/src/trails/add-trailhead.d.ts.map +1 -0
- package/dist/src/trails/add-trailhead.js +88 -0
- package/dist/src/trails/add-trailhead.js.map +1 -0
- package/dist/src/trails/add-verify.js +10 -10
- package/dist/src/trails/add-verify.js.map +1 -1
- package/dist/src/trails/create-scaffold.js +26 -26
- package/dist/src/trails/create-scaffold.js.map +1 -1
- package/dist/src/trails/create.d.ts +6 -6
- package/dist/src/trails/create.d.ts.map +1 -1
- package/dist/src/trails/create.js +29 -29
- package/dist/src/trails/create.js.map +1 -1
- package/dist/src/trails/dev-clean.d.ts +9 -0
- package/dist/src/trails/dev-clean.d.ts.map +1 -0
- package/dist/src/trails/dev-clean.js +65 -0
- package/dist/src/trails/dev-clean.js.map +1 -0
- package/dist/src/trails/dev-reset.d.ts +6 -0
- package/dist/src/trails/dev-reset.d.ts.map +1 -0
- package/dist/src/trails/dev-reset.js +38 -0
- package/dist/src/trails/dev-reset.js.map +1 -0
- package/dist/src/trails/dev-stats.d.ts +7 -0
- package/dist/src/trails/dev-stats.d.ts.map +1 -0
- package/dist/src/trails/dev-stats.js +61 -0
- package/dist/src/trails/dev-stats.js.map +1 -0
- package/dist/src/trails/dev-support.d.ts +64 -0
- package/dist/src/trails/dev-support.d.ts.map +1 -0
- package/dist/src/trails/dev-support.js +178 -0
- package/dist/src/trails/dev-support.js.map +1 -0
- package/dist/src/trails/draft-promote.d.ts +18 -0
- package/dist/src/trails/draft-promote.d.ts.map +1 -0
- package/dist/src/trails/draft-promote.js +386 -0
- package/dist/src/trails/draft-promote.js.map +1 -0
- package/dist/src/trails/guide.d.ts +13 -3
- package/dist/src/trails/guide.d.ts.map +1 -1
- package/dist/src/trails/guide.js +21 -37
- package/dist/src/trails/guide.js.map +1 -1
- package/dist/src/trails/load-app.d.ts +3 -1
- package/dist/src/trails/load-app.d.ts.map +1 -1
- package/dist/src/trails/load-app.js +53 -10
- package/dist/src/trails/load-app.js.map +1 -1
- package/dist/src/trails/project.d.ts.map +1 -1
- package/dist/src/trails/project.js +14 -3
- package/dist/src/trails/project.js.map +1 -1
- package/dist/src/trails/survey.d.ts +4 -58
- package/dist/src/trails/survey.d.ts.map +1 -1
- package/dist/src/trails/survey.js +52 -173
- package/dist/src/trails/survey.js.map +1 -1
- package/dist/src/trails/topo-constants.d.ts +3 -0
- package/dist/src/trails/topo-constants.d.ts.map +1 -0
- package/dist/src/trails/topo-constants.js +3 -0
- package/dist/src/trails/topo-constants.js.map +1 -0
- package/dist/src/trails/topo-export.d.ts +18 -0
- package/dist/src/trails/topo-export.d.ts.map +1 -0
- package/dist/src/trails/topo-export.js +34 -0
- package/dist/src/trails/topo-export.js.map +1 -0
- package/dist/src/trails/topo-history.d.ts +24 -0
- package/dist/src/trails/topo-history.d.ts.map +1 -0
- package/dist/src/trails/topo-history.js +33 -0
- package/dist/src/trails/topo-history.js.map +1 -0
- package/dist/src/trails/topo-pin.d.ts +21 -0
- package/dist/src/trails/topo-pin.d.ts.map +1 -0
- package/dist/src/trails/topo-pin.js +35 -0
- package/dist/src/trails/topo-pin.js.map +1 -0
- package/dist/src/trails/topo-read-support.d.ts +54 -0
- package/dist/src/trails/topo-read-support.d.ts.map +1 -0
- package/dist/src/trails/topo-read-support.js +178 -0
- package/dist/src/trails/topo-read-support.js.map +1 -0
- package/dist/src/trails/topo-reports.d.ts +50 -0
- package/dist/src/trails/topo-reports.d.ts.map +1 -0
- package/dist/src/trails/topo-reports.js +122 -0
- package/dist/src/trails/topo-reports.js.map +1 -0
- package/dist/src/trails/topo-show.d.ts +23 -0
- package/dist/src/trails/topo-show.d.ts.map +1 -0
- package/dist/src/trails/topo-show.js +53 -0
- package/dist/src/trails/topo-show.js.map +1 -0
- package/dist/src/trails/topo-store-support.d.ts +13 -0
- package/dist/src/trails/topo-store-support.d.ts.map +1 -0
- package/dist/src/trails/topo-store-support.js +55 -0
- package/dist/src/trails/topo-store-support.js.map +1 -0
- package/dist/src/trails/topo-support.d.ts +87 -0
- package/dist/src/trails/topo-support.d.ts.map +1 -0
- package/dist/src/trails/topo-support.js +165 -0
- package/dist/src/trails/topo-support.js.map +1 -0
- package/dist/src/trails/topo-unpin.d.ts +15 -0
- package/dist/src/trails/topo-unpin.d.ts.map +1 -0
- package/dist/src/trails/topo-unpin.js +39 -0
- package/dist/src/trails/topo-unpin.js.map +1 -0
- package/dist/src/trails/topo-verify.d.ts +5 -0
- package/dist/src/trails/topo-verify.d.ts.map +1 -0
- package/dist/src/trails/topo-verify.js +28 -0
- package/dist/src/trails/topo-verify.js.map +1 -0
- package/dist/src/trails/topo.d.ts +5 -0
- package/dist/src/trails/topo.d.ts.map +1 -0
- package/dist/src/trails/topo.js +67 -0
- package/dist/src/trails/topo.js.map +1 -0
- package/dist/src/trails/warden.d.ts +1 -1
- package/dist/src/trails/warden.d.ts.map +1 -1
- package/dist/src/trails/warden.js +28 -27
- package/dist/src/trails/warden.js.map +1 -1
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/package.json +8 -7
- package/src/__tests__/create.test.ts +35 -33
- package/src/__tests__/draft-promote.test.ts +144 -0
- package/src/__tests__/guide.test.ts +4 -4
- package/src/__tests__/load-app.test.ts +43 -0
- package/src/__tests__/survey.test.ts +140 -55
- package/src/__tests__/topo-dev.test.ts +424 -0
- package/src/__tests__/warden.test.ts +2 -2
- package/src/app.ts +24 -2
- package/src/clack.ts +1 -1
- package/src/cli.ts +2 -2
- package/src/trails/add-trail.ts +13 -13
- package/src/trails/{add-surface.ts → add-trailhead.ts} +39 -37
- package/src/trails/add-verify.ts +10 -10
- package/src/trails/create-scaffold.ts +28 -28
- package/src/trails/create.ts +42 -42
- package/src/trails/dev-clean.ts +73 -0
- package/src/trails/dev-reset.ts +44 -0
- package/src/trails/dev-stats.ts +64 -0
- package/src/trails/dev-support.ts +326 -0
- package/src/trails/draft-promote.ts +704 -0
- package/src/trails/guide.ts +29 -44
- package/src/trails/load-app.ts +76 -13
- package/src/trails/project.ts +17 -3
- package/src/trails/survey.ts +80 -279
- package/src/trails/topo-constants.ts +2 -0
- package/src/trails/topo-export.ts +39 -0
- package/src/trails/topo-history.ts +40 -0
- package/src/trails/topo-pin.ts +42 -0
- package/src/trails/topo-read-support.ts +332 -0
- package/src/trails/topo-reports.ts +221 -0
- package/src/trails/topo-show.ts +58 -0
- package/src/trails/topo-store-support.ts +96 -0
- package/src/trails/topo-support.ts +274 -0
- package/src/trails/topo-unpin.ts +51 -0
- package/src/trails/topo-verify.ts +29 -0
- package/src/trails/topo.ts +73 -0
- package/src/trails/warden.ts +33 -32
package/src/trails/guide.ts
CHANGED
|
@@ -4,11 +4,14 @@
|
|
|
4
4
|
* Lists trails with descriptions and examples. Detailed guidance is planned for post-v1.
|
|
5
5
|
*/
|
|
6
6
|
|
|
7
|
-
import
|
|
8
|
-
import { Result, trail } from '@ontrails/core';
|
|
7
|
+
import { NotFoundError, Result, trail } from '@ontrails/core';
|
|
9
8
|
import { z } from 'zod';
|
|
10
9
|
|
|
11
10
|
import { loadApp } from './load-app.js';
|
|
11
|
+
import {
|
|
12
|
+
buildCurrentGuideEntries,
|
|
13
|
+
buildCurrentTopoDetail,
|
|
14
|
+
} from './topo-read-support.js';
|
|
12
15
|
|
|
13
16
|
// ---------------------------------------------------------------------------
|
|
14
17
|
// Types
|
|
@@ -25,41 +28,36 @@ interface GuideEntry {
|
|
|
25
28
|
// Helpers
|
|
26
29
|
// ---------------------------------------------------------------------------
|
|
27
30
|
|
|
28
|
-
const
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
const raw = item as unknown as Record<string, unknown>;
|
|
33
|
-
entries.push({
|
|
34
|
-
description:
|
|
35
|
-
typeof raw['description'] === 'string'
|
|
36
|
-
? raw['description']
|
|
37
|
-
: '(no description)',
|
|
38
|
-
exampleCount: Array.isArray(raw['examples'])
|
|
39
|
-
? (raw['examples'] as unknown[]).length
|
|
40
|
-
: 0,
|
|
41
|
-
id: item.id,
|
|
42
|
-
kind: item.kind,
|
|
43
|
-
});
|
|
44
|
-
}
|
|
45
|
-
|
|
46
|
-
return entries;
|
|
47
|
-
};
|
|
31
|
+
export const guideTrail = trail('guide', {
|
|
32
|
+
blaze: async (input, ctx) => {
|
|
33
|
+
const rootDir = ctx.cwd ?? '.';
|
|
34
|
+
const app = await loadApp(input.module, rootDir);
|
|
48
35
|
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
}
|
|
36
|
+
if (input.trailId) {
|
|
37
|
+
const detail = buildCurrentTopoDetail(app, input.trailId, { rootDir });
|
|
38
|
+
if (detail === undefined || detail.kind !== 'trail') {
|
|
39
|
+
return Result.err(
|
|
40
|
+
new NotFoundError(`Trail not found: ${input.trailId}`)
|
|
41
|
+
);
|
|
42
|
+
}
|
|
43
|
+
return Result.ok({
|
|
44
|
+
description: detail.description,
|
|
45
|
+
detours: detail.detours,
|
|
46
|
+
examples: detail.examples,
|
|
47
|
+
id: detail.id,
|
|
48
|
+
kind: detail.kind,
|
|
49
|
+
});
|
|
50
|
+
}
|
|
56
51
|
|
|
57
|
-
|
|
52
|
+
return Result.ok(
|
|
53
|
+
buildCurrentGuideEntries(app, { rootDir }) as GuideEntry[]
|
|
54
|
+
);
|
|
55
|
+
},
|
|
58
56
|
description: 'Runtime guidance for trails',
|
|
59
57
|
examples: [
|
|
60
58
|
{
|
|
61
59
|
description: 'Lists all trails with descriptions and example counts',
|
|
62
|
-
input: {},
|
|
60
|
+
input: { module: './src/app.ts' },
|
|
63
61
|
name: 'List trail guidance',
|
|
64
62
|
},
|
|
65
63
|
],
|
|
@@ -88,17 +86,4 @@ export const guideTrail = trail('guide', {
|
|
|
88
86
|
kind: z.string(),
|
|
89
87
|
}),
|
|
90
88
|
]),
|
|
91
|
-
run: async (input, ctx) => {
|
|
92
|
-
const app = await loadApp(input.module, ctx.cwd ?? '.');
|
|
93
|
-
|
|
94
|
-
if (input.trailId) {
|
|
95
|
-
const item = app.get(input.trailId);
|
|
96
|
-
if (!item) {
|
|
97
|
-
return Result.err(new Error(`Trail not found: ${input.trailId}`));
|
|
98
|
-
}
|
|
99
|
-
return Result.ok(toGuideDetail(item as Trail<unknown, unknown>));
|
|
100
|
-
}
|
|
101
|
-
|
|
102
|
-
return Result.ok(toGuideEntries(app));
|
|
103
|
-
},
|
|
104
89
|
});
|
package/src/trails/load-app.ts
CHANGED
|
@@ -1,31 +1,94 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
1
|
+
import { existsSync, rmSync } from 'node:fs';
|
|
2
|
+
import { basename, dirname, isAbsolute, join, resolve } from 'node:path';
|
|
3
|
+
import { fileURLToPath, pathToFileURL } from 'node:url';
|
|
3
4
|
|
|
4
5
|
import type { Topo } from '@ontrails/core';
|
|
5
6
|
|
|
6
7
|
const URL_SCHEME = /^[a-zA-Z][a-zA-Z\d+.-]*:/;
|
|
7
8
|
|
|
8
|
-
|
|
9
|
-
const
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
}
|
|
9
|
+
const resolveUrlModulePath = (modulePath: string): string => {
|
|
10
|
+
const url = new URL(modulePath);
|
|
11
|
+
return url.protocol === 'file:' ? fileURLToPath(url) : modulePath;
|
|
12
|
+
};
|
|
13
13
|
|
|
14
|
+
const resolveFilesystemModulePath = (
|
|
15
|
+
modulePath: string,
|
|
16
|
+
cwd: string
|
|
17
|
+
): string => {
|
|
14
18
|
const absolutePath = isAbsolute(modulePath)
|
|
15
19
|
? modulePath
|
|
16
20
|
: resolve(cwd, modulePath);
|
|
17
|
-
|
|
21
|
+
if (!absolutePath.endsWith('.js') || existsSync(absolutePath)) {
|
|
22
|
+
return absolutePath;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
const tsPath = absolutePath.replace(/\.js$/, '.ts');
|
|
26
|
+
return existsSync(tsPath) ? tsPath : absolutePath;
|
|
27
|
+
};
|
|
28
|
+
|
|
29
|
+
/** Resolve a module path from cwd so CLI defaults behave like shell paths. */
|
|
30
|
+
const resolveAbsoluteModulePath = (modulePath: string, cwd: string): string =>
|
|
31
|
+
URL_SCHEME.test(modulePath)
|
|
32
|
+
? resolveUrlModulePath(modulePath)
|
|
33
|
+
: resolveFilesystemModulePath(modulePath, cwd);
|
|
34
|
+
|
|
35
|
+
const freshModuleCopyPath = (absolutePath: string): string =>
|
|
36
|
+
join(
|
|
37
|
+
dirname(absolutePath),
|
|
38
|
+
`.__fresh-${Date.now()}-${Math.random().toString(36).slice(2)}-${basename(absolutePath)}`
|
|
39
|
+
);
|
|
40
|
+
|
|
41
|
+
/**
|
|
42
|
+
* Import a module bypassing the ESM cache for the entry file.
|
|
43
|
+
*
|
|
44
|
+
* @remarks
|
|
45
|
+
* Cache-busting applies to the entry module only. Transitive imports resolved
|
|
46
|
+
* by the entry file are still served from Bun's module cache. This is
|
|
47
|
+
* acceptable for the draft promotion workflow (the only caller) because
|
|
48
|
+
* promotion changes which modules the entry file imports, not the modules
|
|
49
|
+
* themselves. If a deeper cache-bust is needed in the future, consider
|
|
50
|
+
* Bun's `Loader.registry` or a full process restart.
|
|
51
|
+
*/
|
|
52
|
+
const importFreshModule = async (
|
|
53
|
+
modulePath: string,
|
|
54
|
+
cwd: string
|
|
55
|
+
): Promise<Record<string, unknown>> => {
|
|
56
|
+
const absolutePath = resolveAbsoluteModulePath(modulePath, cwd);
|
|
57
|
+
if (URL_SCHEME.test(absolutePath) && !absolutePath.startsWith('/')) {
|
|
58
|
+
const url = new URL(absolutePath);
|
|
59
|
+
url.searchParams.set('t', Date.now().toString());
|
|
60
|
+
return (await import(url.href)) as Record<string, unknown>;
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
const freshPath = freshModuleCopyPath(absolutePath);
|
|
64
|
+
await Bun.write(freshPath, await Bun.file(absolutePath).text());
|
|
65
|
+
|
|
66
|
+
try {
|
|
67
|
+
return (await import(pathToFileURL(freshPath).href)) as Record<
|
|
68
|
+
string,
|
|
69
|
+
unknown
|
|
70
|
+
>;
|
|
71
|
+
} finally {
|
|
72
|
+
rmSync(freshPath, { force: true });
|
|
73
|
+
}
|
|
18
74
|
};
|
|
19
75
|
|
|
20
76
|
/** Load a Topo export from a module path relative to cwd. */
|
|
21
77
|
export const loadApp = async (
|
|
22
78
|
modulePath: string,
|
|
23
|
-
cwd: string
|
|
79
|
+
cwd: string,
|
|
80
|
+
options: { fresh?: boolean | undefined } = {}
|
|
24
81
|
): Promise<Topo> => {
|
|
25
|
-
const
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
82
|
+
const resolvedModulePath = resolveAbsoluteModulePath(modulePath, cwd);
|
|
83
|
+
const mod =
|
|
84
|
+
options.fresh === true
|
|
85
|
+
? await importFreshModule(modulePath, cwd)
|
|
86
|
+
: ((await import(
|
|
87
|
+
URL_SCHEME.test(resolvedModulePath) &&
|
|
88
|
+
!resolvedModulePath.startsWith('/')
|
|
89
|
+
? new URL(resolvedModulePath).href
|
|
90
|
+
: pathToFileURL(resolvedModulePath).href
|
|
91
|
+
)) as Record<string, unknown>);
|
|
29
92
|
const app = (mod['default'] ?? mod['app']) as Topo | undefined;
|
|
30
93
|
if (!app?.trails) {
|
|
31
94
|
throw new Error(
|
package/src/trails/project.ts
CHANGED
|
@@ -5,10 +5,24 @@
|
|
|
5
5
|
import { existsSync } from 'node:fs';
|
|
6
6
|
import { join } from 'node:path';
|
|
7
7
|
|
|
8
|
+
import { isDraftMarkedFile } from '@ontrails/warden';
|
|
9
|
+
|
|
8
10
|
/** Return all TypeScript entries in a project's src directory. */
|
|
9
|
-
const
|
|
10
|
-
|
|
11
|
-
|
|
11
|
+
const sourceEntryPriority = (entry: string): number => {
|
|
12
|
+
if (entry === 'app.ts') {
|
|
13
|
+
return 0;
|
|
14
|
+
}
|
|
15
|
+
return isDraftMarkedFile(entry) ? 2 : 1;
|
|
16
|
+
};
|
|
17
|
+
|
|
18
|
+
const scanSourceEntries = (srcDir: string): string[] =>
|
|
19
|
+
[...new Bun.Glob('*.ts').scanSync({ cwd: srcDir })].toSorted((a, b) => {
|
|
20
|
+
const priority = sourceEntryPriority(a) - sourceEntryPriority(b);
|
|
21
|
+
if (priority === 0) {
|
|
22
|
+
return a.localeCompare(b);
|
|
23
|
+
}
|
|
24
|
+
return priority;
|
|
25
|
+
});
|
|
12
26
|
|
|
13
27
|
/** Resolve an entry to an app import if it contains topo(). */
|
|
14
28
|
const toTopoImport = async (
|