@nuucognition/flint-cli 0.2.0-beta.2 → 0.3.0-alpha.1

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,297 @@
1
+ import {
2
+ readFlintToml,
3
+ toKebabCase
4
+ } from "./chunk-KLFK7CPM.js";
5
+
6
+ // ../../packages/flint/dist/chunk-7OFS4TXV.js
7
+ import { join, dirname, basename } from "path";
8
+ import { readFile, writeFile, mkdir, readdir, rm, stat as stat2 } from "fs/promises";
9
+ import { join as join2 } from "path";
10
+ import { randomUUID } from "crypto";
11
+ var FLINT_DIR = ".flint";
12
+ function getFlintConfigDir(flintPath) {
13
+ return join(flintPath, FLINT_DIR);
14
+ }
15
+ function getTypePrefix(_type) {
16
+ return "(Flint)";
17
+ }
18
+ function getMetadataDir(flintPath) {
19
+ return join2(flintPath, "Mesh", "Metadata");
20
+ }
21
+ function getReferencesMetadataDir(flintPath) {
22
+ return join2(getMetadataDir(flintPath), "Codebase References");
23
+ }
24
+ function getConnectionsMetadataDir(flintPath) {
25
+ return join2(getMetadataDir(flintPath), "Flint Connections");
26
+ }
27
+ function getSourcesMetadataDir(flintPath) {
28
+ return join2(getMetadataDir(flintPath), "Sources");
29
+ }
30
+ function getReferenceMetadataPath(flintPath, name) {
31
+ const slug = toKebabCase(name);
32
+ return join2(getReferencesMetadataDir(flintPath), `rf-${slug}.md`);
33
+ }
34
+ function getConnectionMetadataPath(flintPath, name) {
35
+ const slug = toKebabCase(name);
36
+ return join2(getConnectionsMetadataDir(flintPath), `con-${slug}.md`);
37
+ }
38
+ function getSourceMetadataPath(flintPath, importRef) {
39
+ const slug = toKebabCase(importRef.replace("/", "-"));
40
+ return join2(getSourcesMetadataDir(flintPath), `src-${slug}.md`);
41
+ }
42
+ async function fileExists(path) {
43
+ try {
44
+ await stat2(path);
45
+ return true;
46
+ } catch {
47
+ return false;
48
+ }
49
+ }
50
+ function extractId(content) {
51
+ const match = content.match(/^id:\s*(.+)$/m);
52
+ return match?.[1]?.trim() || null;
53
+ }
54
+ function extractNotesSection(content) {
55
+ const body = content.replace(/^---\n[\s\S]*?\n---\n*/, "").trim();
56
+ const idx = body.indexOf("## Notes");
57
+ if (idx === -1) return null;
58
+ return body.substring(idx).trim();
59
+ }
60
+ async function syncMetadataFile(filePath, buildContent) {
61
+ let existingId = null;
62
+ let existingNotes = null;
63
+ if (await fileExists(filePath)) {
64
+ const existing = await readFile(filePath, "utf-8");
65
+ existingId = extractId(existing);
66
+ existingNotes = extractNotesSection(existing);
67
+ }
68
+ const id = existingId || randomUUID();
69
+ const notes = existingNotes || "## Notes\n\n(Add notes here)";
70
+ const newContent = buildContent(id, notes);
71
+ if (existingId) {
72
+ const existing = await readFile(filePath, "utf-8");
73
+ if (existing === newContent) {
74
+ return "synced";
75
+ }
76
+ }
77
+ await writeFile(filePath, newContent);
78
+ return existingId ? "synced" : "created";
79
+ }
80
+ function buildReferenceContent(ref, id, notes) {
81
+ return `---
82
+ id: ${id}
83
+ tags:
84
+ - "#f/metadata"
85
+ - "#f/reference"
86
+ type: ${ref.type}
87
+ ---
88
+
89
+ Execute \`flint resolve codebase ${ref.name}\` to get the local path.
90
+
91
+ ${notes}
92
+ `;
93
+ }
94
+ function buildConnectionContent(declaration, id, notes) {
95
+ return `---
96
+ id: ${id}
97
+ tags:
98
+ - "#f/metadata"
99
+ - "#f/connection"
100
+ type: flint
101
+ ---
102
+
103
+ Execute \`flint resolve connection ${declaration.name}\` to get the local path.
104
+
105
+ ${notes}
106
+ `;
107
+ }
108
+ function buildSourceContent(importRef, id, notes) {
109
+ return `---
110
+ id: ${id}
111
+ tags:
112
+ - "#f/metadata"
113
+ - "#f/source"
114
+ type: flint-export
115
+ ---
116
+
117
+ Execute \`flint resolve source "${importRef}"\` to get the local path.
118
+
119
+ ${notes}
120
+ `;
121
+ }
122
+ async function generateReferenceMetadata(flintPath, ref) {
123
+ const filePath = getReferenceMetadataPath(flintPath, ref.name);
124
+ await mkdir(getReferencesMetadataDir(flintPath), { recursive: true });
125
+ const result = await syncMetadataFile(
126
+ filePath,
127
+ (id, notes) => buildReferenceContent(ref, id, notes)
128
+ );
129
+ return result === "created";
130
+ }
131
+ async function generateConnectionMetadata(flintPath, declaration) {
132
+ const filePath = getConnectionMetadataPath(flintPath, declaration.name);
133
+ await mkdir(getConnectionsMetadataDir(flintPath), { recursive: true });
134
+ const result = await syncMetadataFile(
135
+ filePath,
136
+ (id, notes) => buildConnectionContent(declaration, id, notes)
137
+ );
138
+ return result === "created";
139
+ }
140
+ async function generateSourceMetadata(flintPath, importRef) {
141
+ const filePath = getSourceMetadataPath(flintPath, importRef);
142
+ await mkdir(getSourcesMetadataDir(flintPath), { recursive: true });
143
+ const result = await syncMetadataFile(
144
+ filePath,
145
+ (id, notes) => buildSourceContent(importRef, id, notes)
146
+ );
147
+ return result === "created";
148
+ }
149
+ async function resolveCodebase(flintPath, name) {
150
+ const { readReferencesState } = await import("./workspace-local-LKB4MTN2-OY5UVN3K.js");
151
+ const state = await readReferencesState(flintPath);
152
+ const normalizedName = name.toLowerCase();
153
+ const fulfillment = state.references.find(
154
+ (r) => r.name.toLowerCase() === normalizedName
155
+ );
156
+ if (fulfillment?.path) {
157
+ return { status: "fulfilled", name, type: "codebase", path: fulfillment.path };
158
+ }
159
+ return { status: "unfulfilled", name, type: "codebase" };
160
+ }
161
+ async function resolveConnection(flintPath, name) {
162
+ const { readConnectionsState } = await import("./connections-AXGFYQOK-A6BXCAC7.js");
163
+ const state = await readConnectionsState(flintPath);
164
+ const normalizedName = name.toLowerCase();
165
+ const fulfillment = state.connections.find(
166
+ (c) => c.name.toLowerCase() === normalizedName
167
+ );
168
+ if (fulfillment?.path) {
169
+ return { status: "fulfilled", name, type: "connection", path: fulfillment.path };
170
+ }
171
+ return { status: "unfulfilled", name, type: "connection" };
172
+ }
173
+ async function resolveSource(flintPath, importRef) {
174
+ const parts = importRef.split("/");
175
+ const flintName = parts[0] || importRef;
176
+ const exportName = parts[1] || "";
177
+ const sourcePath = join2(flintPath, "Sources", "Flints", `(Flint) ${flintName}`, `(Mesh) ${exportName}`);
178
+ try {
179
+ await stat2(sourcePath);
180
+ return { status: "fulfilled", name: importRef, type: "source", path: sourcePath };
181
+ } catch {
182
+ return { status: "unfulfilled", name: importRef, type: "source", path: sourcePath };
183
+ }
184
+ }
185
+ async function listMetadataFiles(dirPath, prefix) {
186
+ try {
187
+ const entries = await readdir(dirPath);
188
+ return entries.filter((e) => e.startsWith(prefix) && e.endsWith(".md"));
189
+ } catch {
190
+ return [];
191
+ }
192
+ }
193
+ async function syncMetadata(flintPath) {
194
+ const result = { created: [], removed: [], unchanged: [] };
195
+ const config = await readFlintToml(flintPath);
196
+ if (!config) return result;
197
+ const references = config.workspace?.references || [];
198
+ const expectedRefFiles = new Set(
199
+ references.map((r) => `rf-${toKebabCase(r.name)}.md`)
200
+ );
201
+ for (const ref of references) {
202
+ const created = await generateReferenceMetadata(flintPath, ref);
203
+ const fileName = `rf-${toKebabCase(ref.name)}.md`;
204
+ if (created) {
205
+ result.created.push(fileName);
206
+ } else {
207
+ result.unchanged.push(fileName);
208
+ }
209
+ }
210
+ const existingRefFiles = await listMetadataFiles(
211
+ getReferencesMetadataDir(flintPath),
212
+ "rf-"
213
+ );
214
+ for (const file of existingRefFiles) {
215
+ if (!expectedRefFiles.has(file)) {
216
+ try {
217
+ await rm(join2(getReferencesMetadataDir(flintPath), file));
218
+ result.removed.push(file);
219
+ } catch {
220
+ }
221
+ }
222
+ }
223
+ const connections = config.connections?.flints || [];
224
+ const expectedConFiles = new Set(
225
+ connections.map((c) => `con-${toKebabCase(c.name)}.md`)
226
+ );
227
+ for (const con of connections) {
228
+ const created = await generateConnectionMetadata(flintPath, con);
229
+ const fileName = `con-${toKebabCase(con.name)}.md`;
230
+ if (created) {
231
+ result.created.push(fileName);
232
+ } else {
233
+ result.unchanged.push(fileName);
234
+ }
235
+ }
236
+ const existingConFiles = await listMetadataFiles(
237
+ getConnectionsMetadataDir(flintPath),
238
+ "con-"
239
+ );
240
+ for (const file of existingConFiles) {
241
+ if (!expectedConFiles.has(file)) {
242
+ try {
243
+ await rm(join2(getConnectionsMetadataDir(flintPath), file));
244
+ result.removed.push(file);
245
+ } catch {
246
+ }
247
+ }
248
+ }
249
+ const imports = config.imports?.flints || config.imports?.required || [];
250
+ const expectedSrcFiles = new Set(
251
+ imports.map((ref) => `src-${toKebabCase(ref.replace("/", "-"))}.md`)
252
+ );
253
+ for (const importRef of imports) {
254
+ const created = await generateSourceMetadata(flintPath, importRef);
255
+ const fileName = `src-${toKebabCase(importRef.replace("/", "-"))}.md`;
256
+ if (created) {
257
+ result.created.push(fileName);
258
+ } else {
259
+ result.unchanged.push(fileName);
260
+ }
261
+ }
262
+ const existingSrcFiles = await listMetadataFiles(
263
+ getSourcesMetadataDir(flintPath),
264
+ "src-"
265
+ );
266
+ for (const file of existingSrcFiles) {
267
+ if (!expectedSrcFiles.has(file)) {
268
+ try {
269
+ await rm(join2(getSourcesMetadataDir(flintPath), file));
270
+ result.removed.push(file);
271
+ } catch {
272
+ }
273
+ }
274
+ }
275
+ return result;
276
+ }
277
+ async function ensureMetadataDirs(flintPath) {
278
+ await mkdir(getReferencesMetadataDir(flintPath), { recursive: true });
279
+ await mkdir(getConnectionsMetadataDir(flintPath), { recursive: true });
280
+ await mkdir(getSourcesMetadataDir(flintPath), { recursive: true });
281
+ }
282
+
283
+ export {
284
+ getFlintConfigDir,
285
+ getTypePrefix,
286
+ getReferencesMetadataDir,
287
+ getConnectionsMetadataDir,
288
+ getReferenceMetadataPath,
289
+ getConnectionMetadataPath,
290
+ generateReferenceMetadata,
291
+ generateConnectionMetadata,
292
+ resolveCodebase,
293
+ resolveConnection,
294
+ resolveSource,
295
+ syncMetadata,
296
+ ensureMetadataDirs
297
+ };
@@ -1,4 +1,4 @@
1
- // ../../packages/flint/dist/chunk-CKCIJQXP.js
1
+ // ../../packages/flint/dist/chunk-HCE4DXJK.js
2
2
  import { readdir, readFile, mkdir, writeFile, rm, stat } from "fs/promises";
