@oamm/textor 1.0.10 → 1.0.11
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/bin/textor.js +32 -17
- package/dist/bin/textor.js.map +1 -1
- package/dist/index.cjs +31 -17
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +31 -17
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/bin/textor.js
CHANGED
|
@@ -647,7 +647,8 @@ async function verifyFileIntegrity(filePath, expectedHash, options = {}) {
|
|
|
647
647
|
acceptChanges = false,
|
|
648
648
|
normalization = 'normalizeEOL',
|
|
649
649
|
owner = null,
|
|
650
|
-
actualOwner = null
|
|
650
|
+
actualOwner = null,
|
|
651
|
+
signatures = []
|
|
651
652
|
} = options;
|
|
652
653
|
|
|
653
654
|
if (force) return { valid: true };
|
|
@@ -660,7 +661,7 @@ async function verifyFileIntegrity(filePath, expectedHash, options = {}) {
|
|
|
660
661
|
};
|
|
661
662
|
}
|
|
662
663
|
|
|
663
|
-
const isGenerated = await isTextorGenerated(filePath);
|
|
664
|
+
const isGenerated = await isTextorGenerated(filePath, signatures);
|
|
664
665
|
if (!isGenerated) {
|
|
665
666
|
return {
|
|
666
667
|
valid: false,
|
|
@@ -693,7 +694,7 @@ async function verifyFileIntegrity(filePath, expectedHash, options = {}) {
|
|
|
693
694
|
}
|
|
694
695
|
|
|
695
696
|
async function safeDelete(filePath, options = {}) {
|
|
696
|
-
const { force = false, expectedHash = null, acceptChanges = false, owner = null, actualOwner = null } = options;
|
|
697
|
+
const { force = false, expectedHash = null, acceptChanges = false, owner = null, actualOwner = null, signatures = [] } = options;
|
|
697
698
|
|
|
698
699
|
if (!existsSync(filePath)) {
|
|
699
700
|
return { deleted: false, reason: 'not-found' };
|
|
@@ -703,7 +704,8 @@ async function safeDelete(filePath, options = {}) {
|
|
|
703
704
|
force,
|
|
704
705
|
acceptChanges,
|
|
705
706
|
owner,
|
|
706
|
-
actualOwner
|
|
707
|
+
actualOwner,
|
|
708
|
+
signatures
|
|
707
709
|
});
|
|
708
710
|
if (!integrity.valid) {
|
|
709
711
|
return { deleted: false, reason: integrity.reason, message: integrity.message };
|
|
@@ -745,7 +747,8 @@ async function isSafeToDeleteDir(dirPath, stateFiles = {}, options = {}) {
|
|
|
745
747
|
const fileState = stateFiles[normalizedPath];
|
|
746
748
|
const integrity = await verifyFileIntegrity(filePath, fileState?.hash, {
|
|
747
749
|
...options,
|
|
748
|
-
actualOwner: fileState?.owner
|
|
750
|
+
actualOwner: fileState?.owner,
|
|
751
|
+
signatures: options.signatures || []
|
|
749
752
|
});
|
|
750
753
|
return integrity.valid;
|
|
751
754
|
})
|
|
@@ -841,7 +844,8 @@ async function safeMove(fromPath, toPath, options = {}) {
|
|
|
841
844
|
acceptChanges,
|
|
842
845
|
normalization,
|
|
843
846
|
owner,
|
|
844
|
-
actualOwner
|
|
847
|
+
actualOwner,
|
|
848
|
+
signatures: options.signatures || []
|
|
845
849
|
});
|
|
846
850
|
if (!integrity.valid) {
|
|
847
851
|
throw new Error(integrity.message);
|
|
@@ -2060,7 +2064,8 @@ async function addSectionCommand(route, featurePath, options) {
|
|
|
2060
2064
|
|
|
2061
2065
|
if (routeFilePath) {
|
|
2062
2066
|
if (existsSync(routeFilePath)) {
|
|
2063
|
-
const
|
|
2067
|
+
const configSignatures = Object.values(config.signatures || {});
|
|
2068
|
+
const isGenerated = await isTextorGenerated(routeFilePath, configSignatures);
|
|
2064
2069
|
if (!isGenerated && !options.force) {
|
|
2065
2070
|
throw new Error(`File already exists: ${routeFilePath}\nUse --force to overwrite.`);
|
|
2066
2071
|
}
|
|
@@ -2526,6 +2531,7 @@ async function removeSectionCommand(route, featurePath, options) {
|
|
|
2526
2531
|
|
|
2527
2532
|
const pagesRoot = resolvePath(config, 'pages');
|
|
2528
2533
|
const featuresRoot = resolvePath(config, 'features');
|
|
2534
|
+
const configSignatures = Object.values(config.signatures || {});
|
|
2529
2535
|
|
|
2530
2536
|
// Find route file in state if possible
|
|
2531
2537
|
let routeFilePath = null;
|
|
@@ -2575,7 +2581,8 @@ async function removeSectionCommand(route, featurePath, options) {
|
|
|
2575
2581
|
acceptChanges: options.acceptChanges,
|
|
2576
2582
|
normalization: config.hashing?.normalization,
|
|
2577
2583
|
owner: normalizedRoute,
|
|
2578
|
-
actualOwner: fileState?.owner
|
|
2584
|
+
actualOwner: fileState?.owner,
|
|
2585
|
+
signatures: configSignatures
|
|
2579
2586
|
});
|
|
2580
2587
|
|
|
2581
2588
|
if (result.deleted) {
|
|
@@ -2592,7 +2599,8 @@ async function removeSectionCommand(route, featurePath, options) {
|
|
|
2592
2599
|
stateFiles: state.files,
|
|
2593
2600
|
acceptChanges: options.acceptChanges,
|
|
2594
2601
|
normalization: config.hashing?.normalization,
|
|
2595
|
-
owner: normalizedRoute
|
|
2602
|
+
owner: normalizedRoute,
|
|
2603
|
+
signatures: configSignatures
|
|
2596
2604
|
});
|
|
2597
2605
|
|
|
2598
2606
|
if (result.deleted) {
|
|
@@ -2819,6 +2827,7 @@ async function moveSectionCommand(fromRoute, fromFeature, toRoute, toFeature, op
|
|
|
2819
2827
|
|
|
2820
2828
|
const pagesRoot = resolvePath(config, 'pages');
|
|
2821
2829
|
const featuresRoot = resolvePath(config, 'features');
|
|
2830
|
+
const configSignatures = Object.values(config.signatures || {});
|
|
2822
2831
|
|
|
2823
2832
|
const fromSection = findSection(state, actualFromRoute);
|
|
2824
2833
|
const routeExtension = (fromSection && fromSection.extension) || config.naming.routeExtension;
|
|
@@ -2860,7 +2869,8 @@ async function moveSectionCommand(fromRoute, fromFeature, toRoute, toFeature, op
|
|
|
2860
2869
|
expectedHash: routeFileState?.hash,
|
|
2861
2870
|
acceptChanges: options.acceptChanges,
|
|
2862
2871
|
owner: normalizedFromRoute,
|
|
2863
|
-
actualOwner: routeFileState?.owner
|
|
2872
|
+
actualOwner: routeFileState?.owner,
|
|
2873
|
+
signatures: configSignatures
|
|
2864
2874
|
});
|
|
2865
2875
|
movedFiles.push({ from: fromRoutePath, to: toRoutePath });
|
|
2866
2876
|
|
|
@@ -2957,7 +2967,8 @@ async function moveSectionCommand(fromRoute, fromFeature, toRoute, toFeature, op
|
|
|
2957
2967
|
...options,
|
|
2958
2968
|
fromName: fromFeatureComponentName,
|
|
2959
2969
|
toName: toFeatureComponentName,
|
|
2960
|
-
owner: normalizedFromRoute
|
|
2970
|
+
owner: normalizedFromRoute,
|
|
2971
|
+
signatures: configSignatures
|
|
2961
2972
|
});
|
|
2962
2973
|
movedFiles.push({ from: fromFeaturePath, to: toFeaturePath });
|
|
2963
2974
|
|
|
@@ -3666,6 +3677,7 @@ async function createComponentCommand(componentName, options) {
|
|
|
3666
3677
|
async function removeComponentCommand(identifier, options) {
|
|
3667
3678
|
try {
|
|
3668
3679
|
const config = await loadConfig();
|
|
3680
|
+
const configSignatures = Object.values(config.signatures || {});
|
|
3669
3681
|
|
|
3670
3682
|
if (config.git?.requireCleanRepo && !await isRepoClean()) {
|
|
3671
3683
|
throw new Error('Git repository is not clean. Please commit or stash your changes before proceeding.');
|
|
@@ -3695,7 +3707,8 @@ async function removeComponentCommand(identifier, options) {
|
|
|
3695
3707
|
stateFiles: state.files,
|
|
3696
3708
|
acceptChanges: options.acceptChanges,
|
|
3697
3709
|
normalization: config.hashing?.normalization,
|
|
3698
|
-
owner: identifier
|
|
3710
|
+
owner: identifier,
|
|
3711
|
+
signatures: configSignatures
|
|
3699
3712
|
});
|
|
3700
3713
|
|
|
3701
3714
|
if (result.deleted || (result.reason === 'not-found' && component)) {
|
|
@@ -3744,7 +3757,8 @@ async function listSectionsCommand() {
|
|
|
3744
3757
|
console.log(' No pages directory found.');
|
|
3745
3758
|
} else {
|
|
3746
3759
|
const extensions = [config.naming.routeExtension, '.ts', '.js'];
|
|
3747
|
-
const
|
|
3760
|
+
const signatures = Object.values(config.signatures || {});
|
|
3761
|
+
const sections = await findGeneratedFiles(pagesRoot, extensions, signatures);
|
|
3748
3762
|
|
|
3749
3763
|
if (sections.length === 0) {
|
|
3750
3764
|
console.log(' No Textor-managed sections found.');
|
|
@@ -3848,7 +3862,7 @@ async function listSectionsCommand() {
|
|
|
3848
3862
|
}
|
|
3849
3863
|
}
|
|
3850
3864
|
|
|
3851
|
-
async function findGeneratedFiles(dir, extensions) {
|
|
3865
|
+
async function findGeneratedFiles(dir, extensions, signatures) {
|
|
3852
3866
|
const results = [];
|
|
3853
3867
|
const entries = await readdir(dir);
|
|
3854
3868
|
const exts = Array.isArray(extensions) ? extensions : [extensions];
|
|
@@ -3858,9 +3872,9 @@ async function findGeneratedFiles(dir, extensions) {
|
|
|
3858
3872
|
const stats = await stat(fullPath);
|
|
3859
3873
|
|
|
3860
3874
|
if (stats.isDirectory()) {
|
|
3861
|
-
results.push(...await findGeneratedFiles(fullPath, exts));
|
|
3875
|
+
results.push(...await findGeneratedFiles(fullPath, exts, signatures));
|
|
3862
3876
|
} else if (exts.some(ext => entry.endsWith(ext))) {
|
|
3863
|
-
if (await isTextorGenerated(fullPath)) {
|
|
3877
|
+
if (await isTextorGenerated(fullPath, signatures)) {
|
|
3864
3878
|
results.push(fullPath);
|
|
3865
3879
|
}
|
|
3866
3880
|
}
|
|
@@ -3918,11 +3932,12 @@ async function validateStateCommand(options) {
|
|
|
3918
3932
|
|
|
3919
3933
|
if (options.fix) {
|
|
3920
3934
|
let fixedCount = 0;
|
|
3935
|
+
const signatures = Object.values(config.signatures || {});
|
|
3921
3936
|
|
|
3922
3937
|
// Fix modified files if they still have the Textor signature
|
|
3923
3938
|
for (const mod of results.modified) {
|
|
3924
3939
|
const fullPath = path.join(process.cwd(), mod.path);
|
|
3925
|
-
if (await isTextorGenerated(fullPath)) {
|
|
3940
|
+
if (await isTextorGenerated(fullPath, signatures)) {
|
|
3926
3941
|
state.files[mod.path].hash = mod.newHash;
|
|
3927
3942
|
fixedCount++;
|
|
3928
3943
|
}
|
package/dist/bin/textor.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"textor.js","sources":[],"sourcesContent":[],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"textor.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;"}
|
package/dist/index.cjs
CHANGED
|
@@ -578,7 +578,7 @@ async function isTextorGenerated(filePath, customSignatures = []) {
|
|
|
578
578
|
}
|
|
579
579
|
}
|
|
580
580
|
async function verifyFileIntegrity(filePath, expectedHash, options = {}) {
|
|
581
|
-
const { force = false, acceptChanges = false, normalization = 'normalizeEOL', owner = null, actualOwner = null } = options;
|
|
581
|
+
const { force = false, acceptChanges = false, normalization = 'normalizeEOL', owner = null, actualOwner = null, signatures = [] } = options;
|
|
582
582
|
if (force)
|
|
583
583
|
return { valid: true };
|
|
584
584
|
if (owner && actualOwner && owner !== actualOwner) {
|
|
@@ -588,7 +588,7 @@ async function verifyFileIntegrity(filePath, expectedHash, options = {}) {
|
|
|
588
588
|
message: `Refusing to operate on ${filePath} - owned by ${actualOwner}, but requested by ${owner}. Use --force to override.`
|
|
589
589
|
};
|
|
590
590
|
}
|
|
591
|
-
const isGenerated = await isTextorGenerated(filePath);
|
|
591
|
+
const isGenerated = await isTextorGenerated(filePath, signatures);
|
|
592
592
|
if (!isGenerated) {
|
|
593
593
|
return {
|
|
594
594
|
valid: false,
|
|
@@ -617,7 +617,7 @@ async function verifyFileIntegrity(filePath, expectedHash, options = {}) {
|
|
|
617
617
|
return { valid: true };
|
|
618
618
|
}
|
|
619
619
|
async function safeDelete(filePath, options = {}) {
|
|
620
|
-
const { force = false, expectedHash = null, acceptChanges = false, owner = null, actualOwner = null } = options;
|
|
620
|
+
const { force = false, expectedHash = null, acceptChanges = false, owner = null, actualOwner = null, signatures = [] } = options;
|
|
621
621
|
if (!fs.existsSync(filePath)) {
|
|
622
622
|
return { deleted: false, reason: 'not-found' };
|
|
623
623
|
}
|
|
@@ -625,7 +625,8 @@ async function safeDelete(filePath, options = {}) {
|
|
|
625
625
|
force,
|
|
626
626
|
acceptChanges,
|
|
627
627
|
owner,
|
|
628
|
-
actualOwner
|
|
628
|
+
actualOwner,
|
|
629
|
+
signatures
|
|
629
630
|
});
|
|
630
631
|
if (!integrity.valid) {
|
|
631
632
|
return { deleted: false, reason: integrity.reason, message: integrity.message };
|
|
@@ -657,7 +658,8 @@ async function isSafeToDeleteDir(dirPath, stateFiles = {}, options = {}) {
|
|
|
657
658
|
const fileState = stateFiles[normalizedPath];
|
|
658
659
|
const integrity = await verifyFileIntegrity(filePath, fileState?.hash, {
|
|
659
660
|
...options,
|
|
660
|
-
actualOwner: fileState?.owner
|
|
661
|
+
actualOwner: fileState?.owner,
|
|
662
|
+
signatures: options.signatures || []
|
|
661
663
|
});
|
|
662
664
|
return integrity.valid;
|
|
663
665
|
}));
|
|
@@ -722,7 +724,8 @@ async function safeMove(fromPath, toPath, options = {}) {
|
|
|
722
724
|
acceptChanges,
|
|
723
725
|
normalization,
|
|
724
726
|
owner,
|
|
725
|
-
actualOwner
|
|
727
|
+
actualOwner,
|
|
728
|
+
signatures: options.signatures || []
|
|
726
729
|
});
|
|
727
730
|
if (!integrity.valid) {
|
|
728
731
|
throw new Error(integrity.message);
|
|
@@ -1774,7 +1777,8 @@ async function addSectionCommand(route, featurePath, options) {
|
|
|
1774
1777
|
}
|
|
1775
1778
|
if (routeFilePath) {
|
|
1776
1779
|
if (fs.existsSync(routeFilePath)) {
|
|
1777
|
-
const
|
|
1780
|
+
const configSignatures = Object.values(config.signatures || {});
|
|
1781
|
+
const isGenerated = await isTextorGenerated(routeFilePath, configSignatures);
|
|
1778
1782
|
if (!isGenerated && !options.force) {
|
|
1779
1783
|
throw new Error(`File already exists: ${routeFilePath}\nUse --force to overwrite.`);
|
|
1780
1784
|
}
|
|
@@ -2154,6 +2158,7 @@ async function removeSectionCommand(route, featurePath, options) {
|
|
|
2154
2158
|
const normalizedFeaturePath = featureToDirectoryPath(targetFeaturePath);
|
|
2155
2159
|
const pagesRoot = resolvePath(config, 'pages');
|
|
2156
2160
|
const featuresRoot = resolvePath(config, 'features');
|
|
2161
|
+
const configSignatures = Object.values(config.signatures || {});
|
|
2157
2162
|
// Find route file in state if possible
|
|
2158
2163
|
let routeFilePath = null;
|
|
2159
2164
|
const routeRelPath = Object.keys(state.files).find(f => {
|
|
@@ -2195,7 +2200,8 @@ async function removeSectionCommand(route, featurePath, options) {
|
|
|
2195
2200
|
acceptChanges: options.acceptChanges,
|
|
2196
2201
|
normalization: config.hashing?.normalization,
|
|
2197
2202
|
owner: normalizedRoute,
|
|
2198
|
-
actualOwner: fileState?.owner
|
|
2203
|
+
actualOwner: fileState?.owner,
|
|
2204
|
+
signatures: configSignatures
|
|
2199
2205
|
});
|
|
2200
2206
|
if (result.deleted) {
|
|
2201
2207
|
deletedFiles.push(routeFilePath);
|
|
@@ -2211,7 +2217,8 @@ async function removeSectionCommand(route, featurePath, options) {
|
|
|
2211
2217
|
stateFiles: state.files,
|
|
2212
2218
|
acceptChanges: options.acceptChanges,
|
|
2213
2219
|
normalization: config.hashing?.normalization,
|
|
2214
|
-
owner: normalizedRoute
|
|
2220
|
+
owner: normalizedRoute,
|
|
2221
|
+
signatures: configSignatures
|
|
2215
2222
|
});
|
|
2216
2223
|
if (result.deleted) {
|
|
2217
2224
|
deletedDirs.push(featureDirPath);
|
|
@@ -2407,6 +2414,7 @@ async function moveSectionCommand(fromRoute, fromFeature, toRoute, toFeature, op
|
|
|
2407
2414
|
const normalizedToFeature = actualToFeature ? featureToDirectoryPath(actualToFeature) : null;
|
|
2408
2415
|
const pagesRoot = resolvePath(config, 'pages');
|
|
2409
2416
|
const featuresRoot = resolvePath(config, 'features');
|
|
2417
|
+
const configSignatures = Object.values(config.signatures || {});
|
|
2410
2418
|
const fromSection = findSection(state, actualFromRoute);
|
|
2411
2419
|
const routeExtension = (fromSection && fromSection.extension) || config.naming.routeExtension;
|
|
2412
2420
|
const fromRouteFile = routeToFilePath(normalizedFromRoute, {
|
|
@@ -2439,7 +2447,8 @@ async function moveSectionCommand(fromRoute, fromFeature, toRoute, toFeature, op
|
|
|
2439
2447
|
expectedHash: routeFileState?.hash,
|
|
2440
2448
|
acceptChanges: options.acceptChanges,
|
|
2441
2449
|
owner: normalizedFromRoute,
|
|
2442
|
-
actualOwner: routeFileState?.owner
|
|
2450
|
+
actualOwner: routeFileState?.owner,
|
|
2451
|
+
signatures: configSignatures
|
|
2443
2452
|
});
|
|
2444
2453
|
movedFiles.push({ from: fromRoutePath, to: toRoutePath });
|
|
2445
2454
|
// Update state for moved route file
|
|
@@ -2518,7 +2527,8 @@ async function moveSectionCommand(fromRoute, fromFeature, toRoute, toFeature, op
|
|
|
2518
2527
|
...options,
|
|
2519
2528
|
fromName: fromFeatureComponentName,
|
|
2520
2529
|
toName: toFeatureComponentName,
|
|
2521
|
-
owner: normalizedFromRoute
|
|
2530
|
+
owner: normalizedFromRoute,
|
|
2531
|
+
signatures: configSignatures
|
|
2522
2532
|
});
|
|
2523
2533
|
movedFiles.push({ from: fromFeaturePath, to: toFeaturePath });
|
|
2524
2534
|
await cleanupEmptyDirs(path.dirname(fromFeaturePath), featuresRoot);
|
|
@@ -3047,6 +3057,7 @@ async function createComponentCommand(componentName, options) {
|
|
|
3047
3057
|
async function removeComponentCommand(identifier, options) {
|
|
3048
3058
|
try {
|
|
3049
3059
|
const config = await loadConfig();
|
|
3060
|
+
const configSignatures = Object.values(config.signatures || {});
|
|
3050
3061
|
if (config.git?.requireCleanRepo && !await isRepoClean()) {
|
|
3051
3062
|
throw new Error('Git repository is not clean. Please commit or stash your changes before proceeding.');
|
|
3052
3063
|
}
|
|
@@ -3071,7 +3082,8 @@ async function removeComponentCommand(identifier, options) {
|
|
|
3071
3082
|
stateFiles: state.files,
|
|
3072
3083
|
acceptChanges: options.acceptChanges,
|
|
3073
3084
|
normalization: config.hashing?.normalization,
|
|
3074
|
-
owner: identifier
|
|
3085
|
+
owner: identifier,
|
|
3086
|
+
signatures: configSignatures
|
|
3075
3087
|
});
|
|
3076
3088
|
if (result.deleted || (result.reason === 'not-found' && component)) {
|
|
3077
3089
|
if (result.deleted) {
|
|
@@ -3120,7 +3132,8 @@ async function listSectionsCommand() {
|
|
|
3120
3132
|
}
|
|
3121
3133
|
else {
|
|
3122
3134
|
const extensions = [config.naming.routeExtension, '.ts', '.js'];
|
|
3123
|
-
const
|
|
3135
|
+
const signatures = Object.values(config.signatures || {});
|
|
3136
|
+
const sections = await findGeneratedFiles(pagesRoot, extensions, signatures);
|
|
3124
3137
|
if (sections.length === 0) {
|
|
3125
3138
|
console.log(' No Textor-managed sections found.');
|
|
3126
3139
|
}
|
|
@@ -3215,7 +3228,7 @@ async function listSectionsCommand() {
|
|
|
3215
3228
|
process.exit(1);
|
|
3216
3229
|
}
|
|
3217
3230
|
}
|
|
3218
|
-
async function findGeneratedFiles(dir, extensions) {
|
|
3231
|
+
async function findGeneratedFiles(dir, extensions, signatures) {
|
|
3219
3232
|
const results = [];
|
|
3220
3233
|
const entries = await promises.readdir(dir);
|
|
3221
3234
|
const exts = Array.isArray(extensions) ? extensions : [extensions];
|
|
@@ -3223,10 +3236,10 @@ async function findGeneratedFiles(dir, extensions) {
|
|
|
3223
3236
|
const fullPath = path.join(dir, entry);
|
|
3224
3237
|
const stats = await promises.stat(fullPath);
|
|
3225
3238
|
if (stats.isDirectory()) {
|
|
3226
|
-
results.push(...await findGeneratedFiles(fullPath, exts));
|
|
3239
|
+
results.push(...await findGeneratedFiles(fullPath, exts, signatures));
|
|
3227
3240
|
}
|
|
3228
3241
|
else if (exts.some(ext => entry.endsWith(ext))) {
|
|
3229
|
-
if (await isTextorGenerated(fullPath)) {
|
|
3242
|
+
if (await isTextorGenerated(fullPath, signatures)) {
|
|
3230
3243
|
results.push(fullPath);
|
|
3231
3244
|
}
|
|
3232
3245
|
}
|
|
@@ -3275,10 +3288,11 @@ async function validateStateCommand(options) {
|
|
|
3275
3288
|
}
|
|
3276
3289
|
if (options.fix) {
|
|
3277
3290
|
let fixedCount = 0;
|
|
3291
|
+
const signatures = Object.values(config.signatures || {});
|
|
3278
3292
|
// Fix modified files if they still have the Textor signature
|
|
3279
3293
|
for (const mod of results.modified) {
|
|
3280
3294
|
const fullPath = path.join(process.cwd(), mod.path);
|
|
3281
|
-
if (await isTextorGenerated(fullPath)) {
|
|
3295
|
+
if (await isTextorGenerated(fullPath, signatures)) {
|
|
3282
3296
|
state.files[mod.path].hash = mod.newHash;
|
|
3283
3297
|
fixedCount++;
|
|
3284
3298
|
}
|