canto-data 1.0.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/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Pedro Boueke
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,84 @@
1
+ # canto-data
2
+
3
+ [![npm version](https://img.shields.io/npm/v/canto-data.svg)](https://www.npmjs.com/package/canto-data)
4
+ [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](LICENSE)
5
+ [![CI](https://github.com/pboueke/canto-data/actions/workflows/ci.yml/badge.svg)](https://github.com/pboueke/canto-data/actions/workflows/ci.yml)
6
+
7
+ Data model library for [Canto](https://github.com/pboueke/canto), a private encrypted journaling app. Provides TypeScript types, runtime validation, schema versioning, migration infrastructure, and export format utilities for Canto journals.
8
+
9
+ **MIT-licensed** with **zero dependencies** — use it to build tools that read, validate, or manipulate Canto journals without copyleft obligations.
10
+
11
+ ## Installation
12
+
13
+ ```bash
14
+ npm install canto-data
15
+ ```
16
+
17
+ ## Quick Start
18
+
19
+ ```typescript
20
+ import {
21
+ type JournalContent,
22
+ type Page,
23
+ SCHEMA_VERSION,
24
+ validateJournalContent,
25
+ ValidationError,
26
+ parseManifest,
27
+ migrateIfNeeded,
28
+ } from 'canto-data';
29
+
30
+ // Validate untrusted journal data
31
+ try {
32
+ const journal = validateJournalContent(untrustedData);
33
+ } catch (err) {
34
+ if (err instanceof ValidationError) {
35
+ console.error(`${err.field}: expected ${err.expected}, got ${err.received}`);
36
+ }
37
+ }
38
+
39
+ // Parse an export manifest
40
+ const manifest = parseManifest(manifestJsonString);
41
+
42
+ // Migrate data to latest schema
43
+ const result = migrateIfNeeded(rawData, manifest.schemaVersion);
44
+ ```
45
+
46
+ ## Documentation
47
+
48
+ See **[DATA.md](DATA.md)** for the full data model reference, export format specification, filesystem structure, and usage examples.
49
+
50
+ ## Development
51
+
52
+ ```bash
53
+ git clone https://github.com/pboueke/canto-data.git
54
+ cd canto-data
55
+ npm install
56
+ npm test # run tests
57
+ npm run test:ci # run tests with 100% coverage enforcement
58
+ npm run build # compile to dist/
59
+ ```
60
+
61
+ ## Publishing
62
+
63
+ See the [npm Publishing Setup](#npm-publishing-setup) section below.
64
+
65
+ ### npm Publishing Setup
66
+
67
+ 1. **npm account**: Create/login at [npmjs.com](https://www.npmjs.com/signup)
68
+ 2. **npm token**: Generate an automation token at npmjs.com > Access Tokens > Generate New Token (Automation)
69
+ 3. **GitHub secret**: Add the token as `NPM_TOKEN` in the repo's Settings > Secrets and variables > Actions
70
+ 4. **First publish**: Run `npm run build && npm publish` after `npm login`, or push v1.0.0 to main
71
+ 5. **Subsequent publishes**: Bump version in `package.json`, merge to `main` — GitHub Actions auto-publishes
72
+
73
+ ### Version bump
74
+
75
+ ```bash
76
+ npm version patch # 1.0.0 -> 1.0.1 (bug fix)
77
+ npm version minor # 1.0.0 -> 1.1.0 (new feature)
78
+ npm version major # 1.0.0 -> 2.0.0 (breaking change)
79
+ git push && git push --tags
80
+ ```
81
+
82
+ ## License
83
+
84
+ MIT — see [LICENSE](LICENSE).
@@ -0,0 +1,47 @@
1
+ import type { Page } from './types';
2
+ export interface ExportManifest {
3
+ /** Manifest format version (always 1). */
4
+ version: 1;
5
+ /** Canto journal schema version (semver). Absent in legacy exports (treated as "0.16.0"). */
6
+ schemaVersion?: string;
7
+ appVersion: string;
8
+ exportDate: string;
9
+ encrypted: boolean;
10
+ salt?: string;
11
+ kdfIterations?: number;
12
+ journalTitle: string;
13
+ }
14
+ export interface BuildManifestOptions {
15
+ appVersion: string;
16
+ encrypted: boolean;
17
+ journalTitle: string;
18
+ salt?: string;
19
+ kdfIterations?: number;
20
+ }
21
+ /** Create an ExportManifest with the current SCHEMA_VERSION. */
22
+ export declare function buildExportManifest(opts: BuildManifestOptions): ExportManifest;
23
+ /**
24
+ * Parse and validate a manifest JSON string.
25
+ * Legacy manifests (without schemaVersion) are treated as "0.16.0".
26
+ */
27
+ export declare function parseManifest(json: string): ExportManifest;
28
+ export interface AttachmentEntry {
29
+ /** Index into the flat attachments/ folder inside the ZIP */
30
+ zipFilename: string;
31
+ /** Original on-disk filename (for reading) */
32
+ diskPath: string;
33
+ /** Whether the on-disk file is password-encrypted */
34
+ isPasswordEncrypted: boolean;
35
+ }
36
+ /** Collect unique attachments from pages for export, building portable ZIP filenames. */
37
+ export declare function collectAttachmentEntries(pages: Page[]): AttachmentEntry[];
38
+ /**
39
+ * Rewrite attachment paths in pages to use portable ZIP filenames.
40
+ * Returns cloned pages with updated paths.
41
+ */
42
+ export declare function rewriteAttachmentPaths(pages: Page[], pathMap: Map<string, string>): Page[];
43
+ /** Serialize pages to a map of pageId → JSON string. */
44
+ export declare function serializePages(pages: Page[]): Map<string, string>;
45
+ /** Deserialize pages from a map of filename → JSON string. */
46
+ export declare function deserializePages(entries: Map<string, string>): Page[];
47
+ //# sourceMappingURL=format.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"format.d.ts","sourceRoot":"","sources":["../src/format.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,IAAI,EAAc,MAAM,SAAS,CAAC;AAShD,MAAM,WAAW,cAAc;IAC7B,0CAA0C;IAC1C,OAAO,EAAE,CAAC,CAAC;IACX,6FAA6F;IAC7F,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,UAAU,EAAE,MAAM,CAAC;IACnB,UAAU,EAAE,MAAM,CAAC;IACnB,SAAS,EAAE,OAAO,CAAC;IACnB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,YAAY,EAAE,MAAM,CAAC;CACtB;AAED,MAAM,WAAW,oBAAoB;IACnC,UAAU,EAAE,MAAM,CAAC;IACnB,SAAS,EAAE,OAAO,CAAC;IACnB,YAAY,EAAE,MAAM,CAAC;IACrB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,aAAa,CAAC,EAAE,MAAM,CAAC;CACxB;AAED,gEAAgE;AAChE,wBAAgB,mBAAmB,CAAC,IAAI,EAAE,oBAAoB,GAAG,cAAc,CAW9E;AAED;;;GAGG;AACH,wBAAgB,aAAa,CAAC,IAAI,EAAE,MAAM,GAAG,cAAc,CA+C1D;AAMD,MAAM,WAAW,eAAe;IAC9B,6DAA6D;IAC7D,WAAW,EAAE,MAAM,CAAC;IACpB,8CAA8C;IAC9C,QAAQ,EAAE,MAAM,CAAC;IACjB,qDAAqD;IACrD,mBAAmB,EAAE,OAAO,CAAC;CAC9B;AAED,yFAAyF;AACzF,wBAAgB,wBAAwB,CAAC,KAAK,EAAE,IAAI,EAAE,GAAG,eAAe,EAAE,CAsBzE;AAED;;;GAGG;AACH,wBAAgB,sBAAsB,CAAC,KAAK,EAAE,IAAI,EAAE,EAAE,OAAO,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,GAAG,IAAI,EAAE,CAY1F;AAMD,wDAAwD;AACxD,wBAAgB,cAAc,CAAC,KAAK,EAAE,IAAI,EAAE,GAAG,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CAMjE;AAED,8DAA8D;AAC9D,wBAAgB,gBAAgB,CAAC,OAAO,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,GAAG,IAAI,EAAE,CAOrE"}
package/dist/format.js ADDED
@@ -0,0 +1,128 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.buildExportManifest = buildExportManifest;
4
+ exports.parseManifest = parseManifest;
5
+ exports.collectAttachmentEntries = collectAttachmentEntries;
6
+ exports.rewriteAttachmentPaths = rewriteAttachmentPaths;
7
+ exports.serializePages = serializePages;
8
+ exports.deserializePages = deserializePages;
9
+ const version_1 = require("./version");
10
+ const validation_1 = require("./validation");
11
+ const validation_2 = require("./validation");
12
+ /** Create an ExportManifest with the current SCHEMA_VERSION. */
13
+ function buildExportManifest(opts) {
14
+ return {
15
+ version: 1,
16
+ schemaVersion: version_1.SCHEMA_VERSION,
17
+ appVersion: opts.appVersion,
18
+ exportDate: new Date().toISOString(),
19
+ encrypted: opts.encrypted,
20
+ journalTitle: opts.journalTitle,
21
+ ...(opts.salt ? { salt: opts.salt } : {}),
22
+ ...(opts.kdfIterations ? { kdfIterations: opts.kdfIterations } : {}),
23
+ };
24
+ }
25
+ /**
26
+ * Parse and validate a manifest JSON string.
27
+ * Legacy manifests (without schemaVersion) are treated as "0.16.0".
28
+ */
29
+ function parseManifest(json) {
30
+ let raw;
31
+ try {
32
+ raw = JSON.parse(json);
33
+ }
34
+ catch {
35
+ throw new validation_1.ValidationError('manifest', 'valid JSON', 'parse error');
36
+ }
37
+ if (!raw || typeof raw !== 'object' || Array.isArray(raw)) {
38
+ throw new validation_1.ValidationError('manifest', 'object', typeof raw);
39
+ }
40
+ const o = raw;
41
+ if (o.version !== 1) {
42
+ throw new validation_1.ValidationError('manifest.version', '1', String(o.version));
43
+ }
44
+ if (typeof o.appVersion !== 'string') {
45
+ throw new validation_1.ValidationError('manifest.appVersion', 'string', typeof o.appVersion);
46
+ }
47
+ if (typeof o.exportDate !== 'string') {
48
+ throw new validation_1.ValidationError('manifest.exportDate', 'string', typeof o.exportDate);
49
+ }
50
+ if (typeof o.encrypted !== 'boolean') {
51
+ throw new validation_1.ValidationError('manifest.encrypted', 'boolean', typeof o.encrypted);
52
+ }
53
+ if (typeof o.journalTitle !== 'string') {
54
+ throw new validation_1.ValidationError('manifest.journalTitle', 'string', typeof o.journalTitle);
55
+ }
56
+ // Legacy manifests don't have schemaVersion — default to "0.16.0"
57
+ const schemaVersion = typeof o.schemaVersion === 'string' ? o.schemaVersion : '0.16.0';
58
+ return {
59
+ version: 1,
60
+ schemaVersion,
61
+ appVersion: o.appVersion,
62
+ exportDate: o.exportDate,
63
+ encrypted: o.encrypted,
64
+ journalTitle: o.journalTitle,
65
+ ...(typeof o.salt === 'string' ? { salt: o.salt } : {}),
66
+ ...(typeof o.kdfIterations === 'number' ? { kdfIterations: o.kdfIterations } : {}),
67
+ };
68
+ }
69
+ /** Collect unique attachments from pages for export, building portable ZIP filenames. */
70
+ function collectAttachmentEntries(pages) {
71
+ const seen = new Set();
72
+ const entries = [];
73
+ for (const page of pages) {
74
+ const allAttachments = [...page.images, ...page.files].filter((a) => !a.deleted);
75
+ for (const att of allAttachments) {
76
+ if (!att.path || seen.has(att.path))
77
+ continue;
78
+ seen.add(att.path);
79
+ const parts = att.name.split('.');
80
+ const ext = parts.length > 1 ? parts.pop() : 'bin';
81
+ const zipFilename = `${att.type}-${att.id}.${ext}`;
82
+ entries.push({
83
+ zipFilename,
84
+ diskPath: att.path,
85
+ isPasswordEncrypted: att.encrypted,
86
+ });
87
+ }
88
+ }
89
+ return entries;
90
+ }
91
+ /**
92
+ * Rewrite attachment paths in pages to use portable ZIP filenames.
93
+ * Returns cloned pages with updated paths.
94
+ */
95
+ function rewriteAttachmentPaths(pages, pathMap) {
96
+ return pages.map((page) => ({
97
+ ...page,
98
+ images: page.images.map((a) => ({
99
+ ...a,
100
+ path: pathMap.get(a.path) ?? a.path,
101
+ })),
102
+ files: page.files.map((a) => ({
103
+ ...a,
104
+ path: pathMap.get(a.path) ?? a.path,
105
+ })),
106
+ }));
107
+ }
108
+ // ---------------------------------------------------------------------------
109
+ // Page serialization (pure, no I/O)
110
+ // ---------------------------------------------------------------------------
111
+ /** Serialize pages to a map of pageId → JSON string. */
112
+ function serializePages(pages) {
113
+ const result = new Map();
114
+ for (const page of pages) {
115
+ result.set(page.id, JSON.stringify(page, null, 2));
116
+ }
117
+ return result;
118
+ }
119
+ /** Deserialize pages from a map of filename → JSON string. */
120
+ function deserializePages(entries) {
121
+ const pages = [];
122
+ for (const [, json] of entries) {
123
+ const parsed = JSON.parse(json);
124
+ pages.push((0, validation_2.validatePage)(parsed));
125
+ }
126
+ return pages;
127
+ }
128
+ //# sourceMappingURL=format.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"format.js","sourceRoot":"","sources":["../src/format.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,9 @@
1
+ export type { GeoLocation, Comment, Attachment, Page, PagePreview, JournalSettings, Journal, JournalContent, Filter, SyncProvider, } from './types';
2
+ export { DEFAULT_JOURNAL_SETTINGS, pageToPreview } from './types';
3
+ export { SCHEMA_VERSION, compareVersions, needsMigration, isFutureVersion, isMajorUpgrade, } from './version';
4
+ export { ValidationError, isGeoLocation, isComment, isAttachment, isPage, isJournal, isJournalContent, validateGeoLocation, validateComment, validateAttachment, validatePage, validateJournalSettings, validateJournal, validateJournalContent, } from './validation';
5
+ export type { Migration, MigrationResult } from './migration';
6
+ export { migrateIfNeeded } from './migration';
7
+ export type { ExportManifest, AttachmentEntry, BuildManifestOptions } from './format';
8
+ export { buildExportManifest, parseManifest, collectAttachmentEntries, rewriteAttachmentPaths, serializePages, deserializePages, } from './format';
9
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA,YAAY,EACV,WAAW,EACX,OAAO,EACP,UAAU,EACV,IAAI,EACJ,WAAW,EACX,eAAe,EACf,OAAO,EACP,cAAc,EACd,MAAM,EACN,YAAY,GACb,MAAM,SAAS,CAAC;AAEjB,OAAO,EAAE,wBAAwB,EAAE,aAAa,EAAE,MAAM,SAAS,CAAC;AAGlE,OAAO,EACL,cAAc,EACd,eAAe,EACf,cAAc,EACd,eAAe,EACf,cAAc,GACf,MAAM,WAAW,CAAC;AAGnB,OAAO,EACL,eAAe,EACf,aAAa,EACb,SAAS,EACT,YAAY,EACZ,MAAM,EACN,SAAS,EACT,gBAAgB,EAChB,mBAAmB,EACnB,eAAe,EACf,kBAAkB,EAClB,YAAY,EACZ,uBAAuB,EACvB,eAAe,EACf,sBAAsB,GACvB,MAAM,cAAc,CAAC;AAGtB,YAAY,EAAE,SAAS,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC;AAC9D,OAAO,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC;AAG9C,YAAY,EAAE,cAAc,EAAE,eAAe,EAAE,oBAAoB,EAAE,MAAM,UAAU,CAAC;AACtF,OAAO,EACL,mBAAmB,EACnB,aAAa,EACb,wBAAwB,EACxB,sBAAsB,EACtB,cAAc,EACd,gBAAgB,GACjB,MAAM,UAAU,CAAC"}
package/dist/index.js ADDED
@@ -0,0 +1,39 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.deserializePages = exports.serializePages = exports.rewriteAttachmentPaths = exports.collectAttachmentEntries = exports.parseManifest = exports.buildExportManifest = exports.migrateIfNeeded = exports.validateJournalContent = exports.validateJournal = exports.validateJournalSettings = exports.validatePage = exports.validateAttachment = exports.validateComment = exports.validateGeoLocation = exports.isJournalContent = exports.isJournal = exports.isPage = exports.isAttachment = exports.isComment = exports.isGeoLocation = exports.ValidationError = exports.isMajorUpgrade = exports.isFutureVersion = exports.needsMigration = exports.compareVersions = exports.SCHEMA_VERSION = exports.pageToPreview = exports.DEFAULT_JOURNAL_SETTINGS = void 0;
4
+ var types_1 = require("./types");
5
+ Object.defineProperty(exports, "DEFAULT_JOURNAL_SETTINGS", { enumerable: true, get: function () { return types_1.DEFAULT_JOURNAL_SETTINGS; } });
6
+ Object.defineProperty(exports, "pageToPreview", { enumerable: true, get: function () { return types_1.pageToPreview; } });
7
+ // Version
8
+ var version_1 = require("./version");
9
+ Object.defineProperty(exports, "SCHEMA_VERSION", { enumerable: true, get: function () { return version_1.SCHEMA_VERSION; } });
10
+ Object.defineProperty(exports, "compareVersions", { enumerable: true, get: function () { return version_1.compareVersions; } });
11
+ Object.defineProperty(exports, "needsMigration", { enumerable: true, get: function () { return version_1.needsMigration; } });
12
+ Object.defineProperty(exports, "isFutureVersion", { enumerable: true, get: function () { return version_1.isFutureVersion; } });
13
+ Object.defineProperty(exports, "isMajorUpgrade", { enumerable: true, get: function () { return version_1.isMajorUpgrade; } });
14
+ // Validation
15
+ var validation_1 = require("./validation");
16
+ Object.defineProperty(exports, "ValidationError", { enumerable: true, get: function () { return validation_1.ValidationError; } });
17
+ Object.defineProperty(exports, "isGeoLocation", { enumerable: true, get: function () { return validation_1.isGeoLocation; } });
18
+ Object.defineProperty(exports, "isComment", { enumerable: true, get: function () { return validation_1.isComment; } });
19
+ Object.defineProperty(exports, "isAttachment", { enumerable: true, get: function () { return validation_1.isAttachment; } });
20
+ Object.defineProperty(exports, "isPage", { enumerable: true, get: function () { return validation_1.isPage; } });
21
+ Object.defineProperty(exports, "isJournal", { enumerable: true, get: function () { return validation_1.isJournal; } });
22
+ Object.defineProperty(exports, "isJournalContent", { enumerable: true, get: function () { return validation_1.isJournalContent; } });
23
+ Object.defineProperty(exports, "validateGeoLocation", { enumerable: true, get: function () { return validation_1.validateGeoLocation; } });
24
+ Object.defineProperty(exports, "validateComment", { enumerable: true, get: function () { return validation_1.validateComment; } });
25
+ Object.defineProperty(exports, "validateAttachment", { enumerable: true, get: function () { return validation_1.validateAttachment; } });
26
+ Object.defineProperty(exports, "validatePage", { enumerable: true, get: function () { return validation_1.validatePage; } });
27
+ Object.defineProperty(exports, "validateJournalSettings", { enumerable: true, get: function () { return validation_1.validateJournalSettings; } });
28
+ Object.defineProperty(exports, "validateJournal", { enumerable: true, get: function () { return validation_1.validateJournal; } });
29
+ Object.defineProperty(exports, "validateJournalContent", { enumerable: true, get: function () { return validation_1.validateJournalContent; } });
30
+ var migration_1 = require("./migration");
31
+ Object.defineProperty(exports, "migrateIfNeeded", { enumerable: true, get: function () { return migration_1.migrateIfNeeded; } });
32
+ var format_1 = require("./format");
33
+ Object.defineProperty(exports, "buildExportManifest", { enumerable: true, get: function () { return format_1.buildExportManifest; } });
34
+ Object.defineProperty(exports, "parseManifest", { enumerable: true, get: function () { return format_1.parseManifest; } });
35
+ Object.defineProperty(exports, "collectAttachmentEntries", { enumerable: true, get: function () { return format_1.collectAttachmentEntries; } });
36
+ Object.defineProperty(exports, "rewriteAttachmentPaths", { enumerable: true, get: function () { return format_1.rewriteAttachmentPaths; } });
37
+ Object.defineProperty(exports, "serializePages", { enumerable: true, get: function () { return format_1.serializePages; } });
38
+ Object.defineProperty(exports, "deserializePages", { enumerable: true, get: function () { return format_1.deserializePages; } });
39
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";;;AAcA,iCAAkE;AAAzD,iHAAA,wBAAwB,OAAA;AAAE,sGAAA,aAAa,OAAA;AAEhD,UAAU;AACV,qCAMmB;AALjB,yGAAA,cAAc,OAAA;AACd,0GAAA,eAAe,OAAA;AACf,yGAAA,cAAc,OAAA;AACd,0GAAA,eAAe,OAAA;AACf,yGAAA,cAAc,OAAA;AAGhB,aAAa;AACb,2CAesB;AAdpB,6GAAA,eAAe,OAAA;AACf,2GAAA,aAAa,OAAA;AACb,uGAAA,SAAS,OAAA;AACT,0GAAA,YAAY,OAAA;AACZ,oGAAA,MAAM,OAAA;AACN,uGAAA,SAAS,OAAA;AACT,8GAAA,gBAAgB,OAAA;AAChB,iHAAA,mBAAmB,OAAA;AACnB,6GAAA,eAAe,OAAA;AACf,gHAAA,kBAAkB,OAAA;AAClB,0GAAA,YAAY,OAAA;AACZ,qHAAA,uBAAuB,OAAA;AACvB,6GAAA,eAAe,OAAA;AACf,oHAAA,sBAAsB,OAAA;AAKxB,yCAA8C;AAArC,4GAAA,eAAe,OAAA;AAIxB,mCAOkB;AANhB,6GAAA,mBAAmB,OAAA;AACnB,uGAAA,aAAa,OAAA;AACb,kHAAA,wBAAwB,OAAA;AACxB,gHAAA,sBAAsB,OAAA;AACtB,wGAAA,cAAc,OAAA;AACd,0GAAA,gBAAgB,OAAA"}
@@ -0,0 +1,21 @@
1
+ export interface Migration {
2
+ from: string;
3
+ to: string;
4
+ description: string;
5
+ migrate(data: unknown): unknown;
6
+ }
7
+ export interface MigrationResult {
8
+ data: unknown;
9
+ migrated: boolean;
10
+ fromVersion: string;
11
+ toVersion: string;
12
+ }
13
+ /**
14
+ * Apply any needed migrations to bring data from `fromVersion` to SCHEMA_VERSION.
15
+ *
16
+ * - If `fromVersion` is undefined, treats data as "0.16.0" (legacy).
17
+ * - Migrations apply in sequence (0.16.0 → 0.17.0 → ...).
18
+ * - Throws if the data is from a future version (can't downgrade).
19
+ */
20
+ export declare function migrateIfNeeded(data: unknown, fromVersion?: string): MigrationResult;
21
+ //# sourceMappingURL=migration.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"migration.d.ts","sourceRoot":"","sources":["../src/migration.ts"],"names":[],"mappings":"AAGA,MAAM,WAAW,SAAS;IACxB,IAAI,EAAE,MAAM,CAAC;IACb,EAAE,EAAE,MAAM,CAAC;IACX,WAAW,EAAE,MAAM,CAAC;IACpB,OAAO,CAAC,IAAI,EAAE,OAAO,GAAG,OAAO,CAAC;CACjC;AAED,MAAM,WAAW,eAAe;IAC9B,IAAI,EAAE,OAAO,CAAC;IACd,QAAQ,EAAE,OAAO,CAAC;IAClB,WAAW,EAAE,MAAM,CAAC;IACpB,SAAS,EAAE,MAAM,CAAC;CACnB;AAED;;;;;;GAMG;AACH,wBAAgB,eAAe,CAAC,IAAI,EAAE,OAAO,EAAE,WAAW,CAAC,EAAE,MAAM,GAAG,eAAe,CA4CpF"}
@@ -0,0 +1,47 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.migrateIfNeeded = migrateIfNeeded;
4
+ const version_1 = require("./version");
5
+ const index_1 = require("./migrations/index");
6
+ /**
7
+ * Apply any needed migrations to bring data from `fromVersion` to SCHEMA_VERSION.
8
+ *
9
+ * - If `fromVersion` is undefined, treats data as "0.16.0" (legacy).
10
+ * - Migrations apply in sequence (0.16.0 → 0.17.0 → ...).
11
+ * - Throws if the data is from a future version (can't downgrade).
12
+ */
13
+ function migrateIfNeeded(data, fromVersion) {
14
+ const version = fromVersion ?? '0.16.0';
15
+ if ((0, version_1.isFutureVersion)(version)) {
16
+ throw new Error(`Cannot open data with schema version ${version} — ` +
17
+ `this app supports up to ${version_1.SCHEMA_VERSION}. Please update the app.`);
18
+ }
19
+ if ((0, version_1.compareVersions)(version, version_1.SCHEMA_VERSION) === 0) {
20
+ return { data, migrated: false, fromVersion: version, toVersion: version_1.SCHEMA_VERSION };
21
+ }
22
+ let current = version;
23
+ let result = data;
24
+ // Apply migrations in order
25
+ for (const migration of index_1.MIGRATIONS) {
26
+ if ((0, version_1.compareVersions)(current, migration.from) === 0) {
27
+ try {
28
+ result = migration.migrate(result);
29
+ }
30
+ catch (err) {
31
+ const msg = err instanceof Error ? err.message : String(err);
32
+ throw new Error(`Migration ${migration.from} → ${migration.to} failed: ${msg}` +
33
+ ` (${migration.description})`);
34
+ }
35
+ current = migration.to;
36
+ }
37
+ // Stop if we've reached the target
38
+ if ((0, version_1.compareVersions)(current, version_1.SCHEMA_VERSION) === 0)
39
+ break;
40
+ }
41
+ if ((0, version_1.compareVersions)(current, version_1.SCHEMA_VERSION) !== 0) {
42
+ throw new Error(`No migration path from ${version} to ${version_1.SCHEMA_VERSION}. ` +
43
+ `Reached ${current} but no further migrations available.`);
44
+ }
45
+ return { data: result, migrated: true, fromVersion: version, toVersion: version_1.SCHEMA_VERSION };
46
+ }
47
+ //# sourceMappingURL=migration.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"migration.js","sourceRoot":"","sources":["../src/migration.ts"],"names":[],"mappings":";;AAwBA,0CA4CC;AApED,uCAA6E;AAC7E,8CAAgD;AAgBhD;;;;;;GAMG;AACH,SAAgB,eAAe,CAAC,IAAa,EAAE,WAAoB;IACjE,MAAM,OAAO,GAAG,WAAW,IAAI,QAAQ,CAAC;IAExC,IAAI,IAAA,yBAAe,EAAC,OAAO,CAAC,EAAE,CAAC;QAC7B,MAAM,IAAI,KAAK,CACb,wCAAwC,OAAO,KAAK;YAClD,2BAA2B,wBAAc,0BAA0B,CACtE,CAAC;IACJ,CAAC;IAED,IAAI,IAAA,yBAAe,EAAC,OAAO,EAAE,wBAAc,CAAC,KAAK,CAAC,EAAE,CAAC;QACnD,OAAO,EAAE,IAAI,EAAE,QAAQ,EAAE,KAAK,EAAE,WAAW,EAAE,OAAO,EAAE,SAAS,EAAE,wBAAc,EAAE,CAAC;IACpF,CAAC;IAED,IAAI,OAAO,GAAG,OAAO,CAAC;IACtB,IAAI,MAAM,GAAG,IAAI,CAAC;IAElB,4BAA4B;IAC5B,KAAK,MAAM,SAAS,IAAI,kBAAU,EAAE,CAAC;QACnC,IAAI,IAAA,yBAAe,EAAC,OAAO,EAAE,SAAS,CAAC,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC;YACnD,IAAI,CAAC;gBACH,MAAM,GAAG,SAAS,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC;YACrC,CAAC;YAAC,OAAO,GAAG,EAAE,CAAC;gBACb,MAAM,GAAG,GAAG,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;gBAC7D,MAAM,IAAI,KAAK,CACb,aAAa,SAAS,CAAC,IAAI,MAAM,SAAS,CAAC,EAAE,YAAY,GAAG,EAAE;oBAC5D,KAAK,SAAS,CAAC,WAAW,GAAG,CAChC,CAAC;YACJ,CAAC;YACD,OAAO,GAAG,SAAS,CAAC,EAAE,CAAC;QACzB,CAAC;QAED,mCAAmC;QACnC,IAAI,IAAA,yBAAe,EAAC,OAAO,EAAE,wBAAc,CAAC,KAAK,CAAC;YAAE,MAAM;IAC5D,CAAC;IAED,IAAI,IAAA,yBAAe,EAAC,OAAO,EAAE,wBAAc,CAAC,KAAK,CAAC,EAAE,CAAC;QACnD,MAAM,IAAI,KAAK,CACb,0BAA0B,OAAO,OAAO,wBAAc,IAAI;YACxD,WAAW,OAAO,uCAAuC,CAC5D,CAAC;IACJ,CAAC;IAED,OAAO,EAAE,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,IAAI,EAAE,WAAW,EAAE,OAAO,EAAE,SAAS,EAAE,wBAAc,EAAE,CAAC;AAC3F,CAAC"}
@@ -0,0 +1,6 @@
1
+ import type { Migration } from '../migration';
2
+ /**
3
+ * Registry of all schema migrations, ordered from oldest to newest.
4
+ */
5
+ export declare const MIGRATIONS: Migration[];
6
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/migrations/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,cAAc,CAAC;AAG9C;;GAEG;AACH,eAAO,MAAM,UAAU,EAAE,SAAS,EAAyB,CAAC"}
@@ -0,0 +1,9 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.MIGRATIONS = void 0;
4
+ const v0_16_0_to_v0_17_0_1 = require("./v0_16_0_to_v0_17_0");
5
+ /**
6
+ * Registry of all schema migrations, ordered from oldest to newest.
7
+ */
8
+ exports.MIGRATIONS = [v0_16_0_to_v0_17_0_1.v0_16_0_to_v0_17_0];
9
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/migrations/index.ts"],"names":[],"mappings":";;;AACA,6DAA0D;AAE1D;;GAEG;AACU,QAAA,UAAU,GAAgB,CAAC,uCAAkB,CAAC,CAAC"}
@@ -0,0 +1,9 @@
1
+ import type { Migration } from '../migration';
2
+ /**
3
+ * Migration from schema v0.16.0 to v0.17.0.
4
+ *
5
+ * Removes the deprecated `showMarkdownPlaceholder` field from journal settings.
6
+ * This field was a dead toggle that had no effect on the UI.
7
+ */
8
+ export declare const v0_16_0_to_v0_17_0: Migration;
9
+ //# sourceMappingURL=v0_16_0_to_v0_17_0.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"v0_16_0_to_v0_17_0.d.ts","sourceRoot":"","sources":["../../src/migrations/v0_16_0_to_v0_17_0.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,cAAc,CAAC;AAE9C;;;;;GAKG;AACH,eAAO,MAAM,kBAAkB,EAAE,SAahC,CAAC"}
@@ -0,0 +1,24 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.v0_16_0_to_v0_17_0 = void 0;
4
+ /**
5
+ * Migration from schema v0.16.0 to v0.17.0.
6
+ *
7
+ * Removes the deprecated `showMarkdownPlaceholder` field from journal settings.
8
+ * This field was a dead toggle that had no effect on the UI.
9
+ */
10
+ exports.v0_16_0_to_v0_17_0 = {
11
+ from: '0.16.0',
12
+ to: '0.17.0',
13
+ description: 'Remove deprecated showMarkdownPlaceholder setting',
14
+ migrate(data) {
15
+ if (data && typeof data === 'object' && 'settings' in data) {
16
+ const settings = data.settings;
17
+ if (settings && typeof settings === 'object' && 'showMarkdownPlaceholder' in settings) {
18
+ delete settings.showMarkdownPlaceholder;
19
+ }
20
+ }
21
+ return data;
22
+ },
23
+ };
24
+ //# sourceMappingURL=v0_16_0_to_v0_17_0.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"v0_16_0_to_v0_17_0.js","sourceRoot":"","sources":["../../src/migrations/v0_16_0_to_v0_17_0.ts"],"names":[],"mappings":";;;AAEA;;;;;GAKG;AACU,QAAA,kBAAkB,GAAc;IAC3C,IAAI,EAAE,QAAQ;IACd,EAAE,EAAE,QAAQ;IACZ,WAAW,EAAE,mDAAmD;IAChE,OAAO,CAAC,IAAa;QACnB,IAAI,IAAI,IAAI,OAAO,IAAI,KAAK,QAAQ,IAAI,UAAU,IAAI,IAAI,EAAE,CAAC;YAC3D,MAAM,QAAQ,GAAI,IAAgC,CAAC,QAAQ,CAAC;YAC5D,IAAI,QAAQ,IAAI,OAAO,QAAQ,KAAK,QAAQ,IAAI,yBAAyB,IAAI,QAAQ,EAAE,CAAC;gBACtF,OAAQ,QAAoC,CAAC,uBAAuB,CAAC;YACvE,CAAC;QACH,CAAC;QACD,OAAO,IAAI,CAAC;IACd,CAAC;CACF,CAAC"}
@@ -0,0 +1,93 @@
1
+ export interface GeoLocation {
2
+ latitude: number;
3
+ longitude: number;
4
+ altitude?: number;
5
+ accuracy?: number;
6
+ }
7
+ export interface Comment {
8
+ id: string;
9
+ text: string;
10
+ date: string;
11
+ }
12
+ export interface Attachment {
13
+ id: string;
14
+ path: string;
15
+ name: string;
16
+ type: 'image' | 'file';
17
+ encrypted: boolean;
18
+ size?: number;
19
+ deleted: boolean;
20
+ }
21
+ export interface Page {
22
+ id: string;
23
+ text: string;
24
+ date: string;
25
+ thumbnail?: string;
26
+ location?: GeoLocation;
27
+ tags: string[];
28
+ files: Attachment[];
29
+ images: Attachment[];
30
+ comments: Comment[];
31
+ modified: number;
32
+ deleted: boolean;
33
+ }
34
+ export interface PagePreview {
35
+ id: string;
36
+ date: string;
37
+ previewText: string;
38
+ searchText: string;
39
+ tags: string[];
40
+ hasImage: boolean;
41
+ hasAttachment: boolean;
42
+ hasLocation: boolean;
43
+ hasComments: boolean;
44
+ firstImage?: string;
45
+ thumbnail?: string;
46
+ }
47
+ export type SyncProvider = 'gdrive';
48
+ export interface JournalSettings {
49
+ use24h: boolean;
50
+ previewTags: boolean;
51
+ previewThumbnail: boolean;
52
+ previewIcons: boolean;
53
+ filterBar: boolean;
54
+ sort: 'ascending' | 'descending' | 'none';
55
+ autoLocation: boolean;
56
+ remoteSync: boolean;
57
+ syncProvider?: SyncProvider;
58
+ autoSync: boolean;
59
+ themeOverride?: string;
60
+ }
61
+ export interface Journal {
62
+ id: string;
63
+ title: string;
64
+ icon: string;
65
+ date: string;
66
+ secure: boolean;
67
+ salt: string;
68
+ biometric?: boolean;
69
+ kdfIterations?: number;
70
+ themeOverride?: string;
71
+ }
72
+ export interface JournalContent extends Journal {
73
+ pages: Page[];
74
+ settings: JournalSettings;
75
+ schemaVersion?: string;
76
+ /** @deprecated Use schemaVersion instead. Kept for backward compatibility. */
77
+ version: number;
78
+ }
79
+ export interface Filter {
80
+ query: string;
81
+ properties: {
82
+ tags: string[];
83
+ hasFile: boolean;
84
+ hasImage: boolean;
85
+ hasComments: boolean;
86
+ hasLocation: boolean;
87
+ };
88
+ dateStart?: string;
89
+ dateEnd?: string;
90
+ }
91
+ export declare const DEFAULT_JOURNAL_SETTINGS: JournalSettings;
92
+ export declare function pageToPreview(page: Page): PagePreview;
93
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"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"}
package/dist/types.js ADDED
@@ -0,0 +1,35 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.DEFAULT_JOURNAL_SETTINGS = void 0;
4
+ exports.pageToPreview = pageToPreview;
5
+ exports.DEFAULT_JOURNAL_SETTINGS = {
6
+ use24h: false,
7
+ previewTags: true,
8
+ previewThumbnail: true,
9
+ previewIcons: true,
10
+ filterBar: true,
11
+ sort: 'descending',
12
+ autoLocation: false,
13
+ remoteSync: false,
14
+ autoSync: false,
15
+ };
16
+ function pageToPreview(page) {
17
+ const firstLine = page.text.split('\n').find((l) => l.trim().length > 0) ?? '';
18
+ const previewText = firstLine.substring(0, 120);
19
+ const firstNonEncryptedImage = page.images.find((img) => !img.encrypted && !img.deleted);
20
+ const searchText = page.text.toLowerCase() + ' ' + page.tags.join(' ').toLowerCase();
21
+ return {
22
+ id: page.id,
23
+ date: page.date,
24
+ previewText,
25
+ searchText,
26
+ tags: page.tags,
27
+ hasImage: page.images.length > 0,
28
+ hasAttachment: page.files.length > 0,
29
+ hasLocation: !!page.location,
30
+ hasComments: page.comments.length > 0,
31
+ firstImage: firstNonEncryptedImage?.path,
32
+ thumbnail: page.thumbnail,
33
+ };
34
+ }
35
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":";;;AAgHA,sCAqBC;AAjCY,QAAA,wBAAwB,GAAoB;IACvD,MAAM,EAAE,KAAK;IACb,WAAW,EAAE,IAAI;IACjB,gBAAgB,EAAE,IAAI;IACtB,YAAY,EAAE,IAAI;IAClB,SAAS,EAAE,IAAI;IACf,IAAI,EAAE,YAAY;IAClB,YAAY,EAAE,KAAK;IACnB,UAAU,EAAE,KAAK;IACjB,QAAQ,EAAE,KAAK;CAChB,CAAC;AAEF,SAAgB,aAAa,CAAC,IAAU;IACtC,MAAM,SAAS,GAAG,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC,MAAM,GAAG,CAAC,CAAC,IAAI,EAAE,CAAC;IAC/E,MAAM,WAAW,GAAG,SAAS,CAAC,SAAS,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC;IAEhD,MAAM,sBAAsB,GAAG,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,CAAC,GAAG,CAAC,SAAS,IAAI,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC;IAEzF,MAAM,UAAU,GAAG,IAAI,CAAC,IAAI,CAAC,WAAW,EAAE,GAAG,GAAG,GAAG,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,WAAW,EAAE,CAAC;IAErF,OAAO;QACL,EAAE,EAAE,IAAI,CAAC,EAAE;QACX,IAAI,EAAE,IAAI,CAAC,IAAI;QACf,WAAW;QACX,UAAU;QACV,IAAI,EAAE,IAAI,CAAC,IAAI;QACf,QAAQ,EAAE,IAAI,CAAC,MAAM,CAAC,MAAM,GAAG,CAAC;QAChC,aAAa,EAAE,IAAI,CAAC,KAAK,CAAC,MAAM,GAAG,CAAC;QACpC,WAAW,EAAE,CAAC,CAAC,IAAI,CAAC,QAAQ;QAC5B,WAAW,EAAE,IAAI,CAAC,QAAQ,CAAC,MAAM,GAAG,CAAC;QACrC,UAAU,EAAE,sBAAsB,EAAE,IAAI;QACxC,SAAS,EAAE,IAAI,CAAC,SAAS;KAC1B,CAAC;AACJ,CAAC"}
@@ -0,0 +1,21 @@
1
+ import type { GeoLocation, Comment, Attachment, Page, Journal, JournalContent, JournalSettings } from './types';
2
+ export declare class ValidationError extends Error {
3
+ readonly field: string;
4
+ readonly expected: string;
5
+ readonly received: string;
6
+ constructor(field: string, expected: string, received: string);
7
+ }
8
+ export declare function isGeoLocation(v: unknown): v is GeoLocation;
9
+ export declare function isComment(v: unknown): v is Comment;
10
+ export declare function isAttachment(v: unknown): v is Attachment;
11
+ export declare function isPage(v: unknown): v is Page;
12
+ export declare function isJournal(v: unknown): v is Journal;
13
+ export declare function isJournalContent(v: unknown): v is JournalContent;
14
+ export declare function validateGeoLocation(v: unknown, path?: string): GeoLocation;
15
+ export declare function validateComment(v: unknown, path?: string): Comment;
16
+ export declare function validateAttachment(v: unknown, path?: string): Attachment;
17
+ export declare function validatePage(v: unknown, path?: string): Page;
18
+ export declare function validateJournalSettings(v: unknown, path?: string): JournalSettings;
19
+ export declare function validateJournal(v: unknown, path?: string): Journal;
20
+ export declare function validateJournalContent(v: unknown, path?: string): JournalContent;
21
+ //# sourceMappingURL=validation.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"validation.d.ts","sourceRoot":"","sources":["../src/validation.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,WAAW,EACX,OAAO,EACP,UAAU,EACV,IAAI,EACJ,OAAO,EACP,cAAc,EACd,eAAe,EAChB,MAAM,SAAS,CAAC;AAEjB,qBAAa,eAAgB,SAAQ,KAAK;aAEtB,KAAK,EAAE,MAAM;aACb,QAAQ,EAAE,MAAM;aAChB,QAAQ,EAAE,MAAM;gBAFhB,KAAK,EAAE,MAAM,EACb,QAAQ,EAAE,MAAM,EAChB,QAAQ,EAAE,MAAM;CAKnC;AA4DD,wBAAgB,aAAa,CAAC,CAAC,EAAE,OAAO,GAAG,CAAC,IAAI,WAAW,CAI1D;AAED,wBAAgB,SAAS,CAAC,CAAC,EAAE,OAAO,GAAG,CAAC,IAAI,OAAO,CAIlD;AAED,wBAAgB,YAAY,CAAC,CAAC,EAAE,OAAO,GAAG,CAAC,IAAI,UAAU,CAWxD;AAED,wBAAgB,MAAM,CAAC,CAAC,EAAE,OAAO,GAAG,CAAC,IAAI,IAAI,CAc5C;AAED,wBAAgB,SAAS,CAAC,CAAC,EAAE,OAAO,GAAG,CAAC,IAAI,OAAO,CAUlD;AAED,wBAAgB,gBAAgB,CAAC,CAAC,EAAE,OAAO,GAAG,CAAC,IAAI,cAAc,CAIhE;AAMD,wBAAgB,mBAAmB,CAAC,CAAC,EAAE,OAAO,EAAE,IAAI,SAAa,GAAG,WAAW,CAkB9E;AAED,wBAAgB,eAAe,CAAC,CAAC,EAAE,OAAO,EAAE,IAAI,SAAY,GAAG,OAAO,CAOrE;AAED,wBAAgB,kBAAkB,CAAC,CAAC,EAAE,OAAO,EAAE,IAAI,SAAe,GAAG,UAAU,CAW9E;AAED,wBAAgB,YAAY,CAAC,CAAC,EAAE,OAAO,EAAE,IAAI,SAAS,GAAG,IAAI,CAgC5D;AAED,wBAAgB,uBAAuB,CAAC,CAAC,EAAE,OAAO,EAAE,IAAI,SAAa,GAAG,eAAe,CAiBtF;AAED,wBAAgB,eAAe,CAAC,CAAC,EAAE,OAAO,EAAE,IAAI,SAAY,GAAG,OAAO,CAarE;AAED,wBAAgB,sBAAsB,CAAC,CAAC,EAAE,OAAO,EAAE,IAAI,SAAY,GAAG,cAAc,CAWnF"}
@@ -0,0 +1,244 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.ValidationError = void 0;
4
+ exports.isGeoLocation = isGeoLocation;
5
+ exports.isComment = isComment;
6
+ exports.isAttachment = isAttachment;
7
+ exports.isPage = isPage;
8
+ exports.isJournal = isJournal;
9
+ exports.isJournalContent = isJournalContent;
10
+ exports.validateGeoLocation = validateGeoLocation;
11
+ exports.validateComment = validateComment;
12
+ exports.validateAttachment = validateAttachment;
13
+ exports.validatePage = validatePage;
14
+ exports.validateJournalSettings = validateJournalSettings;
15
+ exports.validateJournal = validateJournal;
16
+ exports.validateJournalContent = validateJournalContent;
17
+ class ValidationError extends Error {
18
+ constructor(field, expected, received) {
19
+ super(`Invalid field "${field}": expected ${expected}, got ${received}`);
20
+ this.field = field;
21
+ this.expected = expected;
22
+ this.received = received;
23
+ this.name = 'ValidationError';
24
+ }
25
+ }
26
+ exports.ValidationError = ValidationError;
27
+ // ---------------------------------------------------------------------------
28
+ // Helpers
29
+ // ---------------------------------------------------------------------------
30
+ function typeOf(v) {
31
+ if (v === null)
32
+ return 'null';
33
+ if (Array.isArray(v))
34
+ return 'array';
35
+ return typeof v;
36
+ }
37
+ function checkType(path, value, expected) {
38
+ const actual = typeOf(value);
39
+ if (actual !== expected) {
40
+ throw new ValidationError(path, expected, actual);
41
+ }
42
+ }
43
+ function checkOptionalType(path, value, expected) {
44
+ if (value !== undefined) {
45
+ checkType(path, value, expected);
46
+ }
47
+ }
48
+ function checkEnum(path, value, allowed) {
49
+ if (typeof value !== 'string' || !allowed.includes(value)) {
50
+ throw new ValidationError(path, `one of ${JSON.stringify(allowed)}`, JSON.stringify(value));
51
+ }
52
+ }
53
+ function checkString(path, value) {
54
+ checkType(path, value, 'string');
55
+ }
56
+ function checkNumber(path, value) {
57
+ checkType(path, value, 'number');
58
+ if (!Number.isFinite(value)) {
59
+ throw new ValidationError(path, 'finite number', String(value));
60
+ }
61
+ }
62
+ function checkBoolean(path, value) {
63
+ checkType(path, value, 'boolean');
64
+ }
65
+ function checkArray(path, value) {
66
+ checkType(path, value, 'array');
67
+ }
68
+ function checkObject(path, value) {
69
+ if (value === null || typeof value !== 'object' || Array.isArray(value)) {
70
+ throw new ValidationError(path, 'object', typeOf(value));
71
+ }
72
+ }
73
+ // ---------------------------------------------------------------------------
74
+ // Type guards (boolean, no throw)
75
+ // ---------------------------------------------------------------------------
76
+ function isGeoLocation(v) {
77
+ if (!v || typeof v !== 'object')
78
+ return false;
79
+ const o = v;
80
+ return typeof o.latitude === 'number' && typeof o.longitude === 'number';
81
+ }
82
+ function isComment(v) {
83
+ if (!v || typeof v !== 'object')
84
+ return false;
85
+ const o = v;
86
+ return typeof o.id === 'string' && typeof o.text === 'string' && typeof o.date === 'string';
87
+ }
88
+ function isAttachment(v) {
89
+ if (!v || typeof v !== 'object')
90
+ return false;
91
+ const o = v;
92
+ return (typeof o.id === 'string' &&
93
+ typeof o.path === 'string' &&
94
+ typeof o.name === 'string' &&
95
+ (o.type === 'image' || o.type === 'file') &&
96
+ typeof o.encrypted === 'boolean' &&
97
+ typeof o.deleted === 'boolean');
98
+ }
99
+ function isPage(v) {
100
+ if (!v || typeof v !== 'object')
101
+ return false;
102
+ const o = v;
103
+ return (typeof o.id === 'string' &&
104
+ typeof o.text === 'string' &&
105
+ typeof o.date === 'string' &&
106
+ Array.isArray(o.tags) &&
107
+ Array.isArray(o.files) &&
108
+ Array.isArray(o.images) &&
109
+ Array.isArray(o.comments) &&
110
+ typeof o.modified === 'number' &&
111
+ typeof o.deleted === 'boolean');
112
+ }
113
+ function isJournal(v) {
114
+ if (!v || typeof v !== 'object')
115
+ return false;
116
+ const o = v;
117
+ return (typeof o.id === 'string' &&
118
+ typeof o.title === 'string' &&
119
+ typeof o.icon === 'string' &&
120
+ typeof o.date === 'string' &&
121
+ typeof o.secure === 'boolean');
122
+ }
123
+ function isJournalContent(v) {
124
+ if (!isJournal(v))
125
+ return false;
126
+ const o = v;
127
+ return Array.isArray(o.pages) && typeof o.settings === 'object' && o.settings !== null;
128
+ }
129
+ // ---------------------------------------------------------------------------
130
+ // Structural validators (throw ValidationError with field path)
131
+ // ---------------------------------------------------------------------------
132
+ function validateGeoLocation(v, path = 'location') {
133
+ checkObject(path, v);
134
+ const o = v;
135
+ checkNumber(`${path}.latitude`, o.latitude);
136
+ checkNumber(`${path}.longitude`, o.longitude);
137
+ if (o.latitude < -90 || o.latitude > 90) {
138
+ throw new ValidationError(`${path}.latitude`, 'number in range [-90, 90]', String(o.latitude));
139
+ }
140
+ if (o.longitude < -180 || o.longitude > 180) {
141
+ throw new ValidationError(`${path}.longitude`, 'number in range [-180, 180]', String(o.longitude));
142
+ }
143
+ checkOptionalType(`${path}.altitude`, o.altitude, 'number');
144
+ checkOptionalType(`${path}.accuracy`, o.accuracy, 'number');
145
+ return v;
146
+ }
147
+ function validateComment(v, path = 'comment') {
148
+ checkObject(path, v);
149
+ const o = v;
150
+ checkString(`${path}.id`, o.id);
151
+ checkString(`${path}.text`, o.text);
152
+ checkString(`${path}.date`, o.date);
153
+ return v;
154
+ }
155
+ function validateAttachment(v, path = 'attachment') {
156
+ checkObject(path, v);
157
+ const o = v;
158
+ checkString(`${path}.id`, o.id);
159
+ checkString(`${path}.path`, o.path);
160
+ checkString(`${path}.name`, o.name);
161
+ checkEnum(`${path}.type`, o.type, ['image', 'file']);
162
+ checkBoolean(`${path}.encrypted`, o.encrypted);
163
+ checkOptionalType(`${path}.size`, o.size, 'number');
164
+ checkBoolean(`${path}.deleted`, o.deleted);
165
+ return v;
166
+ }
167
+ function validatePage(v, path = 'page') {
168
+ checkObject(path, v);
169
+ const o = v;
170
+ checkString(`${path}.id`, o.id);
171
+ checkString(`${path}.text`, o.text);
172
+ checkString(`${path}.date`, o.date);
173
+ checkOptionalType(`${path}.thumbnail`, o.thumbnail, 'string');
174
+ if (o.location !== undefined && o.location !== null) {
175
+ validateGeoLocation(o.location, `${path}.location`);
176
+ }
177
+ checkArray(`${path}.tags`, o.tags);
178
+ for (let i = 0; i < o.tags.length; i++) {
179
+ checkString(`${path}.tags[${i}]`, o.tags[i]);
180
+ if (o.tags[i].trim() === '') {
181
+ throw new ValidationError(`${path}.tags[${i}]`, 'non-empty string', '""');
182
+ }
183
+ }
184
+ checkArray(`${path}.files`, o.files);
185
+ for (let i = 0; i < o.files.length; i++) {
186
+ validateAttachment(o.files[i], `${path}.files[${i}]`);
187
+ }
188
+ checkArray(`${path}.images`, o.images);
189
+ for (let i = 0; i < o.images.length; i++) {
190
+ validateAttachment(o.images[i], `${path}.images[${i}]`);
191
+ }
192
+ checkArray(`${path}.comments`, o.comments);
193
+ for (let i = 0; i < o.comments.length; i++) {
194
+ validateComment(o.comments[i], `${path}.comments[${i}]`);
195
+ }
196
+ checkNumber(`${path}.modified`, o.modified);
197
+ checkBoolean(`${path}.deleted`, o.deleted);
198
+ return v;
199
+ }
200
+ function validateJournalSettings(v, path = 'settings') {
201
+ checkObject(path, v);
202
+ const o = v;
203
+ checkBoolean(`${path}.use24h`, o.use24h);
204
+ checkBoolean(`${path}.previewTags`, o.previewTags);
205
+ checkBoolean(`${path}.previewThumbnail`, o.previewThumbnail);
206
+ checkBoolean(`${path}.previewIcons`, o.previewIcons);
207
+ checkBoolean(`${path}.filterBar`, o.filterBar);
208
+ checkEnum(`${path}.sort`, o.sort, ['ascending', 'descending', 'none']);
209
+ checkBoolean(`${path}.autoLocation`, o.autoLocation);
210
+ checkBoolean(`${path}.remoteSync`, o.remoteSync);
211
+ if (o.syncProvider !== undefined) {
212
+ checkEnum(`${path}.syncProvider`, o.syncProvider, ['gdrive']);
213
+ }
214
+ checkBoolean(`${path}.autoSync`, o.autoSync);
215
+ checkOptionalType(`${path}.themeOverride`, o.themeOverride, 'string');
216
+ return v;
217
+ }
218
+ function validateJournal(v, path = 'journal') {
219
+ checkObject(path, v);
220
+ const o = v;
221
+ checkString(`${path}.id`, o.id);
222
+ checkString(`${path}.title`, o.title);
223
+ checkString(`${path}.icon`, o.icon);
224
+ checkString(`${path}.date`, o.date);
225
+ checkBoolean(`${path}.secure`, o.secure);
226
+ checkOptionalType(`${path}.salt`, o.salt, 'string');
227
+ checkOptionalType(`${path}.biometric`, o.biometric, 'boolean');
228
+ checkOptionalType(`${path}.kdfIterations`, o.kdfIterations, 'number');
229
+ checkOptionalType(`${path}.themeOverride`, o.themeOverride, 'string');
230
+ return v;
231
+ }
232
+ function validateJournalContent(v, path = 'journal') {
233
+ validateJournal(v, path);
234
+ const o = v;
235
+ checkArray(`${path}.pages`, o.pages);
236
+ for (let i = 0; i < o.pages.length; i++) {
237
+ validatePage(o.pages[i], `${path}.pages[${i}]`);
238
+ }
239
+ validateJournalSettings(o.settings, `${path}.settings`);
240
+ // schemaVersion is optional for backward compat (legacy journals lack it)
241
+ checkOptionalType(`${path}.schemaVersion`, o.schemaVersion, 'string');
242
+ return v;
243
+ }
244
+ //# sourceMappingURL=validation.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"validation.js","sourceRoot":"","sources":["../src/validation.ts"],"names":[],"mappings":";;;AA+EA,sCAIC;AAED,8BAIC;AAED,oCAWC;AAED,wBAcC;AAED,8BAUC;AAED,4CAIC;AAMD,kDAkBC;AAED,0CAOC;AAED,gDAWC;AAED,oCAgCC;AAED,0DAiBC;AAED,0CAaC;AAED,wDAWC;AA7PD,MAAa,eAAgB,SAAQ,KAAK;IACxC,YACkB,KAAa,EACb,QAAgB,EAChB,QAAgB;QAEhC,KAAK,CAAC,kBAAkB,KAAK,eAAe,QAAQ,SAAS,QAAQ,EAAE,CAAC,CAAC;QAJzD,UAAK,GAAL,KAAK,CAAQ;QACb,aAAQ,GAAR,QAAQ,CAAQ;QAChB,aAAQ,GAAR,QAAQ,CAAQ;QAGhC,IAAI,CAAC,IAAI,GAAG,iBAAiB,CAAC;IAChC,CAAC;CACF;AATD,0CASC;AAED,8EAA8E;AAC9E,UAAU;AACV,8EAA8E;AAE9E,SAAS,MAAM,CAAC,CAAU;IACxB,IAAI,CAAC,KAAK,IAAI;QAAE,OAAO,MAAM,CAAC;IAC9B,IAAI,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC;QAAE,OAAO,OAAO,CAAC;IACrC,OAAO,OAAO,CAAC,CAAC;AAClB,CAAC;AAED,SAAS,SAAS,CAAC,IAAY,EAAE,KAAc,EAAE,QAAgB;IAC/D,MAAM,MAAM,GAAG,MAAM,CAAC,KAAK,CAAC,CAAC;IAC7B,IAAI,MAAM,KAAK,QAAQ,EAAE,CAAC;QACxB,MAAM,IAAI,eAAe,CAAC,IAAI,EAAE,QAAQ,EAAE,MAAM,CAAC,CAAC;IACpD,CAAC;AACH,CAAC;AAED,SAAS,iBAAiB,CAAC,IAAY,EAAE,KAAc,EAAE,QAAgB;IACvE,IAAI,KAAK,KAAK,SAAS,EAAE,CAAC;QACxB,SAAS,CAAC,IAAI,EAAE,KAAK,EAAE,QAAQ,CAAC,CAAC;IACnC,CAAC;AACH,CAAC;AAED,SAAS,SAAS,CAAC,IAAY,EAAE,KAAc,EAAE,OAA0B;IACzE,IAAI,OAAO,KAAK,KAAK,QAAQ,IAAI,CAAC,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAC,EAAE,CAAC;QAC1D,MAAM,IAAI,eAAe,CAAC,IAAI,EAAE,UAAU,IAAI,CAAC,SAAS,CAAC,OAAO,CAAC,EAAE,EAAE,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,CAAC,CAAC;IAC9F,CAAC;AACH,CAAC;AAED,SAAS,WAAW,CAAC,IAAY,EAAE,KAAc;IAC/C,SAAS,CAAC,IAAI,EAAE,KAAK,EAAE,QAAQ,CAAC,CAAC;AACnC,CAAC;AAED,SAAS,WAAW,CAAC,IAAY,EAAE,KAAc;IAC/C,SAAS,CAAC,IAAI,EAAE,KAAK,EAAE,QAAQ,CAAC,CAAC;IACjC,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,KAAe,CAAC,EAAE,CAAC;QACtC,MAAM,IAAI,eAAe,CAAC,IAAI,EAAE,eAAe,EAAE,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC;IAClE,CAAC;AACH,CAAC;AAED,SAAS,YAAY,CAAC,IAAY,EAAE,KAAc;IAChD,SAAS,CAAC,IAAI,EAAE,KAAK,EAAE,SAAS,CAAC,CAAC;AACpC,CAAC;AAED,SAAS,UAAU,CAAC,IAAY,EAAE,KAAc;IAC9C,SAAS,CAAC,IAAI,EAAE,KAAK,EAAE,OAAO,CAAC,CAAC;AAClC,CAAC;AAED,SAAS,WAAW,CAAC,IAAY,EAAE,KAAc;IAC/C,IAAI,KAAK,KAAK,IAAI,IAAI,OAAO,KAAK,KAAK,QAAQ,IAAI,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,EAAE,CAAC;QACxE,MAAM,IAAI,eAAe,CAAC,IAAI,EAAE,QAAQ,EAAE,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC;IAC3D,CAAC;AACH,CAAC;AAED,8EAA8E;AAC9E,kCAAkC;AAClC,8EAA8E;AAE9E,SAAgB,aAAa,CAAC,CAAU;IACtC,IAAI,CAAC,CAAC,IAAI,OAAO,CAAC,KAAK,QAAQ;QAAE,OAAO,KAAK,CAAC;IAC9C,MAAM,CAAC,GAAG,CAA4B,CAAC;IACvC,OAAO,OAAO,CAAC,CAAC,QAAQ,KAAK,QAAQ,IAAI,OAAO,CAAC,CAAC,SAAS,KAAK,QAAQ,CAAC;AAC3E,CAAC;AAED,SAAgB,SAAS,CAAC,CAAU;IAClC,IAAI,CAAC,CAAC,IAAI,OAAO,CAAC,KAAK,QAAQ;QAAE,OAAO,KAAK,CAAC;IAC9C,MAAM,CAAC,GAAG,CAA4B,CAAC;IACvC,OAAO,OAAO,CAAC,CAAC,EAAE,KAAK,QAAQ,IAAI,OAAO,CAAC,CAAC,IAAI,KAAK,QAAQ,IAAI,OAAO,CAAC,CAAC,IAAI,KAAK,QAAQ,CAAC;AAC9F,CAAC;AAED,SAAgB,YAAY,CAAC,CAAU;IACrC,IAAI,CAAC,CAAC,IAAI,OAAO,CAAC,KAAK,QAAQ;QAAE,OAAO,KAAK,CAAC;IAC9C,MAAM,CAAC,GAAG,CAA4B,CAAC;IACvC,OAAO,CACL,OAAO,CAAC,CAAC,EAAE,KAAK,QAAQ;QACxB,OAAO,CAAC,CAAC,IAAI,KAAK,QAAQ;QAC1B,OAAO,CAAC,CAAC,IAAI,KAAK,QAAQ;QAC1B,CAAC,CAAC,CAAC,IAAI,KAAK,OAAO,IAAI,CAAC,CAAC,IAAI,KAAK,MAAM,CAAC;QACzC,OAAO,CAAC,CAAC,SAAS,KAAK,SAAS;QAChC,OAAO,CAAC,CAAC,OAAO,KAAK,SAAS,CAC/B,CAAC;AACJ,CAAC;AAED,SAAgB,MAAM,CAAC,CAAU;IAC/B,IAAI,CAAC,CAAC,IAAI,OAAO,CAAC,KAAK,QAAQ;QAAE,OAAO,KAAK,CAAC;IAC9C,MAAM,CAAC,GAAG,CAA4B,CAAC;IACvC,OAAO,CACL,OAAO,CAAC,CAAC,EAAE,KAAK,QAAQ;QACxB,OAAO,CAAC,CAAC,IAAI,KAAK,QAAQ;QAC1B,OAAO,CAAC,CAAC,IAAI,KAAK,QAAQ;QAC1B,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,IAAI,CAAC;QACrB,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,KAAK,CAAC;QACtB,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC;QACvB,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,QAAQ,CAAC;QACzB,OAAO,CAAC,CAAC,QAAQ,KAAK,QAAQ;QAC9B,OAAO,CAAC,CAAC,OAAO,KAAK,SAAS,CAC/B,CAAC;AACJ,CAAC;AAED,SAAgB,SAAS,CAAC,CAAU;IAClC,IAAI,CAAC,CAAC,IAAI,OAAO,CAAC,KAAK,QAAQ;QAAE,OAAO,KAAK,CAAC;IAC9C,MAAM,CAAC,GAAG,CAA4B,CAAC;IACvC,OAAO,CACL,OAAO,CAAC,CAAC,EAAE,KAAK,QAAQ;QACxB,OAAO,CAAC,CAAC,KAAK,KAAK,QAAQ;QAC3B,OAAO,CAAC,CAAC,IAAI,KAAK,QAAQ;QAC1B,OAAO,CAAC,CAAC,IAAI,KAAK,QAAQ;QAC1B,OAAO,CAAC,CAAC,MAAM,KAAK,SAAS,CAC9B,CAAC;AACJ,CAAC;AAED,SAAgB,gBAAgB,CAAC,CAAU;IACzC,IAAI,CAAC,SAAS,CAAC,CAAC,CAAC;QAAE,OAAO,KAAK,CAAC;IAChC,MAAM,CAAC,GAAG,CAAuC,CAAC;IAClD,OAAO,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,KAAK,CAAC,IAAI,OAAO,CAAC,CAAC,QAAQ,KAAK,QAAQ,IAAI,CAAC,CAAC,QAAQ,KAAK,IAAI,CAAC;AACzF,CAAC;AAED,8EAA8E;AAC9E,gEAAgE;AAChE,8EAA8E;AAE9E,SAAgB,mBAAmB,CAAC,CAAU,EAAE,IAAI,GAAG,UAAU;IAC/D,WAAW,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC;IACrB,MAAM,CAAC,GAAG,CAA4B,CAAC;IACvC,WAAW,CAAC,GAAG,IAAI,WAAW,EAAE,CAAC,CAAC,QAAQ,CAAC,CAAC;IAC5C,WAAW,CAAC,GAAG,IAAI,YAAY,EAAE,CAAC,CAAC,SAAS,CAAC,CAAC;IAC9C,IAAK,CAAC,CAAC,QAAmB,GAAG,CAAC,EAAE,IAAK,CAAC,CAAC,QAAmB,GAAG,EAAE,EAAE,CAAC;QAChE,MAAM,IAAI,eAAe,CAAC,GAAG,IAAI,WAAW,EAAE,2BAA2B,EAAE,MAAM,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC;IACjG,CAAC;IACD,IAAK,CAAC,CAAC,SAAoB,GAAG,CAAC,GAAG,IAAK,CAAC,CAAC,SAAoB,GAAG,GAAG,EAAE,CAAC;QACpE,MAAM,IAAI,eAAe,CACvB,GAAG,IAAI,YAAY,EACnB,6BAA6B,EAC7B,MAAM,CAAC,CAAC,CAAC,SAAS,CAAC,CACpB,CAAC;IACJ,CAAC;IACD,iBAAiB,CAAC,GAAG,IAAI,WAAW,EAAE,CAAC,CAAC,QAAQ,EAAE,QAAQ,CAAC,CAAC;IAC5D,iBAAiB,CAAC,GAAG,IAAI,WAAW,EAAE,CAAC,CAAC,QAAQ,EAAE,QAAQ,CAAC,CAAC;IAC5D,OAAO,CAAgB,CAAC;AAC1B,CAAC;AAED,SAAgB,eAAe,CAAC,CAAU,EAAE,IAAI,GAAG,SAAS;IAC1D,WAAW,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC;IACrB,MAAM,CAAC,GAAG,CAA4B,CAAC;IACvC,WAAW,CAAC,GAAG,IAAI,KAAK,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC;IAChC,WAAW,CAAC,GAAG,IAAI,OAAO,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC;IACpC,WAAW,CAAC,GAAG,IAAI,OAAO,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC;IACpC,OAAO,CAAY,CAAC;AACtB,CAAC;AAED,SAAgB,kBAAkB,CAAC,CAAU,EAAE,IAAI,GAAG,YAAY;IAChE,WAAW,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC;IACrB,MAAM,CAAC,GAAG,CAA4B,CAAC;IACvC,WAAW,CAAC,GAAG,IAAI,KAAK,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC;IAChC,WAAW,CAAC,GAAG,IAAI,OAAO,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC;IACpC,WAAW,CAAC,GAAG,IAAI,OAAO,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC;IACpC,SAAS,CAAC,GAAG,IAAI,OAAO,EAAE,CAAC,CAAC,IAAI,EAAE,CAAC,OAAO,EAAE,MAAM,CAAC,CAAC,CAAC;IACrD,YAAY,CAAC,GAAG,IAAI,YAAY,EAAE,CAAC,CAAC,SAAS,CAAC,CAAC;IAC/C,iBAAiB,CAAC,GAAG,IAAI,OAAO,EAAE,CAAC,CAAC,IAAI,EAAE,QAAQ,CAAC,CAAC;IACpD,YAAY,CAAC,GAAG,IAAI,UAAU,EAAE,CAAC,CAAC,OAAO,CAAC,CAAC;IAC3C,OAAO,CAAe,CAAC;AACzB,CAAC;AAED,SAAgB,YAAY,CAAC,CAAU,EAAE,IAAI,GAAG,MAAM;IACpD,WAAW,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC;IACrB,MAAM,CAAC,GAAG,CAA4B,CAAC;IACvC,WAAW,CAAC,GAAG,IAAI,KAAK,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC;IAChC,WAAW,CAAC,GAAG,IAAI,OAAO,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC;IACpC,WAAW,CAAC,GAAG,IAAI,OAAO,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC;IACpC,iBAAiB,CAAC,GAAG,IAAI,YAAY,EAAE,CAAC,CAAC,SAAS,EAAE,QAAQ,CAAC,CAAC;IAC9D,IAAI,CAAC,CAAC,QAAQ,KAAK,SAAS,IAAI,CAAC,CAAC,QAAQ,KAAK,IAAI,EAAE,CAAC;QACpD,mBAAmB,CAAC,CAAC,CAAC,QAAQ,EAAE,GAAG,IAAI,WAAW,CAAC,CAAC;IACtD,CAAC;IACD,UAAU,CAAC,GAAG,IAAI,OAAO,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC;IACnC,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAI,CAAC,CAAC,IAAkB,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;QACtD,WAAW,CAAC,GAAG,IAAI,SAAS,CAAC,GAAG,EAAG,CAAC,CAAC,IAAkB,CAAC,CAAC,CAAC,CAAC,CAAC;QAC5D,IAAM,CAAC,CAAC,IAAkB,CAAC,CAAC,CAAY,CAAC,IAAI,EAAE,KAAK,EAAE,EAAE,CAAC;YACvD,MAAM,IAAI,eAAe,CAAC,GAAG,IAAI,SAAS,CAAC,GAAG,EAAE,kBAAkB,EAAE,IAAI,CAAC,CAAC;QAC5E,CAAC;IACH,CAAC;IACD,UAAU,CAAC,GAAG,IAAI,QAAQ,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC;IACrC,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAI,CAAC,CAAC,KAAmB,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;QACvD,kBAAkB,CAAE,CAAC,CAAC,KAAmB,CAAC,CAAC,CAAC,EAAE,GAAG,IAAI,UAAU,CAAC,GAAG,CAAC,CAAC;IACvE,CAAC;IACD,UAAU,CAAC,GAAG,IAAI,SAAS,EAAE,CAAC,CAAC,MAAM,CAAC,CAAC;IACvC,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAI,CAAC,CAAC,MAAoB,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;QACxD,kBAAkB,CAAE,CAAC,CAAC,MAAoB,CAAC,CAAC,CAAC,EAAE,GAAG,IAAI,WAAW,CAAC,GAAG,CAAC,CAAC;IACzE,CAAC;IACD,UAAU,CAAC,GAAG,IAAI,WAAW,EAAE,CAAC,CAAC,QAAQ,CAAC,CAAC;IAC3C,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAI,CAAC,CAAC,QAAsB,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;QAC1D,eAAe,CAAE,CAAC,CAAC,QAAsB,CAAC,CAAC,CAAC,EAAE,GAAG,IAAI,aAAa,CAAC,GAAG,CAAC,CAAC;IAC1E,CAAC;IACD,WAAW,CAAC,GAAG,IAAI,WAAW,EAAE,CAAC,CAAC,QAAQ,CAAC,CAAC;IAC5C,YAAY,CAAC,GAAG,IAAI,UAAU,EAAE,CAAC,CAAC,OAAO,CAAC,CAAC;IAC3C,OAAO,CAAS,CAAC;AACnB,CAAC;AAED,SAAgB,uBAAuB,CAAC,CAAU,EAAE,IAAI,GAAG,UAAU;IACnE,WAAW,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC;IACrB,MAAM,CAAC,GAAG,CAA4B,CAAC;IACvC,YAAY,CAAC,GAAG,IAAI,SAAS,EAAE,CAAC,CAAC,MAAM,CAAC,CAAC;IACzC,YAAY,CAAC,GAAG,IAAI,cAAc,EAAE,CAAC,CAAC,WAAW,CAAC,CAAC;IACnD,YAAY,CAAC,GAAG,IAAI,mBAAmB,EAAE,CAAC,CAAC,gBAAgB,CAAC,CAAC;IAC7D,YAAY,CAAC,GAAG,IAAI,eAAe,EAAE,CAAC,CAAC,YAAY,CAAC,CAAC;IACrD,YAAY,CAAC,GAAG,IAAI,YAAY,EAAE,CAAC,CAAC,SAAS,CAAC,CAAC;IAC/C,SAAS,CAAC,GAAG,IAAI,OAAO,EAAE,CAAC,CAAC,IAAI,EAAE,CAAC,WAAW,EAAE,YAAY,EAAE,MAAM,CAAC,CAAC,CAAC;IACvE,YAAY,CAAC,GAAG,IAAI,eAAe,EAAE,CAAC,CAAC,YAAY,CAAC,CAAC;IACrD,YAAY,CAAC,GAAG,IAAI,aAAa,EAAE,CAAC,CAAC,UAAU,CAAC,CAAC;IACjD,IAAI,CAAC,CAAC,YAAY,KAAK,SAAS,EAAE,CAAC;QACjC,SAAS,CAAC,GAAG,IAAI,eAAe,EAAE,CAAC,CAAC,YAAY,EAAE,CAAC,QAAQ,CAAC,CAAC,CAAC;IAChE,CAAC;IACD,YAAY,CAAC,GAAG,IAAI,WAAW,EAAE,CAAC,CAAC,QAAQ,CAAC,CAAC;IAC7C,iBAAiB,CAAC,GAAG,IAAI,gBAAgB,EAAE,CAAC,CAAC,aAAa,EAAE,QAAQ,CAAC,CAAC;IACtE,OAAO,CAAoB,CAAC;AAC9B,CAAC;AAED,SAAgB,eAAe,CAAC,CAAU,EAAE,IAAI,GAAG,SAAS;IAC1D,WAAW,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC;IACrB,MAAM,CAAC,GAAG,CAA4B,CAAC;IACvC,WAAW,CAAC,GAAG,IAAI,KAAK,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC;IAChC,WAAW,CAAC,GAAG,IAAI,QAAQ,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC;IACtC,WAAW,CAAC,GAAG,IAAI,OAAO,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC;IACpC,WAAW,CAAC,GAAG,IAAI,OAAO,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC;IACpC,YAAY,CAAC,GAAG,IAAI,SAAS,EAAE,CAAC,CAAC,MAAM,CAAC,CAAC;IACzC,iBAAiB,CAAC,GAAG,IAAI,OAAO,EAAE,CAAC,CAAC,IAAI,EAAE,QAAQ,CAAC,CAAC;IACpD,iBAAiB,CAAC,GAAG,IAAI,YAAY,EAAE,CAAC,CAAC,SAAS,EAAE,SAAS,CAAC,CAAC;IAC/D,iBAAiB,CAAC,GAAG,IAAI,gBAAgB,EAAE,CAAC,CAAC,aAAa,EAAE,QAAQ,CAAC,CAAC;IACtE,iBAAiB,CAAC,GAAG,IAAI,gBAAgB,EAAE,CAAC,CAAC,aAAa,EAAE,QAAQ,CAAC,CAAC;IACtE,OAAO,CAAY,CAAC;AACtB,CAAC;AAED,SAAgB,sBAAsB,CAAC,CAAU,EAAE,IAAI,GAAG,SAAS;IACjE,eAAe,CAAC,CAAC,EAAE,IAAI,CAAC,CAAC;IACzB,MAAM,CAAC,GAAG,CAA4B,CAAC;IACvC,UAAU,CAAC,GAAG,IAAI,QAAQ,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC;IACrC,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAI,CAAC,CAAC,KAAmB,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;QACvD,YAAY,CAAE,CAAC,CAAC,KAAmB,CAAC,CAAC,CAAC,EAAE,GAAG,IAAI,UAAU,CAAC,GAAG,CAAC,CAAC;IACjE,CAAC;IACD,uBAAuB,CAAC,CAAC,CAAC,QAAQ,EAAE,GAAG,IAAI,WAAW,CAAC,CAAC;IACxD,0EAA0E;IAC1E,iBAAiB,CAAC,GAAG,IAAI,gBAAgB,EAAE,CAAC,CAAC,aAAa,EAAE,QAAQ,CAAC,CAAC;IACtE,OAAO,CAAmB,CAAC;AAC7B,CAAC"}
@@ -0,0 +1,11 @@
1
+ /** Current Canto journal schema version (semver). */
2
+ export declare const SCHEMA_VERSION = "0.17.0";
3
+ /** Compare two semver strings. Returns -1 (a < b), 0 (equal), or 1 (a > b). */
4
+ export declare function compareVersions(a: string, b: string): -1 | 0 | 1;
5
+ /** True if `version` needs migration to reach SCHEMA_VERSION (strictly older). */
6
+ export declare function needsMigration(version: string): boolean;
7
+ /** True if `version` is newer than SCHEMA_VERSION (can't handle). */
8
+ export declare function isFutureVersion(version: string): boolean;
9
+ /** True if `version` requires a breaking migration (different major version). */
10
+ export declare function isMajorUpgrade(from: string, to: string): boolean;
11
+ //# sourceMappingURL=version.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"version.d.ts","sourceRoot":"","sources":["../src/version.ts"],"names":[],"mappings":"AAAA,qDAAqD;AACrD,eAAO,MAAM,cAAc,WAAW,CAAC;AAWvC,+EAA+E;AAC/E,wBAAgB,eAAe,CAAC,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,MAAM,GAAG,CAAC,CAAC,GAAG,CAAC,GAAG,CAAC,CAQhE;AAED,kFAAkF;AAClF,wBAAgB,cAAc,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAEvD;AAED,qEAAqE;AACrE,wBAAgB,eAAe,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAExD;AAED,iFAAiF;AACjF,wBAAgB,cAAc,CAAC,IAAI,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,GAAG,OAAO,CAIhE"}
@@ -0,0 +1,44 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.SCHEMA_VERSION = void 0;
4
+ exports.compareVersions = compareVersions;
5
+ exports.needsMigration = needsMigration;
6
+ exports.isFutureVersion = isFutureVersion;
7
+ exports.isMajorUpgrade = isMajorUpgrade;
8
+ /** Current Canto journal schema version (semver). */
9
+ exports.SCHEMA_VERSION = '0.17.0';
10
+ /** Parse a semver string into [major, minor, patch]. Throws on invalid format. */
11
+ function parseSemver(v) {
12
+ const parts = v.split('.').map(Number);
13
+ if (parts.length !== 3 || parts.some(isNaN)) {
14
+ throw new Error(`Invalid schema version: "${v}" (expected semver like "1.0.0")`);
15
+ }
16
+ return parts;
17
+ }
18
+ /** Compare two semver strings. Returns -1 (a < b), 0 (equal), or 1 (a > b). */
19
+ function compareVersions(a, b) {
20
+ const [aMaj, aMin, aPat] = parseSemver(a);
21
+ const [bMaj, bMin, bPat] = parseSemver(b);
22
+ if (aMaj !== bMaj)
23
+ return aMaj < bMaj ? -1 : 1;
24
+ if (aMin !== bMin)
25
+ return aMin < bMin ? -1 : 1;
26
+ if (aPat !== bPat)
27
+ return aPat < bPat ? -1 : 1;
28
+ return 0;
29
+ }
30
+ /** True if `version` needs migration to reach SCHEMA_VERSION (strictly older). */
31
+ function needsMigration(version) {
32
+ return compareVersions(version, exports.SCHEMA_VERSION) < 0;
33
+ }
34
+ /** True if `version` is newer than SCHEMA_VERSION (can't handle). */
35
+ function isFutureVersion(version) {
36
+ return compareVersions(version, exports.SCHEMA_VERSION) > 0;
37
+ }
38
+ /** True if `version` requires a breaking migration (different major version). */
39
+ function isMajorUpgrade(from, to) {
40
+ const [fromMaj] = parseSemver(from);
41
+ const [toMaj] = parseSemver(to);
42
+ return toMaj > fromMaj;
43
+ }
44
+ //# sourceMappingURL=version.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"version.js","sourceRoot":"","sources":["../src/version.ts"],"names":[],"mappings":";;;AAaA,0CAQC;AAGD,wCAEC;AAGD,0CAEC;AAGD,wCAIC;AAtCD,qDAAqD;AACxC,QAAA,cAAc,GAAG,QAAQ,CAAC;AAEvC,kFAAkF;AAClF,SAAS,WAAW,CAAC,CAAS;IAC5B,MAAM,KAAK,GAAG,CAAC,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC;IACvC,IAAI,KAAK,CAAC,MAAM,KAAK,CAAC,IAAI,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC;QAC5C,MAAM,IAAI,KAAK,CAAC,4BAA4B,CAAC,kCAAkC,CAAC,CAAC;IACnF,CAAC;IACD,OAAO,KAAiC,CAAC;AAC3C,CAAC;AAED,+EAA+E;AAC/E,SAAgB,eAAe,CAAC,CAAS,EAAE,CAAS;IAClD,MAAM,CAAC,IAAI,EAAE,IAAI,EAAE,IAAI,CAAC,GAAG,WAAW,CAAC,CAAC,CAAC,CAAC;IAC1C,MAAM,CAAC,IAAI,EAAE,IAAI,EAAE,IAAI,CAAC,GAAG,WAAW,CAAC,CAAC,CAAC,CAAC;IAE1C,IAAI,IAAI,KAAK,IAAI;QAAE,OAAO,IAAI,GAAG,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;IAC/C,IAAI,IAAI,KAAK,IAAI;QAAE,OAAO,IAAI,GAAG,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;IAC/C,IAAI,IAAI,KAAK,IAAI;QAAE,OAAO,IAAI,GAAG,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;IAC/C,OAAO,CAAC,CAAC;AACX,CAAC;AAED,kFAAkF;AAClF,SAAgB,cAAc,CAAC,OAAe;IAC5C,OAAO,eAAe,CAAC,OAAO,EAAE,sBAAc,CAAC,GAAG,CAAC,CAAC;AACtD,CAAC;AAED,qEAAqE;AACrE,SAAgB,eAAe,CAAC,OAAe;IAC7C,OAAO,eAAe,CAAC,OAAO,EAAE,sBAAc,CAAC,GAAG,CAAC,CAAC;AACtD,CAAC;AAED,iFAAiF;AACjF,SAAgB,cAAc,CAAC,IAAY,EAAE,EAAU;IACrD,MAAM,CAAC,OAAO,CAAC,GAAG,WAAW,CAAC,IAAI,CAAC,CAAC;IACpC,MAAM,CAAC,KAAK,CAAC,GAAG,WAAW,CAAC,EAAE,CAAC,CAAC;IAChC,OAAO,KAAK,GAAG,OAAO,CAAC;AACzB,CAAC"}
package/package.json ADDED
@@ -0,0 +1,65 @@
1
+ {
2
+ "name": "canto-data",
3
+ "version": "1.0.0",
4
+ "description": "Canto journal data model — types, validation, versioning, and format utilities",
5
+ "license": "MIT",
6
+ "main": "dist/index.js",
7
+ "types": "dist/index.d.ts",
8
+ "exports": {
9
+ ".": {
10
+ "types": "./dist/index.d.ts",
11
+ "default": "./dist/index.js"
12
+ },
13
+ "./types": {
14
+ "types": "./dist/types.d.ts",
15
+ "default": "./dist/types.js"
16
+ },
17
+ "./format": {
18
+ "types": "./dist/format.d.ts",
19
+ "default": "./dist/format.js"
20
+ },
21
+ "./version": {
22
+ "types": "./dist/version.d.ts",
23
+ "default": "./dist/version.js"
24
+ },
25
+ "./validation": {
26
+ "types": "./dist/validation.d.ts",
27
+ "default": "./dist/validation.js"
28
+ },
29
+ "./migration": {
30
+ "types": "./dist/migration.d.ts",
31
+ "default": "./dist/migration.js"
32
+ }
33
+ },
34
+ "files": [
35
+ "dist",
36
+ "LICENSE"
37
+ ],
38
+ "scripts": {
39
+ "build": "tsc",
40
+ "test": "jest",
41
+ "test:coverage": "jest --coverage",
42
+ "test:ci": "jest --coverage --ci",
43
+ "prepublishOnly": "npm run build && npm test"
44
+ },
45
+ "keywords": [
46
+ "canto",
47
+ "journal",
48
+ "data-model",
49
+ "validation",
50
+ "schema"
51
+ ],
52
+ "repository": {
53
+ "type": "git",
54
+ "url": "https://github.com/pboueke/canto-data"
55
+ },
56
+ "engines": {
57
+ "node": ">=18"
58
+ },
59
+ "devDependencies": {
60
+ "@types/jest": "^30.0.0",
61
+ "jest": "^30.3.0",
62
+ "ts-jest": "^29.4.6",
63
+ "typescript": "^5.9.3"
64
+ }
65
+ }