3
3
  import { join, basename, dirname, resolve, relative, sep } from "path";
4
4
  async function exists(path) {
@@ -158,22 +158,6 @@ async function findFilesRecursively(dir, fileName, matches = []) {
158
158
  }
159
159
  return matches;
160
160
  }
161
- async function findExportFiles(dir, files = []) {
162
- try {
163
- const entries = await readdir(dir, { withFileTypes: true });
164
- for (const entry of entries) {
165
- const fullPath = join(dir, entry.name);
166
- if (entry.isFile() && entry.name.startsWith("(Export) ") && entry.name.endsWith(".md")) {
167
- files.push(fullPath);
168
- }
169
- if (entry.isDirectory()) {
170
- await findExportFiles(fullPath, files);
171
- }
172
- }
173
- } catch {
174
- }
175
- return files;
176
- }
177
161
  async function resolveDocument(docRef, flintPath) {
178
162
  const trimmedRef = docRef.trim();
179
163
  if (!trimmedRef) {
@@ -224,13 +208,13 @@ function getDisambiguatedExportName(flintPath, sourcePath, baseName) {
224
208
  return `${baseName} (${dirLabel})`;
225
209
  }
226
210
  async function scanExports(flintPath) {
227
- const { readFlintToml } = await import("./mesh-config-J6WB4RFV-G7RGPOZA.js");
211
+ const { readFlintToml } = await import("./mesh-config-7GOTOVCM-TZEJ43E5.js");
228
212
  const config = await readFlintToml(flintPath);
229
213
  const declarations = config?.exports?.required;
230
- if (declarations && declarations.length > 0) {
231
- return scanExportsFromConfig(flintPath, declarations);
214
+ if (!declarations || declarations.length === 0) {
215
+ return [];
232
216
  }
233
- return scanExportsLegacy(flintPath);
217
+ return scanExportsFromConfig(flintPath, declarations);
234
218
  }
235
219
  async function scanExportsFromConfig(flintPath, declarations) {
236
220
  const manifests = [];
@@ -248,29 +232,10 @@ async function scanExportsFromConfig(flintPath, declarations) {
248
232
  }
249
233
  return manifests;
250
234
  }
251
- async function scanExportsLegacy(flintPath) {
252
- const meshDir = join(flintPath, "Mesh");
253
- if (!await exists(meshDir)) {
254
- return [];
255
- }
256
- const exportFiles = await findExportFiles(meshDir);
257
- const manifests = [];
258
- for (const filePath of exportFiles) {
259
- try {
260
- const content = await readFile(filePath, "utf-8");
261
- const fileName = basename(filePath, ".md");
262
- const name = fileName.replace(/^\(Export\)\s*/, "");
263
- const manifest = parseExportDocument(content, name, filePath);
264
- manifests.push(manifest);
265
- } catch {
266
- }
267
- }
268
- return manifests;
269
- }
270
235
  async function scanExportEligible(flintPath) {
271
236
  const meshDir = join(flintPath, "Mesh");
272
237
  if (!await exists(meshDir)) return [];
273
- const { readFlintToml } = await import("./mesh-config-J6WB4RFV-G7RGPOZA.js");
238
+ const { readFlintToml } = await import("./mesh-config-7GOTOVCM-TZEJ43E5.js");
274
239
  const config = await readFlintToml(flintPath);
275
240
  const declared = new Set(
276
241
  (config?.exports?.required || []).map((d) => d.file.replace(/\.md$/, "").toLowerCase())
@@ -1,4 +1,4 @@
1
- // ../../packages/flint/dist/chunk-7YSFBSPS.js
1
+ // ../../packages/flint/dist/chunk-X3YVJP3U.js
2
2
  import { mkdir, readFile, writeFile } from "fs/promises";
3
3
  import { homedir } from "os";
4
4
  import { join, resolve } from "path";
@@ -159,9 +159,6 @@ async function cleanRegistryFile() {
159
159
  name: entry.name,
160
160
  path: entry.path
161
161
  };
162
- if (entry.type === "flint" || entry.type === "subflint") {
163
- cleanEntry.type = entry.type;
164
- }
165
162
  if (entry.source === "local") {
166
163
  cleanEntry.source = entry.source;
167
164
  }
@@ -185,7 +182,7 @@ async function cleanRegistryFile() {
185
182
  return result;
186
183
  }
187
184
  async function registerFlintByPath(path, options) {
188
- const { readFlintToml, hasFlintToml } = await import("./mesh-config-J6WB4RFV-G7RGPOZA.js");
185
+ const { readFlintToml, hasFlintToml } = await import("./mesh-config-7GOTOVCM-TZEJ43E5.js");
189
186
  const isFlint = await hasFlintToml(path);
190
187
  if (!isFlint) {
191
188
  throw new Error(`Not a valid flint: ${path}
@@ -196,7 +193,6 @@ Missing flint.toml`);
196
193
  throw new Error(`Invalid flint.toml at ${path}: missing flint.name`);
197
194
  }
198
195
  const name = toml.flint.name;
199
- const type = toml.flint.type ?? "flint";
200
196
  const existing = await findFlintByPath(path);
201
197
  if (existing && !options?.force) {
202
198
  throw new Error(`Already registered: "${existing.name}" at ${path}`);
@@ -204,7 +200,6 @@ Missing flint.toml`);
204
200
  const entry = {
205
201
  name,
206
202
  path,
207
- type,
208
203
  source: "local"
209
204
  };
210
205
  if (toml.flint.tags && toml.flint.tags.length > 0) {