@omnifyjp/ts 2.1.1 → 2.1.2
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.
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Generates
|
|
3
|
-
*
|
|
4
|
-
*
|
|
2
|
+
* Generates a single file cleanup command with two phases:
|
|
3
|
+
* 1. Soft-delete expired temp records (keeps physical files)
|
|
4
|
+
* 2. Force-delete soft-deleted records past grace period + remove physical files
|
|
5
5
|
*
|
|
6
6
|
* Only generated when fileConfig.tempFlow is enabled.
|
|
7
7
|
*/
|
|
8
8
|
import { SchemaReader } from './schema-reader.js';
|
|
9
9
|
import type { GeneratedFile, PhpConfig } from './types.js';
|
|
10
|
-
/** Generate the cleanup
|
|
10
|
+
/** Generate the cleanup command (only when tempFlow is enabled). */
|
|
11
11
|
export declare function generateFileCleanup(reader: SchemaReader, config: PhpConfig): GeneratedFile[];
|
|
@@ -1,23 +1,21 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Generates
|
|
3
|
-
*
|
|
4
|
-
*
|
|
2
|
+
* Generates a single file cleanup command with two phases:
|
|
3
|
+
* 1. Soft-delete expired temp records (keeps physical files)
|
|
4
|
+
* 2. Force-delete soft-deleted records past grace period + remove physical files
|
|
5
5
|
*
|
|
6
6
|
* Only generated when fileConfig.tempFlow is enabled.
|
|
7
7
|
*/
|
|
8
8
|
import { baseFile } from './types.js';
|
|
9
|
-
/** Generate the cleanup
|
|
9
|
+
/** Generate the cleanup command (only when tempFlow is enabled). */
|
|
10
10
|
export function generateFileCleanup(reader, config) {
|
|
11
11
|
const fileConfig = reader.getFileConfig();
|
|
12
12
|
if (!fileConfig?.tempFlow)
|
|
13
13
|
return [];
|
|
14
14
|
const modelNamespace = config.models.namespace;
|
|
15
|
-
const
|
|
16
|
-
|
|
17
|
-
files.push(generatePurgeCommand(modelNamespace, fileConfig.purgeAfter ?? '72h'));
|
|
18
|
-
return files;
|
|
15
|
+
const purgeHours = parseDurationHours(fileConfig.purgeAfter ?? '72h');
|
|
16
|
+
return [generateCommand(modelNamespace, purgeHours)];
|
|
19
17
|
}
|
|
20
|
-
/** Parse a duration string like "72h" to hours. */
|
|
18
|
+
/** Parse a duration string like "72h" or "3d" to hours. */
|
|
21
19
|
function parseDurationHours(duration) {
|
|
22
20
|
const match = duration.match(/^(\d+)(h|d)$/);
|
|
23
21
|
if (!match)
|
|
@@ -26,14 +24,21 @@ function parseDurationHours(duration) {
|
|
|
26
24
|
const unit = match[2];
|
|
27
25
|
return unit === 'd' ? value * 24 : value;
|
|
28
26
|
}
|
|
29
|
-
function
|
|
27
|
+
function generateCommand(modelNamespace, purgeHours) {
|
|
30
28
|
const content = `<?php
|
|
31
29
|
|
|
32
30
|
namespace App\\Console\\Commands;
|
|
33
31
|
|
|
34
32
|
/**
|
|
35
|
-
*
|
|
36
|
-
*
|
|
33
|
+
* Two-phase file cleanup:
|
|
34
|
+
* Phase 1: Soft-delete expired temp records (physical files stay on disk)
|
|
35
|
+
* Phase 2: Force-delete soft-deleted records past grace period + remove physical files
|
|
36
|
+
*
|
|
37
|
+
* Usage:
|
|
38
|
+
* php artisan omnify:cleanup-files # run both phases
|
|
39
|
+
* php artisan omnify:cleanup-files --phase=1 # soft-delete only
|
|
40
|
+
* php artisan omnify:cleanup-files --phase=2 # purge only
|
|
41
|
+
* php artisan omnify:cleanup-files --dry-run # preview without changes
|
|
37
42
|
*
|
|
38
43
|
* DO NOT EDIT - This file is auto-generated by Omnify.
|
|
39
44
|
* Any changes will be overwritten on next generation.
|
|
@@ -42,101 +47,82 @@ namespace App\\Console\\Commands;
|
|
|
42
47
|
*/
|
|
43
48
|
|
|
44
49
|
use Illuminate\\Console\\Command;
|
|
50
|
+
use Illuminate\\Support\\Facades\\Storage;
|
|
45
51
|
use ${modelNamespace}\\File;
|
|
46
52
|
|
|
47
|
-
class
|
|
53
|
+
class CleanupFiles extends Command
|
|
48
54
|
{
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
{--dry-run : Show what would be deleted without actually deleting}';
|
|
55
|
+
protected $signature = 'omnify:cleanup-files
|
|
56
|
+
{--phase= : Run specific phase only (1=soft-delete, 2=purge)}
|
|
57
|
+
{--purge-hours=${purgeHours} : Grace period in hours before physical deletion}
|
|
58
|
+
{--dry-run : Preview what would happen without making changes}';
|
|
54
59
|
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
60
|
+
protected $description = 'Clean up expired and deleted file attachments';
|
|
61
|
+
|
|
62
|
+
public function handle(): int
|
|
63
|
+
{
|
|
64
|
+
$phase = $this->option('phase');
|
|
65
|
+
$dryRun = (bool) $this->option('dry-run');
|
|
66
|
+
|
|
67
|
+
$result = self::SUCCESS;
|
|
68
|
+
|
|
69
|
+
if ($phase === null || $phase === '1') {
|
|
70
|
+
$r = $this->phase1SoftDelete($dryRun);
|
|
71
|
+
if ($r !== self::SUCCESS) $result = $r;
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
if ($phase === null || $phase === '2') {
|
|
75
|
+
$r = $this->phase2Purge($dryRun);
|
|
76
|
+
if ($r !== self::SUCCESS) $result = $r;
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
return $result;
|
|
80
|
+
}
|
|
59
81
|
|
|
60
82
|
/**
|
|
61
|
-
*
|
|
83
|
+
* Phase 1: Soft-delete expired temporary file records.
|
|
84
|
+
* Physical files remain on disk for the grace period.
|
|
62
85
|
*/
|
|
63
|
-
|
|
86
|
+
private function phase1SoftDelete(bool $dryRun): int
|
|
64
87
|
{
|
|
65
88
|
$query = File::expired();
|
|
66
89
|
$count = $query->count();
|
|
67
90
|
|
|
68
91
|
if ($count === 0) {
|
|
69
|
-
$this->info('No expired files
|
|
92
|
+
$this->info('[Phase 1] No expired temp files.');
|
|
70
93
|
return self::SUCCESS;
|
|
71
94
|
}
|
|
72
95
|
|
|
73
|
-
if ($
|
|
74
|
-
$this->info("Would soft-delete {$count} expired file
|
|
96
|
+
if ($dryRun) {
|
|
97
|
+
$this->info("[Phase 1] Would soft-delete {$count} expired file(s).");
|
|
75
98
|
return self::SUCCESS;
|
|
76
99
|
}
|
|
77
100
|
|
|
78
|
-
// Soft-delete only — physical files stay on disk
|
|
79
101
|
$deleted = $query->delete();
|
|
102
|
+
$this->info("[Phase 1] Soft-deleted {$deleted} expired file(s). Physical files retained.");
|
|
80
103
|
|
|
81
|
-
$this->info("Soft-deleted {$deleted} expired file record(s). Physical files retained.");
|
|
82
104
|
return self::SUCCESS;
|
|
83
105
|
}
|
|
84
|
-
}
|
|
85
|
-
`;
|
|
86
|
-
return baseFile('app/Console/Commands/CleanupExpiredFiles.php', content);
|
|
87
|
-
}
|
|
88
|
-
function generatePurgeCommand(modelNamespace, purgeAfter) {
|
|
89
|
-
const hours = parseDurationHours(purgeAfter);
|
|
90
|
-
const content = `<?php
|
|
91
|
-
|
|
92
|
-
namespace App\\Console\\Commands;
|
|
93
|
-
|
|
94
|
-
/**
|
|
95
|
-
* Phase 2: Force-delete soft-deleted file records older than the grace period
|
|
96
|
-
* and remove their physical files from storage.
|
|
97
|
-
*
|
|
98
|
-
* DO NOT EDIT - This file is auto-generated by Omnify.
|
|
99
|
-
* Any changes will be overwritten on next generation.
|
|
100
|
-
*
|
|
101
|
-
* @generated by omnify
|
|
102
|
-
*/
|
|
103
|
-
|
|
104
|
-
use Illuminate\\Console\\Command;
|
|
105
|
-
use Illuminate\\Support\\Facades\\Storage;
|
|
106
|
-
use ${modelNamespace}\\File;
|
|
107
|
-
|
|
108
|
-
class PurgeDeletedFiles extends Command
|
|
109
|
-
{
|
|
110
|
-
/**
|
|
111
|
-
* The name and signature of the console command.
|
|
112
|
-
*/
|
|
113
|
-
protected $signature = 'omnify:purge-deleted-files
|
|
114
|
-
{--hours=${hours} : Grace period in hours before physical deletion}
|
|
115
|
-
{--dry-run : Show what would be purged without actually purging}';
|
|
116
106
|
|
|
117
107
|
/**
|
|
118
|
-
*
|
|
108
|
+
* Phase 2: Force-delete soft-deleted records past grace period
|
|
109
|
+
* and remove physical files from storage.
|
|
119
110
|
*/
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
/**
|
|
123
|
-
* Execute the console command.
|
|
124
|
-
*/
|
|
125
|
-
public function handle(): int
|
|
111
|
+
private function phase2Purge(bool $dryRun): int
|
|
126
112
|
{
|
|
127
|
-
$hours = (int) $this->option('hours');
|
|
113
|
+
$hours = (int) $this->option('purge-hours');
|
|
128
114
|
$cutoff = now()->subHours($hours);
|
|
129
115
|
|
|
130
116
|
$query = File::onlyTrashed()->where('deleted_at', '<', $cutoff);
|
|
131
117
|
$count = $query->count();
|
|
132
118
|
|
|
133
119
|
if ($count === 0) {
|
|
134
|
-
$this->info("No soft-deleted files older than {$hours}h
|
|
120
|
+
$this->info("[Phase 2] No soft-deleted files older than {$hours}h.");
|
|
135
121
|
return self::SUCCESS;
|
|
136
122
|
}
|
|
137
123
|
|
|
138
|
-
if ($
|
|
139
|
-
$this->info("Would purge {$count} file(s) older than {$hours}h.");
|
|
124
|
+
if ($dryRun) {
|
|
125
|
+
$this->info("[Phase 2] Would purge {$count} file(s) older than {$hours}h.");
|
|
140
126
|
return self::SUCCESS;
|
|
141
127
|
}
|
|
142
128
|
|
|
@@ -146,11 +132,9 @@ class PurgeDeletedFiles extends Command
|
|
|
146
132
|
$query->chunkById(100, function ($files) use (&$purged, &$errors) {
|
|
147
133
|
foreach ($files as $file) {
|
|
148
134
|
try {
|
|
149
|
-
// Remove physical file from storage
|
|
150
135
|
if ($file->path && Storage::disk($file->disk)->exists($file->path)) {
|
|
151
136
|
Storage::disk($file->disk)->delete($file->path);
|
|
152
137
|
}
|
|
153
|
-
// Force-delete the database record
|
|
154
138
|
$file->forceDelete();
|
|
155
139
|
$purged++;
|
|
156
140
|
} catch (\\Throwable $e) {
|
|
@@ -160,7 +144,7 @@ class PurgeDeletedFiles extends Command
|
|
|
160
144
|
}
|
|
161
145
|
});
|
|
162
146
|
|
|
163
|
-
$this->info("Purged {$purged} file(s). Physical files removed
|
|
147
|
+
$this->info("[Phase 2] Purged {$purged} file(s). Physical files removed.");
|
|
164
148
|
if ($errors > 0) {
|
|
165
149
|
$this->warn("{$errors} file(s) failed to purge.");
|
|
166
150
|
}
|
|
@@ -169,5 +153,5 @@ class PurgeDeletedFiles extends Command
|
|
|
169
153
|
}
|
|
170
154
|
}
|
|
171
155
|
`;
|
|
172
|
-
return baseFile('app/Console/Commands/
|
|
156
|
+
return baseFile('app/Console/Commands/CleanupFiles.php', content);
|
|
173
157
|
}
|