@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.
- package/README.md +0 -1
- package/dist/chunk-2Q7QG2UK.js +374 -0
- package/dist/{chunk-RAH2IR2Z.js → chunk-KLFK7CPM.js} +96 -122
- package/dist/chunk-KVE7WLA2.js +297 -0
- package/dist/{chunk-K5QP4OME.js → chunk-ODSWKVNZ.js} +6 -41
- package/dist/{chunk-VEO4E5HX.js → chunk-OIXBMYAA.js} +2 -7
- package/dist/chunk-T7VT4BN3.js +303 -0
- package/dist/connections-AXGFYQOK-A6BXCAC7.js +43 -0
- package/dist/{exports-KXKBTYJ2-A3QWNDEB.js → exports-B5CYVV5M-KF36KYYW.js} +1 -1
- package/dist/index.js +4945 -7288
- package/dist/{mesh-config-J6WB4RFV-G7RGPOZA.js → mesh-config-7GOTOVCM-TZEJ43E5.js} +15 -11
- package/dist/presets/blank/preset.toml +1 -1
- package/dist/presets/default/preset.toml +1 -7
- package/dist/{registry-5PUMDGQP-YVSEVBB4.js → registry-QJIY5NBV-UDZW4AUU.js} +1 -1
- package/dist/workspace-local-LKB4MTN2-OY5UVN3K.js +70 -0
- package/package.json +5 -5
|
@@ -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-
|
|
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-
|
|
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
|
|
231
|
-
return
|
|
214
|
+
if (!declarations || declarations.length === 0) {
|
|
215
|
+
return [];
|
|
232
216
|
}
|
|
233
|
-
return
|
|
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-
|
|
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-
|
|
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-
|
|
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) {
|