@deskwork/core 0.15.0 → 0.17.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/dist/doctor/rules/legacy-stage-artifact-path.d.ts +28 -0
- package/dist/doctor/rules/legacy-stage-artifact-path.d.ts.map +1 -0
- package/dist/doctor/rules/legacy-stage-artifact-path.js +232 -0
- package/dist/doctor/rules/legacy-stage-artifact-path.js.map +1 -0
- package/dist/doctor/rules/legacy-stage-artifact-path.ts +285 -0
- package/dist/doctor/runner.d.ts.map +1 -1
- package/dist/doctor/runner.js +2 -0
- package/dist/doctor/runner.js.map +1 -1
- package/dist/entry/annotations.d.ts +38 -3
- package/dist/entry/annotations.d.ts.map +1 -1
- package/dist/entry/annotations.js +164 -3
- package/dist/entry/annotations.js.map +1 -1
- package/dist/entry/approve.d.ts +21 -4
- package/dist/entry/approve.d.ts.map +1 -1
- package/dist/entry/approve.js +74 -7
- package/dist/entry/approve.js.map +1 -1
- package/dist/entry/snapshot.d.ts +51 -0
- package/dist/entry/snapshot.d.ts.map +1 -0
- package/dist/entry/snapshot.js +95 -0
- package/dist/entry/snapshot.js.map +1 -0
- package/dist/ingest-derive.d.ts +1 -1
- package/dist/ingest-derive.d.ts.map +1 -1
- package/dist/ingest-derive.js +10 -7
- package/dist/ingest-derive.js.map +1 -1
- package/dist/ingest-id.d.ts +33 -0
- package/dist/ingest-id.d.ts.map +1 -0
- package/dist/ingest-id.js +60 -0
- package/dist/ingest-id.js.map +1 -0
- package/dist/ingest.d.ts.map +1 -1
- package/dist/ingest.js +23 -0
- package/dist/ingest.js.map +1 -1
- package/dist/iterate/iterate.d.ts.map +1 -1
- package/dist/iterate/iterate.js +37 -25
- package/dist/iterate/iterate.js.map +1 -1
- package/dist/review/types.d.ts +56 -1
- package/dist/review/types.d.ts.map +1 -1
- package/dist/review/types.js.map +1 -1
- package/dist/schema/draft-annotation.d.ts +108 -24
- package/dist/schema/draft-annotation.d.ts.map +1 -1
- package/dist/schema/draft-annotation.js +23 -0
- package/dist/schema/draft-annotation.js.map +1 -1
- package/dist/schema/journal-events.d.ts +240 -104
- package/dist/schema/journal-events.d.ts.map +1 -1
- package/dist/scrapbook/crud-at-dir.d.ts +47 -0
- package/dist/scrapbook/crud-at-dir.d.ts.map +1 -0
- package/dist/scrapbook/crud-at-dir.js +114 -0
- package/dist/scrapbook/crud-at-dir.js.map +1 -0
- package/dist/scrapbook/crud-slug.d.ts +33 -0
- package/dist/scrapbook/crud-slug.d.ts.map +1 -0
- package/dist/scrapbook/crud-slug.js +99 -0
- package/dist/scrapbook/crud-slug.js.map +1 -0
- package/dist/scrapbook/format.d.ts +10 -0
- package/dist/scrapbook/format.d.ts.map +1 -0
- package/dist/scrapbook/format.js +41 -0
- package/dist/scrapbook/format.js.map +1 -0
- package/dist/scrapbook/listing.d.ts +94 -0
- package/dist/scrapbook/listing.d.ts.map +1 -0
- package/dist/scrapbook/listing.js +167 -0
- package/dist/scrapbook/listing.js.map +1 -0
- package/dist/scrapbook/paths.d.ts +115 -0
- package/dist/scrapbook/paths.d.ts.map +1 -0
- package/dist/scrapbook/paths.js +149 -0
- package/dist/scrapbook/paths.js.map +1 -0
- package/dist/scrapbook/read.d.ts +54 -0
- package/dist/scrapbook/read.d.ts.map +1 -0
- package/dist/scrapbook/read.js +62 -0
- package/dist/scrapbook/read.js.map +1 -0
- package/dist/scrapbook/seed.d.ts +19 -0
- package/dist/scrapbook/seed.d.ts.map +1 -0
- package/dist/scrapbook/seed.js +46 -0
- package/dist/scrapbook/seed.js.map +1 -0
- package/dist/scrapbook/types.d.ts +44 -0
- package/dist/scrapbook/types.d.ts.map +1 -0
- package/dist/scrapbook/types.js +11 -0
- package/dist/scrapbook/types.js.map +1 -0
- package/dist/scrapbook/validation.d.ts +28 -0
- package/dist/scrapbook/validation.d.ts.map +1 -0
- package/dist/scrapbook/validation.js +98 -0
- package/dist/scrapbook/validation.js.map +1 -0
- package/dist/scrapbook.d.ts +43 -277
- package/dist/scrapbook.d.ts.map +1 -1
- package/dist/scrapbook.js +42 -535
- package/dist/scrapbook.js.map +1 -1
- package/package.json +5 -1
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"listing.js","sourceRoot":"","sources":["../../src/scrapbook/listing.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,115 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Scrapbook path resolvers.
|
|
3
|
+
*
|
|
4
|
+
* Public surface (entry-aware family — refactor-proof):
|
|
5
|
+
* - `scrapbookDirAtPath(projectRoot, config, site, relPath)` — resolve
|
|
6
|
+
* a scrapbook dir for an arbitrary fs-relative path under the site's
|
|
7
|
+
* content directory.
|
|
8
|
+
* - `scrapbookDirForEntry(projectRoot, config, site, entry, index)` —
|
|
9
|
+
* the canonical resolver. Looks up the entry's bound file via the
|
|
10
|
+
* content index when the entry has an id; falls back to the private
|
|
11
|
+
* slug-template path internally for legacy / pre-sidecar entries.
|
|
12
|
+
* - `scrapbookFilePathAtDir(scrapbookDirAbs, filename, opts)` — resolve
|
|
13
|
+
* a filename inside an already-resolved scrapbook dir, with
|
|
14
|
+
* traversal protection.
|
|
15
|
+
*
|
|
16
|
+
* Private (internal — no longer exported from `@deskwork/core/scrapbook`):
|
|
17
|
+
* - `_scrapbookDirSlug(projectRoot, config, site, slug)` — resolve a
|
|
18
|
+
* scrapbook dir by slug-template addressing
|
|
19
|
+
* (`<contentDir>/<slug>/scrapbook`). Used as the fallback inside
|
|
20
|
+
* `scrapbookDirForEntry` when an entry has no id binding yet, and
|
|
21
|
+
* by other internal helpers in the scrapbook module family that
|
|
22
|
+
* accept a slug. The legacy public name `scrapbookDir` was removed
|
|
23
|
+
* in #192 because it gave callers a way to write to the wrong path
|
|
24
|
+
* for entries whose on-disk file diverges from the slug template.
|
|
25
|
+
* - `_scrapbookFilePathSlug(projectRoot, config, site, slug, filename, opts)`
|
|
26
|
+
* — resolve a filename via the slug-template path. Used internally
|
|
27
|
+
* by the legacy slug-keyed read helpers (`readScrapbookFile`,
|
|
28
|
+
* `listScrapbook`, `countScrapbook`).
|
|
29
|
+
*
|
|
30
|
+
* The private helpers are not re-exported from the barrel
|
|
31
|
+
* (`packages/core/src/scrapbook.ts`) and are not in
|
|
32
|
+
* `package.json#exports["./scrapbook"]`. External callers must go
|
|
33
|
+
* through `scrapbookDirForEntry` (entry-aware) or `scrapbookDirAtPath`
|
|
34
|
+
* (path-aware).
|
|
35
|
+
*/
|
|
36
|
+
import type { DeskworkConfig } from '../config.ts';
|
|
37
|
+
import type { ContentIndex } from '../content-index.ts';
|
|
38
|
+
import { type ScrapbookLocation } from './types.ts';
|
|
39
|
+
/**
|
|
40
|
+
* INTERNAL — slug-template scrapbook dir resolver.
|
|
41
|
+
*
|
|
42
|
+
* Resolves to `<contentDir>/<slug>/scrapbook`. Used as the fallback
|
|
43
|
+
* inside `scrapbookDirForEntry` when an entry has no id binding yet,
|
|
44
|
+
* and by the legacy slug-keyed read helpers
|
|
45
|
+
* (`readScrapbookFile`, `listScrapbook`, `countScrapbook`).
|
|
46
|
+
*
|
|
47
|
+
* NOT exported publicly post-#192 — see file-level docstring.
|
|
48
|
+
*/
|
|
49
|
+
export declare function _scrapbookDirSlug(projectRoot: string, config: DeskworkConfig, site: string, slug: string): string;
|
|
50
|
+
/**
|
|
51
|
+
* INTERNAL — slug-template scrapbook file path.
|
|
52
|
+
*
|
|
53
|
+
* NOT exported publicly post-#192. Mirrors `scrapbookFilePathAtDir`
|
|
54
|
+
* but takes a slug instead of a pre-resolved dir.
|
|
55
|
+
*/
|
|
56
|
+
export declare function _scrapbookFilePathSlug(projectRoot: string, config: DeskworkConfig, site: string, slug: string, filename: string, opts?: ScrapbookLocation): string;
|
|
57
|
+
/**
|
|
58
|
+
* Resolve the scrapbook directory for an arbitrary path under the site's
|
|
59
|
+
* content directory. Used by Phase 19c+ callers (e.g. the studio) that
|
|
60
|
+
* already know the fs-relative path of an organizational or tracked node
|
|
61
|
+
* and don't want to re-derive it through the slug regex. The path may
|
|
62
|
+
* contain `/` segments; no `..` or absolute paths allowed.
|
|
63
|
+
*
|
|
64
|
+
* Path-shape validation matches `assertSlug` since the on-disk layout
|
|
65
|
+
* is the same shape — kebab-case segments separated by `/`. Different
|
|
66
|
+
* helper, same constraint.
|
|
67
|
+
*/
|
|
68
|
+
export declare function scrapbookDirAtPath(projectRoot: string, config: DeskworkConfig, site: string, relPath: string): string;
|
|
69
|
+
/**
|
|
70
|
+
* Resolve the scrapbook directory for a tracked calendar entry.
|
|
71
|
+
*
|
|
72
|
+
* This is the canonical public scrapbook-dir resolver post-#192. Callers
|
|
73
|
+
* that previously reached for `scrapbookDir(slug)` go through this
|
|
74
|
+
* helper instead — pass `{ slug }` (id optional) and the resolver will
|
|
75
|
+
* still walk the right path.
|
|
76
|
+
*
|
|
77
|
+
* Derives the scrapbook location from the parent directory of the
|
|
78
|
+
* entry's content file (located via `findEntryFile`, which prefers the
|
|
79
|
+
* frontmatter-id index over the slug template). Falls back to the
|
|
80
|
+
* private slug-template helper (`_scrapbookDirSlug`) for entries that
|
|
81
|
+
* haven't been bound to frontmatter yet (pre-doctor state) — the
|
|
82
|
+
* fallback is internal and the operator never sees a different code
|
|
83
|
+
* path.
|
|
84
|
+
*
|
|
85
|
+
* Refactor-proof: when the operator renames an entry's directory on
|
|
86
|
+
* disk, the next request rebuilds the index and the scrapbook now
|
|
87
|
+
* lives at the new path automatically.
|
|
88
|
+
*
|
|
89
|
+
* @param entry Calendar entry — `id` preferred (Phase 19+); `slug` is
|
|
90
|
+
* used both as the legacy fallback and to locate the
|
|
91
|
+
* `<dirname>/scrapbook/` when the entry has no id yet.
|
|
92
|
+
* @param index Optional pre-built index (per-request memoization). When
|
|
93
|
+
* omitted, this function builds one.
|
|
94
|
+
*/
|
|
95
|
+
export declare function scrapbookDirForEntry(projectRoot: string, config: DeskworkConfig, site: string, entry: {
|
|
96
|
+
id?: string;
|
|
97
|
+
slug: string;
|
|
98
|
+
}, index?: ContentIndex): string;
|
|
99
|
+
/**
|
|
100
|
+
* Resolve a filename inside an already-resolved scrapbook directory.
|
|
101
|
+
* Mirrors `listScrapbookAtDir` — used by callers that have already
|
|
102
|
+
* resolved the on-disk dir via `scrapbookDirForEntry` (id-driven) or
|
|
103
|
+
* `scrapbookDirAtPath` (fs-path-driven).
|
|
104
|
+
*
|
|
105
|
+
* Security guards:
|
|
106
|
+
* - `assertFilename` blocks dotfiles / `..` / absolute paths in the filename
|
|
107
|
+
* - the `startsWith(dir + '/')` containment check blocks any traversal
|
|
108
|
+
* that slipped through (so `secret/` always sits inside the top-level
|
|
109
|
+
* scrapbook dir)
|
|
110
|
+
*
|
|
111
|
+
* The slug-shape validator is bypassed because the caller has already
|
|
112
|
+
* proven the directory exists in the content tree by other means.
|
|
113
|
+
*/
|
|
114
|
+
export declare function scrapbookFilePathAtDir(scrapbookDirAbs: string, filename: string, opts?: ScrapbookLocation): string;
|
|
115
|
+
//# sourceMappingURL=paths.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"paths.d.ts","sourceRoot":"","sources":["../../src/scrapbook/paths.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAkCG;AAGH,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,cAAc,CAAC;AACnD,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAC;AAOxD,OAAO,EAAiB,KAAK,iBAAiB,EAAE,MAAM,YAAY,CAAC;AAMnE;;;;;;;;;GASG;AACH,wBAAgB,iBAAiB,CAC/B,WAAW,EAAE,MAAM,EACnB,MAAM,EAAE,cAAc,EACtB,IAAI,EAAE,MAAM,EACZ,IAAI,EAAE,MAAM,GACX,MAAM,CAIR;AAED;;;;;GAKG;AACH,wBAAgB,sBAAsB,CACpC,WAAW,EAAE,MAAM,EACnB,MAAM,EAAE,cAAc,EACtB,IAAI,EAAE,MAAM,EACZ,IAAI,EAAE,MAAM,EACZ,QAAQ,EAAE,MAAM,EAChB,IAAI,GAAE,iBAAsB,GAC3B,MAAM,CAMR;AAMD;;;;;;;;;;GAUG;AACH,wBAAgB,kBAAkB,CAChC,WAAW,EAAE,MAAM,EACnB,MAAM,EAAE,cAAc,EACtB,IAAI,EAAE,MAAM,EACZ,OAAO,EAAE,MAAM,GACd,MAAM,CAIR;AAED;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AACH,wBAAgB,oBAAoB,CAClC,WAAW,EAAE,MAAM,EACnB,MAAM,EAAE,cAAc,EACtB,IAAI,EAAE,MAAM,EACZ,KAAK,EAAE;IAAE,EAAE,CAAC,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE,EACpC,KAAK,CAAC,EAAE,YAAY,GACnB,MAAM,CAoBR;AAED;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,sBAAsB,CACpC,eAAe,EAAE,MAAM,EACvB,QAAQ,EAAE,MAAM,EAChB,IAAI,GAAE,iBAAsB,GAC3B,MAAM,CAUR"}
|
|
@@ -0,0 +1,149 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Scrapbook path resolvers.
|
|
3
|
+
*
|
|
4
|
+
* Public surface (entry-aware family — refactor-proof):
|
|
5
|
+
* - `scrapbookDirAtPath(projectRoot, config, site, relPath)` — resolve
|
|
6
|
+
* a scrapbook dir for an arbitrary fs-relative path under the site's
|
|
7
|
+
* content directory.
|
|
8
|
+
* - `scrapbookDirForEntry(projectRoot, config, site, entry, index)` —
|
|
9
|
+
* the canonical resolver. Looks up the entry's bound file via the
|
|
10
|
+
* content index when the entry has an id; falls back to the private
|
|
11
|
+
* slug-template path internally for legacy / pre-sidecar entries.
|
|
12
|
+
* - `scrapbookFilePathAtDir(scrapbookDirAbs, filename, opts)` — resolve
|
|
13
|
+
* a filename inside an already-resolved scrapbook dir, with
|
|
14
|
+
* traversal protection.
|
|
15
|
+
*
|
|
16
|
+
* Private (internal — no longer exported from `@deskwork/core/scrapbook`):
|
|
17
|
+
* - `_scrapbookDirSlug(projectRoot, config, site, slug)` — resolve a
|
|
18
|
+
* scrapbook dir by slug-template addressing
|
|
19
|
+
* (`<contentDir>/<slug>/scrapbook`). Used as the fallback inside
|
|
20
|
+
* `scrapbookDirForEntry` when an entry has no id binding yet, and
|
|
21
|
+
* by other internal helpers in the scrapbook module family that
|
|
22
|
+
* accept a slug. The legacy public name `scrapbookDir` was removed
|
|
23
|
+
* in #192 because it gave callers a way to write to the wrong path
|
|
24
|
+
* for entries whose on-disk file diverges from the slug template.
|
|
25
|
+
* - `_scrapbookFilePathSlug(projectRoot, config, site, slug, filename, opts)`
|
|
26
|
+
* — resolve a filename via the slug-template path. Used internally
|
|
27
|
+
* by the legacy slug-keyed read helpers (`readScrapbookFile`,
|
|
28
|
+
* `listScrapbook`, `countScrapbook`).
|
|
29
|
+
*
|
|
30
|
+
* The private helpers are not re-exported from the barrel
|
|
31
|
+
* (`packages/core/src/scrapbook.ts`) and are not in
|
|
32
|
+
* `package.json#exports["./scrapbook"]`. External callers must go
|
|
33
|
+
* through `scrapbookDirForEntry` (entry-aware) or `scrapbookDirAtPath`
|
|
34
|
+
* (path-aware).
|
|
35
|
+
*/
|
|
36
|
+
import { dirname, join, resolve } from 'node:path';
|
|
37
|
+
import { findEntryFile, resolveBlogPostDir, resolveContentDir, } from "../paths.js";
|
|
38
|
+
import { assertFilename, assertSlug } from "./validation.js";
|
|
39
|
+
import { SECRET_SUBDIR } from "./types.js";
|
|
40
|
+
// ---------------------------------------------------------------------------
|
|
41
|
+
// Private — slug-template (used as fallback inside the entry-aware family)
|
|
42
|
+
// ---------------------------------------------------------------------------
|
|
43
|
+
/**
|
|
44
|
+
* INTERNAL — slug-template scrapbook dir resolver.
|
|
45
|
+
*
|
|
46
|
+
* Resolves to `<contentDir>/<slug>/scrapbook`. Used as the fallback
|
|
47
|
+
* inside `scrapbookDirForEntry` when an entry has no id binding yet,
|
|
48
|
+
* and by the legacy slug-keyed read helpers
|
|
49
|
+
* (`readScrapbookFile`, `listScrapbook`, `countScrapbook`).
|
|
50
|
+
*
|
|
51
|
+
* NOT exported publicly post-#192 — see file-level docstring.
|
|
52
|
+
*/
|
|
53
|
+
export function _scrapbookDirSlug(projectRoot, config, site, slug) {
|
|
54
|
+
assertSlug(slug);
|
|
55
|
+
const articleDir = resolveBlogPostDir(projectRoot, config, site, slug);
|
|
56
|
+
return join(articleDir, 'scrapbook');
|
|
57
|
+
}
|
|
58
|
+
/**
|
|
59
|
+
* INTERNAL — slug-template scrapbook file path.
|
|
60
|
+
*
|
|
61
|
+
* NOT exported publicly post-#192. Mirrors `scrapbookFilePathAtDir`
|
|
62
|
+
* but takes a slug instead of a pre-resolved dir.
|
|
63
|
+
*/
|
|
64
|
+
export function _scrapbookFilePathSlug(projectRoot, config, site, slug, filename, opts = {}) {
|
|
65
|
+
return scrapbookFilePathAtDir(_scrapbookDirSlug(projectRoot, config, site, slug), filename, opts);
|
|
66
|
+
}
|
|
67
|
+
// ---------------------------------------------------------------------------
|
|
68
|
+
// Public — path-driven + entry-aware resolvers
|
|
69
|
+
// ---------------------------------------------------------------------------
|
|
70
|
+
/**
|
|
71
|
+
* Resolve the scrapbook directory for an arbitrary path under the site's
|
|
72
|
+
* content directory. Used by Phase 19c+ callers (e.g. the studio) that
|
|
73
|
+
* already know the fs-relative path of an organizational or tracked node
|
|
74
|
+
* and don't want to re-derive it through the slug regex. The path may
|
|
75
|
+
* contain `/` segments; no `..` or absolute paths allowed.
|
|
76
|
+
*
|
|
77
|
+
* Path-shape validation matches `assertSlug` since the on-disk layout
|
|
78
|
+
* is the same shape — kebab-case segments separated by `/`. Different
|
|
79
|
+
* helper, same constraint.
|
|
80
|
+
*/
|
|
81
|
+
export function scrapbookDirAtPath(projectRoot, config, site, relPath) {
|
|
82
|
+
assertSlug(relPath);
|
|
83
|
+
const articleDir = join(resolveContentDir(projectRoot, config, site), relPath);
|
|
84
|
+
return join(articleDir, 'scrapbook');
|
|
85
|
+
}
|
|
86
|
+
/**
|
|
87
|
+
* Resolve the scrapbook directory for a tracked calendar entry.
|
|
88
|
+
*
|
|
89
|
+
* This is the canonical public scrapbook-dir resolver post-#192. Callers
|
|
90
|
+
* that previously reached for `scrapbookDir(slug)` go through this
|
|
91
|
+
* helper instead — pass `{ slug }` (id optional) and the resolver will
|
|
92
|
+
* still walk the right path.
|
|
93
|
+
*
|
|
94
|
+
* Derives the scrapbook location from the parent directory of the
|
|
95
|
+
* entry's content file (located via `findEntryFile`, which prefers the
|
|
96
|
+
* frontmatter-id index over the slug template). Falls back to the
|
|
97
|
+
* private slug-template helper (`_scrapbookDirSlug`) for entries that
|
|
98
|
+
* haven't been bound to frontmatter yet (pre-doctor state) — the
|
|
99
|
+
* fallback is internal and the operator never sees a different code
|
|
100
|
+
* path.
|
|
101
|
+
*
|
|
102
|
+
* Refactor-proof: when the operator renames an entry's directory on
|
|
103
|
+
* disk, the next request rebuilds the index and the scrapbook now
|
|
104
|
+
* lives at the new path automatically.
|
|
105
|
+
*
|
|
106
|
+
* @param entry Calendar entry — `id` preferred (Phase 19+); `slug` is
|
|
107
|
+
* used both as the legacy fallback and to locate the
|
|
108
|
+
* `<dirname>/scrapbook/` when the entry has no id yet.
|
|
109
|
+
* @param index Optional pre-built index (per-request memoization). When
|
|
110
|
+
* omitted, this function builds one.
|
|
111
|
+
*/
|
|
112
|
+
export function scrapbookDirForEntry(projectRoot, config, site, entry, index) {
|
|
113
|
+
const entryId = entry.id ?? '';
|
|
114
|
+
const file = findEntryFile(projectRoot, config, site, entryId, index,
|
|
115
|
+
// Legacy fallback ON — we want a usable path even for pre-doctor entries.
|
|
116
|
+
{ slug: entry.slug });
|
|
117
|
+
if (file === undefined) {
|
|
118
|
+
// No id binding AND no template fallback resolved (template should
|
|
119
|
+
// always resolve since it's just slug substitution; this branch is
|
|
120
|
+
// defensive for empty slugs / future template variants).
|
|
121
|
+
throw new Error(`Cannot resolve scrapbook dir: entry has no id binding and no template fallback (slug="${entry.slug}")`);
|
|
122
|
+
}
|
|
123
|
+
return join(dirname(file), 'scrapbook');
|
|
124
|
+
}
|
|
125
|
+
/**
|
|
126
|
+
* Resolve a filename inside an already-resolved scrapbook directory.
|
|
127
|
+
* Mirrors `listScrapbookAtDir` — used by callers that have already
|
|
128
|
+
* resolved the on-disk dir via `scrapbookDirForEntry` (id-driven) or
|
|
129
|
+
* `scrapbookDirAtPath` (fs-path-driven).
|
|
130
|
+
*
|
|
131
|
+
* Security guards:
|
|
132
|
+
* - `assertFilename` blocks dotfiles / `..` / absolute paths in the filename
|
|
133
|
+
* - the `startsWith(dir + '/')` containment check blocks any traversal
|
|
134
|
+
* that slipped through (so `secret/` always sits inside the top-level
|
|
135
|
+
* scrapbook dir)
|
|
136
|
+
*
|
|
137
|
+
* The slug-shape validator is bypassed because the caller has already
|
|
138
|
+
* proven the directory exists in the content tree by other means.
|
|
139
|
+
*/
|
|
140
|
+
export function scrapbookFilePathAtDir(scrapbookDirAbs, filename, opts = {}) {
|
|
141
|
+
assertFilename(filename);
|
|
142
|
+
const target = opts.secret ? join(scrapbookDirAbs, SECRET_SUBDIR) : scrapbookDirAbs;
|
|
143
|
+
const abs = resolve(target, filename);
|
|
144
|
+
if (!abs.startsWith(scrapbookDirAbs + '/') && abs !== scrapbookDirAbs) {
|
|
145
|
+
throw new Error(`resolved path escapes scrapbook dir: "${filename}" → ${abs}`);
|
|
146
|
+
}
|
|
147
|
+
return abs;
|
|
148
|
+
}
|
|
149
|
+
//# sourceMappingURL=paths.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"paths.js","sourceRoot":"","sources":["../../src/scrapbook/paths.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Read primitives — return file metadata + content as a Buffer.
|
|
3
|
+
*
|
|
4
|
+
* Three addressing modes match the listing/path module:
|
|
5
|
+
* - `readScrapbookFile` — slug-template (legacy public; uses the
|
|
6
|
+
* private `_scrapbookDirSlug` internally).
|
|
7
|
+
* - `readScrapbookFileAtDir` — already-resolved scrapbook dir.
|
|
8
|
+
* - `readScrapbookFileForEntry` — entry-aware via
|
|
9
|
+
* `scrapbookDirForEntry`; the binary endpoint
|
|
10
|
+
* `/api/dev/scrapbook-file?entryId=...` uses this so projects whose
|
|
11
|
+
* feature-doc layout doesn't match the kebab-case slug template
|
|
12
|
+
* can still serve scrapbook assets.
|
|
13
|
+
*
|
|
14
|
+
* Same security guards as the writes via `scrapbookFilePathAtDir`.
|
|
15
|
+
*/
|
|
16
|
+
import type { DeskworkConfig } from '../config.ts';
|
|
17
|
+
import type { ContentIndex } from '../content-index.ts';
|
|
18
|
+
import type { ScrapbookItemKind, ScrapbookLocation } from './types.ts';
|
|
19
|
+
interface ReadResult {
|
|
20
|
+
name: string;
|
|
21
|
+
kind: ScrapbookItemKind;
|
|
22
|
+
size: number;
|
|
23
|
+
mtime: string;
|
|
24
|
+
content: Buffer;
|
|
25
|
+
}
|
|
26
|
+
export declare function readScrapbookFile(projectRoot: string, config: DeskworkConfig, site: string, slug: string, filename: string, opts?: ScrapbookLocation): ReadResult;
|
|
27
|
+
/**
|
|
28
|
+
* Read a scrapbook file given the absolute scrapbook directory. Used
|
|
29
|
+
* by callers that have already resolved the on-disk dir via
|
|
30
|
+
* `scrapbookDirForEntry` (id-driven) or `scrapbookDirAtPath`
|
|
31
|
+
* (fs-path-driven) and don't want to re-derive through the slug
|
|
32
|
+
* template. Mirrors the listing-side primitive `listScrapbookAtDir`.
|
|
33
|
+
*
|
|
34
|
+
* Same security guards as `readScrapbookFile` (filename validation +
|
|
35
|
+
* path-traversal containment) via `scrapbookFilePathAtDir`.
|
|
36
|
+
*/
|
|
37
|
+
export declare function readScrapbookFileAtDir(scrapbookDirAbs: string, filename: string, opts?: ScrapbookLocation): ReadResult;
|
|
38
|
+
/**
|
|
39
|
+
* Read a scrapbook file for a tracked calendar entry. Mirrors
|
|
40
|
+
* `listScrapbookForEntry` / `countScrapbookForEntry` — id-driven
|
|
41
|
+
* resolution via `scrapbookDirForEntry`, slug fallback for pre-bound
|
|
42
|
+
* entries. Used by the studio's `/api/dev/scrapbook-file?entryId=...`
|
|
43
|
+
* variant so projects whose feature-doc layout doesn't match the
|
|
44
|
+
* kebab-case slug template (e.g. `docs/<version>/<status>/<feature>/`)
|
|
45
|
+
* can still serve scrapbook assets — `scrapbookDirAtPath`'s slug
|
|
46
|
+
* validator would otherwise reject any path with dots or uppercase
|
|
47
|
+
* segments.
|
|
48
|
+
*/
|
|
49
|
+
export declare function readScrapbookFileForEntry(projectRoot: string, config: DeskworkConfig, site: string, entry: {
|
|
50
|
+
id?: string;
|
|
51
|
+
slug: string;
|
|
52
|
+
}, filename: string, opts?: ScrapbookLocation, index?: ContentIndex): ReadResult;
|
|
53
|
+
export {};
|
|
54
|
+
//# sourceMappingURL=read.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"read.d.ts","sourceRoot":"","sources":["../../src/scrapbook/read.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAGH,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,cAAc,CAAC;AACnD,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAC;AAOxD,OAAO,KAAK,EAAE,iBAAiB,EAAE,iBAAiB,EAAE,MAAM,YAAY,CAAC;AAEvE,UAAU,UAAU;IAClB,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,iBAAiB,CAAC;IACxB,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,EAAE,MAAM,CAAC;CACjB;AAED,wBAAgB,iBAAiB,CAC/B,WAAW,EAAE,MAAM,EACnB,MAAM,EAAE,cAAc,EACtB,IAAI,EAAE,MAAM,EACZ,IAAI,EAAE,MAAM,EACZ,QAAQ,EAAE,MAAM,EAChB,IAAI,GAAE,iBAAsB,GAC3B,UAAU,CAMZ;AAED;;;;;;;;;GASG;AACH,wBAAgB,sBAAsB,CACpC,eAAe,EAAE,MAAM,EACvB,QAAQ,EAAE,MAAM,EAChB,IAAI,GAAE,iBAAsB,GAC3B,UAAU,CAaZ;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,yBAAyB,CACvC,WAAW,EAAE,MAAM,EACnB,MAAM,EAAE,cAAc,EACtB,IAAI,EAAE,MAAM,EACZ,KAAK,EAAE;IAAE,EAAE,CAAC,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE,EACpC,QAAQ,EAAE,MAAM,EAChB,IAAI,GAAE,iBAAsB,EAC5B,KAAK,CAAC,EAAE,YAAY,GACnB,UAAU,CAMZ"}
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Read primitives — return file metadata + content as a Buffer.
|
|
3
|
+
*
|
|
4
|
+
* Three addressing modes match the listing/path module:
|
|
5
|
+
* - `readScrapbookFile` — slug-template (legacy public; uses the
|
|
6
|
+
* private `_scrapbookDirSlug` internally).
|
|
7
|
+
* - `readScrapbookFileAtDir` — already-resolved scrapbook dir.
|
|
8
|
+
* - `readScrapbookFileForEntry` — entry-aware via
|
|
9
|
+
* `scrapbookDirForEntry`; the binary endpoint
|
|
10
|
+
* `/api/dev/scrapbook-file?entryId=...` uses this so projects whose
|
|
11
|
+
* feature-doc layout doesn't match the kebab-case slug template
|
|
12
|
+
* can still serve scrapbook assets.
|
|
13
|
+
*
|
|
14
|
+
* Same security guards as the writes via `scrapbookFilePathAtDir`.
|
|
15
|
+
*/
|
|
16
|
+
import { existsSync, readFileSync, statSync } from 'node:fs';
|
|
17
|
+
import { _scrapbookDirSlug, scrapbookDirForEntry, scrapbookFilePathAtDir, } from "./paths.js";
|
|
18
|
+
import { classify } from "./validation.js";
|
|
19
|
+
export function readScrapbookFile(projectRoot, config, site, slug, filename, opts = {}) {
|
|
20
|
+
return readScrapbookFileAtDir(_scrapbookDirSlug(projectRoot, config, site, slug), filename, opts);
|
|
21
|
+
}
|
|
22
|
+
/**
|
|
23
|
+
* Read a scrapbook file given the absolute scrapbook directory. Used
|
|
24
|
+
* by callers that have already resolved the on-disk dir via
|
|
25
|
+
* `scrapbookDirForEntry` (id-driven) or `scrapbookDirAtPath`
|
|
26
|
+
* (fs-path-driven) and don't want to re-derive through the slug
|
|
27
|
+
* template. Mirrors the listing-side primitive `listScrapbookAtDir`.
|
|
28
|
+
*
|
|
29
|
+
* Same security guards as `readScrapbookFile` (filename validation +
|
|
30
|
+
* path-traversal containment) via `scrapbookFilePathAtDir`.
|
|
31
|
+
*/
|
|
32
|
+
export function readScrapbookFileAtDir(scrapbookDirAbs, filename, opts = {}) {
|
|
33
|
+
const abs = scrapbookFilePathAtDir(scrapbookDirAbs, filename, opts);
|
|
34
|
+
if (!existsSync(abs))
|
|
35
|
+
throw new Error(`not found: ${filename}`);
|
|
36
|
+
const st = statSync(abs);
|
|
37
|
+
if (!st.isFile())
|
|
38
|
+
throw new Error(`not a file: ${filename}`);
|
|
39
|
+
const content = readFileSync(abs);
|
|
40
|
+
return {
|
|
41
|
+
name: filename,
|
|
42
|
+
kind: classify(filename),
|
|
43
|
+
size: st.size,
|
|
44
|
+
mtime: st.mtime.toISOString(),
|
|
45
|
+
content,
|
|
46
|
+
};
|
|
47
|
+
}
|
|
48
|
+
/**
|
|
49
|
+
* Read a scrapbook file for a tracked calendar entry. Mirrors
|
|
50
|
+
* `listScrapbookForEntry` / `countScrapbookForEntry` — id-driven
|
|
51
|
+
* resolution via `scrapbookDirForEntry`, slug fallback for pre-bound
|
|
52
|
+
* entries. Used by the studio's `/api/dev/scrapbook-file?entryId=...`
|
|
53
|
+
* variant so projects whose feature-doc layout doesn't match the
|
|
54
|
+
* kebab-case slug template (e.g. `docs/<version>/<status>/<feature>/`)
|
|
55
|
+
* can still serve scrapbook assets — `scrapbookDirAtPath`'s slug
|
|
56
|
+
* validator would otherwise reject any path with dots or uppercase
|
|
57
|
+
* segments.
|
|
58
|
+
*/
|
|
59
|
+
export function readScrapbookFileForEntry(projectRoot, config, site, entry, filename, opts = {}, index) {
|
|
60
|
+
return readScrapbookFileAtDir(scrapbookDirForEntry(projectRoot, config, site, entry, index), filename, opts);
|
|
61
|
+
}
|
|
62
|
+
//# sourceMappingURL=read.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"read.js","sourceRoot":"","sources":["../../src/scrapbook/read.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAEH,OAAO,EAAE,UAAU,EAAE,YAAY,EAAE,QAAQ,EAAE,MAAM,SAAS,CAAC;AAG7D,OAAO,EACL,iBAAiB,EACjB,oBAAoB,EACpB,sBAAsB,GACvB,MAAM,YAAY,CAAC;AACpB,OAAO,EAAE,QAAQ,EAAE,MAAM,iBAAiB,CAAC;AAW3C,MAAM,UAAU,iBAAiB,CAC/B,WAAmB,EACnB,MAAsB,EACtB,IAAY,EACZ,IAAY,EACZ,QAAgB,EAChB,OAA0B,EAAE;IAE5B,OAAO,sBAAsB,CAC3B,iBAAiB,CAAC,WAAW,EAAE,MAAM,EAAE,IAAI,EAAE,IAAI,CAAC,EAClD,QAAQ,EACR,IAAI,CACL,CAAC;AACJ,CAAC;AAED;;;;;;;;;GASG;AACH,MAAM,UAAU,sBAAsB,CACpC,eAAuB,EACvB,QAAgB,EAChB,OAA0B,EAAE;IAE5B,MAAM,GAAG,GAAG,sBAAsB,CAAC,eAAe,EAAE,QAAQ,EAAE,IAAI,CAAC,CAAC;IACpE,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC;QAAE,MAAM,IAAI,KAAK,CAAC,cAAc,QAAQ,EAAE,CAAC,CAAC;IAChE,MAAM,EAAE,GAAG,QAAQ,CAAC,GAAG,CAAC,CAAC;IACzB,IAAI,CAAC,EAAE,CAAC,MAAM,EAAE;QAAE,MAAM,IAAI,KAAK,CAAC,eAAe,QAAQ,EAAE,CAAC,CAAC;IAC7D,MAAM,OAAO,GAAG,YAAY,CAAC,GAAG,CAAC,CAAC;IAClC,OAAO;QACL,IAAI,EAAE,QAAQ;QACd,IAAI,EAAE,QAAQ,CAAC,QAAQ,CAAC;QACxB,IAAI,EAAE,EAAE,CAAC,IAAI;QACb,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,WAAW,EAAE;QAC7B,OAAO;KACR,CAAC;AACJ,CAAC;AAED;;;;;;;;;;GAUG;AACH,MAAM,UAAU,yBAAyB,CACvC,WAAmB,EACnB,MAAsB,EACtB,IAAY,EACZ,KAAoC,EACpC,QAAgB,EAChB,OAA0B,EAAE,EAC5B,KAAoB;IAEpB,OAAO,sBAAsB,CAC3B,oBAAoB,CAAC,WAAW,EAAE,MAAM,EAAE,IAAI,EAAE,KAAK,EAAE,KAAK,CAAC,EAC7D,QAAQ,EACR,IAAI,CACL,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Scrapbook seed helpers — scaffolding written at plan time so every
|
|
3
|
+
* Planned article gets a scrapbook home with a templated README.
|
|
4
|
+
*/
|
|
5
|
+
import type { DeskworkConfig } from '../config.ts';
|
|
6
|
+
import type { ScrapbookItem } from './types.ts';
|
|
7
|
+
/**
|
|
8
|
+
* Seed a scrapbook's `README.md` at plan time. Idempotent — if the
|
|
9
|
+
* README already exists, returns null without touching it. Used by
|
|
10
|
+
* the plan skill so every Planned article gets a scrapbook home with
|
|
11
|
+
* a template that names the article and invites receipts.
|
|
12
|
+
*
|
|
13
|
+
* Slug-keyed because plan-time callers operate against a freshly-
|
|
14
|
+
* minted calendar entry whose on-disk file may not yet exist; the
|
|
15
|
+
* slug-template path is the only stable address available at that
|
|
16
|
+
* stage. Routes through the private slug-template helpers internally.
|
|
17
|
+
*/
|
|
18
|
+
export declare function seedScrapbookReadme(projectRoot: string, config: DeskworkConfig, site: string, slug: string, title: string): ScrapbookItem | null;
|
|
19
|
+
//# sourceMappingURL=seed.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"seed.d.ts","sourceRoot":"","sources":["../../src/scrapbook/seed.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAGH,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,cAAc,CAAC;AAGnD,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;AAEhD;;;;;;;;;;GAUG;AACH,wBAAgB,mBAAmB,CACjC,WAAW,EAAE,MAAM,EACnB,MAAM,EAAE,cAAc,EACtB,IAAI,EAAE,MAAM,EACZ,IAAI,EAAE,MAAM,EACZ,KAAK,EAAE,MAAM,GACZ,aAAa,GAAG,IAAI,CAgCtB"}
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Scrapbook seed helpers — scaffolding written at plan time so every
|
|
3
|
+
* Planned article gets a scrapbook home with a templated README.
|
|
4
|
+
*/
|
|
5
|
+
import { existsSync } from 'node:fs';
|
|
6
|
+
import { _createScrapbookMarkdownSlug } from "./crud-slug.js";
|
|
7
|
+
import { _scrapbookFilePathSlug } from "./paths.js";
|
|
8
|
+
/**
|
|
9
|
+
* Seed a scrapbook's `README.md` at plan time. Idempotent — if the
|
|
10
|
+
* README already exists, returns null without touching it. Used by
|
|
11
|
+
* the plan skill so every Planned article gets a scrapbook home with
|
|
12
|
+
* a template that names the article and invites receipts.
|
|
13
|
+
*
|
|
14
|
+
* Slug-keyed because plan-time callers operate against a freshly-
|
|
15
|
+
* minted calendar entry whose on-disk file may not yet exist; the
|
|
16
|
+
* slug-template path is the only stable address available at that
|
|
17
|
+
* stage. Routes through the private slug-template helpers internally.
|
|
18
|
+
*/
|
|
19
|
+
export function seedScrapbookReadme(projectRoot, config, site, slug, title) {
|
|
20
|
+
const abs = _scrapbookFilePathSlug(projectRoot, config, site, slug, 'README.md');
|
|
21
|
+
if (existsSync(abs))
|
|
22
|
+
return null;
|
|
23
|
+
const now = new Date().toISOString().slice(0, 10);
|
|
24
|
+
const body = [
|
|
25
|
+
`# Scrapbook — ${title}`,
|
|
26
|
+
'',
|
|
27
|
+
`Planned ${now}. Working notes, research, receipts, and references`,
|
|
28
|
+
`for the \`${slug}\` dispatch. Committed to git alongside the article;`,
|
|
29
|
+
'not baked to the public site.',
|
|
30
|
+
'',
|
|
31
|
+
'## Receipts',
|
|
32
|
+
'',
|
|
33
|
+
'- ',
|
|
34
|
+
'',
|
|
35
|
+
'## Notes',
|
|
36
|
+
'',
|
|
37
|
+
'- ',
|
|
38
|
+
'',
|
|
39
|
+
'## References',
|
|
40
|
+
'',
|
|
41
|
+
'- ',
|
|
42
|
+
'',
|
|
43
|
+
].join('\n');
|
|
44
|
+
return _createScrapbookMarkdownSlug(projectRoot, config, site, slug, 'README.md', body);
|
|
45
|
+
}
|
|
46
|
+
//# sourceMappingURL=seed.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"seed.js","sourceRoot":"","sources":["../../src/scrapbook/seed.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,UAAU,EAAE,MAAM,SAAS,CAAC;AAErC,OAAO,EAAE,4BAA4B,EAAE,MAAM,gBAAgB,CAAC;AAC9D,OAAO,EAAE,sBAAsB,EAAE,MAAM,YAAY,CAAC;AAGpD;;;;;;;;;;GAUG;AACH,MAAM,UAAU,mBAAmB,CACjC,WAAmB,EACnB,MAAsB,EACtB,IAAY,EACZ,IAAY,EACZ,KAAa;IAEb,MAAM,GAAG,GAAG,sBAAsB,CAAC,WAAW,EAAE,MAAM,EAAE,IAAI,EAAE,IAAI,EAAE,WAAW,CAAC,CAAC;IACjF,IAAI,UAAU,CAAC,GAAG,CAAC;QAAE,OAAO,IAAI,CAAC;IACjC,MAAM,GAAG,GAAG,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE,CAAC,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;IAClD,MAAM,IAAI,GAAG;QACX,iBAAiB,KAAK,EAAE;QACxB,EAAE;QACF,WAAW,GAAG,qDAAqD;QACnE,aAAa,IAAI,sDAAsD;QACvE,+BAA+B;QAC/B,EAAE;QACF,aAAa;QACb,EAAE;QACF,IAAI;QACJ,EAAE;QACF,UAAU;QACV,EAAE;QACF,IAAI;QACJ,EAAE;QACF,eAAe;QACf,EAAE;QACF,IAAI;QACJ,EAAE;KACH,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IACb,OAAO,4BAA4B,CACjC,WAAW,EACX,MAAM,EACN,IAAI,EACJ,IAAI,EACJ,WAAW,EACX,IAAI,CACL,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Scrapbook public types — value-level shapes shared by every helper in
|
|
3
|
+
* the scrapbook module family.
|
|
4
|
+
*
|
|
5
|
+
* Split out of the legacy monolithic `scrapbook.ts` per #202 (file-size
|
|
6
|
+
* cap) so callers can import just the type surface without pulling in
|
|
7
|
+
* the fs-touching primitives.
|
|
8
|
+
*/
|
|
9
|
+
/** Type buckets for scrapbook entries — keyed by extension via `classify`. */
|
|
10
|
+
export type ScrapbookItemKind = 'md' | 'json' | 'js' | 'img' | 'txt' | 'other';
|
|
11
|
+
export interface ScrapbookItem {
|
|
12
|
+
name: string;
|
|
13
|
+
kind: ScrapbookItemKind;
|
|
14
|
+
size: number;
|
|
15
|
+
mtime: string;
|
|
16
|
+
}
|
|
17
|
+
export interface ScrapbookSummary {
|
|
18
|
+
site: string;
|
|
19
|
+
/**
|
|
20
|
+
* The scrapbook's location identifier — a slug for entries tied to a
|
|
21
|
+
* calendar row, or any directory path within `contentDir` for
|
|
22
|
+
* scrapbooks that hang off purely organizational nodes (e.g. an
|
|
23
|
+
* intermediate project directory that isn't itself a calendar entry).
|
|
24
|
+
*/
|
|
25
|
+
slug: string;
|
|
26
|
+
dir: string;
|
|
27
|
+
exists: boolean;
|
|
28
|
+
/** Files at the top of `scrapbook/` (public/published-side notes). */
|
|
29
|
+
items: ScrapbookItem[];
|
|
30
|
+
/**
|
|
31
|
+
* Files inside `scrapbook/secret/` — never to be published. Operators
|
|
32
|
+
* can drop research, drafts, or sensitive notes here knowing the host
|
|
33
|
+
* project's content collection patterns won't pick them up.
|
|
34
|
+
*/
|
|
35
|
+
secretItems: ScrapbookItem[];
|
|
36
|
+
}
|
|
37
|
+
/** Options that select between the public scrapbook root and `secret/`. */
|
|
38
|
+
export interface ScrapbookLocation {
|
|
39
|
+
/** When true, the file lives under `scrapbook/secret/`. Default: false. */
|
|
40
|
+
secret?: boolean;
|
|
41
|
+
}
|
|
42
|
+
/** Well-known subdirectory name for editorially-private scrapbook items. */
|
|
43
|
+
export declare const SECRET_SUBDIR = "secret";
|
|
44
|
+
//# sourceMappingURL=types.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/scrapbook/types.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,8EAA8E;AAC9E,MAAM,MAAM,iBAAiB,GACzB,IAAI,GACJ,MAAM,GACN,IAAI,GACJ,KAAK,GACL,KAAK,GACL,OAAO,CAAC;AAEZ,MAAM,WAAW,aAAa;IAC5B,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,iBAAiB,CAAC;IACxB,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,CAAC;CACf;AAED,MAAM,WAAW,gBAAgB;IAC/B,IAAI,EAAE,MAAM,CAAC;IACb;;;;;OAKG;IACH,IAAI,EAAE,MAAM,CAAC;IACb,GAAG,EAAE,MAAM,CAAC;IACZ,MAAM,EAAE,OAAO,CAAC;IAChB,sEAAsE;IACtE,KAAK,EAAE,aAAa,EAAE,CAAC;IACvB;;;;OAIG;IACH,WAAW,EAAE,aAAa,EAAE,CAAC;CAC9B;AAED,2EAA2E;AAC3E,MAAM,WAAW,iBAAiB;IAChC,2EAA2E;IAC3E,MAAM,CAAC,EAAE,OAAO,CAAC;CAClB;AAED,4EAA4E;AAC5E,eAAO,MAAM,aAAa,WAAW,CAAC"}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Scrapbook public types — value-level shapes shared by every helper in
|
|
3
|
+
* the scrapbook module family.
|
|
4
|
+
*
|
|
5
|
+
* Split out of the legacy monolithic `scrapbook.ts` per #202 (file-size
|
|
6
|
+
* cap) so callers can import just the type surface without pulling in
|
|
7
|
+
* the fs-touching primitives.
|
|
8
|
+
*/
|
|
9
|
+
/** Well-known subdirectory name for editorially-private scrapbook items. */
|
|
10
|
+
export const SECRET_SUBDIR = 'secret';
|
|
11
|
+
//# sourceMappingURL=types.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/scrapbook/types.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AA6CH,4EAA4E;AAC5E,MAAM,CAAC,MAAM,aAAa,GAAG,QAAQ,CAAC"}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Scrapbook validation + classification helpers.
|
|
3
|
+
*
|
|
4
|
+
* Slug + filename validation runs at every fs entry point; a `..` or
|
|
5
|
+
* absolute path that slips through here would let a malicious request
|
|
6
|
+
* read or write outside the scrapbook tree. The route layer relies on
|
|
7
|
+
* these helpers for traversal protection.
|
|
8
|
+
*/
|
|
9
|
+
import type { ScrapbookItemKind } from './types.ts';
|
|
10
|
+
/**
|
|
11
|
+
* A single slug segment — kebab-case lowercase. Used both for flat
|
|
12
|
+
* slugs and as the building block of hierarchical paths.
|
|
13
|
+
*/
|
|
14
|
+
declare const SLUG_SEGMENT_RE: RegExp;
|
|
15
|
+
export declare function assertSlug(slug: string): void;
|
|
16
|
+
/**
|
|
17
|
+
* Split a hierarchical slug into its segments. Each segment is a
|
|
18
|
+
* standalone kebab-case identifier.
|
|
19
|
+
*/
|
|
20
|
+
export declare function slugSegments(slug: string): string[];
|
|
21
|
+
/**
|
|
22
|
+
* True if a slug refers to a nested entry (has at least one `/`).
|
|
23
|
+
*/
|
|
24
|
+
export declare function isNestedSlug(slug: string): boolean;
|
|
25
|
+
export { SLUG_SEGMENT_RE };
|
|
26
|
+
export declare function assertFilename(name: string): void;
|
|
27
|
+
export declare function classify(filename: string): ScrapbookItemKind;
|
|
28
|
+
//# sourceMappingURL=validation.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"validation.d.ts","sourceRoot":"","sources":["../../src/scrapbook/validation.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAGH,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,YAAY,CAAC;AAMpD;;;GAGG;AACH,QAAA,MAAM,eAAe,QAAyB,CAAC;AAW/C,wBAAgB,UAAU,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,CAI7C;AAED;;;GAGG;AACH,wBAAgB,YAAY,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,EAAE,CAEnD;AAED;;GAEG;AACH,wBAAgB,YAAY,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAElD;AAID,OAAO,EAAE,eAAe,EAAE,CAAC;AAE3B,wBAAgB,cAAc,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,CAmBjD;AAMD,wBAAgB,QAAQ,CAAC,QAAQ,EAAE,MAAM,GAAG,iBAAiB,CA6B5D"}
|