lula2 0.6.0 → 0.6.1-nightly.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/dist/_app/immutable/chunks/Bv3eVXV-.js +3 -0
- package/dist/_app/immutable/chunks/{DOBcdfgj.js → Bx6M8uXd.js} +1 -1
- package/dist/_app/immutable/chunks/{aIhTG3uO.js → loOficEe.js} +1 -1
- package/dist/_app/immutable/entry/{app.B7_zLkkx.js → app.BM2rHfpO.js} +2 -2
- package/dist/_app/immutable/entry/start.bUkCSbH7.js +1 -0
- package/dist/_app/immutable/nodes/{0.B9CL1cKq.js → 0.2orJRzbh.js} +1 -1
- package/dist/_app/immutable/nodes/{1.B5-Ctyqh.js → 1.BrMaFf25.js} +1 -1
- package/dist/_app/immutable/nodes/{2.hJcgnwrH.js → 2.hnhHaDbD.js} +1 -1
- package/dist/_app/immutable/nodes/{3.Cln2iH1E.js → 3.BnCLb2wM.js} +1 -1
- package/dist/_app/immutable/nodes/{4.CcGLqOYE.js → 4.Bw-EmQzD.js} +1 -1
- package/dist/_app/version.json +1 -1
- package/dist/cli/commands/crawl.js +51 -0
- package/dist/cli/commands/ui.js +26 -71
- package/dist/cli/server/index.js +26 -71
- package/dist/cli/server/server.js +26 -71
- package/dist/cli/server/spreadsheetRoutes.js +26 -71
- package/dist/cli/server/websocketServer.js +27 -72
- package/dist/index.html +6 -6
- package/dist/index.js +76 -71
- package/package.json +21 -22
- package/dist/_app/immutable/chunks/CayEUOo2.js +0 -3
- package/dist/_app/immutable/entry/start.CJGnwt1e.js +0 -1
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
// cli/server/spreadsheetRoutes.ts
|
|
2
2
|
import crypto from "crypto";
|
|
3
3
|
import { parse as parseCSVSync } from "csv-parse/sync";
|
|
4
|
-
import
|
|
4
|
+
import * as XLSX from "xlsx-republish";
|
|
5
5
|
import express from "express";
|
|
6
6
|
import { existsSync, mkdirSync, readFileSync, writeFileSync } from "fs";
|
|
7
7
|
import { glob } from "glob";
|
|
@@ -140,20 +140,13 @@ async function parseUploadedFile(file) {
|
|
|
140
140
|
const csvContent = file.buffer.toString("utf-8");
|
|
141
141
|
rawData = parseCSV(csvContent);
|
|
142
142
|
} else {
|
|
143
|
-
const workbook =
|
|
144
|
-
const
|
|
145
|
-
|
|
146
|
-
const worksheet = workbook.worksheets[0];
|
|
147
|
-
if (!worksheet) {
|
|
143
|
+
const workbook = XLSX.read(file.buffer, { type: "buffer" });
|
|
144
|
+
const worksheetName = workbook.SheetNames[0];
|
|
145
|
+
if (!worksheetName) {
|
|
148
146
|
throw new Error("No worksheet found in file");
|
|
149
147
|
}
|
|
150
|
-
worksheet
|
|
151
|
-
|
|
152
|
-
row.eachCell({ includeEmpty: true }, (cell, colNumber) => {
|
|
153
|
-
rowData[colNumber - 1] = cell.value;
|
|
154
|
-
});
|
|
155
|
-
rawData[rowNumber - 1] = rowData;
|
|
156
|
-
});
|
|
148
|
+
const worksheet = workbook.Sheets[worksheetName];
|
|
149
|
+
rawData = XLSX.utils.sheet_to_json(worksheet, { header: 1, defval: null });
|
|
157
150
|
}
|
|
158
151
|
return rawData;
|
|
159
152
|
}
|
|
@@ -819,43 +812,20 @@ async function exportAsExcelWithMapping(controls, metadata, columnMappings, res)
|
|
|
819
812
|
});
|
|
820
813
|
return exportControl;
|
|
821
814
|
});
|
|
822
|
-
const wb =
|
|
823
|
-
const ws =
|
|
824
|
-
|
|
825
|
-
ws.columns = headers.map((header) => ({
|
|
826
|
-
header,
|
|
827
|
-
key: header,
|
|
828
|
-
width: Math.min(
|
|
829
|
-
Math.max(
|
|
830
|
-
header.length,
|
|
831
|
-
...worksheetData.map((row) => String(row[header] || "").length)
|
|
832
|
-
) + 2,
|
|
833
|
-
50
|
|
834
|
-
)
|
|
835
|
-
// Auto-size with max width of 50
|
|
836
|
-
}));
|
|
837
|
-
worksheetData.forEach((row) => {
|
|
838
|
-
ws.addRow(row);
|
|
839
|
-
});
|
|
840
|
-
ws.getRow(1).font = { bold: true };
|
|
841
|
-
ws.getRow(1).fill = {
|
|
842
|
-
type: "pattern",
|
|
843
|
-
pattern: "solid",
|
|
844
|
-
fgColor: { argb: "FFE0E0E0" }
|
|
845
|
-
};
|
|
815
|
+
const wb = XLSX.utils.book_new();
|
|
816
|
+
const ws = XLSX.utils.json_to_sheet(worksheetData);
|
|
817
|
+
XLSX.utils.book_append_sheet(wb, ws, "Controls");
|
|
846
818
|
if (metadata) {
|
|
847
|
-
const metaSheet = wb.addWorksheet("Metadata");
|
|
848
819
|
const cleanMetadata = { ...metadata };
|
|
849
820
|
delete cleanMetadata.fieldSchema;
|
|
850
|
-
|
|
851
|
-
|
|
852
|
-
|
|
853
|
-
|
|
854
|
-
|
|
855
|
-
|
|
856
|
-
});
|
|
821
|
+
const metadataArray = Object.entries(cleanMetadata).map(([key, value]) => ({
|
|
822
|
+
Property: key,
|
|
823
|
+
Value: String(value)
|
|
824
|
+
}));
|
|
825
|
+
const metaSheet = XLSX.utils.json_to_sheet(metadataArray);
|
|
826
|
+
XLSX.utils.book_append_sheet(wb, metaSheet, "Metadata");
|
|
857
827
|
}
|
|
858
|
-
const buffer =
|
|
828
|
+
const buffer = XLSX.write(wb, { type: "buffer", bookType: "xlsx" });
|
|
859
829
|
const fileName = `${metadata?.name || "controls"}_export_${Date.now()}.xlsx`;
|
|
860
830
|
res.setHeader(
|
|
861
831
|
"Content-Type",
|
|
@@ -990,21 +960,14 @@ router.post("/parse-excel", upload.single("file"), async (req, res) => {
|
|
|
990
960
|
rows = parseCSV(csvContent);
|
|
991
961
|
sheets = ["Sheet1"];
|
|
992
962
|
} else {
|
|
993
|
-
const workbook =
|
|
994
|
-
|
|
995
|
-
|
|
996
|
-
|
|
997
|
-
const worksheet = workbook.worksheets[0];
|
|
998
|
-
if (!worksheet) {
|
|
963
|
+
const workbook = XLSX.read(req.file.buffer, { type: "buffer" });
|
|
964
|
+
sheets = workbook.SheetNames;
|
|
965
|
+
const worksheetName = workbook.SheetNames[0];
|
|
966
|
+
if (!worksheetName) {
|
|
999
967
|
return res.status(400).json({ error: "No worksheet found in file" });
|
|
1000
968
|
}
|
|
1001
|
-
worksheet
|
|
1002
|
-
|
|
1003
|
-
row.eachCell({ includeEmpty: true }, (cell, colNumber) => {
|
|
1004
|
-
rowData[colNumber - 1] = cell.value;
|
|
1005
|
-
});
|
|
1006
|
-
rows.push(rowData);
|
|
1007
|
-
});
|
|
969
|
+
const worksheet = workbook.Sheets[worksheetName];
|
|
970
|
+
rows = XLSX.utils.sheet_to_json(worksheet, { header: 1, defval: null });
|
|
1008
971
|
}
|
|
1009
972
|
const headerCandidates = rows.slice(0, 5).map((row, index) => ({
|
|
1010
973
|
row: index + 1,
|
|
@@ -1036,20 +999,12 @@ router.post("/parse-excel-sheet", upload.single("file"), async (req, res) => {
|
|
|
1036
999
|
const csvContent = req.file.buffer.toString("utf-8");
|
|
1037
1000
|
rows = parseCSV(csvContent);
|
|
1038
1001
|
} else {
|
|
1039
|
-
const workbook =
|
|
1040
|
-
|
|
1041
|
-
await workbook.xlsx.load(buffer);
|
|
1042
|
-
const worksheet = workbook.getWorksheet(sheetName);
|
|
1043
|
-
if (!worksheet) {
|
|
1002
|
+
const workbook = XLSX.read(req.file.buffer, { type: "buffer" });
|
|
1003
|
+
if (!workbook.SheetNames.includes(sheetName)) {
|
|
1044
1004
|
return res.status(400).json({ error: `Sheet "${sheetName}" not found` });
|
|
1045
1005
|
}
|
|
1046
|
-
worksheet
|
|
1047
|
-
|
|
1048
|
-
row.eachCell({ includeEmpty: true }, (cell, colNumber) => {
|
|
1049
|
-
rowData[colNumber - 1] = cell.value;
|
|
1050
|
-
});
|
|
1051
|
-
rows.push(rowData);
|
|
1052
|
-
});
|
|
1006
|
+
const worksheet = workbook.Sheets[sheetName];
|
|
1007
|
+
rows = XLSX.utils.sheet_to_json(worksheet, { header: 1, defval: null });
|
|
1053
1008
|
}
|
|
1054
1009
|
const headerRowIndex = parseInt(headerRow) - 1;
|
|
1055
1010
|
const headers = rows[headerRowIndex] || [];
|
|
@@ -1290,7 +1290,7 @@ __export(spreadsheetRoutes_exports, {
|
|
|
1290
1290
|
});
|
|
1291
1291
|
import crypto from "crypto";
|
|
1292
1292
|
import { parse as parseCSVSync } from "csv-parse/sync";
|
|
1293
|
-
import
|
|
1293
|
+
import * as XLSX from "xlsx-republish";
|
|
1294
1294
|
import express from "express";
|
|
1295
1295
|
import { existsSync as existsSync3, mkdirSync as mkdirSync2, readFileSync as readFileSync3, writeFileSync as writeFileSync2 } from "fs";
|
|
1296
1296
|
import { glob } from "glob";
|
|
@@ -1385,20 +1385,13 @@ async function parseUploadedFile(file) {
|
|
|
1385
1385
|
const csvContent = file.buffer.toString("utf-8");
|
|
1386
1386
|
rawData = parseCSV(csvContent);
|
|
1387
1387
|
} else {
|
|
1388
|
-
const workbook =
|
|
1389
|
-
const
|
|
1390
|
-
|
|
1391
|
-
const worksheet = workbook.worksheets[0];
|
|
1392
|
-
if (!worksheet) {
|
|
1388
|
+
const workbook = XLSX.read(file.buffer, { type: "buffer" });
|
|
1389
|
+
const worksheetName = workbook.SheetNames[0];
|
|
1390
|
+
if (!worksheetName) {
|
|
1393
1391
|
throw new Error("No worksheet found in file");
|
|
1394
1392
|
}
|
|
1395
|
-
worksheet
|
|
1396
|
-
|
|
1397
|
-
row.eachCell({ includeEmpty: true }, (cell, colNumber) => {
|
|
1398
|
-
rowData[colNumber - 1] = cell.value;
|
|
1399
|
-
});
|
|
1400
|
-
rawData[rowNumber - 1] = rowData;
|
|
1401
|
-
});
|
|
1393
|
+
const worksheet = workbook.Sheets[worksheetName];
|
|
1394
|
+
rawData = XLSX.utils.sheet_to_json(worksheet, { header: 1, defval: null });
|
|
1402
1395
|
}
|
|
1403
1396
|
return rawData;
|
|
1404
1397
|
}
|
|
@@ -1969,43 +1962,20 @@ async function exportAsExcelWithMapping(controls, metadata, columnMappings, res)
|
|
|
1969
1962
|
});
|
|
1970
1963
|
return exportControl;
|
|
1971
1964
|
});
|
|
1972
|
-
const wb =
|
|
1973
|
-
const ws =
|
|
1974
|
-
|
|
1975
|
-
ws.columns = headers.map((header) => ({
|
|
1976
|
-
header,
|
|
1977
|
-
key: header,
|
|
1978
|
-
width: Math.min(
|
|
1979
|
-
Math.max(
|
|
1980
|
-
header.length,
|
|
1981
|
-
...worksheetData.map((row) => String(row[header] || "").length)
|
|
1982
|
-
) + 2,
|
|
1983
|
-
50
|
|
1984
|
-
)
|
|
1985
|
-
// Auto-size with max width of 50
|
|
1986
|
-
}));
|
|
1987
|
-
worksheetData.forEach((row) => {
|
|
1988
|
-
ws.addRow(row);
|
|
1989
|
-
});
|
|
1990
|
-
ws.getRow(1).font = { bold: true };
|
|
1991
|
-
ws.getRow(1).fill = {
|
|
1992
|
-
type: "pattern",
|
|
1993
|
-
pattern: "solid",
|
|
1994
|
-
fgColor: { argb: "FFE0E0E0" }
|
|
1995
|
-
};
|
|
1965
|
+
const wb = XLSX.utils.book_new();
|
|
1966
|
+
const ws = XLSX.utils.json_to_sheet(worksheetData);
|
|
1967
|
+
XLSX.utils.book_append_sheet(wb, ws, "Controls");
|
|
1996
1968
|
if (metadata) {
|
|
1997
|
-
const metaSheet = wb.addWorksheet("Metadata");
|
|
1998
1969
|
const cleanMetadata = { ...metadata };
|
|
1999
1970
|
delete cleanMetadata.fieldSchema;
|
|
2000
|
-
|
|
2001
|
-
|
|
2002
|
-
|
|
2003
|
-
|
|
2004
|
-
|
|
2005
|
-
|
|
2006
|
-
|
|
2007
|
-
}
|
|
2008
|
-
const buffer = await wb.xlsx.writeBuffer();
|
|
1971
|
+
const metadataArray = Object.entries(cleanMetadata).map(([key, value]) => ({
|
|
1972
|
+
Property: key,
|
|
1973
|
+
Value: String(value)
|
|
1974
|
+
}));
|
|
1975
|
+
const metaSheet = XLSX.utils.json_to_sheet(metadataArray);
|
|
1976
|
+
XLSX.utils.book_append_sheet(wb, metaSheet, "Metadata");
|
|
1977
|
+
}
|
|
1978
|
+
const buffer = XLSX.write(wb, { type: "buffer", bookType: "xlsx" });
|
|
2009
1979
|
const fileName = `${metadata?.name || "controls"}_export_${Date.now()}.xlsx`;
|
|
2010
1980
|
res.setHeader(
|
|
2011
1981
|
"Content-Type",
|
|
@@ -2247,21 +2217,14 @@ var init_spreadsheetRoutes = __esm({
|
|
|
2247
2217
|
rows = parseCSV(csvContent);
|
|
2248
2218
|
sheets = ["Sheet1"];
|
|
2249
2219
|
} else {
|
|
2250
|
-
const workbook =
|
|
2251
|
-
|
|
2252
|
-
|
|
2253
|
-
|
|
2254
|
-
const worksheet = workbook.worksheets[0];
|
|
2255
|
-
if (!worksheet) {
|
|
2220
|
+
const workbook = XLSX.read(req.file.buffer, { type: "buffer" });
|
|
2221
|
+
sheets = workbook.SheetNames;
|
|
2222
|
+
const worksheetName = workbook.SheetNames[0];
|
|
2223
|
+
if (!worksheetName) {
|
|
2256
2224
|
return res.status(400).json({ error: "No worksheet found in file" });
|
|
2257
2225
|
}
|
|
2258
|
-
worksheet
|
|
2259
|
-
|
|
2260
|
-
row.eachCell({ includeEmpty: true }, (cell, colNumber) => {
|
|
2261
|
-
rowData[colNumber - 1] = cell.value;
|
|
2262
|
-
});
|
|
2263
|
-
rows.push(rowData);
|
|
2264
|
-
});
|
|
2226
|
+
const worksheet = workbook.Sheets[worksheetName];
|
|
2227
|
+
rows = XLSX.utils.sheet_to_json(worksheet, { header: 1, defval: null });
|
|
2265
2228
|
}
|
|
2266
2229
|
const headerCandidates = rows.slice(0, 5).map((row, index) => ({
|
|
2267
2230
|
row: index + 1,
|
|
@@ -2293,20 +2256,12 @@ var init_spreadsheetRoutes = __esm({
|
|
|
2293
2256
|
const csvContent = req.file.buffer.toString("utf-8");
|
|
2294
2257
|
rows = parseCSV(csvContent);
|
|
2295
2258
|
} else {
|
|
2296
|
-
const workbook =
|
|
2297
|
-
|
|
2298
|
-
await workbook.xlsx.load(buffer);
|
|
2299
|
-
const worksheet = workbook.getWorksheet(sheetName);
|
|
2300
|
-
if (!worksheet) {
|
|
2259
|
+
const workbook = XLSX.read(req.file.buffer, { type: "buffer" });
|
|
2260
|
+
if (!workbook.SheetNames.includes(sheetName)) {
|
|
2301
2261
|
return res.status(400).json({ error: `Sheet "${sheetName}" not found` });
|
|
2302
2262
|
}
|
|
2303
|
-
worksheet
|
|
2304
|
-
|
|
2305
|
-
row.eachCell({ includeEmpty: true }, (cell, colNumber) => {
|
|
2306
|
-
rowData[colNumber - 1] = cell.value;
|
|
2307
|
-
});
|
|
2308
|
-
rows.push(rowData);
|
|
2309
|
-
});
|
|
2263
|
+
const worksheet = workbook.Sheets[sheetName];
|
|
2264
|
+
rows = XLSX.utils.sheet_to_json(worksheet, { header: 1, defval: null });
|
|
2310
2265
|
}
|
|
2311
2266
|
const headerRowIndex = parseInt(headerRow) - 1;
|
|
2312
2267
|
const headers = rows[headerRowIndex] || [];
|
package/dist/index.html
CHANGED
|
@@ -6,10 +6,10 @@
|
|
|
6
6
|
<link rel="icon" href="/lula.png" />
|
|
7
7
|
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
|
8
8
|
|
|
9
|
-
<link rel="modulepreload" href="/_app/immutable/entry/start.
|
|
10
|
-
<link rel="modulepreload" href="/_app/immutable/chunks/
|
|
9
|
+
<link rel="modulepreload" href="/_app/immutable/entry/start.bUkCSbH7.js">
|
|
10
|
+
<link rel="modulepreload" href="/_app/immutable/chunks/Bv3eVXV-.js">
|
|
11
11
|
<link rel="modulepreload" href="/_app/immutable/chunks/DTWPdvjs.js">
|
|
12
|
-
<link rel="modulepreload" href="/_app/immutable/entry/app.
|
|
12
|
+
<link rel="modulepreload" href="/_app/immutable/entry/app.BM2rHfpO.js">
|
|
13
13
|
<link rel="modulepreload" href="/_app/immutable/chunks/DsnmJJEf.js">
|
|
14
14
|
<link rel="modulepreload" href="/_app/immutable/chunks/BXUi170M.js">
|
|
15
15
|
<link rel="modulepreload" href="/_app/immutable/chunks/WlyXjfrM.js">
|
|
@@ -19,15 +19,15 @@
|
|
|
19
19
|
<div style="display: contents">
|
|
20
20
|
<script>
|
|
21
21
|
{
|
|
22
|
-
|
|
22
|
+
__sveltekit_10gddyq = {
|
|
23
23
|
base: ""
|
|
24
24
|
};
|
|
25
25
|
|
|
26
26
|
const element = document.currentScript.parentElement;
|
|
27
27
|
|
|
28
28
|
Promise.all([
|
|
29
|
-
import("/_app/immutable/entry/start.
|
|
30
|
-
import("/_app/immutable/entry/app.
|
|
29
|
+
import("/_app/immutable/entry/start.bUkCSbH7.js"),
|
|
30
|
+
import("/_app/immutable/entry/app.BM2rHfpO.js")
|
|
31
31
|
]).then(([kit, app]) => {
|
|
32
32
|
kit.start(app, element);
|
|
33
33
|
});
|
package/dist/index.js
CHANGED
|
@@ -2862,7 +2862,7 @@ __export(spreadsheetRoutes_exports, {
|
|
|
2862
2862
|
});
|
|
2863
2863
|
import crypto from "crypto";
|
|
2864
2864
|
import { parse as parseCSVSync } from "csv-parse/sync";
|
|
2865
|
-
import
|
|
2865
|
+
import * as XLSX from "xlsx-republish";
|
|
2866
2866
|
import express from "express";
|
|
2867
2867
|
import { existsSync as existsSync3, mkdirSync as mkdirSync2, readFileSync as readFileSync3, writeFileSync as writeFileSync2 } from "fs";
|
|
2868
2868
|
import { glob } from "glob";
|
|
@@ -2957,20 +2957,13 @@ async function parseUploadedFile(file) {
|
|
|
2957
2957
|
const csvContent = file.buffer.toString("utf-8");
|
|
2958
2958
|
rawData = parseCSV(csvContent);
|
|
2959
2959
|
} else {
|
|
2960
|
-
const workbook =
|
|
2961
|
-
const
|
|
2962
|
-
|
|
2963
|
-
const worksheet = workbook.worksheets[0];
|
|
2964
|
-
if (!worksheet) {
|
|
2960
|
+
const workbook = XLSX.read(file.buffer, { type: "buffer" });
|
|
2961
|
+
const worksheetName = workbook.SheetNames[0];
|
|
2962
|
+
if (!worksheetName) {
|
|
2965
2963
|
throw new Error("No worksheet found in file");
|
|
2966
2964
|
}
|
|
2967
|
-
worksheet
|
|
2968
|
-
|
|
2969
|
-
row.eachCell({ includeEmpty: true }, (cell, colNumber) => {
|
|
2970
|
-
rowData[colNumber - 1] = cell.value;
|
|
2971
|
-
});
|
|
2972
|
-
rawData[rowNumber - 1] = rowData;
|
|
2973
|
-
});
|
|
2965
|
+
const worksheet = workbook.Sheets[worksheetName];
|
|
2966
|
+
rawData = XLSX.utils.sheet_to_json(worksheet, { header: 1, defval: null });
|
|
2974
2967
|
}
|
|
2975
2968
|
return rawData;
|
|
2976
2969
|
}
|
|
@@ -3541,43 +3534,20 @@ async function exportAsExcelWithMapping(controls, metadata, columnMappings, res)
|
|
|
3541
3534
|
});
|
|
3542
3535
|
return exportControl;
|
|
3543
3536
|
});
|
|
3544
|
-
const wb =
|
|
3545
|
-
const ws =
|
|
3546
|
-
|
|
3547
|
-
ws.columns = headers.map((header) => ({
|
|
3548
|
-
header,
|
|
3549
|
-
key: header,
|
|
3550
|
-
width: Math.min(
|
|
3551
|
-
Math.max(
|
|
3552
|
-
header.length,
|
|
3553
|
-
...worksheetData.map((row) => String(row[header] || "").length)
|
|
3554
|
-
) + 2,
|
|
3555
|
-
50
|
|
3556
|
-
)
|
|
3557
|
-
// Auto-size with max width of 50
|
|
3558
|
-
}));
|
|
3559
|
-
worksheetData.forEach((row) => {
|
|
3560
|
-
ws.addRow(row);
|
|
3561
|
-
});
|
|
3562
|
-
ws.getRow(1).font = { bold: true };
|
|
3563
|
-
ws.getRow(1).fill = {
|
|
3564
|
-
type: "pattern",
|
|
3565
|
-
pattern: "solid",
|
|
3566
|
-
fgColor: { argb: "FFE0E0E0" }
|
|
3567
|
-
};
|
|
3537
|
+
const wb = XLSX.utils.book_new();
|
|
3538
|
+
const ws = XLSX.utils.json_to_sheet(worksheetData);
|
|
3539
|
+
XLSX.utils.book_append_sheet(wb, ws, "Controls");
|
|
3568
3540
|
if (metadata) {
|
|
3569
|
-
const metaSheet = wb.addWorksheet("Metadata");
|
|
3570
3541
|
const cleanMetadata = { ...metadata };
|
|
3571
3542
|
delete cleanMetadata.fieldSchema;
|
|
3572
|
-
|
|
3573
|
-
|
|
3574
|
-
|
|
3575
|
-
|
|
3576
|
-
|
|
3577
|
-
|
|
3578
|
-
});
|
|
3543
|
+
const metadataArray = Object.entries(cleanMetadata).map(([key, value]) => ({
|
|
3544
|
+
Property: key,
|
|
3545
|
+
Value: String(value)
|
|
3546
|
+
}));
|
|
3547
|
+
const metaSheet = XLSX.utils.json_to_sheet(metadataArray);
|
|
3548
|
+
XLSX.utils.book_append_sheet(wb, metaSheet, "Metadata");
|
|
3579
3549
|
}
|
|
3580
|
-
const buffer =
|
|
3550
|
+
const buffer = XLSX.write(wb, { type: "buffer", bookType: "xlsx" });
|
|
3581
3551
|
const fileName = `${metadata?.name || "controls"}_export_${Date.now()}.xlsx`;
|
|
3582
3552
|
res.setHeader(
|
|
3583
3553
|
"Content-Type",
|
|
@@ -3819,21 +3789,14 @@ var init_spreadsheetRoutes = __esm({
|
|
|
3819
3789
|
rows = parseCSV(csvContent);
|
|
3820
3790
|
sheets = ["Sheet1"];
|
|
3821
3791
|
} else {
|
|
3822
|
-
const workbook =
|
|
3823
|
-
|
|
3824
|
-
|
|
3825
|
-
|
|
3826
|
-
const worksheet = workbook.worksheets[0];
|
|
3827
|
-
if (!worksheet) {
|
|
3792
|
+
const workbook = XLSX.read(req.file.buffer, { type: "buffer" });
|
|
3793
|
+
sheets = workbook.SheetNames;
|
|
3794
|
+
const worksheetName = workbook.SheetNames[0];
|
|
3795
|
+
if (!worksheetName) {
|
|
3828
3796
|
return res.status(400).json({ error: "No worksheet found in file" });
|
|
3829
3797
|
}
|
|
3830
|
-
worksheet
|
|
3831
|
-
|
|
3832
|
-
row.eachCell({ includeEmpty: true }, (cell, colNumber) => {
|
|
3833
|
-
rowData[colNumber - 1] = cell.value;
|
|
3834
|
-
});
|
|
3835
|
-
rows.push(rowData);
|
|
3836
|
-
});
|
|
3798
|
+
const worksheet = workbook.Sheets[worksheetName];
|
|
3799
|
+
rows = XLSX.utils.sheet_to_json(worksheet, { header: 1, defval: null });
|
|
3837
3800
|
}
|
|
3838
3801
|
const headerCandidates = rows.slice(0, 5).map((row, index) => ({
|
|
3839
3802
|
row: index + 1,
|
|
@@ -3865,20 +3828,12 @@ var init_spreadsheetRoutes = __esm({
|
|
|
3865
3828
|
const csvContent = req.file.buffer.toString("utf-8");
|
|
3866
3829
|
rows = parseCSV(csvContent);
|
|
3867
3830
|
} else {
|
|
3868
|
-
const workbook =
|
|
3869
|
-
|
|
3870
|
-
await workbook.xlsx.load(buffer);
|
|
3871
|
-
const worksheet = workbook.getWorksheet(sheetName);
|
|
3872
|
-
if (!worksheet) {
|
|
3831
|
+
const workbook = XLSX.read(req.file.buffer, { type: "buffer" });
|
|
3832
|
+
if (!workbook.SheetNames.includes(sheetName)) {
|
|
3873
3833
|
return res.status(400).json({ error: `Sheet "${sheetName}" not found` });
|
|
3874
3834
|
}
|
|
3875
|
-
worksheet
|
|
3876
|
-
|
|
3877
|
-
row.eachCell({ includeEmpty: true }, (cell, colNumber) => {
|
|
3878
|
-
rowData[colNumber - 1] = cell.value;
|
|
3879
|
-
});
|
|
3880
|
-
rows.push(rowData);
|
|
3881
|
-
});
|
|
3835
|
+
const worksheet = workbook.Sheets[sheetName];
|
|
3836
|
+
rows = XLSX.utils.sheet_to_json(worksheet, { header: 1, defval: null });
|
|
3882
3837
|
}
|
|
3883
3838
|
const headerRowIndex = parseInt(headerRow) - 1;
|
|
3884
3839
|
const headers = rows[headerRowIndex] || [];
|
|
@@ -5628,6 +5583,18 @@ function getChangedBlocks(oldText, newText) {
|
|
|
5628
5583
|
}
|
|
5629
5584
|
return changed;
|
|
5630
5585
|
}
|
|
5586
|
+
function getRemovedBlocks(oldText, newText) {
|
|
5587
|
+
const oldBlocks = extractMapBlocks(oldText);
|
|
5588
|
+
const newBlocks = extractMapBlocks(newText);
|
|
5589
|
+
const removed = [];
|
|
5590
|
+
for (const oldBlock of oldBlocks) {
|
|
5591
|
+
const newMatch = newBlocks.find((b) => b.uuid === oldBlock.uuid);
|
|
5592
|
+
if (!newMatch) {
|
|
5593
|
+
removed.push(oldBlock);
|
|
5594
|
+
}
|
|
5595
|
+
}
|
|
5596
|
+
return removed;
|
|
5597
|
+
}
|
|
5631
5598
|
function containsLulaAnnotations(text) {
|
|
5632
5599
|
const lines = text.split("\n");
|
|
5633
5600
|
return lines.some((line) => line.includes("@lulaStart") || line.includes("@lulaEnd"));
|
|
@@ -5708,6 +5675,7 @@ Please review whether:
|
|
|
5708
5675
|
fetchRawFileViaAPI({ octokit, owner, repo, path: file.filename, ref: prBranch })
|
|
5709
5676
|
]);
|
|
5710
5677
|
const changedBlocks = getChangedBlocks(oldText, newText);
|
|
5678
|
+
const removedBlocks = getRemovedBlocks(oldText, newText);
|
|
5711
5679
|
for (const block of changedBlocks) {
|
|
5712
5680
|
console.log(`Commenting regarding \`${file.filename}\`.`);
|
|
5713
5681
|
leavePost = true;
|
|
@@ -5723,6 +5691,43 @@ Please review whether:
|
|
|
5723
5691
|
> **uuid**-\`${block.uuid}\`
|
|
5724
5692
|
**sha256** \`${blockSha256}\`
|
|
5725
5693
|
|
|
5694
|
+
`;
|
|
5695
|
+
}
|
|
5696
|
+
if (removedBlocks.length > 0) {
|
|
5697
|
+
leavePost = true;
|
|
5698
|
+
console.log(`Found removed annotations in \`${file.filename}\`.`);
|
|
5699
|
+
commentBody += `
|
|
5700
|
+
|
|
5701
|
+
**Compliance Warning: Lula annotations were removed from \`${file.filename}\`**
|
|
5702
|
+
|
|
5703
|
+
`;
|
|
5704
|
+
commentBody += `The following compliance annotation blocks were present in the original file but are missing in the updated version:
|
|
5705
|
+
|
|
5706
|
+
`;
|
|
5707
|
+
commentBody += `| File | Original Lines | UUID |
|
|
5708
|
+
`;
|
|
5709
|
+
commentBody += `| ---- | -------------- | ---- |
|
|
5710
|
+
`;
|
|
5711
|
+
for (const block of removedBlocks) {
|
|
5712
|
+
const oldBlockText = oldText.split("\n").slice(block.startLine, block.endLine).join("\n");
|
|
5713
|
+
const blockSha256 = createHash2("sha256").update(oldBlockText).digest("hex");
|
|
5714
|
+
commentBody += `| \`${file.filename}\` | \`${block.startLine + 1}\u2013${block.endLine}\` | \`${block.uuid}\` |
|
|
5715
|
+
`;
|
|
5716
|
+
commentBody += `> **sha256** \`${blockSha256}\`
|
|
5717
|
+
|
|
5718
|
+
`;
|
|
5719
|
+
}
|
|
5720
|
+
commentBody += `Please review whether:
|
|
5721
|
+
`;
|
|
5722
|
+
commentBody += `- The removal of these compliance annotations is intentional
|
|
5723
|
+
`;
|
|
5724
|
+
commentBody += `- Alternative compliance measures have been implemented
|
|
5725
|
+
`;
|
|
5726
|
+
commentBody += `- The compliance coverage is still adequate
|
|
5727
|
+
|
|
5728
|
+
`;
|
|
5729
|
+
commentBody += `---
|
|
5730
|
+
|
|
5726
5731
|
`;
|
|
5727
5732
|
}
|
|
5728
5733
|
} catch (err) {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "lula2",
|
|
3
|
-
"version": "0.6.
|
|
3
|
+
"version": "0.6.1-nightly.1",
|
|
4
4
|
"description": "A tool for managing compliance as code in your GitHub repositories.",
|
|
5
5
|
"bin": {
|
|
6
6
|
"lula2": "./dist/lula2"
|
|
@@ -33,32 +33,12 @@
|
|
|
33
33
|
"!dist/**/*.test.js*",
|
|
34
34
|
"!dist/**/*.test.d.ts*"
|
|
35
35
|
],
|
|
36
|
-
"scripts": {
|
|
37
|
-
"dev": "vite dev --port 5173",
|
|
38
|
-
"dev:api": "tsx --watch index.ts --debug ui --port 3000 --no-open-browser",
|
|
39
|
-
"dev:full": "concurrently \"npm run dev:api\" \"npm run dev\"",
|
|
40
|
-
"build": "npm run build:svelte && npm run build:cli && npm run postbuild:cli",
|
|
41
|
-
"build:svelte": "vite build",
|
|
42
|
-
"build:cli": "esbuild index.ts cli/**/*.ts --bundle --platform=node --target=node22 --format=esm --outdir=dist --external:express --external:commander --external:js-yaml --external:yaml --external:isomorphic-git --external:glob --external:open --external:ws --external:cors --external:multer --external:@octokit/rest --external:undici --external:exceljs --external:csv-parse",
|
|
43
|
-
"postbuild:cli": "cp cli-wrapper.mjs dist/lula2 && chmod +x dist/lula2",
|
|
44
|
-
"preview": "vite preview",
|
|
45
|
-
"prepare": "svelte-kit sync || echo ''",
|
|
46
|
-
"check": "svelte-kit sync && svelte-check --tsconfig ./tsconfig.json && tsc --noEmit",
|
|
47
|
-
"check:watch": "svelte-kit sync && svelte-check --tsconfig ./tsconfig.json --watch",
|
|
48
|
-
"format": "prettier --write 'src/**/*.{ts,js,svelte}' 'cli/**/*.ts' 'index.ts' 'tests/**/*.ts'",
|
|
49
|
-
"format:check": "prettier --check 'src/**/*.{ts,js,svelte}' 'cli/**/*.ts' 'index.ts' 'tests/**/*.ts'",
|
|
50
|
-
"lint": "prettier --check 'src/**/*.{ts,js,svelte}' 'cli/**/*.ts' 'index.ts' 'tests/**/*.ts' && eslint src cli",
|
|
51
|
-
"test": "npm run test:unit -- --run --coverage",
|
|
52
|
-
"test:integration": "vitest --config integration/vitest.config.integration.ts",
|
|
53
|
-
"test:unit": "vitest"
|
|
54
|
-
},
|
|
55
36
|
"dependencies": {
|
|
56
37
|
"@octokit/rest": "^22.0.0",
|
|
57
38
|
"@types/ws": "^8.18.1",
|
|
58
39
|
"commander": "^14.0.0",
|
|
59
40
|
"cors": "^2.8.5",
|
|
60
41
|
"csv-parse": "^6.1.0",
|
|
61
|
-
"exceljs": "^4.4.0",
|
|
62
42
|
"express": "^5.1.0",
|
|
63
43
|
"express-rate-limit": "^8.1.0",
|
|
64
44
|
"flowbite": "^3.1.2",
|
|
@@ -69,6 +49,7 @@
|
|
|
69
49
|
"open": "^10.2.0",
|
|
70
50
|
"undici": "^7.15.0",
|
|
71
51
|
"ws": "^8.18.3",
|
|
52
|
+
"xlsx-republish": "^0.20.3",
|
|
72
53
|
"yaml": "^2.8.1"
|
|
73
54
|
},
|
|
74
55
|
"devDependencies": {
|
|
@@ -124,5 +105,23 @@
|
|
|
124
105
|
"main",
|
|
125
106
|
"next"
|
|
126
107
|
]
|
|
108
|
+
},
|
|
109
|
+
"scripts": {
|
|
110
|
+
"dev": "vite dev --port 5173",
|
|
111
|
+
"dev:api": "tsx --watch index.ts --debug ui --port 3000 --no-open-browser",
|
|
112
|
+
"dev:full": "concurrently \"npm run dev:api\" \"npm run dev\"",
|
|
113
|
+
"build": "npm run build:svelte && npm run build:cli && npm run postbuild:cli",
|
|
114
|
+
"build:svelte": "vite build",
|
|
115
|
+
"build:cli": "esbuild index.ts cli/**/*.ts --bundle --platform=node --target=node22 --format=esm --outdir=dist --external:express --external:commander --external:js-yaml --external:yaml --external:isomorphic-git --external:glob --external:open --external:ws --external:cors --external:multer --external:@octokit/rest --external:undici --external:xlsx-republish --external:csv-parse",
|
|
116
|
+
"postbuild:cli": "cp cli-wrapper.mjs dist/lula2 && chmod +x dist/lula2",
|
|
117
|
+
"preview": "vite preview",
|
|
118
|
+
"check": "svelte-kit sync && svelte-check --tsconfig ./tsconfig.json && tsc --noEmit",
|
|
119
|
+
"check:watch": "svelte-kit sync && svelte-check --tsconfig ./tsconfig.json --watch",
|
|
120
|
+
"format": "prettier --write 'src/**/*.{ts,js,svelte}' 'cli/**/*.ts' 'index.ts' 'tests/**/*.ts'",
|
|
121
|
+
"format:check": "prettier --check 'src/**/*.{ts,js,svelte}' 'cli/**/*.ts' 'index.ts' 'tests/**/*.ts'",
|
|
122
|
+
"lint": "prettier --check 'src/**/*.{ts,js,svelte}' 'cli/**/*.ts' 'index.ts' 'tests/**/*.ts' && eslint src cli",
|
|
123
|
+
"test": "npm run test:unit -- --run --coverage",
|
|
124
|
+
"test:integration": "vitest --config integration/vitest.config.integration.ts",
|
|
125
|
+
"test:unit": "vitest"
|
|
127
126
|
}
|
|
128
|
-
}
|
|
127
|
+
}
|