@nuucognition/flint-cli 0.3.0-alpha.1 → 0.4.0-alpha.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,243 @@
1
+ import {
2
+ getMeshExportSources,
3
+ getSourceRepositories,
4
+ nameFormats
5
+ } from "./chunk-GQSLJAUU.js";
6
+
7
+ // ../../packages/flint/dist/chunk-Q3TNNVO6.js
8
+ import { readFile, writeFile, mkdir, stat, readdir, unlink } from "fs/promises";
9
+ import { join } from "path";
10
+ import { randomUUID } from "crypto";
11
+ function getMetadataDir(flintPath) {
12
+ return join(flintPath, "Mesh", "Metadata");
13
+ }
14
+ function getSourcesMetadataDir(flintPath) {
15
+ return join(getMetadataDir(flintPath), "Sources");
16
+ }
17
+ async function fileExists(path) {
18
+ try {
19
+ await stat(path);
20
+ return true;
21
+ } catch {
22
+ return false;
23
+ }
24
+ }
25
+ function extractId(content) {
26
+ const match = content.match(/^id:\s*(.+)$/m);
27
+ return match?.[1]?.trim() || null;
28
+ }
29
+ function extractNotesSection(content) {
30
+ const body = content.replace(/^---\n[\s\S]*?\n---\n*/, "").trim();
31
+ const idx = body.indexOf("## Notes");
32
+ if (idx === -1) return null;
33
+ return body.substring(idx).trim();
34
+ }
35
+ async function syncMetadataFile(filePath, buildContent) {
36
+ let existingId = null;
37
+ let existingNotes = null;
38
+ if (await fileExists(filePath)) {
39
+ const existing = await readFile(filePath, "utf-8");
40
+ existingId = extractId(existing);
41
+ existingNotes = extractNotesSection(existing);
42
+ }
43
+ const id = existingId || randomUUID();
44
+ const notes = existingNotes || "## Notes\n\n(Add notes here)";
45
+ const newContent = buildContent(id, notes);
46
+ if (existingId) {
47
+ const existing = await readFile(filePath, "utf-8");
48
+ if (existing === newContent) {
49
+ return "synced";
50
+ }
51
+ }
52
+ await writeFile(filePath, newContent);
53
+ return existingId ? "synced" : "created";
54
+ }
55
+ function getSourceMeshExportDir(flintPath) {
56
+ return join(getSourcesMetadataDir(flintPath), "Mesh Exports");
57
+ }
58
+ function getSourceMeshExportPath(flintPath, ref) {
59
+ const parts = ref.split("/");
60
+ const flintName = parts[0] || ref;
61
+ const exportName = parts[1] || "";
62
+ const flintSnake = nameFormats(flintName).snake;
63
+ const exportSnake = nameFormats(exportName).snake;
64
+ return join(getSourceMeshExportDir(flintPath), `src-me-${flintSnake}-${exportSnake}.md`);
65
+ }
66
+ function buildMeshExportContent(ref, id, notes) {
67
+ return `---
68
+ id: ${id}
69
+ tags:
70
+ - "#f/metadata"
71
+ - "#f/source"
72
+ type: flint-mesh
73
+ ---
74
+
75
+ Execute \`flint resolve source "${ref}"\` to get the local path.
76
+
77
+ ${notes}
78
+ `;
79
+ }
80
+ async function generateSourceMeshExportMetadata(flintPath, ref) {
81
+ const filePath = getSourceMeshExportPath(flintPath, ref);
82
+ await mkdir(getSourceMeshExportDir(flintPath), { recursive: true });
83
+ const result = await syncMetadataFile(
84
+ filePath,
85
+ (id, notes) => buildMeshExportContent(ref, id, notes)
86
+ );
87
+ return result === "created";
88
+ }
89
+ async function removeSourceMeshExportMetadata(flintPath, ref) {
90
+ const filePath = getSourceMeshExportPath(flintPath, ref);
91
+ try {
92
+ await unlink(filePath);
93
+ return true;
94
+ } catch {
95
+ return false;
96
+ }
97
+ }
98
+ async function syncSourceMeshExportMetadata(flintPath) {
99
+ await mkdir(getSourceMeshExportDir(flintPath), { recursive: true });
100
+ const meshexports = await getMeshExportSources(flintPath);
101
+ const created = [];
102
+ const unchanged = [];
103
+ const removed = [];
104
+ for (const ref of meshexports) {
105
+ const changed = await generateSourceMeshExportMetadata(flintPath, ref);
106
+ const parts = ref.split("/");
107
+ const flintSnake = nameFormats(parts[0] || "").snake;
108
+ const exportSnake = nameFormats(parts[1] || "").snake;
109
+ const key = `src-me-${flintSnake}-${exportSnake}`;
110
+ if (changed) {
111
+ created.push(key);
112
+ } else {
113
+ unchanged.push(key);
114
+ }
115
+ }
116
+ try {
117
+ const dir = getSourceMeshExportDir(flintPath);
118
+ const files = await readdir(dir);
119
+ const declaredFiles = new Set(
120
+ meshexports.map((ref) => {
121
+ const parts = ref.split("/");
122
+ const flintSnake = nameFormats(parts[0] || "").snake;
123
+ const exportSnake = nameFormats(parts[1] || "").snake;
124
+ return `src-me-${flintSnake}-${exportSnake}.md`;
125
+ })
126
+ );
127
+ for (const file of files) {
128
+ if (file.startsWith("src-me-") && !declaredFiles.has(file)) {
129
+ await unlink(join(dir, file)).catch(() => {
130
+ });
131
+ removed.push(file.replace(".md", ""));
132
+ }
133
+ }
134
+ } catch {
135
+ }
136
+ return { created, removed, unchanged };
137
+ }
138
+ function getSourceRepoMetadataDir(flintPath) {
139
+ return join(getSourcesMetadataDir(flintPath), "Repos");
140
+ }
141
+ function getSourceRepoMetadataPath(flintPath, name) {
142
+ const { snake } = nameFormats(name);
143
+ return join(getSourceRepoMetadataDir(flintPath), `src-repo-${snake}.md`);
144
+ }
145
+ function buildSourceRepoContent(name, url, id, notes) {
146
+ return `---
147
+ id: ${id}
148
+ tags:
149
+ - "#f/metadata"
150
+ - "#f/source-repo"
151
+ type: source-repo
152
+ ---
153
+
154
+ Source repository: **${name}**
155
+ URL: ${url}
156
+
157
+ ${notes}
158
+ `;
159
+ }
160
+ async function generateSourceRepoMetadata(flintPath, name, url) {
161
+ const filePath = getSourceRepoMetadataPath(flintPath, name);
162
+ await mkdir(getSourceRepoMetadataDir(flintPath), { recursive: true });
163
+ const result = await syncMetadataFile(
164
+ filePath,
165
+ (id, notes) => buildSourceRepoContent(name, url, id, notes)
166
+ );
167
+ return result === "created";
168
+ }
169
+ async function removeSourceRepoMetadata(flintPath, name) {
170
+ const filePath = getSourceRepoMetadataPath(flintPath, name);
171
+ try {
172
+ await unlink(filePath);
173
+ return true;
174
+ } catch {
175
+ return false;
176
+ }
177
+ }
178
+ async function syncSourceRepoMetadata(flintPath) {
179
+ await mkdir(getSourceRepoMetadataDir(flintPath), { recursive: true });
180
+ const declarations = await getSourceRepositories(flintPath);
181
+ const created = [];
182
+ const unchanged = [];
183
+ const removed = [];
184
+ for (const decl of declarations) {
185
+ const changed = await generateSourceRepoMetadata(flintPath, decl.name, decl.url);
186
+ const key = `src-repo-${nameFormats(decl.name).snake}`;
187
+ if (changed) {
188
+ created.push(key);
189
+ } else {
190
+ unchanged.push(key);
191
+ }
192
+ }
193
+ try {
194
+ const dir = getSourceRepoMetadataDir(flintPath);
195
+ const files = await readdir(dir);
196
+ const declaredSnakes = new Set(
197
+ declarations.map((d) => `src-repo-${nameFormats(d.name).snake}.md`)
198
+ );
199
+ for (const file of files) {
200
+ if (file.startsWith("src-repo-") && !declaredSnakes.has(file)) {
201
+ await unlink(join(dir, file)).catch(() => {
202
+ });
203
+ removed.push(file.replace(".md", ""));
204
+ }
205
+ }
206
+ } catch {
207
+ }
208
+ return { created, removed, unchanged };
209
+ }
210
+ async function resolveSource(flintPath, ref) {
211
+ const parts = ref.split("/");
212
+ const flintName = parts[0] || ref;
213
+ const exportName = parts[1] || "";
214
+ const sourcePath = join(flintPath, "Sources", "Flints", `(Flint) ${flintName}`, `(Mesh Export) ${exportName}`);
215
+ try {
216
+ await stat(sourcePath);
217
+ return { status: "fulfilled", name: ref, type: "flint-mesh", path: sourcePath };
218
+ } catch {
219
+ return { status: "unfulfilled", name: ref, type: "flint-mesh", path: sourcePath };
220
+ }
221
+ }
222
+ async function ensureMetadataDirs(flintPath) {
223
+ await mkdir(getSourcesMetadataDir(flintPath), { recursive: true });
224
+ await mkdir(getSourceRepoMetadataDir(flintPath), { recursive: true });
225
+ await mkdir(getSourceMeshExportDir(flintPath), { recursive: true });
226
+ }
227
+
228
+ export {
229
+ getMetadataDir,
230
+ getSourcesMetadataDir,
231
+ getSourceMeshExportDir,
232
+ getSourceMeshExportPath,
233
+ generateSourceMeshExportMetadata,
234
+ removeSourceMeshExportMetadata,
235
+ syncSourceMeshExportMetadata,
236
+ getSourceRepoMetadataDir,
237
+ getSourceRepoMetadataPath,
238
+ generateSourceRepoMetadata,
239
+ removeSourceRepoMetadata,
240
+ syncSourceRepoMetadata,
241
+ resolveSource,
242
+ ensureMetadataDirs
243
+ };
@@ -1,4 +1,4 @@
1
- // ../../packages/flint/dist/chunk-X3YVJP3U.js
1
+ // ../../packages/flint/dist/chunk-JGOCUBLW.js
2
2
  import { mkdir, readFile, writeFile } from "fs/promises";
3
3
  import { homedir } from "os";
4
4
  import { join, resolve } from "path";
@@ -182,7 +182,7 @@ async function cleanRegistryFile() {
182
182
  return result;
183
183
  }
184
184
  async function registerFlintByPath(path, options) {
185
- const { readFlintToml, hasFlintToml } = await import("./mesh-config-7GOTOVCM-TZEJ43E5.js");
185
+ const { readFlintToml, hasFlintToml } = await import("./mesh-config-TEPKR6QZ-TINWSM6H.js");
186
186
  const isFlint = await hasFlintToml(path);
187
187
  if (!isFlint) {
188
188
  throw new Error(`Not a valid flint: ${path}
@@ -197,6 +197,10 @@ Missing flint.toml`);
197
197
  if (existing && !options?.force) {
198
198
  throw new Error(`Already registered: "${existing.name}" at ${path}`);
199
199
  }
200
+ const nameTaken = await isFlintNameTaken(name);
201
+ if (nameTaken && resolve(nameTaken.path) !== resolve(path)) {
202
+ throw new Error(`Name "${name}" is already taken by a flint at ${nameTaken.path}`);
203
+ }
200
204
  const entry = {
201
205
  name,
202
206
  path,