@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
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"journal-events.d.ts","sourceRoot":"","sources":["../../src/schema/journal-events.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AA4ExB,eAAO,MAAM,kBAAkB
|
|
1
|
+
{"version":3,"file":"journal-events.d.ts","sourceRoot":"","sources":["../../src/schema/journal-events.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AA4ExB,eAAO,MAAM,kBAAkB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;IAQ7B,CAAC;AAEH,MAAM,MAAM,YAAY,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,kBAAkB,CAAC,CAAC"}
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Entry-aware CRUD primitives — operate on a pre-resolved scrapbook dir.
|
|
3
|
+
*
|
|
4
|
+
* The studio's mutation routes resolve the scrapbook directory via
|
|
5
|
+
* `scrapbookDirForEntry` (entry-id driven; refactor-proof) and then call
|
|
6
|
+
* these `*AtDir` helpers. Mirrors the listing-side `listScrapbookAtDir` /
|
|
7
|
+
* `readScrapbookFileAtDir` primitives.
|
|
8
|
+
*
|
|
9
|
+
* Same security guards as the slug-shape helpers via
|
|
10
|
+
* `scrapbookFilePathAtDir`: filename validation + path-traversal
|
|
11
|
+
* containment.
|
|
12
|
+
*
|
|
13
|
+
* This is the public mutation surface post-#192. The slug-template
|
|
14
|
+
* mutation primitives (`createScrapbookMarkdown`, `saveScrapbookFile`,
|
|
15
|
+
* `renameScrapbookFile`, `deleteScrapbookFile`, `writeScrapbookUpload`)
|
|
16
|
+
* were collapsed to private helpers in the same change — external
|
|
17
|
+
* callers go through these `*AtDir` functions plus a dir resolved by
|
|
18
|
+
* `scrapbookDirForEntry`.
|
|
19
|
+
*/
|
|
20
|
+
import type { ScrapbookItem, ScrapbookLocation } from './types.ts';
|
|
21
|
+
/**
|
|
22
|
+
* Create a new markdown note inside an already-resolved scrapbook dir.
|
|
23
|
+
* Mirrors the legacy `createScrapbookMarkdown` (now private) but takes
|
|
24
|
+
* the dir directly.
|
|
25
|
+
*/
|
|
26
|
+
export declare function createScrapbookMarkdownAtDir(scrapbookDirAbs: string, filename: string, body: string, opts?: ScrapbookLocation): ScrapbookItem;
|
|
27
|
+
/**
|
|
28
|
+
* Overwrite an existing file's contents inside an already-resolved scrapbook
|
|
29
|
+
* dir. Mirrors the legacy `saveScrapbookFile` (now private).
|
|
30
|
+
*/
|
|
31
|
+
export declare function saveScrapbookFileAtDir(scrapbookDirAbs: string, filename: string, body: string | Buffer, opts?: ScrapbookLocation): ScrapbookItem;
|
|
32
|
+
/**
|
|
33
|
+
* Rename a file inside an already-resolved scrapbook dir. Mirrors the
|
|
34
|
+
* legacy `renameScrapbookFile` (now private).
|
|
35
|
+
*/
|
|
36
|
+
export declare function renameScrapbookFileAtDir(scrapbookDirAbs: string, oldName: string, newName: string, opts?: ScrapbookLocation): ScrapbookItem;
|
|
37
|
+
/**
|
|
38
|
+
* Delete a file inside an already-resolved scrapbook dir. Mirrors the
|
|
39
|
+
* legacy `deleteScrapbookFile` (now private).
|
|
40
|
+
*/
|
|
41
|
+
export declare function deleteScrapbookFileAtDir(scrapbookDirAbs: string, filename: string, opts?: ScrapbookLocation): void;
|
|
42
|
+
/**
|
|
43
|
+
* Write an uploaded file inside an already-resolved scrapbook dir.
|
|
44
|
+
* Mirrors the legacy `writeScrapbookUpload` (now private).
|
|
45
|
+
*/
|
|
46
|
+
export declare function writeScrapbookUploadAtDir(scrapbookDirAbs: string, filename: string, content: Buffer, opts?: ScrapbookLocation): ScrapbookItem;
|
|
47
|
+
//# sourceMappingURL=crud-at-dir.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"crud-at-dir.d.ts","sourceRoot":"","sources":["../../src/scrapbook/crud-at-dir.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;GAkBG;AAaH,OAAO,KAAK,EAAE,aAAa,EAAE,iBAAiB,EAAE,MAAM,YAAY,CAAC;AAEnE;;;;GAIG;AACH,wBAAgB,4BAA4B,CAC1C,eAAe,EAAE,MAAM,EACvB,QAAQ,EAAE,MAAM,EAChB,IAAI,EAAE,MAAM,EACZ,IAAI,GAAE,iBAAsB,GAC3B,aAAa,CAiBf;AAED;;;GAGG;AACH,wBAAgB,sBAAsB,CACpC,eAAe,EAAE,MAAM,EACvB,QAAQ,EAAE,MAAM,EAChB,IAAI,EAAE,MAAM,GAAG,MAAM,EACrB,IAAI,GAAE,iBAAsB,GAC3B,aAAa,CAWf;AAED;;;GAGG;AACH,wBAAgB,wBAAwB,CACtC,eAAe,EAAE,MAAM,EACvB,OAAO,EAAE,MAAM,EACf,OAAO,EAAE,MAAM,EACf,IAAI,GAAE,iBAAsB,GAC3B,aAAa,CAef;AAED;;;GAGG;AACH,wBAAgB,wBAAwB,CACtC,eAAe,EAAE,MAAM,EACvB,QAAQ,EAAE,MAAM,EAChB,IAAI,GAAE,iBAAsB,GAC3B,IAAI,CAIN;AAED;;;GAGG;AACH,wBAAgB,yBAAyB,CACvC,eAAe,EAAE,MAAM,EACvB,QAAQ,EAAE,MAAM,EAChB,OAAO,EAAE,MAAM,EACf,IAAI,GAAE,iBAAsB,GAC3B,aAAa,CAcf"}
|
|
@@ -0,0 +1,114 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Entry-aware CRUD primitives — operate on a pre-resolved scrapbook dir.
|
|
3
|
+
*
|
|
4
|
+
* The studio's mutation routes resolve the scrapbook directory via
|
|
5
|
+
* `scrapbookDirForEntry` (entry-id driven; refactor-proof) and then call
|
|
6
|
+
* these `*AtDir` helpers. Mirrors the listing-side `listScrapbookAtDir` /
|
|
7
|
+
* `readScrapbookFileAtDir` primitives.
|
|
8
|
+
*
|
|
9
|
+
* Same security guards as the slug-shape helpers via
|
|
10
|
+
* `scrapbookFilePathAtDir`: filename validation + path-traversal
|
|
11
|
+
* containment.
|
|
12
|
+
*
|
|
13
|
+
* This is the public mutation surface post-#192. The slug-template
|
|
14
|
+
* mutation primitives (`createScrapbookMarkdown`, `saveScrapbookFile`,
|
|
15
|
+
* `renameScrapbookFile`, `deleteScrapbookFile`, `writeScrapbookUpload`)
|
|
16
|
+
* were collapsed to private helpers in the same change — external
|
|
17
|
+
* callers go through these `*AtDir` functions plus a dir resolved by
|
|
18
|
+
* `scrapbookDirForEntry`.
|
|
19
|
+
*/
|
|
20
|
+
import { existsSync, mkdirSync, renameSync, rmSync, statSync, writeFileSync, } from 'node:fs';
|
|
21
|
+
import { dirname } from 'node:path';
|
|
22
|
+
import { scrapbookFilePathAtDir } from "./paths.js";
|
|
23
|
+
import { classify } from "./validation.js";
|
|
24
|
+
/**
|
|
25
|
+
* Create a new markdown note inside an already-resolved scrapbook dir.
|
|
26
|
+
* Mirrors the legacy `createScrapbookMarkdown` (now private) but takes
|
|
27
|
+
* the dir directly.
|
|
28
|
+
*/
|
|
29
|
+
export function createScrapbookMarkdownAtDir(scrapbookDirAbs, filename, body, opts = {}) {
|
|
30
|
+
if (!filename.endsWith('.md')) {
|
|
31
|
+
throw new Error(`create endpoint only accepts .md files: "${filename}"`);
|
|
32
|
+
}
|
|
33
|
+
const abs = scrapbookFilePathAtDir(scrapbookDirAbs, filename, opts);
|
|
34
|
+
if (existsSync(abs)) {
|
|
35
|
+
throw new Error(`file already exists: "${filename}"`);
|
|
36
|
+
}
|
|
37
|
+
mkdirSync(dirname(abs), { recursive: true });
|
|
38
|
+
writeFileSync(abs, body, 'utf-8');
|
|
39
|
+
const st = statSync(abs);
|
|
40
|
+
return {
|
|
41
|
+
name: filename,
|
|
42
|
+
kind: 'md',
|
|
43
|
+
size: st.size,
|
|
44
|
+
mtime: st.mtime.toISOString(),
|
|
45
|
+
};
|
|
46
|
+
}
|
|
47
|
+
/**
|
|
48
|
+
* Overwrite an existing file's contents inside an already-resolved scrapbook
|
|
49
|
+
* dir. Mirrors the legacy `saveScrapbookFile` (now private).
|
|
50
|
+
*/
|
|
51
|
+
export function saveScrapbookFileAtDir(scrapbookDirAbs, filename, body, opts = {}) {
|
|
52
|
+
const abs = scrapbookFilePathAtDir(scrapbookDirAbs, filename, opts);
|
|
53
|
+
if (!existsSync(abs))
|
|
54
|
+
throw new Error(`file not found: "${filename}"`);
|
|
55
|
+
writeFileSync(abs, body);
|
|
56
|
+
const st = statSync(abs);
|
|
57
|
+
return {
|
|
58
|
+
name: filename,
|
|
59
|
+
kind: classify(filename),
|
|
60
|
+
size: st.size,
|
|
61
|
+
mtime: st.mtime.toISOString(),
|
|
62
|
+
};
|
|
63
|
+
}
|
|
64
|
+
/**
|
|
65
|
+
* Rename a file inside an already-resolved scrapbook dir. Mirrors the
|
|
66
|
+
* legacy `renameScrapbookFile` (now private).
|
|
67
|
+
*/
|
|
68
|
+
export function renameScrapbookFileAtDir(scrapbookDirAbs, oldName, newName, opts = {}) {
|
|
69
|
+
const oldAbs = scrapbookFilePathAtDir(scrapbookDirAbs, oldName, opts);
|
|
70
|
+
const newAbs = scrapbookFilePathAtDir(scrapbookDirAbs, newName, opts);
|
|
71
|
+
if (!existsSync(oldAbs))
|
|
72
|
+
throw new Error(`file not found: "${oldName}"`);
|
|
73
|
+
if (existsSync(newAbs) && oldAbs !== newAbs) {
|
|
74
|
+
throw new Error(`target name already exists: "${newName}"`);
|
|
75
|
+
}
|
|
76
|
+
renameSync(oldAbs, newAbs);
|
|
77
|
+
const st = statSync(newAbs);
|
|
78
|
+
return {
|
|
79
|
+
name: newName,
|
|
80
|
+
kind: classify(newName),
|
|
81
|
+
size: st.size,
|
|
82
|
+
mtime: st.mtime.toISOString(),
|
|
83
|
+
};
|
|
84
|
+
}
|
|
85
|
+
/**
|
|
86
|
+
* Delete a file inside an already-resolved scrapbook dir. Mirrors the
|
|
87
|
+
* legacy `deleteScrapbookFile` (now private).
|
|
88
|
+
*/
|
|
89
|
+
export function deleteScrapbookFileAtDir(scrapbookDirAbs, filename, opts = {}) {
|
|
90
|
+
const abs = scrapbookFilePathAtDir(scrapbookDirAbs, filename, opts);
|
|
91
|
+
if (!existsSync(abs))
|
|
92
|
+
throw new Error(`file not found: "${filename}"`);
|
|
93
|
+
rmSync(abs);
|
|
94
|
+
}
|
|
95
|
+
/**
|
|
96
|
+
* Write an uploaded file inside an already-resolved scrapbook dir.
|
|
97
|
+
* Mirrors the legacy `writeScrapbookUpload` (now private).
|
|
98
|
+
*/
|
|
99
|
+
export function writeScrapbookUploadAtDir(scrapbookDirAbs, filename, content, opts = {}) {
|
|
100
|
+
const abs = scrapbookFilePathAtDir(scrapbookDirAbs, filename, opts);
|
|
101
|
+
if (existsSync(abs)) {
|
|
102
|
+
throw new Error(`file already exists: "${filename}" — rename first`);
|
|
103
|
+
}
|
|
104
|
+
mkdirSync(dirname(abs), { recursive: true });
|
|
105
|
+
writeFileSync(abs, content);
|
|
106
|
+
const st = statSync(abs);
|
|
107
|
+
return {
|
|
108
|
+
name: filename,
|
|
109
|
+
kind: classify(filename),
|
|
110
|
+
size: st.size,
|
|
111
|
+
mtime: st.mtime.toISOString(),
|
|
112
|
+
};
|
|
113
|
+
}
|
|
114
|
+
//# sourceMappingURL=crud-at-dir.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"crud-at-dir.js","sourceRoot":"","sources":["../../src/scrapbook/crud-at-dir.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* INTERNAL — slug-template CRUD primitives.
|
|
3
|
+
*
|
|
4
|
+
* These were the public mutation surface pre-#192 but are now private:
|
|
5
|
+
* external callers go through the entry-aware `*AtDir` family in
|
|
6
|
+
* `crud-at-dir.ts` after resolving the dir via `scrapbookDirForEntry`
|
|
7
|
+
* (or `scrapbookDirAtPath`). This module is the implementation home
|
|
8
|
+
* for the legacy slug-template path and is re-used inside the scrapbook
|
|
9
|
+
* module family — `seed.ts` calls these helpers to seed a slug-keyed
|
|
10
|
+
* README at plan time.
|
|
11
|
+
*
|
|
12
|
+
* NOT re-exported from the barrel (`packages/core/src/scrapbook.ts`).
|
|
13
|
+
*
|
|
14
|
+
* Same security guards as the entry-aware `*AtDir` family — filename
|
|
15
|
+
* validation + path-traversal containment via the underlying
|
|
16
|
+
* `scrapbookFilePathAtDir`.
|
|
17
|
+
*/
|
|
18
|
+
import type { DeskworkConfig } from '../config.ts';
|
|
19
|
+
import type { ScrapbookItem, ScrapbookLocation } from './types.ts';
|
|
20
|
+
/**
|
|
21
|
+
* INTERNAL — create a new markdown note in the slug-template scrapbook.
|
|
22
|
+
* Used by `seed.ts`. Refuses to overwrite existing files.
|
|
23
|
+
*/
|
|
24
|
+
export declare function _createScrapbookMarkdownSlug(projectRoot: string, config: DeskworkConfig, site: string, slug: string, filename: string, body: string, opts?: ScrapbookLocation): ScrapbookItem;
|
|
25
|
+
/** INTERNAL — overwrite an existing file's contents (slug-template). */
|
|
26
|
+
export declare function _saveScrapbookFileSlug(projectRoot: string, config: DeskworkConfig, site: string, slug: string, filename: string, body: string | Buffer, opts?: ScrapbookLocation): ScrapbookItem;
|
|
27
|
+
/** INTERNAL — rename a file (slug-template). */
|
|
28
|
+
export declare function _renameScrapbookFileSlug(projectRoot: string, config: DeskworkConfig, site: string, slug: string, oldName: string, newName: string, opts?: ScrapbookLocation): ScrapbookItem;
|
|
29
|
+
/** INTERNAL — delete a file (slug-template). */
|
|
30
|
+
export declare function _deleteScrapbookFileSlug(projectRoot: string, config: DeskworkConfig, site: string, slug: string, filename: string, opts?: ScrapbookLocation): void;
|
|
31
|
+
/** INTERNAL — write an uploaded file (slug-template). */
|
|
32
|
+
export declare function _writeScrapbookUploadSlug(projectRoot: string, config: DeskworkConfig, site: string, slug: string, filename: string, content: Buffer, opts?: ScrapbookLocation): ScrapbookItem;
|
|
33
|
+
//# sourceMappingURL=crud-slug.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"crud-slug.d.ts","sourceRoot":"","sources":["../../src/scrapbook/crud-slug.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AAWH,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,cAAc,CAAC;AAGnD,OAAO,KAAK,EAAE,aAAa,EAAE,iBAAiB,EAAE,MAAM,YAAY,CAAC;AAEnE;;;GAGG;AACH,wBAAgB,4BAA4B,CAC1C,WAAW,EAAE,MAAM,EACnB,MAAM,EAAE,cAAc,EACtB,IAAI,EAAE,MAAM,EACZ,IAAI,EAAE,MAAM,EACZ,QAAQ,EAAE,MAAM,EAChB,IAAI,EAAE,MAAM,EACZ,IAAI,GAAE,iBAAsB,GAC3B,aAAa,CAiBf;AAED,wEAAwE;AACxE,wBAAgB,sBAAsB,CACpC,WAAW,EAAE,MAAM,EACnB,MAAM,EAAE,cAAc,EACtB,IAAI,EAAE,MAAM,EACZ,IAAI,EAAE,MAAM,EACZ,QAAQ,EAAE,MAAM,EAChB,IAAI,EAAE,MAAM,GAAG,MAAM,EACrB,IAAI,GAAE,iBAAsB,GAC3B,aAAa,CAWf;AAED,gDAAgD;AAChD,wBAAgB,wBAAwB,CACtC,WAAW,EAAE,MAAM,EACnB,MAAM,EAAE,cAAc,EACtB,IAAI,EAAE,MAAM,EACZ,IAAI,EAAE,MAAM,EACZ,OAAO,EAAE,MAAM,EACf,OAAO,EAAE,MAAM,EACf,IAAI,GAAE,iBAAsB,GAC3B,aAAa,CAef;AAED,gDAAgD;AAChD,wBAAgB,wBAAwB,CACtC,WAAW,EAAE,MAAM,EACnB,MAAM,EAAE,cAAc,EACtB,IAAI,EAAE,MAAM,EACZ,IAAI,EAAE,MAAM,EACZ,QAAQ,EAAE,MAAM,EAChB,IAAI,GAAE,iBAAsB,GAC3B,IAAI,CAIN;AAED,yDAAyD;AACzD,wBAAgB,yBAAyB,CACvC,WAAW,EAAE,MAAM,EACnB,MAAM,EAAE,cAAc,EACtB,IAAI,EAAE,MAAM,EACZ,IAAI,EAAE,MAAM,EACZ,QAAQ,EAAE,MAAM,EAChB,OAAO,EAAE,MAAM,EACf,IAAI,GAAE,iBAAsB,GAC3B,aAAa,CAcf"}
|
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* INTERNAL — slug-template CRUD primitives.
|
|
3
|
+
*
|
|
4
|
+
* These were the public mutation surface pre-#192 but are now private:
|
|
5
|
+
* external callers go through the entry-aware `*AtDir` family in
|
|
6
|
+
* `crud-at-dir.ts` after resolving the dir via `scrapbookDirForEntry`
|
|
7
|
+
* (or `scrapbookDirAtPath`). This module is the implementation home
|
|
8
|
+
* for the legacy slug-template path and is re-used inside the scrapbook
|
|
9
|
+
* module family — `seed.ts` calls these helpers to seed a slug-keyed
|
|
10
|
+
* README at plan time.
|
|
11
|
+
*
|
|
12
|
+
* NOT re-exported from the barrel (`packages/core/src/scrapbook.ts`).
|
|
13
|
+
*
|
|
14
|
+
* Same security guards as the entry-aware `*AtDir` family — filename
|
|
15
|
+
* validation + path-traversal containment via the underlying
|
|
16
|
+
* `scrapbookFilePathAtDir`.
|
|
17
|
+
*/
|
|
18
|
+
import { existsSync, mkdirSync, renameSync, rmSync, statSync, writeFileSync, } from 'node:fs';
|
|
19
|
+
import { dirname } from 'node:path';
|
|
20
|
+
import { _scrapbookFilePathSlug } from "./paths.js";
|
|
21
|
+
import { classify } from "./validation.js";
|
|
22
|
+
/**
|
|
23
|
+
* INTERNAL — create a new markdown note in the slug-template scrapbook.
|
|
24
|
+
* Used by `seed.ts`. Refuses to overwrite existing files.
|
|
25
|
+
*/
|
|
26
|
+
export function _createScrapbookMarkdownSlug(projectRoot, config, site, slug, filename, body, opts = {}) {
|
|
27
|
+
if (!filename.endsWith('.md')) {
|
|
28
|
+
throw new Error(`create endpoint only accepts .md files: "${filename}"`);
|
|
29
|
+
}
|
|
30
|
+
const abs = _scrapbookFilePathSlug(projectRoot, config, site, slug, filename, opts);
|
|
31
|
+
if (existsSync(abs)) {
|
|
32
|
+
throw new Error(`file already exists: "${filename}"`);
|
|
33
|
+
}
|
|
34
|
+
mkdirSync(dirname(abs), { recursive: true });
|
|
35
|
+
writeFileSync(abs, body, 'utf-8');
|
|
36
|
+
const st = statSync(abs);
|
|
37
|
+
return {
|
|
38
|
+
name: filename,
|
|
39
|
+
kind: 'md',
|
|
40
|
+
size: st.size,
|
|
41
|
+
mtime: st.mtime.toISOString(),
|
|
42
|
+
};
|
|
43
|
+
}
|
|
44
|
+
/** INTERNAL — overwrite an existing file's contents (slug-template). */
|
|
45
|
+
export function _saveScrapbookFileSlug(projectRoot, config, site, slug, filename, body, opts = {}) {
|
|
46
|
+
const abs = _scrapbookFilePathSlug(projectRoot, config, site, slug, filename, opts);
|
|
47
|
+
if (!existsSync(abs))
|
|
48
|
+
throw new Error(`file not found: "${filename}"`);
|
|
49
|
+
writeFileSync(abs, body);
|
|
50
|
+
const st = statSync(abs);
|
|
51
|
+
return {
|
|
52
|
+
name: filename,
|
|
53
|
+
kind: classify(filename),
|
|
54
|
+
size: st.size,
|
|
55
|
+
mtime: st.mtime.toISOString(),
|
|
56
|
+
};
|
|
57
|
+
}
|
|
58
|
+
/** INTERNAL — rename a file (slug-template). */
|
|
59
|
+
export function _renameScrapbookFileSlug(projectRoot, config, site, slug, oldName, newName, opts = {}) {
|
|
60
|
+
const oldAbs = _scrapbookFilePathSlug(projectRoot, config, site, slug, oldName, opts);
|
|
61
|
+
const newAbs = _scrapbookFilePathSlug(projectRoot, config, site, slug, newName, opts);
|
|
62
|
+
if (!existsSync(oldAbs))
|
|
63
|
+
throw new Error(`file not found: "${oldName}"`);
|
|
64
|
+
if (existsSync(newAbs) && oldAbs !== newAbs) {
|
|
65
|
+
throw new Error(`target name already exists: "${newName}"`);
|
|
66
|
+
}
|
|
67
|
+
renameSync(oldAbs, newAbs);
|
|
68
|
+
const st = statSync(newAbs);
|
|
69
|
+
return {
|
|
70
|
+
name: newName,
|
|
71
|
+
kind: classify(newName),
|
|
72
|
+
size: st.size,
|
|
73
|
+
mtime: st.mtime.toISOString(),
|
|
74
|
+
};
|
|
75
|
+
}
|
|
76
|
+
/** INTERNAL — delete a file (slug-template). */
|
|
77
|
+
export function _deleteScrapbookFileSlug(projectRoot, config, site, slug, filename, opts = {}) {
|
|
78
|
+
const abs = _scrapbookFilePathSlug(projectRoot, config, site, slug, filename, opts);
|
|
79
|
+
if (!existsSync(abs))
|
|
80
|
+
throw new Error(`file not found: "${filename}"`);
|
|
81
|
+
rmSync(abs);
|
|
82
|
+
}
|
|
83
|
+
/** INTERNAL — write an uploaded file (slug-template). */
|
|
84
|
+
export function _writeScrapbookUploadSlug(projectRoot, config, site, slug, filename, content, opts = {}) {
|
|
85
|
+
const abs = _scrapbookFilePathSlug(projectRoot, config, site, slug, filename, opts);
|
|
86
|
+
if (existsSync(abs)) {
|
|
87
|
+
throw new Error(`file already exists: "${filename}" — rename first`);
|
|
88
|
+
}
|
|
89
|
+
mkdirSync(dirname(abs), { recursive: true });
|
|
90
|
+
writeFileSync(abs, content);
|
|
91
|
+
const st = statSync(abs);
|
|
92
|
+
return {
|
|
93
|
+
name: filename,
|
|
94
|
+
kind: classify(filename),
|
|
95
|
+
size: st.size,
|
|
96
|
+
mtime: st.mtime.toISOString(),
|
|
97
|
+
};
|
|
98
|
+
}
|
|
99
|
+
//# sourceMappingURL=crud-slug.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"crud-slug.js","sourceRoot":"","sources":["../../src/scrapbook/crud-slug.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Formatting helpers for the studio chip / viewer.
|
|
3
|
+
*
|
|
4
|
+
* Pure stringly-typed conversions — no fs, no config — so the studio
|
|
5
|
+
* client can import these without pulling in the rest of the scrapbook
|
|
6
|
+
* module family.
|
|
7
|
+
*/
|
|
8
|
+
export declare function formatRelativeTime(iso: string, now?: Date): string;
|
|
9
|
+
export declare function formatSize(bytes: number): string;
|
|
10
|
+
//# sourceMappingURL=format.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"format.d.ts","sourceRoot":"","sources":["../../src/scrapbook/format.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,wBAAgB,kBAAkB,CAAC,GAAG,EAAE,MAAM,EAAE,GAAG,GAAE,IAAiB,GAAG,MAAM,CAkB9E;AAED,wBAAgB,UAAU,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAIhD"}
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Formatting helpers for the studio chip / viewer.
|
|
3
|
+
*
|
|
4
|
+
* Pure stringly-typed conversions — no fs, no config — so the studio
|
|
5
|
+
* client can import these without pulling in the rest of the scrapbook
|
|
6
|
+
* module family.
|
|
7
|
+
*/
|
|
8
|
+
export function formatRelativeTime(iso, now = new Date()) {
|
|
9
|
+
const then = new Date(iso).getTime();
|
|
10
|
+
const diff = now.getTime() - then;
|
|
11
|
+
if (diff < 0)
|
|
12
|
+
return 'just now';
|
|
13
|
+
const s = Math.floor(diff / 1000);
|
|
14
|
+
if (s < 60)
|
|
15
|
+
return `${s}s ago`;
|
|
16
|
+
const m = Math.floor(s / 60);
|
|
17
|
+
if (m < 60)
|
|
18
|
+
return `${m}m ago`;
|
|
19
|
+
const h = Math.floor(m / 60);
|
|
20
|
+
if (h < 48)
|
|
21
|
+
return `${h}h ago`;
|
|
22
|
+
const d = Math.floor(h / 24);
|
|
23
|
+
if (d < 14)
|
|
24
|
+
return `${d}d ago`;
|
|
25
|
+
const w = Math.floor(d / 7);
|
|
26
|
+
if (w < 9)
|
|
27
|
+
return `${w}w ago`;
|
|
28
|
+
const months = Math.floor(d / 30);
|
|
29
|
+
if (months < 18)
|
|
30
|
+
return `${months}mo ago`;
|
|
31
|
+
const y = Math.floor(d / 365);
|
|
32
|
+
return `${y}y ago`;
|
|
33
|
+
}
|
|
34
|
+
export function formatSize(bytes) {
|
|
35
|
+
if (bytes < 1024)
|
|
36
|
+
return `${bytes} B`;
|
|
37
|
+
if (bytes < 1024 * 1024)
|
|
38
|
+
return `${(bytes / 1024).toFixed(1)} KB`;
|
|
39
|
+
return `${(bytes / (1024 * 1024)).toFixed(1)} MB`;
|
|
40
|
+
}
|
|
41
|
+
//# sourceMappingURL=format.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"format.js","sourceRoot":"","sources":["../../src/scrapbook/format.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,MAAM,UAAU,kBAAkB,CAAC,GAAW,EAAE,MAAY,IAAI,IAAI,EAAE;IACpE,MAAM,IAAI,GAAG,IAAI,IAAI,CAAC,GAAG,CAAC,CAAC,OAAO,EAAE,CAAC;IACrC,MAAM,IAAI,GAAG,GAAG,CAAC,OAAO,EAAE,GAAG,IAAI,CAAC;IAClC,IAAI,IAAI,GAAG,CAAC;QAAE,OAAO,UAAU,CAAC;IAChC,MAAM,CAAC,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,GAAG,IAAI,CAAC,CAAC;IAClC,IAAI,CAAC,GAAG,EAAE;QAAE,OAAO,GAAG,CAAC,OAAO,CAAC;IAC/B,MAAM,CAAC,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC,GAAG,EAAE,CAAC,CAAC;IAC7B,IAAI,CAAC,GAAG,EAAE;QAAE,OAAO,GAAG,CAAC,OAAO,CAAC;IAC/B,MAAM,CAAC,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC,GAAG,EAAE,CAAC,CAAC;IAC7B,IAAI,CAAC,GAAG,EAAE;QAAE,OAAO,GAAG,CAAC,OAAO,CAAC;IAC/B,MAAM,CAAC,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC,GAAG,EAAE,CAAC,CAAC;IAC7B,IAAI,CAAC,GAAG,EAAE;QAAE,OAAO,GAAG,CAAC,OAAO,CAAC;IAC/B,MAAM,CAAC,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC;IAC5B,IAAI,CAAC,GAAG,CAAC;QAAE,OAAO,GAAG,CAAC,OAAO,CAAC;IAC9B,MAAM,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC,GAAG,EAAE,CAAC,CAAC;IAClC,IAAI,MAAM,GAAG,EAAE;QAAE,OAAO,GAAG,MAAM,QAAQ,CAAC;IAC1C,MAAM,CAAC,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC,GAAG,GAAG,CAAC,CAAC;IAC9B,OAAO,GAAG,CAAC,OAAO,CAAC;AACrB,CAAC;AAED,MAAM,UAAU,UAAU,CAAC,KAAa;IACtC,IAAI,KAAK,GAAG,IAAI;QAAE,OAAO,GAAG,KAAK,IAAI,CAAC;IACtC,IAAI,KAAK,GAAG,IAAI,GAAG,IAAI;QAAE,OAAO,GAAG,CAAC,KAAK,GAAG,IAAI,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,KAAK,CAAC;IAClE,OAAO,GAAG,CAAC,KAAK,GAAG,CAAC,IAAI,GAAG,IAAI,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,KAAK,CAAC;AACpD,CAAC"}
|
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Scrapbook listing + counting helpers.
|
|
3
|
+
*
|
|
4
|
+
* Read-only inventory of a scrapbook directory: sorted item lists +
|
|
5
|
+
* total counts, with a public/secret split.
|
|
6
|
+
*
|
|
7
|
+
* Three addressing modes — slug-template (`listScrapbook` /
|
|
8
|
+
* `countScrapbook`), pre-resolved dir (`listScrapbookAtDir`), and
|
|
9
|
+
* entry-aware (`listScrapbookForEntry` / `countScrapbookForEntry`).
|
|
10
|
+
* The slug-template variants stay public because read-side callers
|
|
11
|
+
* (the studio scrapbook viewer page, the dashboard chip count) operate
|
|
12
|
+
* on a path key that's structurally a slug; the legacy entry point is
|
|
13
|
+
* still useful at that boundary. The mutation side (#192) collapsed
|
|
14
|
+
* to entry-aware only.
|
|
15
|
+
*/
|
|
16
|
+
import type { DeskworkConfig } from '../config.ts';
|
|
17
|
+
import type { ContentIndex } from '../content-index.ts';
|
|
18
|
+
import { type ScrapbookSummary } from './types.ts';
|
|
19
|
+
/**
|
|
20
|
+
* List the items in a scrapbook, sorted newest-mtime first. Returns
|
|
21
|
+
* both public items (top-level files) and secret items (files inside
|
|
22
|
+
* `scrapbook/secret/`). Subdirectories at the top level OTHER than
|
|
23
|
+
* `secret/` are ignored — deskwork doesn't recurse into arbitrary
|
|
24
|
+
* trees inside a scrapbook.
|
|
25
|
+
*/
|
|
26
|
+
export declare function listScrapbook(projectRoot: string, config: DeskworkConfig, site: string, slug: string): ScrapbookSummary;
|
|
27
|
+
/**
|
|
28
|
+
* List a scrapbook by absolute directory path. Used by callers that
|
|
29
|
+
* have already resolved the on-disk path via `scrapbookDirForEntry`
|
|
30
|
+
* (id-driven) or `scrapbookDirAtPath` (fs-path-driven) and don't want
|
|
31
|
+
* to re-derive through the slug template. The `slug` parameter is only
|
|
32
|
+
* used to populate the returned summary's identifier field — it does
|
|
33
|
+
* not influence path resolution.
|
|
34
|
+
*
|
|
35
|
+
* Internal primitive shared by `listScrapbook` (slug-based) and
|
|
36
|
+
* `listScrapbookForEntry` (id-driven).
|
|
37
|
+
*/
|
|
38
|
+
export declare function listScrapbookAtDir(site: string, slug: string, dir: string): ScrapbookSummary;
|
|
39
|
+
/**
|
|
40
|
+
* List scrapbook items for a tracked calendar entry. Resolves the
|
|
41
|
+
* scrapbook directory via the content index when available (id binding),
|
|
42
|
+
* falling back to slug-based addressing for entries that haven't been
|
|
43
|
+
* bound to frontmatter yet (pre-doctor state).
|
|
44
|
+
*
|
|
45
|
+
* Mirrors the shape of `countScrapbookForEntry`. Used by the studio
|
|
46
|
+
* review-page drawer + content-detail panel so writingcontrol-shape
|
|
47
|
+
* entries (where the file path diverges from the slug template) list
|
|
48
|
+
* items at the correct on-disk location.
|
|
49
|
+
*
|
|
50
|
+
* @param entry Calendar entry — `id` preferred; `slug` is both the
|
|
51
|
+
* legacy fallback and the disambiguator the underlying
|
|
52
|
+
* resolver uses when the index is incomplete.
|
|
53
|
+
* @param index Optional pre-built per-request index. When omitted, the
|
|
54
|
+
* resolver builds one on demand.
|
|
55
|
+
*/
|
|
56
|
+
export declare function listScrapbookForEntry(projectRoot: string, config: DeskworkConfig, site: string, entry: {
|
|
57
|
+
id?: string;
|
|
58
|
+
slug: string;
|
|
59
|
+
}, index?: ContentIndex): ScrapbookSummary;
|
|
60
|
+
/**
|
|
61
|
+
* Total item count (public + secret). Used by the studio chip for the
|
|
62
|
+
* badge — operators want a single "has scrapbook content" signal that
|
|
63
|
+
* counts everything attached to this entry.
|
|
64
|
+
*
|
|
65
|
+
* Slug-based addressing: resolves `<contentDir>/<slug>/scrapbook/`. For
|
|
66
|
+
* entries whose on-disk path doesn't match the slug template (e.g.
|
|
67
|
+
* writingcontrol-shape projects where slug `the-outbound` lives at
|
|
68
|
+
* `projects/the-outbound/index.md`), use `countScrapbookForEntry`
|
|
69
|
+
* instead — it derives the path from the bound file via the content
|
|
70
|
+
* index.
|
|
71
|
+
*/
|
|
72
|
+
export declare function countScrapbook(projectRoot: string, config: DeskworkConfig, site: string, slug: string): number;
|
|
73
|
+
/**
|
|
74
|
+
* Count scrapbook items for a tracked calendar entry. Resolves the
|
|
75
|
+
* scrapbook directory via the content index when available (id binding),
|
|
76
|
+
* falling back to slug-based addressing for entries that haven't been
|
|
77
|
+
* bound to frontmatter yet (pre-doctor state).
|
|
78
|
+
*
|
|
79
|
+
* Mirrors the shape of `scrapbookDirForEntry` — same resolver, same
|
|
80
|
+
* legacy-slug fallback. Used by the studio dashboard chip so writing-
|
|
81
|
+
* control-shape entries (where the file path diverges from the slug
|
|
82
|
+
* template) report the correct count.
|
|
83
|
+
*
|
|
84
|
+
* @param entry Calendar entry — `id` preferred (Phase 19+); `slug` is
|
|
85
|
+
* both the legacy fallback and the disambiguator the
|
|
86
|
+
* underlying resolver uses when the index is incomplete.
|
|
87
|
+
* @param index Optional pre-built per-request index. When omitted, the
|
|
88
|
+
* resolver builds one on demand.
|
|
89
|
+
*/
|
|
90
|
+
export declare function countScrapbookForEntry(projectRoot: string, config: DeskworkConfig, site: string, entry: {
|
|
91
|
+
id?: string;
|
|
92
|
+
slug: string;
|
|
93
|
+
}, index?: ContentIndex): number;
|
|
94
|
+
//# sourceMappingURL=listing.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"listing.d.ts","sourceRoot":"","sources":["../../src/scrapbook/listing.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAIH,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,cAAc,CAAC;AACnD,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAC;AAGxD,OAAO,EAGL,KAAK,gBAAgB,EACtB,MAAM,YAAY,CAAC;AAMpB;;;;;;GAMG;AACH,wBAAgB,aAAa,CAC3B,WAAW,EAAE,MAAM,EACnB,MAAM,EAAE,cAAc,EACtB,IAAI,EAAE,MAAM,EACZ,IAAI,EAAE,MAAM,GACX,gBAAgB,CAGlB;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,kBAAkB,CAChC,IAAI,EAAE,MAAM,EACZ,IAAI,EAAE,MAAM,EACZ,GAAG,EAAE,MAAM,GACV,gBAAgB,CAQlB;AAED;;;;;;;;;;;;;;;;GAgBG;AACH,wBAAgB,qBAAqB,CACnC,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,gBAAgB,CAGlB;AA6CD;;;;;;;;;;;GAWG;AACH,wBAAgB,cAAc,CAC5B,WAAW,EAAE,MAAM,EACnB,MAAM,EAAE,cAAc,EACtB,IAAI,EAAE,MAAM,EACZ,IAAI,EAAE,MAAM,GACX,MAAM,CAOR;AAED;;;;;;;;;;;;;;;;GAgBG;AACH,wBAAgB,sBAAsB,CACpC,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,CAOR"}
|
|
@@ -0,0 +1,167 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Scrapbook listing + counting helpers.
|
|
3
|
+
*
|
|
4
|
+
* Read-only inventory of a scrapbook directory: sorted item lists +
|
|
5
|
+
* total counts, with a public/secret split.
|
|
6
|
+
*
|
|
7
|
+
* Three addressing modes — slug-template (`listScrapbook` /
|
|
8
|
+
* `countScrapbook`), pre-resolved dir (`listScrapbookAtDir`), and
|
|
9
|
+
* entry-aware (`listScrapbookForEntry` / `countScrapbookForEntry`).
|
|
10
|
+
* The slug-template variants stay public because read-side callers
|
|
11
|
+
* (the studio scrapbook viewer page, the dashboard chip count) operate
|
|
12
|
+
* on a path key that's structurally a slug; the legacy entry point is
|
|
13
|
+
* still useful at that boundary. The mutation side (#192) collapsed
|
|
14
|
+
* to entry-aware only.
|
|
15
|
+
*/
|
|
16
|
+
import { existsSync, readdirSync, statSync } from 'node:fs';
|
|
17
|
+
import { join } from 'node:path';
|
|
18
|
+
import { _scrapbookDirSlug, scrapbookDirForEntry } from "./paths.js";
|
|
19
|
+
import { classify } from "./validation.js";
|
|
20
|
+
import { SECRET_SUBDIR, } from "./types.js";
|
|
21
|
+
// ---------------------------------------------------------------------------
|
|
22
|
+
// Listing
|
|
23
|
+
// ---------------------------------------------------------------------------
|
|
24
|
+
/**
|
|
25
|
+
* List the items in a scrapbook, sorted newest-mtime first. Returns
|
|
26
|
+
* both public items (top-level files) and secret items (files inside
|
|
27
|
+
* `scrapbook/secret/`). Subdirectories at the top level OTHER than
|
|
28
|
+
* `secret/` are ignored — deskwork doesn't recurse into arbitrary
|
|
29
|
+
* trees inside a scrapbook.
|
|
30
|
+
*/
|
|
31
|
+
export function listScrapbook(projectRoot, config, site, slug) {
|
|
32
|
+
const dir = _scrapbookDirSlug(projectRoot, config, site, slug);
|
|
33
|
+
return listScrapbookAtDir(site, slug, dir);
|
|
34
|
+
}
|
|
35
|
+
/**
|
|
36
|
+
* List a scrapbook by absolute directory path. Used by callers that
|
|
37
|
+
* have already resolved the on-disk path via `scrapbookDirForEntry`
|
|
38
|
+
* (id-driven) or `scrapbookDirAtPath` (fs-path-driven) and don't want
|
|
39
|
+
* to re-derive through the slug template. The `slug` parameter is only
|
|
40
|
+
* used to populate the returned summary's identifier field — it does
|
|
41
|
+
* not influence path resolution.
|
|
42
|
+
*
|
|
43
|
+
* Internal primitive shared by `listScrapbook` (slug-based) and
|
|
44
|
+
* `listScrapbookForEntry` (id-driven).
|
|
45
|
+
*/
|
|
46
|
+
export function listScrapbookAtDir(site, slug, dir) {
|
|
47
|
+
if (!existsSync(dir)) {
|
|
48
|
+
return { site, slug, dir, exists: false, items: [], secretItems: [] };
|
|
49
|
+
}
|
|
50
|
+
const items = listFilesInDir(dir);
|
|
51
|
+
const secretDir = join(dir, SECRET_SUBDIR);
|
|
52
|
+
const secretItems = existsSync(secretDir) ? listFilesInDir(secretDir) : [];
|
|
53
|
+
return { site, slug, dir, exists: true, items, secretItems };
|
|
54
|
+
}
|
|
55
|
+
/**
|
|
56
|
+
* List scrapbook items for a tracked calendar entry. Resolves the
|
|
57
|
+
* scrapbook directory via the content index when available (id binding),
|
|
58
|
+
* falling back to slug-based addressing for entries that haven't been
|
|
59
|
+
* bound to frontmatter yet (pre-doctor state).
|
|
60
|
+
*
|
|
61
|
+
* Mirrors the shape of `countScrapbookForEntry`. Used by the studio
|
|
62
|
+
* review-page drawer + content-detail panel so writingcontrol-shape
|
|
63
|
+
* entries (where the file path diverges from the slug template) list
|
|
64
|
+
* items at the correct on-disk location.
|
|
65
|
+
*
|
|
66
|
+
* @param entry Calendar entry — `id` preferred; `slug` is both the
|
|
67
|
+
* legacy fallback and the disambiguator the underlying
|
|
68
|
+
* resolver uses when the index is incomplete.
|
|
69
|
+
* @param index Optional pre-built per-request index. When omitted, the
|
|
70
|
+
* resolver builds one on demand.
|
|
71
|
+
*/
|
|
72
|
+
export function listScrapbookForEntry(projectRoot, config, site, entry, index) {
|
|
73
|
+
const dir = scrapbookDirForEntry(projectRoot, config, site, entry, index);
|
|
74
|
+
return listScrapbookAtDir(site, entry.slug, dir);
|
|
75
|
+
}
|
|
76
|
+
/** Internal helper — list files (not subdirs/dotfiles) at a given path. */
|
|
77
|
+
function listFilesInDir(dir) {
|
|
78
|
+
const items = [];
|
|
79
|
+
for (const e of readdirSync(dir, { withFileTypes: true })) {
|
|
80
|
+
if (!e.isFile())
|
|
81
|
+
continue;
|
|
82
|
+
if (e.name.startsWith('.'))
|
|
83
|
+
continue;
|
|
84
|
+
const abs = join(dir, e.name);
|
|
85
|
+
const st = statSync(abs);
|
|
86
|
+
items.push({
|
|
87
|
+
name: e.name,
|
|
88
|
+
kind: classify(e.name),
|
|
89
|
+
size: st.size,
|
|
90
|
+
mtime: st.mtime.toISOString(),
|
|
91
|
+
});
|
|
92
|
+
}
|
|
93
|
+
items.sort((a, b) => b.mtime.localeCompare(a.mtime));
|
|
94
|
+
return items;
|
|
95
|
+
}
|
|
96
|
+
// ---------------------------------------------------------------------------
|
|
97
|
+
// Counting
|
|
98
|
+
// ---------------------------------------------------------------------------
|
|
99
|
+
/**
|
|
100
|
+
* Count items inside an absolute scrapbook directory — files at the top
|
|
101
|
+
* level plus files inside the `secret/` subdirectory. Returns 0 if the
|
|
102
|
+
* directory doesn't exist; tolerates fs errors so a transient permission
|
|
103
|
+
* issue or race never crashes the dashboard render. Internal primitive
|
|
104
|
+
* shared by `countScrapbook` (slug-based) and `countScrapbookForEntry`
|
|
105
|
+
* (id-driven).
|
|
106
|
+
*/
|
|
107
|
+
function countScrapbookAtDir(dir) {
|
|
108
|
+
try {
|
|
109
|
+
if (!existsSync(dir))
|
|
110
|
+
return 0;
|
|
111
|
+
const top = listFilesInDir(dir);
|
|
112
|
+
const secretDir = join(dir, SECRET_SUBDIR);
|
|
113
|
+
const secret = existsSync(secretDir) ? listFilesInDir(secretDir) : [];
|
|
114
|
+
return top.length + secret.length;
|
|
115
|
+
}
|
|
116
|
+
catch {
|
|
117
|
+
return 0;
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
/**
|
|
121
|
+
* Total item count (public + secret). Used by the studio chip for the
|
|
122
|
+
* badge — operators want a single "has scrapbook content" signal that
|
|
123
|
+
* counts everything attached to this entry.
|
|
124
|
+
*
|
|
125
|
+
* Slug-based addressing: resolves `<contentDir>/<slug>/scrapbook/`. For
|
|
126
|
+
* entries whose on-disk path doesn't match the slug template (e.g.
|
|
127
|
+
* writingcontrol-shape projects where slug `the-outbound` lives at
|
|
128
|
+
* `projects/the-outbound/index.md`), use `countScrapbookForEntry`
|
|
129
|
+
* instead — it derives the path from the bound file via the content
|
|
130
|
+
* index.
|
|
131
|
+
*/
|
|
132
|
+
export function countScrapbook(projectRoot, config, site, slug) {
|
|
133
|
+
try {
|
|
134
|
+
const dir = _scrapbookDirSlug(projectRoot, config, site, slug);
|
|
135
|
+
return countScrapbookAtDir(dir);
|
|
136
|
+
}
|
|
137
|
+
catch {
|
|
138
|
+
return 0;
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
/**
|
|
142
|
+
* Count scrapbook items for a tracked calendar entry. Resolves the
|
|
143
|
+
* scrapbook directory via the content index when available (id binding),
|
|
144
|
+
* falling back to slug-based addressing for entries that haven't been
|
|
145
|
+
* bound to frontmatter yet (pre-doctor state).
|
|
146
|
+
*
|
|
147
|
+
* Mirrors the shape of `scrapbookDirForEntry` — same resolver, same
|
|
148
|
+
* legacy-slug fallback. Used by the studio dashboard chip so writing-
|
|
149
|
+
* control-shape entries (where the file path diverges from the slug
|
|
150
|
+
* template) report the correct count.
|
|
151
|
+
*
|
|
152
|
+
* @param entry Calendar entry — `id` preferred (Phase 19+); `slug` is
|
|
153
|
+
* both the legacy fallback and the disambiguator the
|
|
154
|
+
* underlying resolver uses when the index is incomplete.
|
|
155
|
+
* @param index Optional pre-built per-request index. When omitted, the
|
|
156
|
+
* resolver builds one on demand.
|
|
157
|
+
*/
|
|
158
|
+
export function countScrapbookForEntry(projectRoot, config, site, entry, index) {
|
|
159
|
+
try {
|
|
160
|
+
const dir = scrapbookDirForEntry(projectRoot, config, site, entry, index);
|
|
161
|
+
return countScrapbookAtDir(dir);
|
|
162
|
+
}
|
|
163
|
+
catch {
|
|
164
|
+
return 0;
|
|
165
|
+
}
|
|
166
|
+
}
|
|
167
|
+
//# sourceMappingURL=listing.js.map
|