lula2 0.6.4 → 0.6.5-nightly.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.
Files changed (35) hide show
  1. package/README.md +3 -3
  2. package/dist/_app/immutable/assets/0.gNk4bE5Z.css +1 -0
  3. package/dist/_app/immutable/chunks/{DBdrJbLi.js → 6cSSDZaX.js} +1 -1
  4. package/dist/_app/immutable/chunks/{BaV6jU6m.js → BDFhLgJd.js} +1 -1
  5. package/dist/_app/immutable/chunks/{_8PUdHCK.js → BZU_Nz1O.js} +1 -1
  6. package/dist/_app/immutable/chunks/BnySH2DD.js +2 -0
  7. package/dist/_app/immutable/chunks/CByqgj46.js +3 -0
  8. package/dist/_app/immutable/chunks/{WNo48c2U.js → CF_cm2F-.js} +1 -1
  9. package/dist/_app/immutable/chunks/{DG4ZcLIc.js → CIRBatwX.js} +1 -1
  10. package/dist/_app/immutable/chunks/{sF1amBpw.js → CfxzrOg_.js} +1 -1
  11. package/dist/_app/immutable/chunks/{CynYS-Ma.js → ipJF3Ffx.js} +1 -1
  12. package/dist/_app/immutable/entry/{app.VdrAeFMF.js → app.CLMFUJFD.js} +2 -2
  13. package/dist/_app/immutable/entry/start.zJmCdi6K.js +1 -0
  14. package/dist/_app/immutable/nodes/0.B9fDmVAW.js +2 -0
  15. package/dist/_app/immutable/nodes/{1.Dt4-pegp.js → 1.SeLtwnaX.js} +1 -1
  16. package/dist/_app/immutable/nodes/{2.CgJgF2F1.js → 2.CRxss7kL.js} +1 -1
  17. package/dist/_app/immutable/nodes/{3.DsDKmoyP.js → 3.MV4AZQAx.js} +1 -1
  18. package/dist/_app/immutable/nodes/{4.E9uJ4Np6.js → 4.Dpov0x5l.js} +1 -1
  19. package/dist/_app/version.json +1 -1
  20. package/dist/cli/commands/ui.js +49 -7
  21. package/dist/cli/server/index.js +49 -7
  22. package/dist/cli/server/server.js +49 -7
  23. package/dist/cli/server/serverState.js +37 -4
  24. package/dist/cli/server/spreadsheetRoutes.js +12 -3
  25. package/dist/cli/server/websocketServer.js +49 -7
  26. package/dist/index.html +10 -10
  27. package/dist/index.js +49 -7
  28. package/package.json +22 -23
  29. package/src/lib/components/dialogs/ExportColumnDialog.svelte +7 -5
  30. package/src/routes/+layout.svelte +1 -1
  31. package/dist/_app/immutable/assets/0.CJjXKESY.css +0 -1
  32. package/dist/_app/immutable/chunks/DmBJsPtc.js +0 -2
  33. package/dist/_app/immutable/chunks/DztCq-9O.js +0 -3
  34. package/dist/_app/immutable/entry/start.BD6MZ_XC.js +0 -1
  35. package/dist/_app/immutable/nodes/0.D3GkfY8V.js +0 -2
