@ontrails/schema 1.0.0-beta.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/src/io.ts ADDED
@@ -0,0 +1,115 @@
1
+ /**
2
+ * File I/O for surface maps and lock files.
3
+ */
4
+
5
+ import { mkdir } from 'node:fs/promises';
6
+ import { join } from 'node:path';
7
+
8
+ import type { ReadOptions, SurfaceMap, WriteOptions } from './types.js';
9
+
10
+ // ---------------------------------------------------------------------------
11
+ // Constants
12
+ // ---------------------------------------------------------------------------
13
+
14
+ const DEFAULT_DIR = '.trails';
15
+ const SURFACE_MAP_FILE = '_surface.json';
16
+ const SURFACE_LOCK_FILE = 'surface.lock';
17
+
18
+ // ---------------------------------------------------------------------------
19
+ // Helpers
20
+ // ---------------------------------------------------------------------------
21
+
22
+ const isNotFound = (err: unknown): boolean =>
23
+ typeof err === 'object' &&
24
+ err !== null &&
25
+ (err as NodeJS.ErrnoException).code === 'ENOENT';
26
+
27
+ const resolveDir = (options?: ReadOptions | WriteOptions): string =>
28
+ options?.dir ?? DEFAULT_DIR;
29
+
30
+ const ensureDir = async (dir: string): Promise<void> => {
31
+ await mkdir(dir, { recursive: true });
32
+ };
33
+
34
+ // ---------------------------------------------------------------------------
35
+ // Surface Map
36
+ // ---------------------------------------------------------------------------
37
+
38
+ /**
39
+ * Write a surface map to `<dir>/_surface.json`.
40
+ *
41
+ * Creates the directory if it doesn't exist. Returns the file path.
42
+ */
43
+ export const writeSurfaceMap = async (
44
+ surfaceMap: SurfaceMap,
45
+ options?: WriteOptions
46
+ ): Promise<string> => {
47
+ const dir = resolveDir(options);
48
+ await ensureDir(dir);
49
+ const filePath = join(dir, SURFACE_MAP_FILE);
50
+ const json = `${JSON.stringify(surfaceMap, null, 2)}\n`;
51
+ await Bun.write(filePath, json);
52
+ return filePath;
53
+ };
54
+
55
+ /**
56
+ * Read a surface map from `<dir>/_surface.json`.
57
+ *
58
+ * Returns `null` if the file doesn't exist.
59
+ */
60
+ export const readSurfaceMap = async (
61
+ options?: ReadOptions
62
+ ): Promise<SurfaceMap | null> => {
63
+ const dir = resolveDir(options);
64
+ const filePath = join(dir, SURFACE_MAP_FILE);
65
+ try {
66
+ const content = await Bun.file(filePath).text();
67
+ return JSON.parse(content) as SurfaceMap;
68
+ } catch (error: unknown) {
69
+ if (isNotFound(error)) {
70
+ return null;
71
+ }
72
+ throw error;
73
+ }
74
+ };
75
+
76
+ // ---------------------------------------------------------------------------
77
+ // Surface Lock
78
+ // ---------------------------------------------------------------------------
79
+
80
+ /**
81
+ * Write a hash to `<dir>/surface.lock` as a single line.
82
+ *
83
+ * Creates the directory if it doesn't exist. Returns the file path.
84
+ */
85
+ export const writeSurfaceLock = async (
86
+ hash: string,
87
+ options?: WriteOptions
88
+ ): Promise<string> => {
89
+ const dir = resolveDir(options);
90
+ await ensureDir(dir);
91
+ const filePath = join(dir, SURFACE_LOCK_FILE);
92
+ await Bun.write(filePath, `${hash}\n`);
93
+ return filePath;
94
+ };
95
+
96
+ /**
97
+ * Read the hash from `<dir>/surface.lock`.
98
+ *
99
+ * Returns `null` if the file doesn't exist.
100
+ */
101
+ export const readSurfaceLock = async (
102
+ options?: ReadOptions
103
+ ): Promise<string | null> => {
104
+ const dir = resolveDir(options);
105
+ const filePath = join(dir, SURFACE_LOCK_FILE);
106
+ try {
107
+ const content = await Bun.file(filePath).text();
108
+ return content.trim();
109
+ } catch (error: unknown) {
110
+ if (isNotFound(error)) {
111
+ return null;
112
+ }
113
+ throw error;
114
+ }
115
+ };
package/src/types.ts ADDED
@@ -0,0 +1,71 @@
1
+ /**
2
+ * Types for surface maps, diffing, and lock files.
3
+ */
4
+
5
+ // ---------------------------------------------------------------------------
6
+ // JSON Schema (lightweight alias)
7
+ // ---------------------------------------------------------------------------
8
+
9
+ /** A JSON Schema object produced by zodToJsonSchema. */
10
+ export type JsonSchema = Readonly<Record<string, unknown>>;
11
+
12
+ // ---------------------------------------------------------------------------
13
+ // Surface Map
14
+ // ---------------------------------------------------------------------------
15
+
16
+ export interface SurfaceMapEntry {
17
+ readonly id: string;
18
+ readonly kind: 'trail' | 'hike' | 'event';
19
+ readonly surfaces: readonly string[];
20
+ readonly input?: JsonSchema | undefined;
21
+ readonly output?: JsonSchema | undefined;
22
+ readonly readOnly?: boolean | undefined;
23
+ readonly destructive?: boolean | undefined;
24
+ readonly idempotent?: boolean | undefined;
25
+ readonly deprecated?: boolean | undefined;
26
+ readonly replacedBy?: string | undefined;
27
+ readonly follows?: readonly string[] | undefined;
28
+ readonly detours?: Readonly<Record<string, readonly string[]>> | undefined;
29
+ readonly exampleCount: number;
30
+ readonly description?: string | undefined;
31
+ }
32
+
33
+ export interface SurfaceMap {
34
+ readonly version: string;
35
+ readonly generatedAt: string;
36
+ readonly entries: readonly SurfaceMapEntry[];
37
+ }
38
+
39
+ // ---------------------------------------------------------------------------
40
+ // Diff
41
+ // ---------------------------------------------------------------------------
42
+
43
+ export interface DiffEntry {
44
+ readonly id: string;
45
+ readonly kind: 'trail' | 'hike' | 'event';
46
+ readonly change: 'added' | 'removed' | 'modified';
47
+ readonly severity: 'info' | 'warning' | 'breaking';
48
+ readonly details: readonly string[];
49
+ }
50
+
51
+ export interface DiffResult {
52
+ readonly entries: readonly DiffEntry[];
53
+ readonly breaking: readonly DiffEntry[];
54
+ readonly warnings: readonly DiffEntry[];
55
+ readonly info: readonly DiffEntry[];
56
+ readonly hasBreaking: boolean;
57
+ }
58
+
59
+ // ---------------------------------------------------------------------------
60
+ // I/O options
61
+ // ---------------------------------------------------------------------------
62
+
63
+ export interface WriteOptions {
64
+ /** Directory to write to. Defaults to ".trails/" */
65
+ readonly dir?: string | undefined;
66
+ }
67
+
68
+ export interface ReadOptions {
69
+ /** Directory to read from. Defaults to ".trails/" */
70
+ readonly dir?: string | undefined;
71
+ }
package/tsconfig.json ADDED
@@ -0,0 +1,9 @@
1
+ {
2
+ "extends": "../../tsconfig.json",
3
+ "compilerOptions": {
4
+ "outDir": "dist",
5
+ "rootDir": "src"
6
+ },
7
+ "include": ["src"],
8
+ "exclude": ["**/__tests__/**", "**/*.test.ts", "dist"]
9
+ }
@@ -0,0 +1 @@
1
+ {"root":["./src/diff.ts","./src/generate.ts","./src/hash.ts","./src/index.ts","./src/io.ts","./src/types.ts"],"version":"5.9.3"}