@nuucognition/flint-cli 0.2.0-beta.2 → 0.3.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.
package/README.md CHANGED
@@ -64,7 +64,6 @@ flint list --full-path
64
64
  | `--json` | Output as JSON |
65
65
  | `--full-path` | Show full paths |
66
66
  | `-s, --status` | Show valid/broken status |
67
- | `--sub` | Include subflints (dev mode only) |
68
67
 
69
68
  **Aliases:** `flint ls`
70
69
 
@@ -0,0 +1,374 @@
1
+ import {
2
+ generateReferenceMetadata,
3
+ getFlintConfigDir,
4
+ getReferenceMetadataPath,
5
+ getReferencesMetadataDir
6
+ } from "./chunk-KVE7WLA2.js";
7
+ import {
8
+ getWorkspaceReferences,
9
+ getWorkspaceRepositories,
10
+ getWorkspaceSourceRepositories,
11
+ parse
12
+ } from "./chunk-KLFK7CPM.js";
13
+
14
+ // ../../packages/flint/dist/chunk-K24H5FBA.js
15
+ import { readFile, writeFile, mkdir, stat, unlink, access } from "fs/promises";
16
+ import { join } from "path";
17
+ import { exec } from "child_process";
18
+ import { promisify } from "util";
19
+ import { rm } from "fs/promises";
20
+ var execAsync = promisify(exec);
21
+ var LEGACY_WORKSPACE_CONFIG_FILENAME = "workspace.toml";
22
+ function getWorkspaceReferencesDir(flintPath) {
23
+ return getReferencesMetadataDir(flintPath);
24
+ }
25
+ function toKebabCase(name) {
26
+ return name.toLowerCase().replace(/\s+/g, "-");
27
+ }
28
+ function getWorkspaceReferenceFilePath(flintPath, name) {
29
+ return getReferenceMetadataPath(flintPath, name);
30
+ }
31
+ function getLegacyWorkspaceConfigPath(flintPath) {
32
+ return join(getFlintConfigDir(flintPath), LEGACY_WORKSPACE_CONFIG_FILENAME);
33
+ }
34
+ function getLegacyWorkspaceDir(flintPath) {
35
+ return join(flintPath, "Workspace");
36
+ }
37
+ function getReferencesStatePath(flintPath) {
38
+ return join(getFlintConfigDir(flintPath), "references.json");
39
+ }
40
+ async function readReferencesState(flintPath) {
41
+ try {
42
+ const content = await readFile(getReferencesStatePath(flintPath), "utf-8");
43
+ return JSON.parse(content);
44
+ } catch {
45
+ return { version: 1, references: [] };
46
+ }
47
+ }
48
+ async function writeReferencesState(flintPath, state) {
49
+ const statePath = getReferencesStatePath(flintPath);
50
+ await mkdir(getFlintConfigDir(flintPath), { recursive: true });
51
+ await writeFile(statePath, JSON.stringify(state, null, 2));
52
+ }
53
+ async function updateReferenceState(flintPath, name, type, path) {
54
+ const state = await readReferencesState(flintPath);
55
+ const fulfillment = {
56
+ name,
57
+ type,
58
+ path,
59
+ fulfilled: (/* @__PURE__ */ new Date()).toISOString()
60
+ };
61
+ const existingIndex = state.references.findIndex(
62
+ (r) => r.name.toLowerCase() === name.toLowerCase()
63
+ );
64
+ if (existingIndex >= 0) {
65
+ state.references[existingIndex] = fulfillment;
66
+ } else {
67
+ state.references.push(fulfillment);
68
+ }
69
+ await writeReferencesState(flintPath, state);
70
+ }
71
+ async function removeReferenceState(flintPath, name) {
72
+ const state = await readReferencesState(flintPath);
73
+ const normalizedName = name.toLowerCase();
74
+ const index = state.references.findIndex(
75
+ (r) => r.name.toLowerCase() === normalizedName
76
+ );
77
+ if (index >= 0) {
78
+ state.references.splice(index, 1);
79
+ await writeReferencesState(flintPath, state);
80
+ return true;
81
+ }
82
+ return false;
83
+ }
84
+ async function pathExists(path) {
85
+ try {
86
+ await stat(path);
87
+ return true;
88
+ } catch {
89
+ return false;
90
+ }
91
+ }
92
+ async function readReferencePath(flintPath, name) {
93
+ const state = await readReferencesState(flintPath);
94
+ const normalizedName = name.toLowerCase();
95
+ const fulfillment = state.references.find(
96
+ (r) => r.name.toLowerCase() === normalizedName
97
+ );
98
+ return fulfillment?.path || null;
99
+ }
100
+ async function writeReferenceFile(flintPath, name, targetPath, type = "codebase") {
101
+ await generateReferenceMetadata(flintPath, { name, type });
102
+ await updateReferenceState(flintPath, name, type, targetPath);
103
+ return getWorkspaceReferenceFilePath(flintPath, name);
104
+ }
105
+ async function deleteReferenceFile(flintPath, name) {
106
+ const filePath = getWorkspaceReferenceFilePath(flintPath, name);
107
+ try {
108
+ await unlink(filePath);
109
+ return true;
110
+ } catch (error) {
111
+ if (error.code === "ENOENT") {
112
+ return false;
113
+ }
114
+ throw error;
115
+ }
116
+ }
117
+ async function getWorkspaceStatus(flintPath) {
118
+ const declarations = await getWorkspaceReferences(flintPath);
119
+ const statuses = [];
120
+ for (const ref of declarations) {
121
+ const referencePath = await readReferencePath(flintPath, ref.name);
122
+ if (!referencePath) {
123
+ statuses.push({
124
+ name: ref.name,
125
+ type: ref.type,
126
+ status: "unfulfilled"
127
+ });
128
+ } else if (await pathExists(referencePath)) {
129
+ statuses.push({
130
+ name: ref.name,
131
+ type: ref.type,
132
+ status: "fulfilled",
133
+ path: referencePath
134
+ });
135
+ } else {
136
+ statuses.push({
137
+ name: ref.name,
138
+ type: ref.type,
139
+ status: "missing",
140
+ path: referencePath
141
+ });
142
+ }
143
+ }
144
+ return statuses;
145
+ }
146
+ async function getUnfulfilledWorkspaces(flintPath) {
147
+ const statuses = await getWorkspaceStatus(flintPath);
148
+ return statuses.filter((s) => s.status === "unfulfilled").map((s) => s.name);
149
+ }
150
+ async function setWorkspacePath(flintPath, name, path) {
151
+ const declarations = await getWorkspaceReferences(flintPath);
152
+ const ref = declarations.find((r) => r.name.toLowerCase() === name.toLowerCase());
153
+ const type = ref?.type || "codebase";
154
+ await writeReferenceFile(flintPath, name, path, type);
155
+ }
156
+ async function removeWorkspacePath(flintPath, name) {
157
+ await removeReferenceState(flintPath, name);
158
+ return deleteReferenceFile(flintPath, name);
159
+ }
160
+ async function getWorkspacePath(flintPath, name) {
161
+ return readReferencePath(flintPath, name);
162
+ }
163
+ function getWorkspaceRepositoriesDir(flintPath) {
164
+ return join(flintPath, "Workspace", "Repositories");
165
+ }
166
+ function getRepositoryPath(flintPath, name) {
167
+ const kebabName = toKebabCase(name);
168
+ return join(getWorkspaceRepositoriesDir(flintPath), kebabName);
169
+ }
170
+ async function createRepository(flintPath, name, url) {
171
+ const repositoriesDir = getWorkspaceRepositoriesDir(flintPath);
172
+ await mkdir(repositoriesDir, { recursive: true });
173
+ const repoPath = getRepositoryPath(flintPath, name);
174
+ if (await pathExists(repoPath)) {
175
+ throw new Error(`Repository folder already exists: ${repoPath}`);
176
+ }
177
+ await mkdir(repoPath, { recursive: true });
178
+ try {
179
+ await execAsync("git init", { cwd: repoPath });
180
+ await execAsync(`git remote add origin "${url}"`, { cwd: repoPath });
181
+ } catch (error) {
182
+ const message = error instanceof Error ? error.message : String(error);
183
+ await rm(repoPath, { recursive: true, force: true });
184
+ throw new Error(`Failed to initialize repository: ${message}`);
185
+ }
186
+ return repoPath;
187
+ }
188
+ async function cloneRepository(flintPath, name, url) {
189
+ const repositoriesDir = getWorkspaceRepositoriesDir(flintPath);
190
+ await mkdir(repositoriesDir, { recursive: true });
191
+ const repoPath = getRepositoryPath(flintPath, name);
192
+ if (await pathExists(repoPath)) {
193
+ throw new Error(`Repository folder already exists: ${repoPath}`);
194
+ }
195
+ try {
196
+ await execAsync(`git clone "${url}" "${repoPath}"`);
197
+ } catch (error) {
198
+ const message = error instanceof Error ? error.message : String(error);
199
+ throw new Error(`Failed to clone repository: ${message}`);
200
+ }
201
+ return repoPath;
202
+ }
203
+ async function removeRepositoryFolder(flintPath, name) {
204
+ const repoPath = getRepositoryPath(flintPath, name);
205
+ if (!await pathExists(repoPath)) {
206
+ return false;
207
+ }
208
+ await rm(repoPath, { recursive: true, force: true });
209
+ return true;
210
+ }
211
+ async function updateRepository(flintPath, name, url) {
212
+ const repoPath = getRepositoryPath(flintPath, name);
213
+ if (await pathExists(repoPath)) {
214
+ await execAsync("git pull", { cwd: repoPath });
215
+ return repoPath;
216
+ }
217
+ return cloneRepository(flintPath, name, url);
218
+ }
219
+ async function freshCloneRepository(flintPath, name, url) {
220
+ await removeRepositoryFolder(flintPath, name);
221
+ return cloneRepository(flintPath, name, url);
222
+ }
223
+ async function getRepositoryStatus(flintPath) {
224
+ const declarations = await getWorkspaceRepositories(flintPath);
225
+ const statuses = [];
226
+ for (const repo of declarations) {
227
+ const repoPath = getRepositoryPath(flintPath, repo.name);
228
+ const exists = await pathExists(repoPath);
229
+ statuses.push({
230
+ name: repo.name,
231
+ url: repo.url,
232
+ status: exists ? "cloned" : "missing",
233
+ path: repoPath
234
+ });
235
+ }
236
+ return statuses;
237
+ }
238
+ function getWorkspaceSourceRepositoriesDir(flintPath) {
239
+ return join(flintPath, "Sources", "Repos");
240
+ }
241
+ function getSourceRepositoryPath(flintPath, name) {
242
+ const kebabName = toKebabCase(name);
243
+ return join(getWorkspaceSourceRepositoriesDir(flintPath), kebabName);
244
+ }
245
+ async function cloneSourceRepository(flintPath, name, url) {
246
+ const repositoriesDir = getWorkspaceSourceRepositoriesDir(flintPath);
247
+ await mkdir(repositoriesDir, { recursive: true });
248
+ const repoPath = getSourceRepositoryPath(flintPath, name);
249
+ if (await pathExists(repoPath)) {
250
+ throw new Error(`Source repository folder already exists: ${repoPath}`);
251
+ }
252
+ try {
253
+ await execAsync(`git clone --depth 1 "${url}" "${repoPath}"`);
254
+ } catch (error) {
255
+ const message = error instanceof Error ? error.message : String(error);
256
+ throw new Error(`Failed to clone source repository: ${message}`);
257
+ }
258
+ const gitDir = join(repoPath, ".git");
259
+ try {
260
+ await rm(gitDir, { recursive: true, force: true });
261
+ } catch {
262
+ }
263
+ return repoPath;
264
+ }
265
+ async function removeSourceRepositoryFolder(flintPath, name) {
266
+ const repoPath = getSourceRepositoryPath(flintPath, name);
267
+ if (!await pathExists(repoPath)) {
268
+ return false;
269
+ }
270
+ await rm(repoPath, { recursive: true, force: true });
271
+ return true;
272
+ }
273
+ async function updateSourceRepository(flintPath, name, url) {
274
+ await removeSourceRepositoryFolder(flintPath, name);
275
+ return cloneSourceRepository(flintPath, name, url);
276
+ }
277
+ async function getSourceRepositoryStatus(flintPath) {
278
+ const declarations = await getWorkspaceSourceRepositories(flintPath);
279
+ const statuses = [];
280
+ for (const repo of declarations) {
281
+ const repoPath = getSourceRepositoryPath(flintPath, repo.name);
282
+ const exists = await pathExists(repoPath);
283
+ statuses.push({
284
+ name: repo.name,
285
+ url: repo.url,
286
+ status: exists ? "cloned" : "missing",
287
+ path: repoPath
288
+ });
289
+ }
290
+ return statuses;
291
+ }
292
+ async function readLegacyWorkspaceConfig(flintPath) {
293
+ const configPath = getLegacyWorkspaceConfigPath(flintPath);
294
+ try {
295
+ const content = await readFile(configPath, "utf-8");
296
+ return parse(content);
297
+ } catch (error) {
298
+ if (error.code === "ENOENT") {
299
+ return {};
300
+ }
301
+ throw error;
302
+ }
303
+ }
304
+ async function legacyWorkspaceConfigExists(flintPath) {
305
+ try {
306
+ await access(getLegacyWorkspaceConfigPath(flintPath));
307
+ return true;
308
+ } catch {
309
+ return false;
310
+ }
311
+ }
312
+ async function migrateWorkspaceConfig(flintPath) {
313
+ const result = { migrated: [], removed: false };
314
+ if (!await legacyWorkspaceConfigExists(flintPath)) {
315
+ return result;
316
+ }
317
+ const legacyConfig = await readLegacyWorkspaceConfig(flintPath);
318
+ if (Object.keys(legacyConfig).length === 0) {
319
+ try {
320
+ await unlink(getLegacyWorkspaceConfigPath(flintPath));
321
+ result.removed = true;
322
+ } catch {
323
+ }
324
+ return result;
325
+ }
326
+ for (const [name, entry] of Object.entries(legacyConfig)) {
327
+ if (entry && typeof entry === "object" && "path" in entry) {
328
+ await generateReferenceMetadata(flintPath, { name, type: "codebase" });
329
+ await updateReferenceState(flintPath, name, "codebase", entry.path);
330
+ result.migrated.push(name);
331
+ }
332
+ }
333
+ try {
334
+ await unlink(getLegacyWorkspaceConfigPath(flintPath));
335
+ result.removed = true;
336
+ } catch {
337
+ }
338
+ return result;
339
+ }
340
+
341
+ export {
342
+ getWorkspaceReferencesDir,
343
+ getWorkspaceReferenceFilePath,
344
+ getLegacyWorkspaceConfigPath,
345
+ getLegacyWorkspaceDir,
346
+ getReferencesStatePath,
347
+ readReferencesState,
348
+ writeReferencesState,
349
+ updateReferenceState,
350
+ removeReferenceState,
351
+ readReferencePath,
352
+ writeReferenceFile,
353
+ deleteReferenceFile,
354
+ getWorkspaceStatus,
355
+ getUnfulfilledWorkspaces,
356
+ setWorkspacePath,
357
+ removeWorkspacePath,
358
+ getWorkspacePath,
359
+ getWorkspaceRepositoriesDir,
360
+ getRepositoryPath,
361
+ createRepository,
362
+ cloneRepository,
363
+ removeRepositoryFolder,
364
+ updateRepository,
365
+ freshCloneRepository,
366
+ getRepositoryStatus,
367
+ getWorkspaceSourceRepositoriesDir,
368
+ getSourceRepositoryPath,
369
+ cloneSourceRepository,
370
+ removeSourceRepositoryFolder,
371
+ updateSourceRepository,
372
+ getSourceRepositoryStatus,
373
+ migrateWorkspaceConfig
374
+ };
@@ -1,6 +1,6 @@
1
- // ../../packages/flint/dist/chunk-2WZYXQX5.js
2
- import { readFile, writeFile, stat } from "fs/promises";
3
- import { join } from "path";
1
+ // ../../packages/flint/dist/chunk-HP5CLO2G.js
2
+ import { readFile, writeFile, stat, mkdir } from "fs/promises";
3
+ import { join as pathJoin } from "path";
4
4
 
