@oamm/textor 1.0.10 → 1.0.12
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 +51 -22
- package/dist/bin/textor.js.map +1 -1
- package/dist/index.cjs +53 -22
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +53 -22
- 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,9 +2064,14 @@ 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
|
+
if (routeFilePath.endsWith('.astro')) {
|
|
2071
|
+
console.log(`⚠ File already exists and is not managed by Textor. Adopting and merging: ${routeFilePath}`);
|
|
2072
|
+
} else {
|
|
2073
|
+
throw new Error(`File already exists: ${routeFilePath}\nUse --force to overwrite.`);
|
|
2074
|
+
}
|
|
2066
2075
|
}
|
|
2067
2076
|
}
|
|
2068
2077
|
}
|
|
@@ -2526,6 +2535,7 @@ async function removeSectionCommand(route, featurePath, options) {
|
|
|
2526
2535
|
|
|
2527
2536
|
const pagesRoot = resolvePath(config, 'pages');
|
|
2528
2537
|
const featuresRoot = resolvePath(config, 'features');
|
|
2538
|
+
const configSignatures = Object.values(config.signatures || {});
|
|
2529
2539
|
|
|
2530
2540
|
// Find route file in state if possible
|
|
2531
2541
|
let routeFilePath = null;
|
|
@@ -2575,7 +2585,8 @@ async function removeSectionCommand(route, featurePath, options) {
|
|
|
2575
2585
|
acceptChanges: options.acceptChanges,
|
|
2576
2586
|
normalization: config.hashing?.normalization,
|
|
2577
2587
|
owner: normalizedRoute,
|
|
2578
|
-
actualOwner: fileState?.owner
|
|
2588
|
+
actualOwner: fileState?.owner,
|
|
2589
|
+
signatures: configSignatures
|
|
2579
2590
|
});
|
|
2580
2591
|
|
|
2581
2592
|
if (result.deleted) {
|
|
@@ -2592,7 +2603,8 @@ async function removeSectionCommand(route, featurePath, options) {
|
|
|
2592
2603
|
stateFiles: state.files,
|
|
2593
2604
|
acceptChanges: options.acceptChanges,
|
|
2594
2605
|
normalization: config.hashing?.normalization,
|
|
2595
|
-
owner: normalizedRoute
|
|
2606
|
+
owner: normalizedRoute,
|
|
2607
|
+
signatures: configSignatures
|
|
2596
2608
|
});
|
|
2597
2609
|
|
|
2598
2610
|
if (result.deleted) {
|
|
@@ -2819,6 +2831,7 @@ async function moveSectionCommand(fromRoute, fromFeature, toRoute, toFeature, op
|
|
|
2819
2831
|
|
|
2820
2832
|
const pagesRoot = resolvePath(config, 'pages');
|
|
2821
2833
|
const featuresRoot = resolvePath(config, 'features');
|
|
2834
|
+
const configSignatures = Object.values(config.signatures || {});
|
|
2822
2835
|
|
|
2823
2836
|
const fromSection = findSection(state, actualFromRoute);
|
|
2824
2837
|
const routeExtension = (fromSection && fromSection.extension) || config.naming.routeExtension;
|
|
@@ -2860,7 +2873,8 @@ async function moveSectionCommand(fromRoute, fromFeature, toRoute, toFeature, op
|
|
|
2860
2873
|
expectedHash: routeFileState?.hash,
|
|
2861
2874
|
acceptChanges: options.acceptChanges,
|
|
2862
2875
|
owner: normalizedFromRoute,
|
|
2863
|
-
actualOwner: routeFileState?.owner
|
|
2876
|
+
actualOwner: routeFileState?.owner,
|
|
2877
|
+
signatures: configSignatures
|
|
2864
2878
|
});
|
|
2865
2879
|
movedFiles.push({ from: fromRoutePath, to: toRoutePath });
|
|
2866
2880
|
|
|
@@ -2957,7 +2971,8 @@ async function moveSectionCommand(fromRoute, fromFeature, toRoute, toFeature, op
|
|
|
2957
2971
|
...options,
|
|
2958
2972
|
fromName: fromFeatureComponentName,
|
|
2959
2973
|
toName: toFeatureComponentName,
|
|
2960
|
-
owner: normalizedFromRoute
|
|
2974
|
+
owner: normalizedFromRoute,
|
|
2975
|
+
signatures: configSignatures
|
|
2961
2976
|
});
|
|
2962
2977
|
movedFiles.push({ from: fromFeaturePath, to: toFeaturePath });
|
|
2963
2978
|
|
|
@@ -3666,6 +3681,7 @@ async function createComponentCommand(componentName, options) {
|
|
|
3666
3681
|
async function removeComponentCommand(identifier, options) {
|
|
3667
3682
|
try {
|
|
3668
3683
|
const config = await loadConfig();
|
|
3684
|
+
const configSignatures = Object.values(config.signatures || {});
|
|
3669
3685
|
|
|
3670
3686
|
if (config.git?.requireCleanRepo && !await isRepoClean()) {
|
|
3671
3687
|
throw new Error('Git repository is not clean. Please commit or stash your changes before proceeding.');
|
|
@@ -3695,7 +3711,8 @@ async function removeComponentCommand(identifier, options) {
|
|
|
3695
3711
|
stateFiles: state.files,
|
|
3696
3712
|
acceptChanges: options.acceptChanges,
|
|
3697
3713
|
normalization: config.hashing?.normalization,
|
|
3698
|
-
owner: identifier
|
|
3714
|
+
owner: identifier,
|
|
3715
|
+
signatures: configSignatures
|
|
3699
3716
|
});
|
|
3700
3717
|
|
|
3701
3718
|
if (result.deleted || (result.reason === 'not-found' && component)) {
|
|
@@ -3744,7 +3761,8 @@ async function listSectionsCommand() {
|
|
|
3744
3761
|
console.log(' No pages directory found.');
|
|
3745
3762
|
} else {
|
|
3746
3763
|
const extensions = [config.naming.routeExtension, '.ts', '.js'];
|
|
3747
|
-
const
|
|
3764
|
+
const signatures = Object.values(config.signatures || {});
|
|
3765
|
+
const sections = await findGeneratedFiles(pagesRoot, extensions, signatures);
|
|
3748
3766
|
|
|
3749
3767
|
if (sections.length === 0) {
|
|
3750
3768
|
console.log(' No Textor-managed sections found.');
|
|
@@ -3848,7 +3866,7 @@ async function listSectionsCommand() {
|
|
|
3848
3866
|
}
|
|
3849
3867
|
}
|
|
3850
3868
|
|
|
3851
|
-
async function findGeneratedFiles(dir, extensions) {
|
|
3869
|
+
async function findGeneratedFiles(dir, extensions, signatures) {
|
|
3852
3870
|
const results = [];
|
|
3853
3871
|
const entries = await readdir(dir);
|
|
3854
3872
|
const exts = Array.isArray(extensions) ? extensions : [extensions];
|
|
@@ -3858,9 +3876,9 @@ async function findGeneratedFiles(dir, extensions) {
|
|
|
3858
3876
|
const stats = await stat(fullPath);
|
|
3859
3877
|
|
|
3860
3878
|
if (stats.isDirectory()) {
|
|
3861
|
-
results.push(...await findGeneratedFiles(fullPath, exts));
|
|
3879
|
+
results.push(...await findGeneratedFiles(fullPath, exts, signatures));
|
|
3862
3880
|
} else if (exts.some(ext => entry.endsWith(ext))) {
|
|
3863
|
-
if (await isTextorGenerated(fullPath)) {
|
|
3881
|
+
if (await isTextorGenerated(fullPath, signatures)) {
|
|
3864
3882
|
results.push(fullPath);
|
|
3865
3883
|
}
|
|
3866
3884
|
}
|
|
@@ -3918,11 +3936,12 @@ async function validateStateCommand(options) {
|
|
|
3918
3936
|
|
|
3919
3937
|
if (options.fix) {
|
|
3920
3938
|
let fixedCount = 0;
|
|
3939
|
+
const signatures = Object.values(config.signatures || {});
|
|
3921
3940
|
|
|
3922
3941
|
// Fix modified files if they still have the Textor signature
|
|
3923
3942
|
for (const mod of results.modified) {
|
|
3924
3943
|
const fullPath = path.join(process.cwd(), mod.path);
|
|
3925
|
-
if (await isTextorGenerated(fullPath)) {
|
|
3944
|
+
if (await isTextorGenerated(fullPath, signatures)) {
|
|
3926
3945
|
state.files[mod.path].hash = mod.newHash;
|
|
3927
3946
|
fixedCount++;
|
|
3928
3947
|
}
|
|
@@ -4348,8 +4367,9 @@ async function adoptFile(relPath, config, state, options) {
|
|
|
4348
4367
|
else if (ext === '.js' || ext === '.jsx') signature = config.signatures.javascript;
|
|
4349
4368
|
|
|
4350
4369
|
let finalContent = content;
|
|
4370
|
+
const shouldAddSignature = signature && !content.includes(signature) && options.signature !== false;
|
|
4351
4371
|
|
|
4352
|
-
if (
|
|
4372
|
+
if (shouldAddSignature) {
|
|
4353
4373
|
if (options.dryRun) {
|
|
4354
4374
|
console.log(` ~ Would add signature to ${relPath}`);
|
|
4355
4375
|
} else {
|
|
@@ -4359,9 +4379,17 @@ async function adoptFile(relPath, config, state, options) {
|
|
|
4359
4379
|
}
|
|
4360
4380
|
} else {
|
|
4361
4381
|
if (options.dryRun) {
|
|
4362
|
-
|
|
4382
|
+
if (signature && !content.includes(signature) && options.signature === false) {
|
|
4383
|
+
console.log(` + Would adopt without signature (explicitly requested): ${relPath}`);
|
|
4384
|
+
} else {
|
|
4385
|
+
console.log(` + Would adopt (already has signature or no signature for ext): ${relPath}`);
|
|
4386
|
+
}
|
|
4363
4387
|
} else {
|
|
4364
|
-
|
|
4388
|
+
if (signature && !content.includes(signature) && options.signature === false) {
|
|
4389
|
+
console.log(` + Adopting without signature (explicitly requested): ${relPath}`);
|
|
4390
|
+
} else {
|
|
4391
|
+
console.log(` + Adopting: ${relPath}`);
|
|
4392
|
+
}
|
|
4365
4393
|
}
|
|
4366
4394
|
}
|
|
4367
4395
|
|
|
@@ -4371,7 +4399,8 @@ async function adoptFile(relPath, config, state, options) {
|
|
|
4371
4399
|
kind: inferKind(relPath, config),
|
|
4372
4400
|
hash: hash,
|
|
4373
4401
|
timestamp: new Date().toISOString(),
|
|
4374
|
-
synced: true
|
|
4402
|
+
synced: true,
|
|
4403
|
+
hasSignature: options.signature !== false
|
|
4375
4404
|
};
|
|
4376
4405
|
}
|
|
4377
4406
|
|
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,9 +1777,15 @@ 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
|
+
if (routeFilePath.endsWith('.astro')) {
|
|
1784
|
+
console.log(`⚠ File already exists and is not managed by Textor. Adopting and merging: ${routeFilePath}`);
|
|
1785
|
+
}
|
|
1786
|
+
else {
|
|
1787
|
+
throw new Error(`File already exists: ${routeFilePath}\nUse --force to overwrite.`);
|
|
1788
|
+
}
|
|
1780
1789
|
}
|
|
1781
1790
|
}
|
|
1782
1791
|
}
|
|
@@ -2154,6 +2163,7 @@ async function removeSectionCommand(route, featurePath, options) {
|
|
|
2154
2163
|
const normalizedFeaturePath = featureToDirectoryPath(targetFeaturePath);
|
|
2155
2164
|
const pagesRoot = resolvePath(config, 'pages');
|
|
2156
2165
|
const featuresRoot = resolvePath(config, 'features');
|
|
2166
|
+
const configSignatures = Object.values(config.signatures || {});
|
|
2157
2167
|
// Find route file in state if possible
|
|
2158
2168
|
let routeFilePath = null;
|
|
2159
2169
|
const routeRelPath = Object.keys(state.files).find(f => {
|
|
@@ -2195,7 +2205,8 @@ async function removeSectionCommand(route, featurePath, options) {
|
|
|
2195
2205
|
acceptChanges: options.acceptChanges,
|
|
2196
2206
|
normalization: config.hashing?.normalization,
|
|
2197
2207
|
owner: normalizedRoute,
|
|
2198
|
-
actualOwner: fileState?.owner
|
|
2208
|
+
actualOwner: fileState?.owner,
|
|
2209
|
+
signatures: configSignatures
|
|
2199
2210
|
});
|
|
2200
2211
|
if (result.deleted) {
|
|
2201
2212
|
deletedFiles.push(routeFilePath);
|
|
@@ -2211,7 +2222,8 @@ async function removeSectionCommand(route, featurePath, options) {
|
|
|
2211
2222
|
stateFiles: state.files,
|
|
2212
2223
|
acceptChanges: options.acceptChanges,
|
|
2213
2224
|
normalization: config.hashing?.normalization,
|
|
2214
|
-
owner: normalizedRoute
|
|
2225
|
+
owner: normalizedRoute,
|
|
2226
|
+
signatures: configSignatures
|
|
2215
2227
|
});
|
|
2216
2228
|
if (result.deleted) {
|
|
2217
2229
|
deletedDirs.push(featureDirPath);
|
|
@@ -2407,6 +2419,7 @@ async function moveSectionCommand(fromRoute, fromFeature, toRoute, toFeature, op
|
|
|
2407
2419
|
const normalizedToFeature = actualToFeature ? featureToDirectoryPath(actualToFeature) : null;
|
|
2408
2420
|
const pagesRoot = resolvePath(config, 'pages');
|
|
2409
2421
|
const featuresRoot = resolvePath(config, 'features');
|
|
2422
|
+
const configSignatures = Object.values(config.signatures || {});
|
|
2410
2423
|
const fromSection = findSection(state, actualFromRoute);
|
|
2411
2424
|
const routeExtension = (fromSection && fromSection.extension) || config.naming.routeExtension;
|
|
2412
2425
|
const fromRouteFile = routeToFilePath(normalizedFromRoute, {
|
|
@@ -2439,7 +2452,8 @@ async function moveSectionCommand(fromRoute, fromFeature, toRoute, toFeature, op
|
|
|
2439
2452
|
expectedHash: routeFileState?.hash,
|
|
2440
2453
|
acceptChanges: options.acceptChanges,
|
|
2441
2454
|
owner: normalizedFromRoute,
|
|
2442
|
-
actualOwner: routeFileState?.owner
|
|
2455
|
+
actualOwner: routeFileState?.owner,
|
|
2456
|
+
signatures: configSignatures
|
|
2443
2457
|
});
|
|
2444
2458
|
movedFiles.push({ from: fromRoutePath, to: toRoutePath });
|
|
2445
2459
|
// Update state for moved route file
|
|
@@ -2518,7 +2532,8 @@ async function moveSectionCommand(fromRoute, fromFeature, toRoute, toFeature, op
|
|
|
2518
2532
|
...options,
|
|
2519
2533
|
fromName: fromFeatureComponentName,
|
|
2520
2534
|
toName: toFeatureComponentName,
|
|
2521
|
-
owner: normalizedFromRoute
|
|
2535
|
+
owner: normalizedFromRoute,
|
|
2536
|
+
signatures: configSignatures
|
|
2522
2537
|
});
|
|
2523
2538
|
movedFiles.push({ from: fromFeaturePath, to: toFeaturePath });
|
|
2524
2539
|
await cleanupEmptyDirs(path.dirname(fromFeaturePath), featuresRoot);
|
|
@@ -3047,6 +3062,7 @@ async function createComponentCommand(componentName, options) {
|
|
|
3047
3062
|
async function removeComponentCommand(identifier, options) {
|
|
3048
3063
|
try {
|
|
3049
3064
|
const config = await loadConfig();
|
|
3065
|
+
const configSignatures = Object.values(config.signatures || {});
|
|
3050
3066
|
if (config.git?.requireCleanRepo && !await isRepoClean()) {
|
|
3051
3067
|
throw new Error('Git repository is not clean. Please commit or stash your changes before proceeding.');
|
|
3052
3068
|
}
|
|
@@ -3071,7 +3087,8 @@ async function removeComponentCommand(identifier, options) {
|
|
|
3071
3087
|
stateFiles: state.files,
|
|
3072
3088
|
acceptChanges: options.acceptChanges,
|
|
3073
3089
|
normalization: config.hashing?.normalization,
|
|
3074
|
-
owner: identifier
|
|
3090
|
+
owner: identifier,
|
|
3091
|
+
signatures: configSignatures
|
|
3075
3092
|
});
|
|
3076
3093
|
if (result.deleted || (result.reason === 'not-found' && component)) {
|
|
3077
3094
|
if (result.deleted) {
|
|
@@ -3120,7 +3137,8 @@ async function listSectionsCommand() {
|
|
|
3120
3137
|
}
|
|
3121
3138
|
else {
|
|
3122
3139
|
const extensions = [config.naming.routeExtension, '.ts', '.js'];
|
|
3123
|
-
const
|
|
3140
|
+
const signatures = Object.values(config.signatures || {});
|
|
3141
|
+
const sections = await findGeneratedFiles(pagesRoot, extensions, signatures);
|
|
3124
3142
|
if (sections.length === 0) {
|
|
3125
3143
|
console.log(' No Textor-managed sections found.');
|
|
3126
3144
|
}
|
|
@@ -3215,7 +3233,7 @@ async function listSectionsCommand() {
|
|
|
3215
3233
|
process.exit(1);
|
|
3216
3234
|
}
|
|
3217
3235
|
}
|
|
3218
|
-
async function findGeneratedFiles(dir, extensions) {
|
|
3236
|
+
async function findGeneratedFiles(dir, extensions, signatures) {
|
|
3219
3237
|
const results = [];
|
|
3220
3238
|
const entries = await promises.readdir(dir);
|
|
3221
3239
|
const exts = Array.isArray(extensions) ? extensions : [extensions];
|
|
@@ -3223,10 +3241,10 @@ async function findGeneratedFiles(dir, extensions) {
|
|
|
3223
3241
|
const fullPath = path.join(dir, entry);
|
|
3224
3242
|
const stats = await promises.stat(fullPath);
|
|
3225
3243
|
if (stats.isDirectory()) {
|
|
3226
|
-
results.push(...await findGeneratedFiles(fullPath, exts));
|
|
3244
|
+
results.push(...await findGeneratedFiles(fullPath, exts, signatures));
|
|
3227
3245
|
}
|
|
3228
3246
|
else if (exts.some(ext => entry.endsWith(ext))) {
|
|
3229
|
-
if (await isTextorGenerated(fullPath)) {
|
|
3247
|
+
if (await isTextorGenerated(fullPath, signatures)) {
|
|
3230
3248
|
results.push(fullPath);
|
|
3231
3249
|
}
|
|
3232
3250
|
}
|
|
@@ -3275,10 +3293,11 @@ async function validateStateCommand(options) {
|
|
|
3275
3293
|
}
|
|
3276
3294
|
if (options.fix) {
|
|
3277
3295
|
let fixedCount = 0;
|
|
3296
|
+
const signatures = Object.values(config.signatures || {});
|
|
3278
3297
|
// Fix modified files if they still have the Textor signature
|
|
3279
3298
|
for (const mod of results.modified) {
|
|
3280
3299
|
const fullPath = path.join(process.cwd(), mod.path);
|
|
3281
|
-
if (await isTextorGenerated(fullPath)) {
|
|
3300
|
+
if (await isTextorGenerated(fullPath, signatures)) {
|
|
3282
3301
|
state.files[mod.path].hash = mod.newHash;
|
|
3283
3302
|
fixedCount++;
|
|
3284
3303
|
}
|
|
@@ -3660,7 +3679,8 @@ async function adoptFile(relPath, config, state, options) {
|
|
|
3660
3679
|
else if (ext === '.js' || ext === '.jsx')
|
|
3661
3680
|
signature = config.signatures.javascript;
|
|
3662
3681
|
let finalContent = content;
|
|
3663
|
-
|
|
3682
|
+
const shouldAddSignature = signature && !content.includes(signature) && options.signature !== false;
|
|
3683
|
+
if (shouldAddSignature) {
|
|
3664
3684
|
if (options.dryRun) {
|
|
3665
3685
|
console.log(` ~ Would add signature to ${relPath}`);
|
|
3666
3686
|
}
|
|
@@ -3672,10 +3692,20 @@ async function adoptFile(relPath, config, state, options) {
|
|
|
3672
3692
|
}
|
|
3673
3693
|
else {
|
|
3674
3694
|
if (options.dryRun) {
|
|
3675
|
-
|
|
3695
|
+
if (signature && !content.includes(signature) && options.signature === false) {
|
|
3696
|
+
console.log(` + Would adopt without signature (explicitly requested): ${relPath}`);
|
|
3697
|
+
}
|
|
3698
|
+
else {
|
|
3699
|
+
console.log(` + Would adopt (already has signature or no signature for ext): ${relPath}`);
|
|
3700
|
+
}
|
|
3676
3701
|
}
|
|
3677
3702
|
else {
|
|
3678
|
-
|
|
3703
|
+
if (signature && !content.includes(signature) && options.signature === false) {
|
|
3704
|
+
console.log(` + Adopting without signature (explicitly requested): ${relPath}`);
|
|
3705
|
+
}
|
|
3706
|
+
else {
|
|
3707
|
+
console.log(` + Adopting: ${relPath}`);
|
|
3708
|
+
}
|
|
3679
3709
|
}
|
|
3680
3710
|
}
|
|
3681
3711
|
if (!options.dryRun) {
|
|
@@ -3684,7 +3714,8 @@ async function adoptFile(relPath, config, state, options) {
|
|
|
3684
3714
|
kind: inferKind(relPath, config),
|
|
3685
3715
|
hash: hash,
|
|
3686
3716
|
timestamp: new Date().toISOString(),
|
|
3687
|
-
synced: true
|
|
3717
|
+
synced: true,
|
|
3718
|
+
hasSignature: options.signature !== false
|
|
3688
3719
|
};
|
|
3689
3720
|
}
|
|
3690
3721
|
return true;
|