@drewpayment/mink 0.1.0 → 0.2.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.
@@ -0,0 +1,179 @@
1
+ import { join } from "path";
2
+ import { existsSync, writeFileSync, readFileSync, mkdirSync } from "fs";
3
+
4
+ export const DEFAULT_TEMPLATES: Record<string, string> = {
5
+ "quick-capture": `---
6
+ created: "{{created}}"
7
+ updated: "{{updated}}"
8
+ tags: []
9
+ category: inbox
10
+ ---
11
+
12
+ # {{title}}
13
+
14
+ {{body}}
15
+ `,
16
+
17
+ "daily-note": `---
18
+ created: "{{created}}"
19
+ updated: "{{updated}}"
20
+ tags: [daily]
21
+ category: areas
22
+ ---
23
+
24
+ # {{date}}
25
+
26
+ ## Focus
27
+
28
+ -
29
+
30
+ ## Notes
31
+
32
+ -
33
+
34
+ ## Tasks
35
+
36
+ - [ ]
37
+
38
+ ## Reflections
39
+
40
+ `,
41
+
42
+ meeting: `---
43
+ created: "{{created}}"
44
+ updated: "{{updated}}"
45
+ tags: [meeting]
46
+ category: areas
47
+ ---
48
+
49
+ # {{title}}
50
+
51
+ **Date**: {{date}}
52
+ **Attendees**:
53
+
54
+ ## Agenda
55
+
56
+ -
57
+
58
+ ## Discussion
59
+
60
+ -
61
+
62
+ ## Decisions
63
+
64
+ -
65
+
66
+ ## Action Items
67
+
68
+ - [ ]
69
+ `,
70
+
71
+ project: `---
72
+ created: "{{created}}"
73
+ updated: "{{updated}}"
74
+ tags: [project]
75
+ category: projects
76
+ status: active
77
+ ---
78
+
79
+ # {{title}}
80
+
81
+ ## Overview
82
+
83
+ {{body}}
84
+
85
+ ## Goals
86
+
87
+ -
88
+
89
+ ## Key Decisions
90
+
91
+ -
92
+
93
+ ## Links
94
+
95
+ -
96
+ `,
97
+
98
+ area: `---
99
+ created: "{{created}}"
100
+ updated: "{{updated}}"
101
+ tags: [area]
102
+ category: areas
103
+ ---
104
+
105
+ # {{title}}
106
+
107
+ ## Purpose
108
+
109
+ {{body}}
110
+
111
+ ## Standards
112
+
113
+ -
114
+
115
+ ## Key Resources
116
+
117
+ -
118
+ `,
119
+
120
+ person: `---
121
+ created: "{{created}}"
122
+ updated: "{{updated}}"
123
+ tags: [person]
124
+ category: resources
125
+ ---
126
+
127
+ # {{title}}
128
+
129
+ ## Role
130
+
131
+ ## Context
132
+
133
+ ## 1:1 Notes
134
+
135
+ -
136
+
137
+ ## Key Projects
138
+
139
+ -
140
+ `,
141
+ };
142
+
143
+ export function seedTemplates(templatesDir: string): void {
144
+ mkdirSync(templatesDir, { recursive: true });
145
+ for (const [name, content] of Object.entries(DEFAULT_TEMPLATES)) {
146
+ const filePath = join(templatesDir, `${name}.md`);
147
+ if (!existsSync(filePath)) {
148
+ writeFileSync(filePath, content);
149
+ }
150
+ }
151
+ }
152
+
153
+ export function loadTemplate(
154
+ templatesDir: string,
155
+ templateName: string,
156
+ vars: Record<string, string>
157
+ ): string | null {
158
+ const filePath = join(templatesDir, `${templateName}.md`);
159
+ let content: string;
160
+ if (existsSync(filePath)) {
161
+ content = readFileSync(filePath, "utf-8");
162
+ } else if (DEFAULT_TEMPLATES[templateName]) {
163
+ content = DEFAULT_TEMPLATES[templateName];
164
+ } else {
165
+ return null;
166
+ }
167
+ return fillTemplate(content, vars);
168
+ }
169
+
170
+ export function fillTemplate(
171
+ template: string,
172
+ vars: Record<string, string>
173
+ ): string {
174
+ let result = template;
175
+ for (const [key, value] of Object.entries(vars)) {
176
+ result = result.replaceAll(`{{${key}}}`, value);
177
+ }
178
+ return result;
179
+ }
@@ -0,0 +1,132 @@
1
+ import { join } from "path";
2
+ import { homedir } from "os";
3
+ import { existsSync, mkdirSync } from "fs";
4
+ import { resolveConfigValue } from "./global-config";
5
+ import { safeReadJson } from "./fs-utils";
6
+ import type { VaultManifest } from "../types/note";
7
+
8
+ const DEFAULT_VAULT_PATH = join(homedir(), ".mink", "wiki");
9
+
10
+ export function resolveVaultPath(): string {
11
+ const resolved = resolveConfigValue("wiki.path");
12
+ const raw = resolved.value;
13
+ if (raw.startsWith("~/")) {
14
+ return join(homedir(), raw.slice(2));
15
+ }
16
+ return raw;
17
+ }
18
+
19
+ export function vaultRoot(): string {
20
+ return resolveVaultPath();
21
+ }
22
+
23
+ export function vaultInbox(): string {
24
+ return join(resolveVaultPath(), "inbox");
25
+ }
26
+
27
+ export function vaultProjects(slug?: string): string {
28
+ const base = join(resolveVaultPath(), "projects");
29
+ return slug ? join(base, slug) : base;
30
+ }
31
+
32
+ export function vaultAreas(): string {
33
+ return join(resolveVaultPath(), "areas");
34
+ }
35
+
36
+ export function vaultDailyDir(): string {
37
+ return join(resolveVaultPath(), "areas", "daily");
38
+ }
39
+
40
+ export function vaultResources(): string {
41
+ return join(resolveVaultPath(), "resources");
42
+ }
43
+
44
+ export function vaultArchives(): string {
45
+ return join(resolveVaultPath(), "archives");
46
+ }
47
+
48
+ export function vaultTemplates(): string {
49
+ return join(resolveVaultPath(), "templates");
50
+ }
51
+
52
+ export function vaultPatterns(): string {
53
+ return join(resolveVaultPath(), "patterns");
54
+ }
55
+
56
+ export function vaultManifestPath(): string {
57
+ return join(resolveVaultPath(), ".mink-vault.json");
58
+ }
59
+
60
+ export function vaultIndexPath(): string {
61
+ return join(resolveVaultPath(), ".mink-index.json");
62
+ }
63
+
64
+ export function vaultMasterIndexPath(): string {
65
+ return join(resolveVaultPath(), "_index.md");
66
+ }
67
+
68
+ export function isVaultInitialized(): boolean {
69
+ return existsSync(vaultManifestPath());
70
+ }
71
+
72
+ export function isInsideVault(cwd: string): boolean {
73
+ const vault = resolveVaultPath();
74
+ const normalizedCwd = cwd.replace(/\/+$/, "");
75
+ const normalizedVault = vault.replace(/\/+$/, "");
76
+ return (
77
+ normalizedCwd === normalizedVault ||
78
+ normalizedCwd.startsWith(normalizedVault + "/")
79
+ );
80
+ }
81
+
82
+ export function isWikiEnabled(): boolean {
83
+ const resolved = resolveConfigValue("wiki.enabled");
84
+ return resolved.value === "true";
85
+ }
86
+
87
+ export function loadVaultManifest(): VaultManifest | null {
88
+ const raw = safeReadJson(vaultManifestPath());
89
+ if (raw === null || typeof raw !== "object") return null;
90
+ return raw as VaultManifest;
91
+ }
92
+
93
+ const VAULT_DIRS = [
94
+ "",
95
+ "inbox",
96
+ "projects",
97
+ "areas",
98
+ "areas/daily",
99
+ "resources",
100
+ "archives",
101
+ "templates",
102
+ "patterns",
103
+ ];
104
+
105
+ export function ensureVaultStructure(): void {
106
+ const root = resolveVaultPath();
107
+ for (const dir of VAULT_DIRS) {
108
+ mkdirSync(join(root, dir), { recursive: true });
109
+ }
110
+ }
111
+
112
+ export function categoryToDir(
113
+ category: string,
114
+ projectSlug?: string
115
+ ): string {
116
+ const root = resolveVaultPath();
117
+ switch (category) {
118
+ case "projects":
119
+ return projectSlug
120
+ ? join(root, "projects", projectSlug)
121
+ : join(root, "projects");
122
+ case "areas":
123
+ return join(root, "areas");
124
+ case "resources":
125
+ return join(root, "resources");
126
+ case "archives":
127
+ return join(root, "archives");
128
+ case "inbox":
129
+ default:
130
+ return join(root, "inbox");
131
+ }
132
+ }
@@ -4,6 +4,7 @@ export interface GlobalConfig {
4
4
  "wiki.sync-mode"?: string;
5
5
  "wiki.git-backup"?: string;
6
6
  "wiki.git-remote"?: string;
7
+ "notes.default-category"?: string;
7
8
  }