5
5
  // ../../node_modules/.pnpm/smol-toml@1.6.0/node_modules/smol-toml/dist/error.js
6
6
  function getLineColFromPtr(string, ptr) {
@@ -828,8 +828,9 @@ function stringify(obj, { maxDepth = 1e3, numbersAsFloat = false } = {}) {
828
828
  return str;
829
829
  }
830
830
 
831
- // ../../packages/flint/dist/chunk-2WZYXQX5.js
831
+ // ../../packages/flint/dist/chunk-HP5CLO2G.js
832
832
  import { randomUUID } from "crypto";
833
+ var join = pathJoin;
833
834
  function resolveShardMode(decl) {
834
835
  return decl.mode;
835
836
  }
@@ -839,7 +840,7 @@ function isLocalShard(decl) {
839
840
  }
840
841
  var FLINT_CONFIG_FILENAME = "flint.toml";
841
842
  var FLINT_JSON_FILENAME = "flint.json";
842
- var FLINT_VERSION = "0.2.0";
843
+ var FLINT_VERSION = "0.3.0";
843
844
  function toKebabCase(name) {
844
845
  return name.replace(/\([^)]*\)\s*/g, "").toLowerCase().replace(/\s+/g, "-").replace(/[^a-z0-9-]/g, "").replace(/^-+|-+$/g, "");
845
846
  }
