@omnifyjp/ts 2.1.0 → 2.1.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
|
@@ -1,8 +1,11 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Generates
|
|
2
|
+
* Generates two-phase file cleanup commands:
|
|
3
|
+
* - Phase 1 (CleanupExpiredFiles): Soft-delete expired temp records — keeps physical files
|
|
4
|
+
* - Phase 2 (PurgeDeletedFiles): Force-delete old soft-deleted records + remove physical files
|
|
5
|
+
*
|
|
3
6
|
* Only generated when fileConfig.tempFlow is enabled.
|
|
4
7
|
*/
|
|
5
8
|
import { SchemaReader } from './schema-reader.js';
|
|
6
9
|
import type { GeneratedFile, PhpConfig } from './types.js';
|
|
7
|
-
/** Generate the cleanup
|
|
10
|
+
/** Generate the cleanup commands (only when tempFlow is enabled). */
|
|
8
11
|
export declare function generateFileCleanup(reader: SchemaReader, config: PhpConfig): GeneratedFile[];
|
|
@@ -1,19 +1,40 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Generates
|
|
2
|
+
* Generates two-phase file cleanup commands:
|
|
3
|
+
* - Phase 1 (CleanupExpiredFiles): Soft-delete expired temp records — keeps physical files
|
|
4
|
+
* - Phase 2 (PurgeDeletedFiles): Force-delete old soft-deleted records + remove physical files
|
|
5
|
+
*
|
|
3
6
|
* Only generated when fileConfig.tempFlow is enabled.
|
|
4
7
|
*/
|
|
5
8
|
import { baseFile } from './types.js';
|
|
6
|
-
/** Generate the cleanup
|
|
9
|
+
/** Generate the cleanup commands (only when tempFlow is enabled). */
|
|
7
10
|
export function generateFileCleanup(reader, config) {
|
|
8
11
|
const fileConfig = reader.getFileConfig();
|
|
9
12
|
if (!fileConfig?.tempFlow)
|
|
10
13
|
return [];
|
|
11
14
|
const modelNamespace = config.models.namespace;
|
|
15
|
+
const files = [];
|
|
16
|
+
files.push(generateCleanupCommand(modelNamespace));
|
|
17
|
+
files.push(generatePurgeCommand(modelNamespace, fileConfig.purgeAfter ?? '72h'));
|
|
18
|
+
return files;
|
|
19
|
+
}
|
|
20
|
+
/** Parse a duration string like "72h" to hours. */
|
|
21
|
+
function parseDurationHours(duration) {
|
|
22
|
+
const match = duration.match(/^(\d+)(h|d)$/);
|
|
23
|
+
if (!match)
|
|
24
|
+
return 72;
|
|
25
|
+
const value = parseInt(match[1], 10);
|
|
26
|
+
const unit = match[2];
|
|
27
|
+
return unit === 'd' ? value * 24 : value;
|
|
28
|
+
}
|
|
29
|
+
function generateCleanupCommand(modelNamespace) {
|
|
12
30
|
const content = `<?php
|
|
13
31
|
|
|
14
32
|
namespace App\\Console\\Commands;
|
|
15
33
|
|
|
16
34
|
/**
|
|
35
|
+
* Phase 1: Soft-delete expired temporary file records.
|
|
36
|
+
* Physical files are kept on disk for the grace period.
|
|
37
|
+
*
|
|
17
38
|
* DO NOT EDIT - This file is auto-generated by Omnify.
|
|
18
39
|
* Any changes will be overwritten on next generation.
|
|
19
40
|
*
|
|
@@ -21,7 +42,6 @@ namespace App\\Console\\Commands;
|
|
|
21
42
|
*/
|
|
22
43
|
|
|
23
44
|
use Illuminate\\Console\\Command;
|
|
24
|
-
use Illuminate\\Support\\Facades\\Storage;
|
|
25
45
|
use ${modelNamespace}\\File;
|
|
26
46
|
|
|
27
47
|
class CleanupExpiredFiles extends Command
|
|
@@ -35,7 +55,7 @@ class CleanupExpiredFiles extends Command
|
|
|
35
55
|
/**
|
|
36
56
|
* The console command description.
|
|
37
57
|
*/
|
|
38
|
-
protected $description = '
|
|
58
|
+
protected $description = 'Soft-delete expired temporary file records (keeps physical files)';
|
|
39
59
|
|
|
40
60
|
/**
|
|
41
61
|
* Execute the console command.
|
|
@@ -51,29 +71,103 @@ class CleanupExpiredFiles extends Command
|
|
|
51
71
|
}
|
|
52
72
|
|
|
53
73
|
if ($this->option('dry-run')) {
|
|
54
|
-
$this->info("Would delete {$count} expired file(s).");
|
|
74
|
+
$this->info("Would soft-delete {$count} expired file record(s).");
|
|
75
|
+
return self::SUCCESS;
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
// Soft-delete only — physical files stay on disk
|
|
79
|
+
$deleted = $query->delete();
|
|
80
|
+
|
|
81
|
+
$this->info("Soft-deleted {$deleted} expired file record(s). Physical files retained.");
|
|
82
|
+
return self::SUCCESS;
|
|
83
|
+
}
|
|
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
|
+
|
|
117
|
+
/**
|
|
118
|
+
* The console command description.
|
|
119
|
+
*/
|
|
120
|
+
protected $description = 'Force-delete old soft-deleted file records and remove physical files from disk';
|
|
121
|
+
|
|
122
|
+
/**
|
|
123
|
+
* Execute the console command.
|
|
124
|
+
*/
|
|
125
|
+
public function handle(): int
|
|
126
|
+
{
|
|
127
|
+
$hours = (int) $this->option('hours');
|
|
128
|
+
$cutoff = now()->subHours($hours);
|
|
129
|
+
|
|
130
|
+
$query = File::onlyTrashed()->where('deleted_at', '<', $cutoff);
|
|
131
|
+
$count = $query->count();
|
|
132
|
+
|
|
133
|
+
if ($count === 0) {
|
|
134
|
+
$this->info("No soft-deleted files older than {$hours}h found.");
|
|
135
|
+
return self::SUCCESS;
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
if ($this->option('dry-run')) {
|
|
139
|
+
$this->info("Would purge {$count} file(s) older than {$hours}h.");
|
|
55
140
|
return self::SUCCESS;
|
|
56
141
|
}
|
|
57
142
|
|
|
58
|
-
$
|
|
59
|
-
$
|
|
143
|
+
$purged = 0;
|
|
144
|
+
$errors = 0;
|
|
145
|
+
|
|
146
|
+
$query->chunkById(100, function ($files) use (&$purged, &$errors) {
|
|
60
147
|
foreach ($files as $file) {
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
Storage::disk($file->disk)->
|
|
148
|
+
try {
|
|
149
|
+
// Remove physical file from storage
|
|
150
|
+
if ($file->path && Storage::disk($file->disk)->exists($file->path)) {
|
|
151
|
+
Storage::disk($file->disk)->delete($file->path);
|
|
152
|
+
}
|
|
153
|
+
// Force-delete the database record
|
|
154
|
+
$file->forceDelete();
|
|
155
|
+
$purged++;
|
|
156
|
+
} catch (\\Throwable $e) {
|
|
157
|
+
$this->error("Failed to purge file {$file->id}: {$e->getMessage()}");
|
|
158
|
+
$errors++;
|
|
64
159
|
}
|
|
65
|
-
// Soft delete the record
|
|
66
|
-
$file->delete();
|
|
67
|
-
$deleted++;
|
|
68
160
|
}
|
|
69
161
|
});
|
|
70
162
|
|
|
71
|
-
$this->info("
|
|
72
|
-
|
|
163
|
+
$this->info("Purged {$purged} file(s). Physical files removed from disk.");
|
|
164
|
+
if ($errors > 0) {
|
|
165
|
+
$this->warn("{$errors} file(s) failed to purge.");
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
return $errors > 0 ? self::FAILURE : self::SUCCESS;
|
|
73
169
|
}
|
|
74
170
|
}
|
|
75
171
|
`;
|
|
76
|
-
return
|
|
77
|
-
baseFile('app/Console/Commands/CleanupExpiredFiles.php', content),
|
|
78
|
-
];
|
|
172
|
+
return baseFile('app/Console/Commands/PurgeDeletedFiles.php', content);
|
|
79
173
|
}
|
package/dist/types.d.ts
CHANGED
|
@@ -10,6 +10,8 @@ export interface FileConfigExport {
|
|
|
10
10
|
readonly tempFlow?: boolean;
|
|
11
11
|
readonly tempTtl?: string;
|
|
12
12
|
readonly cleanupSchedule?: string;
|
|
13
|
+
readonly purgeAfter?: string;
|
|
14
|
+
readonly purgeSchedule?: string;
|
|
13
15
|
readonly defaultDisk?: string;
|
|
14
16
|
}
|
|
15
17
|
/** Top-level schemas.json structure. */
|