8
9
 
9
10
  export type ConfigKey = keyof GlobalConfig & string;
@@ -46,6 +47,12 @@ export const CONFIG_KEYS: ConfigKeyMeta[] = [
46
47
  envVar: "MINK_WIKI_GIT_REMOTE",
47
48
  description: "Git remote name for push",
48
49
  },
50
+ {
51
+ key: "notes.default-category",
52
+ default: "inbox",
53
+ envVar: "MINK_NOTES_DEFAULT_CATEGORY",
54
+ description: "Default category for notes captured via CLI",
55
+ },
49
56
  ];
50
57
 
51
58
  const VALID_KEYS = new Set<string>(CONFIG_KEYS.map((k) => k.key));
@@ -0,0 +1,60 @@
1
+ export type NoteCategory =
2
+ | "inbox"
3
+ | "projects"
4
+ | "areas"
5
+ | "resources"
6
+ | "archives";
7
+
8
+ export const NOTE_CATEGORIES: NoteCategory[] = [
9
+ "inbox",
10
+ "projects",
11
+ "areas",
12
+ "resources",
13
+ "archives",
14
+ ];
15
+
16
+ export interface NoteMetadata {
17
+ title: string;
18
+ category: NoteCategory;
19
+ tags: string[];
20
+ created: string;
21
+ updated: string;
22
+ template?: string;
23
+ projectSlug?: string;
24
+ sourceProject?: string;
25
+ body: string;
26
+ }
27
+
28
+ export interface NoteFrontmatter {
29
+ created: string;
30
+ updated: string;
31
+ tags: string[];
32
+ category: NoteCategory;
33
+ source_project?: string;
34
+ aliases?: string[];
35
+ [key: string]: unknown;
36
+ }
37
+
38
+ export interface VaultManifest {
39
+ version: number;
40
+ createdAt: string;
41
+ totalNotes: number;
42
+ categories: Record<NoteCategory, number>;
43
+ lastOrganized: string;
44
+ }
45
+
46
+ export interface VaultIndexEntry {
47
+ filePath: string;
48
+ title: string;
49
+ description: string;
50
+ tags: string[];
51
+ category: NoteCategory;
52
+ estimatedTokens: number;
53
+ lastModified: string;
54
+ }
55
+
56
+ export interface VaultIndex {
57
+ lastScanTimestamp: string;
58
+ totalNotes: number;
59
+ entries: Record<string, VaultIndexEntry>;
60
+ }