@@ -869,29 +870,17 @@ var DEFAULT_SHARD_SOURCES = {
869
870
  orbcode: "NUU-Cognition/shard-orbcode",
870
871
  projects: "NUU-Cognition/shard-projects"
871
872
  };
872
- var DEFAULT_MOD_SOURCES = {
873
- "claude-code": "NUU-Cognition/flint-mod-claude-code",
874
- agents: "NUU-Cognition/flint-mod-agents"
875
- };
876
- function createFlintToml(name, shards = [], mods = [], type = "flint") {
873
+ function createFlintToml(name, shards = []) {
877
874
  const shardDeclarations = {};
878
875
  for (const shard of shards) {
879
876
  shardDeclarations[shard] = { source: DEFAULT_SHARD_SOURCES[shard] || shard };
880
877
  }
881
878
  const config = {
882
879
  flint: {
883
- name,
884
- type
880
+ name
885
881
  },
886
882
  shards: shardDeclarations
887
883
  };
888
- if (mods.length > 0) {
889
- const modDeclarations = {};
890
- for (const mod of mods) {
891
- modDeclarations[mod] = { source: DEFAULT_MOD_SOURCES[mod] || mod };
892
- }
893
- config.mods = modDeclarations;
894
- }
895
884
  return config;
896
885
  }
897
886
  function createFlintJson() {
@@ -1018,18 +1007,6 @@ function formatFlintToml(config) {
1018
1007
  lines.push("");
1019
1008
  }
1020
1009
  }
1021
- if (config.mods) {
1022
- const modDeclarations = getModDeclarationsFromConfig(config);
1023
- if (Object.keys(modDeclarations).length > 0) {
1024
- lines.push("[mods]");
1025
- for (const [name, decl] of Object.entries(modDeclarations)) {
1026
- const fields = { source: decl.source };
1027
- if (decl.dev) fields.dev = true;
1028
- lines.push(`${name} = ${inlineTable(fields)}`);
1029
- }
1030
- lines.push("");
1031
- }
1032
- }
1033
1010
  if (config.exports?.required?.length) {
1034
1011
  lines.push("[exports]");
1035
1012
  const items = config.exports.required.map((e) => {
@@ -1078,15 +1055,13 @@ function formatFlintToml(config) {
1078
1055
  lines.push(`remote = ${tv(config.git.remote)}`);
1079
1056
  lines.push("");
1080
1057
  }
1081
- if (config.lattices?.length) {
1082
- for (const lattice of config.lattices) {
1083
- lines.push("[[lattices]]");
1084
- lines.push(`name = ${tv(lattice.name)}`);
1085
- lines.push(`path = ${tv(lattice.path)}`);
1086
- lines.push("");
1087
- }
1058
+ if (config.lattices?.references?.length) {
1059
+ lines.push("[lattices]");
1060
+ const items = config.lattices.references.map((l) => ({ name: l.name }));
1061
+ lines.push(`references = ${inlineTableArray(items).join("\n")}`);
1062
+ lines.push("");
1088
1063
  }
1089
- const knownKeys = /* @__PURE__ */ new Set(["flint", "shards", "mods", "exports", "imports", "workspace", "connections", "git", "lattices"]);
1064
+ const knownKeys = /* @__PURE__ */ new Set(["flint", "shards", "exports", "imports", "workspace", "connections", "git", "lattices"]);
1090
1065
  const unknownKeys = Object.keys(config).filter((k) => !knownKeys.has(k));
1091
1066
  if (unknownKeys.length > 0) {
1092
1067
  const unknownConfig = {};
@@ -1138,70 +1113,6 @@ async function removeShardFromConfig(flintPath, shardName) {
1138
1113
  }
1139
1114
  await writeFlintToml(flintPath, config);
1140
1115
  }
1141
- async function addModToConfig(flintPath, modName, source = "builtin", options = {}) {
1142
- let config = await readFlintToml(flintPath);
1143
- if (!config) {
1144
- throw new Error("flint.toml not found");
1145
- }
1146
- const kebabName = toKebabCase(modName);
1147
- if (!config.mods) {
1148
- config.mods = {};
1149
- }
1150
- const declaration = { source };
1151
- if (options.dev) declaration.dev = true;
1152
- config.mods[kebabName] = declaration;
1153
- await writeFlintToml(flintPath, config);
1154
- }
1155
- async function removeModFromConfig(flintPath, modName) {
1156
- let config = await readFlintToml(flintPath);
1157
- if (!config?.mods) return;
1158
- const kebabName = toKebabCase(modName);
1159
- delete config.mods[kebabName];
1160
- if (config.mods.required) {
1161
- config.mods.required = config.mods.required.filter((n) => n !== kebabName);
1162
- }
1163
- await writeFlintToml(flintPath, config);
1164
- }
1165
- function getModDeclarationsFromConfig(config) {
1166
- if (!config.mods) return {};
1167
- const declarations = {};
1168
- for (const [key, value] of Object.entries(config.mods)) {
1169
- if (key === "required") continue;
1170
- if (value && typeof value === "object" && !Array.isArray(value) && "source" in value) {
1171
- declarations[key] = value;
1172
- }
1173
- }
1174
- if (config.mods.required && Array.isArray(config.mods.required)) {
1175
- for (const name of config.mods.required) {
1176
- if (!declarations[name]) {
1177
- declarations[name] = { source: "builtin" };
1178
- }
1179
- }
1180
- }
1181
- return declarations;
1182
- }
1183
- async function getModDeclarations(flintPath) {
1184
- const config = await readFlintToml(flintPath);
1185
- if (!config) return {};
1186
- return getModDeclarationsFromConfig(config);
1187
- }
1188
- async function migrateModConfig(flintPath) {
1189
- const config = await readFlintToml(flintPath);
1190
- if (!config?.mods?.required || !Array.isArray(config.mods.required)) {
1191
- return false;
1192
- }
1193
- if (config.mods.required.length === 0) {
1194
- return false;
1195
- }
1196
- for (const name of config.mods.required) {
1197
- if (!config.mods[name]) {
1198
- config.mods[name] = { source: "builtin" };
1199
- }
1200
- }
1201
- delete config.mods.required;
1202
- await writeFlintToml(flintPath, config);
1203
- return true;
1204
- }
1205
1116
  async function getRequiredShardNames(flintPath) {
1206
1117
  const config = await readFlintToml(flintPath);
1207
1118
  if (!config?.shards) return [];
@@ -1376,40 +1287,101 @@ async function getWorkspaceSourceRepository(flintPath, name) {
1376
1287
  const normalizedName = name.toLowerCase();
1377
1288
  return config?.workspace?.sources?.repositories?.find((r) => r.name.toLowerCase() === normalizedName) || null;
1378
1289
  }
1379
- async function addLatticeReference(flintPath, name, path) {
1290
+ function getLatticesStatePath(flintPath) {
1291
+ return pathJoin(flintPath, ".flint", "lattices.json");
1292
+ }
1293
+ async function readLatticesState(flintPath) {
1294
+ const statePath = getLatticesStatePath(flintPath);
1295
+ try {
1296
+ const content = await readFile(statePath, "utf-8");
1297
+ return JSON.parse(content);
1298
+ } catch {
1299
+ return { version: 1, lattices: [] };
1300
+ }
1301
+ }
1302
+ async function writeLatticesState(flintPath, state) {
1303
+ const statePath = getLatticesStatePath(flintPath);
1304
+ const dir = pathJoin(flintPath, ".flint");
1305
+ await mkdir(dir, { recursive: true });
1306
+ await writeFile(statePath, JSON.stringify(state, null, 2) + "\n");
1307
+ }
1308
+ async function addLatticeDeclaration(flintPath, name) {
1380
1309
  let config = await readFlintToml(flintPath);
1381
1310
  if (!config) {
1382
1311
  throw new Error("flint.toml not found");
1383
1312
  }
1384
1313
  if (!config.lattices) {
1385
- config.lattices = [];
1314
+ config.lattices = { references: [] };
1386
1315
  }
1387
- const existing = config.lattices.find((entry) => entry.name.toLowerCase() === name.toLowerCase());
1316
+ if (!config.lattices.references) {
1317
+ config.lattices.references = [];
1318
+ }
1319
+ const existing = config.lattices.references.find(
1320
+ (entry) => entry.name.toLowerCase() === name.toLowerCase()
1321
+ );
1388
1322
  if (existing) {
1389
- throw new Error(`Lattice "${name}" already exists`);
1323
+ throw new Error(`Lattice "${name}" is already declared`);
1390
1324
  }
1391
- config.lattices.push({ name, path });
1325
+ config.lattices.references.push({ name });
1392
1326
  await writeFlintToml(flintPath, config);
1393
1327
  }
1394
- async function removeLatticeReference(flintPath, name) {
1328
+ async function removeLatticeDeclaration(flintPath, name) {
1395
1329
  let config = await readFlintToml(flintPath);
1396
- if (!config?.lattices) return false;
1330
+ if (!config?.lattices?.references) return false;
1397
1331
  const normalizedName = name.toLowerCase();
1398
- const index = config.lattices.findIndex((entry) => entry.name.toLowerCase() === normalizedName);
1332
+ const index = config.lattices.references.findIndex(
1333
+ (entry) => entry.name.toLowerCase() === normalizedName
1334
+ );
1399
1335
  if (index === -1) return false;
1400
- config.lattices.splice(index, 1);
1336
+ config.lattices.references.splice(index, 1);
1401
1337
  await writeFlintToml(flintPath, config);
1338
+ const state = await readLatticesState(flintPath);
1339
+ state.lattices = state.lattices.filter(
1340
+ (l) => l.name.toLowerCase() !== normalizedName
1341
+ );
1342
+ await writeLatticesState(flintPath, state);
1402
1343
  return true;
1403
1344
  }
1404
- async function getLatticeReferences(flintPath) {
1345
+ async function fulfillLattice(flintPath, name, latticePath, lang) {
1346
+ const fulfillment = {
1347
+ name,
1348
+ path: latticePath,
1349
+ lang,
1350
+ fulfilled: (/* @__PURE__ */ new Date()).toISOString()
1351
+ };
1352
+ const state = await readLatticesState(flintPath);
1353
+ const existingIndex = state.lattices.findIndex(
1354
+ (l) => l.name.toLowerCase() === name.toLowerCase()
1355
+ );
1356
+ if (existingIndex >= 0) {
1357
+ state.lattices[existingIndex] = fulfillment;
1358
+ } else {
1359
+ state.lattices.push(fulfillment);
1360
+ }
1361
+ await writeLatticesState(flintPath, state);
1362
+ return fulfillment;
1363
+ }
1364
+ async function getLatticeDeclarations(flintPath) {
1405
1365
  const config = await readFlintToml(flintPath);
1406
- return config?.lattices || [];
1366
+ return config?.lattices?.references || [];
1407
1367
  }
1408
- async function getLatticeReference(flintPath, name) {
1368
+ async function getLatticeDeclaration(flintPath, name) {
1409
1369
  const config = await readFlintToml(flintPath);
1410
1370
  const normalizedName = name.toLowerCase();
1411
- return config?.lattices?.find((entry) => entry.name.toLowerCase() === normalizedName) || null;
1412
- }
1371
+ return config?.lattices?.references?.find(
1372
+ (entry) => entry.name.toLowerCase() === normalizedName
1373
+ ) || null;
1374
+ }
1375
+ async function getLatticeFulfillment(flintPath, name) {
1376
+ const state = await readLatticesState(flintPath);
1377
+ return state.lattices.find(
1378
+ (l) => l.name.toLowerCase() === name.toLowerCase()
1379
+ ) || null;
1380
+ }
1381
+ var addLatticeReference = async (flintPath, name, _path) => addLatticeDeclaration(flintPath, name);
1382
+ var removeLatticeReference = async (flintPath, name) => removeLatticeDeclaration(flintPath, name);
1383
+ var getLatticeReferences = async (flintPath) => getLatticeDeclarations(flintPath);
1384
+ var getLatticeReference = async (flintPath, name) => getLatticeDeclaration(flintPath, name);
1413
1385
  async function addExportToConfig(flintPath, declaration) {
1414
1386
  let config = await readFlintToml(flintPath);
1415
1387
  if (!config) {
@@ -1524,11 +1496,6 @@ export {
1524
1496
  writeFlintToml,
1525
1497
  addShardToConfig,
1526
1498
  removeShardFromConfig,
1527
- addModToConfig,
1528
- removeModFromConfig,
1529
- getModDeclarationsFromConfig,
1530
- getModDeclarations,
1531
- migrateModConfig,
1532
1499
  getRequiredShardNames,
1533
1500
  getShardDeclarationsFromConfig,
1534
1501
  getShardDeclarations,
@@ -1547,6 +1514,13 @@ export {
1547
1514
  removeWorkspaceSourceRepository,
1548
1515
  getWorkspaceSourceRepositories,
1549
1516
  getWorkspaceSourceRepository,
1517
+ readLatticesState,
1518
+ addLatticeDeclaration,
1519
+ removeLatticeDeclaration,
1520
+ fulfillLattice,
1521
+ getLatticeDeclarations,
1522
+ getLatticeDeclaration,
1523
+ getLatticeFulfillment,
1550
1524
  addLatticeReference,
1551
1525
  removeLatticeReference,
1552
1526
  getLatticeReferences,