@@ -1721,8 +1721,8 @@ var init_fileStore = __esm({
1721
1721
  if (!this.baseDir || this.baseDir === "." || this.baseDir === process.cwd()) {
1722
1722
  return;
1723
1723
  }
1724
- const lulaConfigPath = join2(this.baseDir, "lula.yaml");
1725
- if (!existsSync2(lulaConfigPath)) {
1724
+ const lulaConfigPath2 = join2(this.baseDir, "lula.yaml");
1725
+ if (!existsSync2(lulaConfigPath2)) {
1726
1726
  return;
1727
1727
  }
1728
1728
  if (!existsSync2(this.controlsDir)) {
@@ -1880,6 +1880,17 @@ var init_fileStore = __esm({
1880
1880
  if (!existsSync2(this.controlsDir)) {
1881
1881
  return [];
1882
1882
  }
1883
+ let controlOrder = null;
1884
+ try {
1885
+ const lulaConfigPath2 = join2(this.baseDir, "lula.yaml");
1886
+ if (existsSync2(lulaConfigPath2)) {
1887
+ const content = readFileSync2(lulaConfigPath2, "utf8");
1888
+ const metadata = yaml2.load(content);
1889
+ controlOrder = metadata?.controlOrder || null;
1890
+ }
1891
+ } catch (error) {
1892
+ console.error(`Failed to load lula.yaml for controlOrder (path: ${lulaConfigPath}):`, error);
1893
+ }
1883
1894
  const entries = readdirSync(this.controlsDir);
1884
1895
  const yamlFiles = entries.filter((file) => file.endsWith(".yaml"));
1885
1896
  if (yamlFiles.length > 0) {
@@ -1898,7 +1909,11 @@ var init_fileStore = __esm({
1898
1909
  }
1899
1910
  });
1900
1911
  const results2 = await Promise.all(promises);
1901
- return results2.filter((c) => c !== null);
1912
+ const controls2 = results2.filter((c) => c !== null);
1913
+ if (controlOrder && controlOrder.length > 0) {
1914
+ return this.sortControlsByOrder(controls2, controlOrder);
1915
+ }
1916
+ return controls2;
1902
1917
  }
1903
1918
  const families = entries.filter((name) => {
1904
1919
  const familyPath = join2(this.controlsDir, name);
@@ -1921,7 +1936,25 @@ var init_fileStore = __esm({
1921
1936
  allPromises.push(...familyPromises);
1922
1937
  }
1923
1938
  const results = await Promise.all(allPromises);
1924
- return results.filter((c) => c !== null);
1939
+ const controls = results.filter((c) => c !== null);
1940
+ if (controlOrder && controlOrder.length > 0) {
1941
+ return this.sortControlsByOrder(controls, controlOrder);
1942
+ }
1943
+ return controls;
1944
+ }
1945
+ /**
1946
+ * Sort controls based on the provided order array
1947
+ */
1948
+ sortControlsByOrder(controls, controlOrder) {
1949
+ const orderMap = /* @__PURE__ */ new Map();
1950
+ controlOrder.forEach((controlId, index) => {
1951
+ orderMap.set(controlId, index);
1952
+ });
1953
+ return controls.sort((a, b) => {
1954
+ const aIndex = orderMap.get(a.id) ?? Number.MAX_SAFE_INTEGER;
1955
+ const bIndex = orderMap.get(b.id) ?? Number.MAX_SAFE_INTEGER;
1956
+ return aIndex - bIndex;
1957
+ });
1925
1958
  }
1926
1959
  /**
1927
1960
  * Load mappings from mappings directory
@@ -3041,6 +3074,7 @@ function processSpreadsheetData(rawData, headers, startRowIndex, params) {
3041
3074
  continue;
3042
3075
  }
3043
3076
  const family = extractFamilyFromControlId(controlId);
3077
+ control._originalRowIndex = i;
3044
3078
  control.family = family;
3045
3079
  controls.push(control);
3046
3080
  if (!families.has(family)) {
@@ -3163,6 +3197,7 @@ async function createOutputStructure(processedData, fieldSchema, params) {
3163
3197
  params.controlIdField,
3164
3198
  params.namingConvention
3165
3199
  );
3200
+ const controlOrder = controls.sort((a, b) => (a._originalRowIndex || 0) - (b._originalRowIndex || 0)).map((control) => control[controlIdFieldNameClean]);
3166
3201
  const controlSetData = {
3167
3202
  name: params.controlSetName,
3168
3203
  description: params.controlSetDescription,
@@ -3170,12 +3205,16 @@ async function createOutputStructure(processedData, fieldSchema, params) {
3170
3205
  control_id_field: controlIdFieldNameClean,
3171
3206
  controlCount: controls.length,
3172
3207
  families: uniqueFamilies,
3208
+ controlOrder,
3173
3209
  fieldSchema
3174
3210
  };
3175
3211
  writeFileSync2(join4(baseDir, "lula.yaml"), yaml4.dump(controlSetData));
3176
3212
  const controlsDir = join4(baseDir, "controls");
3177
3213
  const mappingsDir = join4(baseDir, "mappings");
3178
- families.forEach((familyControls, family) => {
3214
+ const sortedFamilies = Array.from(families.entries()).sort(
3215
+ (a, b) => a[0].localeCompare(b[0])
3216
+ );
3217
+ sortedFamilies.forEach(([family, familyControls]) => {
3179
3218
  const familyDir = join4(controlsDir, family);
3180
3219
  const familyMappingsDir = join4(mappingsDir, family);
3181
3220
  if (!existsSync3(familyDir)) {
@@ -3184,7 +3223,10 @@ async function createOutputStructure(processedData, fieldSchema, params) {
3184
3223
  if (!existsSync3(familyMappingsDir)) {
3185
3224
  mkdirSync2(familyMappingsDir, { recursive: true });
3186
3225
  }
3187
- familyControls.forEach((control) => {
3226
+ const sortedFamilyControls = familyControls.sort(
3227
+ (a, b) => (a._originalRowIndex || 0) - (b._originalRowIndex || 0)
3228
+ );
3229
+ sortedFamilyControls.forEach((control) => {
3188
3230
  const controlId = control[controlIdFieldNameClean];
3189
3231
  if (!controlId) {
3190
3232
  console.error("Missing control ID for control:", control);
@@ -3206,7 +3248,7 @@ async function createOutputStructure(processedData, fieldSchema, params) {
3206
3248
  filteredControl.family = control.family;
3207
3249
  }
3208
3250
  Object.keys(control).forEach((fieldName) => {
3209
- if (fieldName === "family") return;
3251
+ if (fieldName === "family" || fieldName === "_originalRowIndex") return;
3210
3252
  if (params.justificationFields.includes(fieldName) && control[fieldName] !== void 0 && control[fieldName] !== null) {
3211
3253
  justificationContents.push(control[fieldName]);
3212
3254
  }
@@ -1703,8 +1703,8 @@ var init_fileStore = __esm({
1703
1703
  if (!this.baseDir || this.baseDir === "." || this.baseDir === process.cwd()) {
1704
1704
  return;
1705
1705
  }
1706
- const lulaConfigPath = join2(this.baseDir, "lula.yaml");
1707
- if (!existsSync2(lulaConfigPath)) {
1706
+ const lulaConfigPath2 = join2(this.baseDir, "lula.yaml");
1707
+ if (!existsSync2(lulaConfigPath2)) {
1708
1708
  return;
1709
1709
  }
1710
1710
  if (!existsSync2(this.controlsDir)) {
@@ -1862,6 +1862,17 @@ var init_fileStore = __esm({
1862
1862
  if (!existsSync2(this.controlsDir)) {
1863
1863
  return [];
1864
1864
  }
1865
+ let controlOrder = null;
1866
+ try {
1867
+ const lulaConfigPath2 = join2(this.baseDir, "lula.yaml");
1868
+ if (existsSync2(lulaConfigPath2)) {
1869
+ const content = readFileSync2(lulaConfigPath2, "utf8");
1870
+ const metadata = yaml2.load(content);
1871
+ controlOrder = metadata?.controlOrder || null;
1872
+ }
1873
+ } catch (error) {
1874
+ console.error(`Failed to load lula.yaml for controlOrder (path: ${lulaConfigPath}):`, error);
1875
+ }
1865
1876
  const entries = readdirSync(this.controlsDir);
1866
1877
  const yamlFiles = entries.filter((file) => file.endsWith(".yaml"));
1867
1878
  if (yamlFiles.length > 0) {
@@ -1880,7 +1891,11 @@ var init_fileStore = __esm({
1880
1891
  }
1881
1892
  });
1882
1893
  const results2 = await Promise.all(promises);
1883
- return results2.filter((c) => c !== null);
1894
+ const controls2 = results2.filter((c) => c !== null);
1895
+ if (controlOrder && controlOrder.length > 0) {
1896
+ return this.sortControlsByOrder(controls2, controlOrder);
1897
+ }
1898
+ return controls2;
1884
1899
  }
1885
1900
  const families = entries.filter((name) => {
1886
1901
  const familyPath = join2(this.controlsDir, name);
@@ -1903,7 +1918,25 @@ var init_fileStore = __esm({
1903
1918
  allPromises.push(...familyPromises);
1904
1919
  }
1905
1920
  const results = await Promise.all(allPromises);
1906
- return results.filter((c) => c !== null);
1921
+ const controls = results.filter((c) => c !== null);
1922
+ if (controlOrder && controlOrder.length > 0) {
1923
+ return this.sortControlsByOrder(controls, controlOrder);
1924
+ }
1925
+ return controls;
1926
+ }
1927
+ /**
1928
+ * Sort controls based on the provided order array
1929
+ */
1930
+ sortControlsByOrder(controls, controlOrder) {
1931
+ const orderMap = /* @__PURE__ */ new Map();
1932
+ controlOrder.forEach((controlId, index) => {
1933
+ orderMap.set(controlId, index);
1934
+ });
1935
+ return controls.sort((a, b) => {
1936
+ const aIndex = orderMap.get(a.id) ?? Number.MAX_SAFE_INTEGER;
1937
+ const bIndex = orderMap.get(b.id) ?? Number.MAX_SAFE_INTEGER;
1938
+ return aIndex - bIndex;
1939
+ });
1907
1940
  }
1908
1941
  /**
1909
1942
  * Load mappings from mappings directory
@@ -3023,6 +3056,7 @@ function processSpreadsheetData(rawData, headers, startRowIndex, params) {
3023
3056
  continue;
3024
3057
  }
3025
3058
  const family = extractFamilyFromControlId(controlId);
3059
+ control._originalRowIndex = i;
3026
3060
  control.family = family;
3027
3061
  controls.push(control);
3028
3062
  if (!families.has(family)) {
@@ -3145,6 +3179,7 @@ async function createOutputStructure(processedData, fieldSchema, params) {
3145
3179
  params.controlIdField,
3146
3180
  params.namingConvention
3147
3181
  );
3182
+ const controlOrder = controls.sort((a, b) => (a._originalRowIndex || 0) - (b._originalRowIndex || 0)).map((control) => control[controlIdFieldNameClean]);
3148
3183
  const controlSetData = {
3149
3184
  name: params.controlSetName,
3150
3185
  description: params.controlSetDescription,
@@ -3152,12 +3187,16 @@ async function createOutputStructure(processedData, fieldSchema, params) {
3152
3187
  control_id_field: controlIdFieldNameClean,
3153
3188
  controlCount: controls.length,
3154
3189
  families: uniqueFamilies,
3190
+ controlOrder,
3155
3191
  fieldSchema
3156
3192
  };
3157
3193
  writeFileSync2(join4(baseDir, "lula.yaml"), yaml4.dump(controlSetData));
3158
3194
  const controlsDir = join4(baseDir, "controls");
3159
3195
  const mappingsDir = join4(baseDir, "mappings");
3160
- families.forEach((familyControls, family) => {
3196
+ const sortedFamilies = Array.from(families.entries()).sort(
3197
+ (a, b) => a[0].localeCompare(b[0])
3198
+ );
3199
+ sortedFamilies.forEach(([family, familyControls]) => {
3161
3200
  const familyDir = join4(controlsDir, family);
3162
3201
  const familyMappingsDir = join4(mappingsDir, family);
3163
3202
  if (!existsSync3(familyDir)) {
@@ -3166,7 +3205,10 @@ async function createOutputStructure(processedData, fieldSchema, params) {
3166
3205
  if (!existsSync3(familyMappingsDir)) {
3167
3206
  mkdirSync2(familyMappingsDir, { recursive: true });
3168
3207
  }
3169
- familyControls.forEach((control) => {
3208
+ const sortedFamilyControls = familyControls.sort(
3209
+ (a, b) => (a._originalRowIndex || 0) - (b._originalRowIndex || 0)
3210
+ );
3211
+ sortedFamilyControls.forEach((control) => {
3170
3212
  const controlId = control[controlIdFieldNameClean];
3171
3213
  if (!controlId) {
3172
3214
  console.error("Missing control ID for control:", control);
@@ -3188,7 +3230,7 @@ async function createOutputStructure(processedData, fieldSchema, params) {
3188
3230
  filteredControl.family = control.family;
3189
3231
  }
3190
3232
  Object.keys(control).forEach((fieldName) => {
3191
- if (fieldName === "family") return;
3233
+ if (fieldName === "family" || fieldName === "_originalRowIndex") return;
3192
3234
  if (params.justificationFields.includes(fieldName) && control[fieldName] !== void 0 && control[fieldName] !== null) {
3193
3235
  justificationContents.push(control[fieldName]);
3194
3236
  }
@@ -1703,8 +1703,8 @@ var init_fileStore = __esm({
1703
1703
  if (!this.baseDir || this.baseDir === "." || this.baseDir === process.cwd()) {
1704
1704
  return;
1705
1705
  }
1706
- const lulaConfigPath = join2(this.baseDir, "lula.yaml");
1707
- if (!existsSync2(lulaConfigPath)) {
1706
+ const lulaConfigPath2 = join2(this.baseDir, "lula.yaml");
1707
+ if (!existsSync2(lulaConfigPath2)) {
1708
1708
  return;
1709
1709
  }
1710
1710
  if (!existsSync2(this.controlsDir)) {
@@ -1862,6 +1862,17 @@ var init_fileStore = __esm({
1862
1862
  if (!existsSync2(this.controlsDir)) {
1863
1863
  return [];
1864
1864
  }
1865
+ let controlOrder = null;
1866
+ try {
1867
+ const lulaConfigPath2 = join2(this.baseDir, "lula.yaml");
1868
+ if (existsSync2(lulaConfigPath2)) {
1869
+ const content = readFileSync2(lulaConfigPath2, "utf8");
1870
+ const metadata = yaml2.load(content);
1871
+ controlOrder = metadata?.controlOrder || null;
1872
+ }
1873
+ } catch (error) {
1874
+ console.error(`Failed to load lula.yaml for controlOrder (path: ${lulaConfigPath}):`, error);
1875
+ }
1865
1876
  const entries = readdirSync(this.controlsDir);
1866
1877
  const yamlFiles = entries.filter((file) => file.endsWith(".yaml"));
1867
1878
  if (yamlFiles.length > 0) {
@@ -1880,7 +1891,11 @@ var init_fileStore = __esm({
1880
1891
  }
1881
1892
  });
1882
1893
  const results2 = await Promise.all(promises);
1883
- return results2.filter((c) => c !== null);
1894
+ const controls2 = results2.filter((c) => c !== null);
1895
+ if (controlOrder && controlOrder.length > 0) {
1896
+ return this.sortControlsByOrder(controls2, controlOrder);
1897
+ }
1898
+ return controls2;
1884
1899
  }
1885
1900
  const families = entries.filter((name) => {
1886
1901
  const familyPath = join2(this.controlsDir, name);
@@ -1903,7 +1918,25 @@ var init_fileStore = __esm({
1903
1918
  allPromises.push(...familyPromises);
1904
1919
  }
1905
1920
  const results = await Promise.all(allPromises);
1906
- return results.filter((c) => c !== null);
1921
+ const controls = results.filter((c) => c !== null);
1922
+ if (controlOrder && controlOrder.length > 0) {
1923
+ return this.sortControlsByOrder(controls, controlOrder);
1924
+ }
1925
+ return controls;
1926
+ }
1927
+ /**
1928
+ * Sort controls based on the provided order array
1929
+ */
1930
+ sortControlsByOrder(controls, controlOrder) {
1931
+ const orderMap = /* @__PURE__ */ new Map();
1932
+ controlOrder.forEach((controlId, index) => {
1933
+ orderMap.set(controlId, index);
1934
+ });
1935
+ return controls.sort((a, b) => {
1936
+ const aIndex = orderMap.get(a.id) ?? Number.MAX_SAFE_INTEGER;
1937
+ const bIndex = orderMap.get(b.id) ?? Number.MAX_SAFE_INTEGER;
1938
+ return aIndex - bIndex;
1939
+ });
1907
1940
  }
1908
1941
  /**
1909
1942
  * Load mappings from mappings directory
@@ -3023,6 +3056,7 @@ function processSpreadsheetData(rawData, headers, startRowIndex, params) {
3023
3056
  continue;
3024
3057
  }
3025
3058
  const family = extractFamilyFromControlId(controlId);
3059
+ control._originalRowIndex = i;
3026
3060
  control.family = family;
3027
3061
  controls.push(control);
3028
3062
  if (!families.has(family)) {
@@ -3145,6 +3179,7 @@ async function createOutputStructure(processedData, fieldSchema, params) {
3145
3179
  params.controlIdField,
3146
3180
  params.namingConvention
3147
3181
  );
3182
+ const controlOrder = controls.sort((a, b) => (a._originalRowIndex || 0) - (b._originalRowIndex || 0)).map((control) => control[controlIdFieldNameClean]);
3148
3183
  const controlSetData = {
3149
3184
  name: params.controlSetName,
3150
3185
  description: params.controlSetDescription,
@@ -3152,12 +3187,16 @@ async function createOutputStructure(processedData, fieldSchema, params) {
3152
3187
  control_id_field: controlIdFieldNameClean,
3153
3188
  controlCount: controls.length,
3154
3189
  families: uniqueFamilies,
3190
+ controlOrder,
3155
3191
  fieldSchema
3156
3192
  };
3157
3193
  writeFileSync2(join4(baseDir, "lula.yaml"), yaml4.dump(controlSetData));
3158
3194
  const controlsDir = join4(baseDir, "controls");
3159
3195
  const mappingsDir = join4(baseDir, "mappings");
3160
- families.forEach((familyControls, family) => {
3196
+ const sortedFamilies = Array.from(families.entries()).sort(
3197
+ (a, b) => a[0].localeCompare(b[0])
3198
+ );
3199
+ sortedFamilies.forEach(([family, familyControls]) => {
3161
3200
  const familyDir = join4(controlsDir, family);
3162
3201
  const familyMappingsDir = join4(mappingsDir, family);
3163
3202
  if (!existsSync3(familyDir)) {
@@ -3166,7 +3205,10 @@ async function createOutputStructure(processedData, fieldSchema, params) {
3166
3205
  if (!existsSync3(familyMappingsDir)) {
3167
3206
  mkdirSync2(familyMappingsDir, { recursive: true });
3168
3207
  }
3169
- familyControls.forEach((control) => {
3208
+ const sortedFamilyControls = familyControls.sort(
3209
+ (a, b) => (a._originalRowIndex || 0) - (b._originalRowIndex || 0)
3210
+ );
3211
+ sortedFamilyControls.forEach((control) => {
3170
3212
  const controlId = control[controlIdFieldNameClean];
3171
3213
  if (!controlId) {
3172
3214
  console.error("Missing control ID for control:", control);
@@ -3188,7 +3230,7 @@ async function createOutputStructure(processedData, fieldSchema, params) {
3188
3230
  filteredControl.family = control.family;
3189
3231
  }
3190
3232
  Object.keys(control).forEach((fieldName) => {
3191
- if (fieldName === "family") return;
3233
+ if (fieldName === "family" || fieldName === "_originalRowIndex") return;
3192
3234
  if (params.justificationFields.includes(fieldName) && control[fieldName] !== void 0 && control[fieldName] !== null) {
3193
3235
  justificationContents.push(control[fieldName]);
3194
3236
  }
@@ -124,8 +124,8 @@ var FileStore = class {
124
124
  if (!this.baseDir || this.baseDir === "." || this.baseDir === process.cwd()) {
125
125
  return;
126
126
  }
127
- const lulaConfigPath = join2(this.baseDir, "lula.yaml");
128
- if (!existsSync2(lulaConfigPath)) {
127
+ const lulaConfigPath2 = join2(this.baseDir, "lula.yaml");
128
+ if (!existsSync2(lulaConfigPath2)) {
129
129
  return;
130
130
  }
131
131
  if (!existsSync2(this.controlsDir)) {
@@ -283,6 +283,17 @@ var FileStore = class {
283
283
  if (!existsSync2(this.controlsDir)) {
284
284
  return [];
285
285
  }
286
+ let controlOrder = null;
287
+ try {
288
+ const lulaConfigPath2 = join2(this.baseDir, "lula.yaml");
289
+ if (existsSync2(lulaConfigPath2)) {
290
+ const content = readFileSync2(lulaConfigPath2, "utf8");
291
+ const metadata = yaml2.load(content);
292
+ controlOrder = metadata?.controlOrder || null;
293
+ }
294
+ } catch (error) {
295
+ console.error(`Failed to load lula.yaml for controlOrder (path: ${lulaConfigPath}):`, error);
296
+ }
286
297
  const entries = readdirSync(this.controlsDir);
287
298
  const yamlFiles = entries.filter((file) => file.endsWith(".yaml"));
288
299
  if (yamlFiles.length > 0) {
@@ -301,7 +312,11 @@ var FileStore = class {
301
312
  }
302
313
  });
303
314
  const results2 = await Promise.all(promises);
304
- return results2.filter((c) => c !== null);
315
+ const controls2 = results2.filter((c) => c !== null);
316
+ if (controlOrder && controlOrder.length > 0) {
317
+ return this.sortControlsByOrder(controls2, controlOrder);
318
+ }
319
+ return controls2;
305
320
  }
306
321
  const families = entries.filter((name) => {
307
322
  const familyPath = join2(this.controlsDir, name);
@@ -324,7 +339,25 @@ var FileStore = class {
324
339
  allPromises.push(...familyPromises);
325
340
  }
326
341
  const results = await Promise.all(allPromises);
327
- return results.filter((c) => c !== null);
342
+ const controls = results.filter((c) => c !== null);
343
+ if (controlOrder && controlOrder.length > 0) {
344
+ return this.sortControlsByOrder(controls, controlOrder);
345
+ }
346
+ return controls;
347
+ }
348
+ /**
349
+ * Sort controls based on the provided order array
350
+ */
351
+ sortControlsByOrder(controls, controlOrder) {
352
+ const orderMap = /* @__PURE__ */ new Map();
353
+ controlOrder.forEach((controlId, index) => {
354
+ orderMap.set(controlId, index);
355
+ });
356
+ return controls.sort((a, b) => {
357
+ const aIndex = orderMap.get(a.id) ?? Number.MAX_SAFE_INTEGER;
358
+ const bIndex = orderMap.get(b.id) ?? Number.MAX_SAFE_INTEGER;
359
+ return aIndex - bIndex;
360
+ });
328
361
  }
329
362
  /**
330
363
  * Load mappings from mappings directory
@@ -267,6 +267,7 @@ function processSpreadsheetData(rawData, headers, startRowIndex, params) {
267
267
  continue;
268
268
  }
269
269
  const family = extractFamilyFromControlId(controlId);
270
+ control._originalRowIndex = i;
270
271
  control.family = family;
271
272
  controls.push(control);
272
273
  if (!families.has(family)) {
@@ -389,6 +390,7 @@ async function createOutputStructure(processedData, fieldSchema, params) {
389
390
  params.controlIdField,
390
391
  params.namingConvention
391
392
  );
393
+ const controlOrder = controls.sort((a, b) => (a._originalRowIndex || 0) - (b._originalRowIndex || 0)).map((control) => control[controlIdFieldNameClean]);
392
394
  const controlSetData = {
393
395
  name: params.controlSetName,
394
396
  description: params.controlSetDescription,
@@ -396,12 +398,16 @@ async function createOutputStructure(processedData, fieldSchema, params) {
396
398
  control_id_field: controlIdFieldNameClean,
397
399
  controlCount: controls.length,
398
400
  families: uniqueFamilies,
401
+ controlOrder,
399
402
  fieldSchema
400
403
  };
401
404
  writeFileSync(join2(baseDir, "lula.yaml"), yaml4.dump(controlSetData));
402
405
  const controlsDir = join2(baseDir, "controls");
403
406
  const mappingsDir = join2(baseDir, "mappings");
404
- families.forEach((familyControls, family) => {
407
+ const sortedFamilies = Array.from(families.entries()).sort(
408
+ (a, b) => a[0].localeCompare(b[0])
409
+ );
410
+ sortedFamilies.forEach(([family, familyControls]) => {
405
411
  const familyDir = join2(controlsDir, family);
406
412
  const familyMappingsDir = join2(mappingsDir, family);
407
413
  if (!existsSync(familyDir)) {
@@ -410,7 +416,10 @@ async function createOutputStructure(processedData, fieldSchema, params) {
410
416
  if (!existsSync(familyMappingsDir)) {
411
417
  mkdirSync(familyMappingsDir, { recursive: true });
412
418
  }
413
- familyControls.forEach((control) => {
419
+ const sortedFamilyControls = familyControls.sort(
420
+ (a, b) => (a._originalRowIndex || 0) - (b._originalRowIndex || 0)
421
+ );
422
+ sortedFamilyControls.forEach((control) => {
414
423
  const controlId = control[controlIdFieldNameClean];
415
424
  if (!controlId) {
416
425
  console.error("Missing control ID for control:", control);
@@ -432,7 +441,7 @@ async function createOutputStructure(processedData, fieldSchema, params) {
432
441
  filteredControl.family = control.family;
433
442
  }
434
443
  Object.keys(control).forEach((fieldName) => {
435
- if (fieldName === "family") return;
444
+ if (fieldName === "family" || fieldName === "_originalRowIndex") return;
436
445
  if (params.justificationFields.includes(fieldName) && control[fieldName] !== void 0 && control[fieldName] !== null) {
437
446
  justificationContents.push(control[fieldName]);
438
447
  }
@@ -150,8 +150,8 @@ var init_fileStore = __esm({
150
150
  if (!this.baseDir || this.baseDir === "." || this.baseDir === process.cwd()) {
151
151
  return;
152
152
  }
153
- const lulaConfigPath = join2(this.baseDir, "lula.yaml");
154
- if (!existsSync2(lulaConfigPath)) {
153
+ const lulaConfigPath2 = join2(this.baseDir, "lula.yaml");
154
+ if (!existsSync2(lulaConfigPath2)) {
155
155
  return;
156
156
  }
157
157
  if (!existsSync2(this.controlsDir)) {
@@ -309,6 +309,17 @@ var init_fileStore = __esm({
309
309
  if (!existsSync2(this.controlsDir)) {
310
310
  return [];
311
311
  }
312
+ let controlOrder = null;
313
+ try {
314
+ const lulaConfigPath2 = join2(this.baseDir, "lula.yaml");
315
+ if (existsSync2(lulaConfigPath2)) {
316
+ const content = readFileSync2(lulaConfigPath2, "utf8");
317
+ const metadata = yaml2.load(content);
318
+ controlOrder = metadata?.controlOrder || null;
319
+ }
320
+ } catch (error) {
321
+ console.error(`Failed to load lula.yaml for controlOrder (path: ${lulaConfigPath}):`, error);
322
+ }
312
323
  const entries = readdirSync(this.controlsDir);
313
324
  const yamlFiles = entries.filter((file) => file.endsWith(".yaml"));
314
325
  if (yamlFiles.length > 0) {
@@ -327,7 +338,11 @@ var init_fileStore = __esm({
327
338
  }
328
339
  });
329
340
  const results2 = await Promise.all(promises);
330
- return results2.filter((c) => c !== null);
341
+ const controls2 = results2.filter((c) => c !== null);
342
+ if (controlOrder && controlOrder.length > 0) {
343
+ return this.sortControlsByOrder(controls2, controlOrder);
344
+ }
345
+ return controls2;
331
346
  }
332
347
  const families = entries.filter((name) => {
333
348
  const familyPath = join2(this.controlsDir, name);
@@ -350,7 +365,25 @@ var init_fileStore = __esm({
350
365
  allPromises.push(...familyPromises);
351
366
  }
352
367
  const results = await Promise.all(allPromises);
353
- return results.filter((c) => c !== null);
368
+ const controls = results.filter((c) => c !== null);
369
+ if (controlOrder && controlOrder.length > 0) {
370
+ return this.sortControlsByOrder(controls, controlOrder);
371
+ }
372
+ return controls;
373
+ }
374
+ /**
375
+ * Sort controls based on the provided order array
376
+ */
377
+ sortControlsByOrder(controls, controlOrder) {
378
+ const orderMap = /* @__PURE__ */ new Map();
379
+ controlOrder.forEach((controlId, index) => {
380
+ orderMap.set(controlId, index);
381
+ });
382
+ return controls.sort((a, b) => {
383
+ const aIndex = orderMap.get(a.id) ?? Number.MAX_SAFE_INTEGER;
384
+ const bIndex = orderMap.get(b.id) ?? Number.MAX_SAFE_INTEGER;
385
+ return aIndex - bIndex;
386
+ });
354
387
  }
355
388
  /**
356
389
  * Load mappings from mappings directory
@@ -1470,6 +1503,7 @@ function processSpreadsheetData(rawData, headers, startRowIndex, params) {
1470
1503
  continue;
1471
1504
  }
1472
1505
  const family = extractFamilyFromControlId(controlId);
1506
+ control._originalRowIndex = i;
1473
1507
  control.family = family;
1474
1508
  controls.push(control);
1475
1509
  if (!families.has(family)) {
@@ -1592,6 +1626,7 @@ async function createOutputStructure(processedData, fieldSchema, params) {
1592
1626
  params.controlIdField,
1593
1627
  params.namingConvention
1594
1628
  );
1629
+ const controlOrder = controls.sort((a, b) => (a._originalRowIndex || 0) - (b._originalRowIndex || 0)).map((control) => control[controlIdFieldNameClean]);
1595
1630
  const controlSetData = {
1596
1631
  name: params.controlSetName,
1597
1632
  description: params.controlSetDescription,
@@ -1599,12 +1634,16 @@ async function createOutputStructure(processedData, fieldSchema, params) {
1599
1634
  control_id_field: controlIdFieldNameClean,
1600
1635
  controlCount: controls.length,
1601
1636
  families: uniqueFamilies,
1637
+ controlOrder,
1602
1638
  fieldSchema
1603
1639
  };
1604
1640
  writeFileSync2(join4(baseDir, "lula.yaml"), yaml4.dump(controlSetData));
1605
1641
  const controlsDir = join4(baseDir, "controls");
1606
1642
  const mappingsDir = join4(baseDir, "mappings");
1607
- families.forEach((familyControls, family) => {
1643
+ const sortedFamilies = Array.from(families.entries()).sort(
1644
+ (a, b) => a[0].localeCompare(b[0])
1645
+ );
1646
+ sortedFamilies.forEach(([family, familyControls]) => {
1608
1647
  const familyDir = join4(controlsDir, family);
1609
1648
  const familyMappingsDir = join4(mappingsDir, family);
1610
1649
  if (!existsSync3(familyDir)) {
@@ -1613,7 +1652,10 @@ async function createOutputStructure(processedData, fieldSchema, params) {
1613
1652
  if (!existsSync3(familyMappingsDir)) {
1614
1653
  mkdirSync2(familyMappingsDir, { recursive: true });
1615
1654
  }
1616
- familyControls.forEach((control) => {
1655
+ const sortedFamilyControls = familyControls.sort(
1656
+ (a, b) => (a._originalRowIndex || 0) - (b._originalRowIndex || 0)
1657
+ );
1658
+ sortedFamilyControls.forEach((control) => {
1617
1659
  const controlId = control[controlIdFieldNameClean];
1618
1660
  if (!controlId) {
1619
1661
  console.error("Missing control ID for control:", control);
@@ -1635,7 +1677,7 @@ async function createOutputStructure(processedData, fieldSchema, params) {
1635
1677
  filteredControl.family = control.family;
1636
1678
  }
1637
1679
  Object.keys(control).forEach((fieldName) => {
1638
- if (fieldName === "family") return;
1680
+ if (fieldName === "family" || fieldName === "_originalRowIndex") return;
1639
1681
  if (params.justificationFields.includes(fieldName) && control[fieldName] !== void 0 && control[fieldName] !== null) {
1640
1682
  justificationContents.push(control[fieldName]);
1641
1683
  }
package/dist/index.html CHANGED
@@ -6,28 +6,28 @@
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.BD6MZ_XC.js">
10
- <link rel="modulepreload" href="/_app/immutable/chunks/DztCq-9O.js">
11
- <link rel="modulepreload" href="/_app/immutable/chunks/DmBJsPtc.js">
12
- <link rel="modulepreload" href="/_app/immutable/entry/app.VdrAeFMF.js">
9
+ <link rel="modulepreload" href="/_app/immutable/entry/start.zJmCdi6K.js">
10
+ <link rel="modulepreload" href="/_app/immutable/chunks/CByqgj46.js">
11
+ <link rel="modulepreload" href="/_app/immutable/chunks/BnySH2DD.js">
12
+ <link rel="modulepreload" href="/_app/immutable/entry/app.CLMFUJFD.js">
13
13
  <link rel="modulepreload" href="/_app/immutable/chunks/DsnmJJEf.js">
14
- <link rel="modulepreload" href="/_app/immutable/chunks/BaV6jU6m.js">
15
- <link rel="modulepreload" href="/_app/immutable/chunks/DBdrJbLi.js">
16
- <link rel="modulepreload" href="/_app/immutable/chunks/CynYS-Ma.js">
14
+ <link rel="modulepreload" href="/_app/immutable/chunks/BDFhLgJd.js">
15
+ <link rel="modulepreload" href="/_app/immutable/chunks/6cSSDZaX.js">
16
+ <link rel="modulepreload" href="/_app/immutable/chunks/ipJF3Ffx.js">
17
17
  </head>
18
18
  <body data-sveltekit-preload-data="hover">
19
19
  <div style="display: contents">
20
20
  <script>
21
21
  {
22
- __sveltekit_t1ry3i = {
22
+ __sveltekit_1m4uc3h = {
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.BD6MZ_XC.js"),
30
- import("/_app/immutable/entry/app.VdrAeFMF.js")
29
+ import("/_app/immutable/entry/start.zJmCdi6K.js"),
30
+ import("/_app/immutable/entry/app.CLMFUJFD.js")
31
31
  ]).then(([kit, app]) => {
32
32
  kit.start(app, element);
33
33
  });