@omnifyjp/ts 3.0.0 → 3.1.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.
- package/dist/cli.js +4 -0
- package/dist/php/base-model-generator.js +5 -4
- package/dist/php/controller-generator.js +5 -5
- package/dist/php/file-model-generator.js +20 -16
- package/dist/php/file-trait-generator.js +6 -5
- package/dist/php/locales-generator.js +4 -4
- package/dist/php/model-generator.js +16 -9
- package/dist/php/policy-generator.js +4 -4
- package/dist/php/request-generator.js +6 -6
- package/dist/php/resource-generator.js +4 -4
- package/dist/php/service-generator.js +4 -4
- package/dist/php/trait-generator.js +4 -4
- package/dist/php/translation-model-generator.js +4 -4
- package/dist/php/types.d.ts +29 -0
- package/dist/php/types.js +48 -0
- package/package.json +1 -1
package/dist/cli.js
CHANGED
|
@@ -47,12 +47,16 @@ function resolveFromConfig(configPath) {
|
|
|
47
47
|
const laravelConfig = config.codegen?.laravel;
|
|
48
48
|
const laravelEnabled = laravelConfig?.enable === true;
|
|
49
49
|
const laravelOverrides = laravelEnabled ? {
|
|
50
|
+
structure: laravelConfig?.structure,
|
|
50
51
|
model: laravelConfig?.model,
|
|
51
52
|
request: laravelConfig?.request,
|
|
52
53
|
resource: laravelConfig?.resource,
|
|
53
54
|
factory: laravelConfig?.factory,
|
|
54
55
|
provider: laravelConfig?.provider,
|
|
55
56
|
policy: laravelConfig?.policy,
|
|
57
|
+
controller: laravelConfig?.controller,
|
|
58
|
+
service: laravelConfig?.service,
|
|
59
|
+
route: laravelConfig?.route,
|
|
56
60
|
nestedset: laravelConfig?.nestedset,
|
|
57
61
|
} : undefined;
|
|
58
62
|
return {
|
|
@@ -2,13 +2,13 @@
|
|
|
2
2
|
* Generates the BaseModel class.
|
|
3
3
|
* Morph map registration is handled exclusively by OmnifyServiceProvider.
|
|
4
4
|
*/
|
|
5
|
-
import { baseFile } from './types.js';
|
|
5
|
+
import { baseFile, resolveSharedBasePath, resolveSharedBaseNamespace } from './types.js';
|
|
6
6
|
/** Generate the BaseModel class. */
|
|
7
7
|
export function generateBaseModel(config) {
|
|
8
|
-
const
|
|
8
|
+
const ns = resolveSharedBaseNamespace(config, 'Models', config.models.baseNamespace);
|
|
9
9
|
const content = `<?php
|
|
10
10
|
|
|
11
|
-
namespace ${
|
|
11
|
+
namespace ${ns};
|
|
12
12
|
|
|
13
13
|
/**
|
|
14
14
|
* Base model class for all Omnify-generated models.
|
|
@@ -25,7 +25,8 @@ class BaseModel extends Model
|
|
|
25
25
|
{
|
|
26
26
|
}
|
|
27
27
|
`;
|
|
28
|
+
const path = resolveSharedBasePath(config, 'Models', 'BaseModel.php', config.models.basePath);
|
|
28
29
|
return [
|
|
29
|
-
baseFile(
|
|
30
|
+
baseFile(path, content),
|
|
30
31
|
];
|
|
31
32
|
}
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
* Generates base + editable controller classes for schemas with `options.api`.
|
|
3
3
|
*/
|
|
4
4
|
import { toPascalCase } from './naming-helper.js';
|
|
5
|
-
import { baseFile, userFile } from './types.js';
|
|
5
|
+
import { baseFile, userFile, resolveModularBasePath, resolveModularBaseNamespace } from './types.js';
|
|
6
6
|
const DEFAULT_ACTIONS = ['index', 'store', 'show', 'update', 'destroy'];
|
|
7
7
|
/** Generate controller classes for all schemas with api config. */
|
|
8
8
|
export function generateControllers(reader, config) {
|
|
@@ -25,9 +25,9 @@ function generateBaseController(name, schema, reader, config) {
|
|
|
25
25
|
const lookup = api.lookup ?? true;
|
|
26
26
|
const bulkDelete = api.bulkDelete ?? false;
|
|
27
27
|
const restore = api.restore ?? (schema.options?.softDelete ?? false);
|
|
28
|
-
const baseNs = config.controllers.baseNamespace;
|
|
28
|
+
const baseNs = resolveModularBaseNamespace(config, name, 'Controllers', config.controllers.baseNamespace);
|
|
29
29
|
const modelNs = config.models.namespace;
|
|
30
|
-
const serviceBaseNs = config.services.baseNamespace;
|
|
30
|
+
const serviceBaseNs = resolveModularBaseNamespace(config, name, 'Services', config.services.baseNamespace);
|
|
31
31
|
const requestNs = config.requests.namespace;
|
|
32
32
|
const resourceNs = config.resources.namespace;
|
|
33
33
|
// Build imports
|
|
@@ -145,12 +145,12 @@ abstract class ${modelName}ControllerBase extends Controller
|
|
|
145
145
|
${methods.join('\n')}
|
|
146
146
|
}
|
|
147
147
|
`;
|
|
148
|
-
return baseFile(`${
|
|
148
|
+
return baseFile(resolveModularBasePath(config, name, 'Controllers', `${modelName}ControllerBase.php`, config.controllers.basePath), content);
|
|
149
149
|
}
|
|
150
150
|
function generateUserController(name, schema, config) {
|
|
151
151
|
const modelName = toPascalCase(name);
|
|
152
152
|
const group = schema.group ? toPascalCase(schema.group) : null;
|
|
153
|
-
const baseNs = config.controllers.baseNamespace;
|
|
153
|
+
const baseNs = resolveModularBaseNamespace(config, name, 'Controllers', config.controllers.baseNamespace);
|
|
154
154
|
const userNs = group
|
|
155
155
|
? `${config.controllers.namespace}\\Api\\V1\\${group}`
|
|
156
156
|
: `${config.controllers.namespace}\\Api\\V1`;
|
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
* - FileStatusEnum.php (base, always overwritten)
|
|
6
6
|
* - FileLocales.php (base, always overwritten)
|
|
7
7
|
*/
|
|
8
|
-
import { baseFile, userFile } from './types.js';
|
|
8
|
+
import { baseFile, userFile, resolveModularBasePath, resolveModularBaseNamespace, resolveSharedBaseNamespace } from './types.js';
|
|
9
9
|
/** Generate all File model infrastructure files. */
|
|
10
10
|
export function generateFileModels(reader, config) {
|
|
11
11
|
if (!reader.hasFileProperties())
|
|
@@ -22,7 +22,11 @@ export function generateFileModels(reader, config) {
|
|
|
22
22
|
return files;
|
|
23
23
|
}
|
|
24
24
|
function generateFileBaseModel(config, defaultDisk) {
|
|
25
|
-
const baseNamespace = config.models.baseNamespace;
|
|
25
|
+
const baseNamespace = resolveModularBaseNamespace(config, 'File', 'Models', config.models.baseNamespace);
|
|
26
|
+
const localesNamespace = resolveModularBaseNamespace(config, 'File', 'Locales', config.models.baseNamespace + '\\Locales');
|
|
27
|
+
const traitsNamespace = resolveSharedBaseNamespace(config, 'Traits', config.models.baseNamespace + '\\Traits');
|
|
28
|
+
const sharedModelsNamespace = resolveSharedBaseNamespace(config, 'Models', config.models.baseNamespace);
|
|
29
|
+
const enumNamespace = resolveModularBaseNamespace(config, 'File', 'Enums', config.models.namespace);
|
|
26
30
|
const modelNamespace = config.models.namespace;
|
|
27
31
|
const content = `<?php
|
|
28
32
|
|
|
@@ -39,8 +43,8 @@ use Illuminate\\Database\\Eloquent\\Concerns\\HasUuids;
|
|
|
39
43
|
use Illuminate\\Database\\Eloquent\\Relations\\MorphTo;
|
|
40
44
|
use Illuminate\\Database\\Eloquent\\SoftDeletes;
|
|
41
45
|
use Illuminate\\Database\\Eloquent\\Builder;
|
|
42
|
-
use ${
|
|
43
|
-
use ${baseNamespace}\\
|
|
46
|
+
use ${localesNamespace}\\FileLocales;
|
|
47
|
+
use ${traitsNamespace}\\HasLocalizedDisplayName;${sharedModelsNamespace !== baseNamespace ? `\nuse ${sharedModelsNamespace}\\BaseModel;` : ''}
|
|
44
48
|
|
|
45
49
|
/**
|
|
46
50
|
* FileBaseModel
|
|
@@ -55,7 +59,7 @@ use ${baseNamespace}\\Traits\\HasLocalizedDisplayName;
|
|
|
55
59
|
* @property string $original_name
|
|
56
60
|
* @property string $mime_type
|
|
57
61
|
* @property int $size
|
|
58
|
-
* @property \\${
|
|
62
|
+
* @property \\${enumNamespace}\\FileStatusEnum $status
|
|
59
63
|
* @property \\Illuminate\\Support\\Carbon|null $expires_at
|
|
60
64
|
* @property int $sort_order
|
|
61
65
|
*/
|
|
@@ -126,7 +130,7 @@ class FileBaseModel extends BaseModel
|
|
|
126
130
|
return [
|
|
127
131
|
'size' => 'integer',
|
|
128
132
|
'sort_order' => 'integer',
|
|
129
|
-
'status' => \\${
|
|
133
|
+
'status' => \\${enumNamespace}\\FileStatusEnum::class,
|
|
130
134
|
'expires_at' => 'datetime',
|
|
131
135
|
];
|
|
132
136
|
}
|
|
@@ -190,7 +194,7 @@ class FileBaseModel extends BaseModel
|
|
|
190
194
|
*/
|
|
191
195
|
public function isPermanent(): bool
|
|
192
196
|
{
|
|
193
|
-
return $this->status === \\${
|
|
197
|
+
return $this->status === \\${enumNamespace}\\FileStatusEnum::Permanent;
|
|
194
198
|
}
|
|
195
199
|
|
|
196
200
|
/**
|
|
@@ -198,7 +202,7 @@ class FileBaseModel extends BaseModel
|
|
|
198
202
|
*/
|
|
199
203
|
public function isExpired(): bool
|
|
200
204
|
{
|
|
201
|
-
return $this->status === \\${
|
|
205
|
+
return $this->status === \\${enumNamespace}\\FileStatusEnum::Temporary
|
|
202
206
|
&& $this->expires_at !== null
|
|
203
207
|
&& $this->expires_at->isPast();
|
|
204
208
|
}
|
|
@@ -209,7 +213,7 @@ class FileBaseModel extends BaseModel
|
|
|
209
213
|
public function makePermanent(): static
|
|
210
214
|
{
|
|
211
215
|
$this->update([
|
|
212
|
-
'status' => \\${
|
|
216
|
+
'status' => \\${enumNamespace}\\FileStatusEnum::Permanent,
|
|
213
217
|
'expires_at' => null,
|
|
214
218
|
]);
|
|
215
219
|
|
|
@@ -217,11 +221,11 @@ class FileBaseModel extends BaseModel
|
|
|
217
221
|
}
|
|
218
222
|
}
|
|
219
223
|
`;
|
|
220
|
-
return baseFile(
|
|
224
|
+
return baseFile(resolveModularBasePath(config, 'File', 'Models', 'FileBaseModel.php', config.models.basePath), content);
|
|
221
225
|
}
|
|
222
226
|
function generateFileUserModel(config) {
|
|
223
227
|
const modelNamespace = config.models.namespace;
|
|
224
|
-
const baseNamespace = config.models.baseNamespace;
|
|
228
|
+
const baseNamespace = resolveModularBaseNamespace(config, 'File', 'Models', config.models.baseNamespace);
|
|
225
229
|
const factoryNamespace = config.factories.namespace;
|
|
226
230
|
const content = `<?php
|
|
227
231
|
|
|
@@ -258,7 +262,7 @@ class File extends FileBaseModel
|
|
|
258
262
|
return userFile(`${config.models.path}/File.php`, content);
|
|
259
263
|
}
|
|
260
264
|
function generateFileStatusEnum(config) {
|
|
261
|
-
const modelNamespace = config.models.namespace;
|
|
265
|
+
const modelNamespace = resolveModularBaseNamespace(config, 'File', 'Enums', config.models.namespace);
|
|
262
266
|
const content = `<?php
|
|
263
267
|
|
|
264
268
|
namespace ${modelNamespace};
|
|
@@ -296,10 +300,10 @@ enum FileStatusEnum: string
|
|
|
296
300
|
}
|
|
297
301
|
}
|
|
298
302
|
`;
|
|
299
|
-
return baseFile(
|
|
303
|
+
return baseFile(resolveModularBasePath(config, 'File', 'Enums', 'FileStatusEnum.php', config.models.path), content);
|
|
300
304
|
}
|
|
301
305
|
function generateFileLocales(config, locales) {
|
|
302
|
-
const baseNamespace = config.models.baseNamespace;
|
|
306
|
+
const baseNamespace = resolveModularBaseNamespace(config, 'File', 'Locales', config.models.baseNamespace + '\\Locales');
|
|
303
307
|
// Display names for the File model
|
|
304
308
|
const displayNames = {
|
|
305
309
|
ja: 'ファイル',
|
|
@@ -329,7 +333,7 @@ function generateFileLocales(config, locales) {
|
|
|
329
333
|
.join(',\n');
|
|
330
334
|
const content = `<?php
|
|
331
335
|
|
|
332
|
-
namespace ${baseNamespace}
|
|
336
|
+
namespace ${baseNamespace};
|
|
333
337
|
|
|
334
338
|
/**
|
|
335
339
|
* DO NOT EDIT - This file is auto-generated by Omnify.
|
|
@@ -346,7 +350,7 @@ ${propertyNamesPhp},
|
|
|
346
350
|
];
|
|
347
351
|
}
|
|
348
352
|
`;
|
|
349
|
-
return baseFile(
|
|
353
|
+
return baseFile(resolveModularBasePath(config, 'File', 'Locales', 'FileLocales.php', config.models.basePath + '/Locales'), content);
|
|
350
354
|
}
|
|
351
355
|
function formatPhpArray(obj) {
|
|
352
356
|
const entries = Object.entries(obj)
|
|
@@ -1,14 +1,15 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Generates the HasFiles trait for models with File-type properties.
|
|
3
3
|
*/
|
|
4
|
-
import { baseFile } from './types.js';
|
|
4
|
+
import { baseFile, resolveModularBasePath, resolveModularBaseNamespace } from './types.js';
|
|
5
5
|
/** Generate the HasFiles trait. */
|
|
6
6
|
export function generateFileTrait(config) {
|
|
7
|
-
const
|
|
7
|
+
const traitsNamespace = resolveModularBaseNamespace(config, 'File', 'Traits', config.models.baseNamespace + '\\Traits');
|
|
8
|
+
const enumNamespace = resolveModularBaseNamespace(config, 'File', 'Enums', config.models.namespace);
|
|
8
9
|
const modelNamespace = config.models.namespace;
|
|
9
10
|
const content = `<?php
|
|
10
11
|
|
|
11
|
-
namespace ${
|
|
12
|
+
namespace ${traitsNamespace};
|
|
12
13
|
|
|
13
14
|
/**
|
|
14
15
|
* Trait for models with polymorphic file attachments.
|
|
@@ -21,7 +22,7 @@ namespace ${baseNamespace}\\Traits;
|
|
|
21
22
|
|
|
22
23
|
use Illuminate\\Database\\Eloquent\\Relations\\MorphMany;
|
|
23
24
|
use ${modelNamespace}\\File;
|
|
24
|
-
use ${
|
|
25
|
+
use ${enumNamespace}\\FileStatusEnum;
|
|
25
26
|
|
|
26
27
|
trait HasFiles
|
|
27
28
|
{
|
|
@@ -91,6 +92,6 @@ trait HasFiles
|
|
|
91
92
|
}
|
|
92
93
|
`;
|
|
93
94
|
return [
|
|
94
|
-
baseFile(
|
|
95
|
+
baseFile(resolveModularBasePath(config, 'File', 'Traits', 'HasFiles.php', config.models.basePath + '/Traits'), content),
|
|
95
96
|
];
|
|
96
97
|
}
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
* Port of LocalesGenerator.php — generates Locales classes with display name constants.
|
|
3
3
|
*/
|
|
4
4
|
import { toPascalCase, toSnakeCase } from './naming-helper.js';
|
|
5
|
-
import { baseFile } from './types.js';
|
|
5
|
+
import { baseFile, resolveModularBasePath, resolveModularBaseNamespace } from './types.js';
|
|
6
6
|
/** Generate Locales classes for all project-owned object schemas. */
|
|
7
7
|
export function generateLocales(reader, config) {
|
|
8
8
|
const files = [];
|
|
@@ -15,14 +15,14 @@ export function generateLocales(reader, config) {
|
|
|
15
15
|
}
|
|
16
16
|
function generateLocalesClass(name, schema, reader, config) {
|
|
17
17
|
const modelName = toPascalCase(name);
|
|
18
|
-
const baseNamespace = config.models.baseNamespace;
|
|
18
|
+
const baseNamespace = resolveModularBaseNamespace(config, name, 'Locales', config.models.baseNamespace + '\\Locales');
|
|
19
19
|
const displayNames = buildDisplayNames(schema);
|
|
20
20
|
const propertyDisplayNames = buildPropertyDisplayNames(schema, reader, name);
|
|
21
21
|
const displayNamesPhp = formatArrayConstant(displayNames, 8);
|
|
22
22
|
const propertyDisplayNamesPhp = formatNestedArrayConstant(propertyDisplayNames, 8);
|
|
23
23
|
const content = `<?php
|
|
24
24
|
|
|
25
|
-
namespace ${baseNamespace}
|
|
25
|
+
namespace ${baseNamespace};
|
|
26
26
|
|
|
27
27
|
/**
|
|
28
28
|
* Localized display names for ${modelName}.
|
|
@@ -49,7 +49,7 @@ class ${modelName}Locales
|
|
|
49
49
|
public const PROPERTY_DISPLAY_NAMES = ${propertyDisplayNamesPhp};
|
|
50
50
|
}
|
|
51
51
|
`;
|
|
52
|
-
return baseFile(
|
|
52
|
+
return baseFile(resolveModularBasePath(config, name, 'Locales', `${modelName}Locales.php`, config.models.basePath + '/Locales'), content);
|
|
53
53
|
}
|
|
54
54
|
function buildDisplayNames(schema) {
|
|
55
55
|
const displayName = schema.displayName;
|
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
import { toPascalCase, toSnakeCase, toCamelCase } from './naming-helper.js';
|
|
5
5
|
import { toCast, toPhpDocType, isHiddenByDefault } from './type-mapper.js';
|
|
6
6
|
import { buildRelation } from './relation-builder.js';
|
|
7
|
-
import { baseFile, userFile } from './types.js';
|
|
7
|
+
import { baseFile, userFile, resolveModularBasePath, resolveModularBaseNamespace, resolveSharedBaseNamespace } from './types.js';
|
|
8
8
|
/** Generate base model and user model for all project-owned object schemas,
|
|
9
9
|
* plus user models for package schemas (extending the package model). */
|
|
10
10
|
export function generateModels(reader, config) {
|
|
@@ -33,7 +33,10 @@ function generateForSchema(name, schema, reader, config) {
|
|
|
33
33
|
}
|
|
34
34
|
function generateBaseModel(name, schema, reader, config) {
|
|
35
35
|
const modelName = toPascalCase(name);
|
|
36
|
-
const baseNamespace = config.models.baseNamespace;
|
|
36
|
+
const baseNamespace = resolveModularBaseNamespace(config, name, 'Models', config.models.baseNamespace);
|
|
37
|
+
const localesNamespace = resolveModularBaseNamespace(config, name, 'Locales', config.models.baseNamespace + '\\Locales');
|
|
38
|
+
const traitsNamespace = resolveSharedBaseNamespace(config, 'Traits', config.models.baseNamespace + '\\Traits');
|
|
39
|
+
const sharedModelsNamespace = resolveSharedBaseNamespace(config, 'Models', config.models.baseNamespace);
|
|
37
40
|
const modelNamespace = config.models.namespace;
|
|
38
41
|
const options = schema.options ?? {};
|
|
39
42
|
const properties = (schema.properties ?? {});
|
|
@@ -59,7 +62,7 @@ function generateBaseModel(name, schema, reader, config) {
|
|
|
59
62
|
const prop = properties[p];
|
|
60
63
|
return prop && prop['type'] === 'File';
|
|
61
64
|
});
|
|
62
|
-
const imports = buildImports(baseNamespace, modelName, hasSoftDelete, isAuthenticatable, hasTranslatable, properties, needsUuidTrait, needsUlidTrait, hasNestedSet, config.nestedset.namespace, hasFiles, modelNamespace);
|
|
65
|
+
const imports = buildImports(baseNamespace, modelName, hasSoftDelete, isAuthenticatable, hasTranslatable, properties, needsUuidTrait, needsUlidTrait, hasNestedSet, config.nestedset.namespace, hasFiles, modelNamespace, localesNamespace, traitsNamespace, sharedModelsNamespace);
|
|
63
66
|
const docProperties = buildDocProperties(properties, expandedProperties, propertyOrder);
|
|
64
67
|
const baseClass = isAuthenticatable ? 'Authenticatable' : 'BaseModel';
|
|
65
68
|
const implementsClause = hasTranslatable ? ' implements TranslatableContract' : '';
|
|
@@ -171,12 +174,12 @@ ${casts} ];
|
|
|
171
174
|
${relations}${accessors}${fileAccessors}${nestedSetMethod}
|
|
172
175
|
}
|
|
173
176
|
`;
|
|
174
|
-
return baseFile(`${
|
|
177
|
+
return baseFile(resolveModularBasePath(config, name, 'Models', `${modelName}BaseModel.php`, config.models.basePath), content);
|
|
175
178
|
}
|
|
176
179
|
function generateUserModel(name, config, hasNestedSet = false) {
|
|
177
180
|
const modelName = toPascalCase(name);
|
|
178
181
|
const modelNamespace = config.models.namespace;
|
|
179
|
-
const baseNamespace = config.models.baseNamespace;
|
|
182
|
+
const baseNamespace = resolveModularBaseNamespace(config, name, 'Models', config.models.baseNamespace);
|
|
180
183
|
const factoryNamespace = config.factories.namespace;
|
|
181
184
|
const nestedSetNamespace = config.nestedset.namespace;
|
|
182
185
|
const imports = [
|
|
@@ -223,8 +226,12 @@ ${traits.join('\n')}
|
|
|
223
226
|
`;
|
|
224
227
|
return userFile(`${config.models.path}/${modelName}.php`, content);
|
|
225
228
|
}
|
|
226
|
-
function buildImports(baseNamespace, modelName, hasSoftDelete, isAuthenticatable, hasTranslatable, properties, needsUuidTrait = false, needsUlidTrait = false, hasNestedSet = false, nestedSetNamespace = 'Aimeos\\Nestedset', hasFiles = false, modelNamespace = '') {
|
|
229
|
+
function buildImports(baseNamespace, modelName, hasSoftDelete, isAuthenticatable, hasTranslatable, properties, needsUuidTrait = false, needsUlidTrait = false, hasNestedSet = false, nestedSetNamespace = 'Aimeos\\Nestedset', hasFiles = false, modelNamespace = '', localesNamespace = '', traitsNamespace = '', sharedModelsNamespace = '') {
|
|
227
230
|
const lines = [];
|
|
231
|
+
// Import BaseModel from shared namespace when in modular mode
|
|
232
|
+
if (sharedModelsNamespace && sharedModelsNamespace !== baseNamespace && !isAuthenticatable) {
|
|
233
|
+
lines.push(`use ${sharedModelsNamespace}\\BaseModel;`);
|
|
234
|
+
}
|
|
228
235
|
if (isAuthenticatable) {
|
|
229
236
|
lines.push('use Illuminate\\Foundation\\Auth\\User as Authenticatable;');
|
|
230
237
|
lines.push('use Illuminate\\Notifications\\Notifiable;');
|
|
@@ -241,10 +248,10 @@ function buildImports(baseNamespace, modelName, hasSoftDelete, isAuthenticatable
|
|
|
241
248
|
lines.push(`use Illuminate\\Database\\Eloquent\\Relations\\${type};`);
|
|
242
249
|
}
|
|
243
250
|
lines.push('use Illuminate\\Database\\Eloquent\\Collection as EloquentCollection;');
|
|
244
|
-
lines.push(`use ${baseNamespace
|
|
245
|
-
lines.push(`use ${baseNamespace
|
|
251
|
+
lines.push(`use ${traitsNamespace || baseNamespace + '\\Traits'}\\HasLocalizedDisplayName;`);
|
|
252
|
+
lines.push(`use ${localesNamespace || baseNamespace + '\\Locales'}\\${modelName}Locales;`);
|
|
246
253
|
if (hasFiles) {
|
|
247
|
-
lines.push(`use ${baseNamespace
|
|
254
|
+
lines.push(`use ${traitsNamespace || baseNamespace + '\\Traits'}\\HasFiles;`);
|
|
248
255
|
if (modelNamespace) {
|
|
249
256
|
lines.push(`use ${modelNamespace}\\File;`);
|
|
250
257
|
}
|
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
* Only generates for schemas that have `policies` defined.
|
|
6
6
|
*/
|
|
7
7
|
import { toPascalCase, toSnakeCase, toCamelCase } from './naming-helper.js';
|
|
8
|
-
import { baseFile, userFile } from './types.js';
|
|
8
|
+
import { baseFile, userFile, resolveModularBasePath, resolveModularBaseNamespace } from './types.js';
|
|
9
9
|
// ============================================================================
|
|
10
10
|
// Action mapping: Omnify → Laravel
|
|
11
11
|
// ============================================================================
|
|
@@ -45,7 +45,7 @@ function generateForSchema(name, schema, reader, config) {
|
|
|
45
45
|
}
|
|
46
46
|
function generateBasePolicyClass(name, schema, reader, config) {
|
|
47
47
|
const modelName = toPascalCase(name);
|
|
48
|
-
const baseNamespace = config.policies.baseNamespace;
|
|
48
|
+
const baseNamespace = resolveModularBaseNamespace(config, name, 'Policies', config.policies.baseNamespace);
|
|
49
49
|
const modelNamespace = config.models.namespace;
|
|
50
50
|
const policies = schema.policies;
|
|
51
51
|
const hasSoftDelete = schema.options?.softDelete ?? false;
|
|
@@ -89,12 +89,12 @@ class ${modelName}PolicyBase
|
|
|
89
89
|
${methods.join('\n')}${cidrHelper}
|
|
90
90
|
}
|
|
91
91
|
`;
|
|
92
|
-
return baseFile(`${
|
|
92
|
+
return baseFile(resolveModularBasePath(config, name, 'Policies', `${modelName}PolicyBase.php`, config.policies.basePath), content);
|
|
93
93
|
}
|
|
94
94
|
function generateUserPolicyClass(name, config) {
|
|
95
95
|
const modelName = toPascalCase(name);
|
|
96
96
|
const policyNamespace = config.policies.namespace;
|
|
97
|
-
const baseNamespace = config.policies.baseNamespace;
|
|
97
|
+
const baseNamespace = resolveModularBaseNamespace(config, name, 'Policies', config.policies.baseNamespace);
|
|
98
98
|
const content = `<?php
|
|
99
99
|
|
|
100
100
|
namespace ${policyNamespace};
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
*/
|
|
4
4
|
import { toPascalCase, toSnakeCase, toCamelCase } from './naming-helper.js';
|
|
5
5
|
import { toStoreRules, toUpdateRules, formatRules, hasRuleObject } from './type-mapper.js';
|
|
6
|
-
import { baseFile, userFile } from './types.js';
|
|
6
|
+
import { baseFile, userFile, resolveModularBasePath, resolveModularBaseNamespace } from './types.js';
|
|
7
7
|
/** Generate Store/Update request classes for all project-owned visible object schemas. */
|
|
8
8
|
export function generateRequests(reader, config) {
|
|
9
9
|
const files = [];
|
|
@@ -24,8 +24,8 @@ function generateForSchema(name, schema, reader, config) {
|
|
|
24
24
|
}
|
|
25
25
|
function generateBaseRequest(name, schema, reader, config, action) {
|
|
26
26
|
const modelName = toPascalCase(name);
|
|
27
|
-
const baseNamespace = config.requests.baseNamespace;
|
|
28
|
-
const
|
|
27
|
+
const baseNamespace = resolveModularBaseNamespace(config, name, 'Requests', config.requests.baseNamespace);
|
|
28
|
+
const modelLocalesNamespace = resolveModularBaseNamespace(config, name, 'Locales', config.models.baseNamespace + '\\Locales');
|
|
29
29
|
const properties = (schema.properties ?? {});
|
|
30
30
|
const expandedProperties = reader.getExpandedProperties(name);
|
|
31
31
|
const propertyOrder = reader.getPropertyOrder(name);
|
|
@@ -136,7 +136,7 @@ function generateBaseRequest(name, schema, reader, config, action) {
|
|
|
136
136
|
attributeKeys.push(snakeName);
|
|
137
137
|
}
|
|
138
138
|
const rulesContent = rulesLines.join('\n');
|
|
139
|
-
const localesClass = `${
|
|
139
|
+
const localesClass = `${modelLocalesNamespace}\\${modelName}Locales`;
|
|
140
140
|
const attributeKeysList = attributeKeys.map(k => ` '${k}',`).join('\n');
|
|
141
141
|
const ruleImport = needsRuleImport ? '\nuse Illuminate\\Validation\\Rule;' : '';
|
|
142
142
|
const content = `<?php
|
|
@@ -222,12 +222,12 @@ ${attributeKeysList}
|
|
|
222
222
|
}
|
|
223
223
|
}
|
|
224
224
|
`;
|
|
225
|
-
return baseFile(`${
|
|
225
|
+
return baseFile(resolveModularBasePath(config, name, 'Requests', `${modelName}${action}RequestBase.php`, config.requests.basePath), content);
|
|
226
226
|
}
|
|
227
227
|
function generateUserRequest(name, config, action) {
|
|
228
228
|
const modelName = toPascalCase(name);
|
|
229
229
|
const requestNamespace = config.requests.namespace;
|
|
230
|
-
const baseNamespace = config.requests.baseNamespace;
|
|
230
|
+
const baseNamespace = resolveModularBaseNamespace(config, name, 'Requests', config.requests.baseNamespace);
|
|
231
231
|
const content = `<?php
|
|
232
232
|
|
|
233
233
|
/**
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
*/
|
|
4
4
|
import { toPascalCase, toSnakeCase, toCamelCase } from './naming-helper.js';
|
|
5
5
|
import { isHiddenByDefault, toResourceExpression } from './type-mapper.js';
|
|
6
|
-
import { baseFile, userFile } from './types.js';
|
|
6
|
+
import { baseFile, userFile, resolveModularBasePath, resolveModularBaseNamespace } from './types.js';
|
|
7
7
|
/** Generate Resource classes for all project-owned visible object schemas. */
|
|
8
8
|
export function generateResources(reader, config) {
|
|
9
9
|
const files = [];
|
|
@@ -17,7 +17,7 @@ export function generateResources(reader, config) {
|
|
|
17
17
|
}
|
|
18
18
|
function generateBaseResource(name, schema, reader, config) {
|
|
19
19
|
const modelName = toPascalCase(name);
|
|
20
|
-
const baseNamespace = config.resources.baseNamespace;
|
|
20
|
+
const baseNamespace = resolveModularBaseNamespace(config, name, 'Resources', config.resources.baseNamespace);
|
|
21
21
|
const resourceNamespace = config.resources.namespace;
|
|
22
22
|
const modelNamespace = config.models.namespace;
|
|
23
23
|
const properties = (schema.properties ?? {});
|
|
@@ -114,12 +114,12 @@ ${fieldsContent}
|
|
|
114
114
|
}
|
|
115
115
|
}
|
|
116
116
|
`;
|
|
117
|
-
return baseFile(`${
|
|
117
|
+
return baseFile(resolveModularBasePath(config, name, 'Resources', `${modelName}ResourceBase.php`, config.resources.basePath), content);
|
|
118
118
|
}
|
|
119
119
|
function generateUserResource(name, config) {
|
|
120
120
|
const modelName = toPascalCase(name);
|
|
121
121
|
const resourceNamespace = config.resources.namespace;
|
|
122
|
-
const baseNamespace = config.resources.baseNamespace;
|
|
122
|
+
const baseNamespace = resolveModularBaseNamespace(config, name, 'Resources', config.resources.baseNamespace);
|
|
123
123
|
const content = `<?php
|
|
124
124
|
|
|
125
125
|
/**
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
* Generates base + editable service classes for schemas with `options.api`.
|
|
3
3
|
*/
|
|
4
4
|
import { toPascalCase, toSnakeCase } from './naming-helper.js';
|
|
5
|
-
import { baseFile, userFile } from './types.js';
|
|
5
|
+
import { baseFile, userFile, resolveModularBasePath, resolveModularBaseNamespace } from './types.js';
|
|
6
6
|
/** Generate service classes for all schemas with api config. */
|
|
7
7
|
export function generateServices(reader, config) {
|
|
8
8
|
const files = [];
|
|
@@ -27,7 +27,7 @@ function generateBaseService(name, schema, reader, config) {
|
|
|
27
27
|
const restore = api.restore ?? (schema.options?.softDelete ?? false);
|
|
28
28
|
const perPage = api.perPage ?? 15;
|
|
29
29
|
const lookup = api.lookup ?? true;
|
|
30
|
-
const baseNs = config.services.baseNamespace;
|
|
30
|
+
const baseNs = resolveModularBaseNamespace(config, name, 'Services', config.services.baseNamespace);
|
|
31
31
|
const modelNs = config.models.namespace;
|
|
32
32
|
const properties = schema.properties ?? {};
|
|
33
33
|
const propertyOrder = reader.getPropertyOrder(name);
|
|
@@ -186,7 +186,7 @@ class ${modelName}ServiceBase
|
|
|
186
186
|
${methods.join('\n')}
|
|
187
187
|
}
|
|
188
188
|
`;
|
|
189
|
-
return baseFile(`${
|
|
189
|
+
return baseFile(resolveModularBasePath(config, name, 'Services', `${modelName}ServiceBase.php`, config.services.basePath), content);
|
|
190
190
|
}
|
|
191
191
|
// ============================================================================
|
|
192
192
|
// Search / Filter / Sort block builders
|
|
@@ -291,7 +291,7 @@ function buildSortBlock(sortableFields) {
|
|
|
291
291
|
function generateUserService(name, schema, config) {
|
|
292
292
|
const modelName = toPascalCase(name);
|
|
293
293
|
const group = schema.group ? toPascalCase(schema.group) : null;
|
|
294
|
-
const baseNs = config.services.baseNamespace;
|
|
294
|
+
const baseNs = resolveModularBaseNamespace(config, name, 'Services', config.services.baseNamespace);
|
|
295
295
|
const userNs = group
|
|
296
296
|
? `${config.services.namespace}\\${group}`
|
|
297
297
|
: config.services.namespace;
|
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Port of TraitGenerator.php — generates HasLocalizedDisplayName trait.
|
|
3
3
|
*/
|
|
4
|
-
import { baseFile } from './types.js';
|
|
4
|
+
import { baseFile, resolveSharedBasePath, resolveSharedBaseNamespace } from './types.js';
|
|
5
5
|
/** Generate the HasLocalizedDisplayName trait. */
|
|
6
6
|
export function generateTrait(config) {
|
|
7
|
-
const
|
|
7
|
+
const ns = resolveSharedBaseNamespace(config, 'Traits', config.models.baseNamespace + '\\Traits');
|
|
8
8
|
const content = `<?php
|
|
9
9
|
|
|
10
|
-
namespace ${
|
|
10
|
+
namespace ${ns};
|
|
11
11
|
|
|
12
12
|
/**
|
|
13
13
|
* Trait for localized display names.
|
|
@@ -99,6 +99,6 @@ trait HasLocalizedDisplayName
|
|
|
99
99
|
}
|
|
100
100
|
`;
|
|
101
101
|
return [
|
|
102
|
-
baseFile(
|
|
102
|
+
baseFile(resolveSharedBasePath(config, 'Traits', 'HasLocalizedDisplayName.php', config.models.basePath + '/Traits'), content),
|
|
103
103
|
];
|
|
104
104
|
}
|
|
@@ -8,7 +8,7 @@
|
|
|
8
8
|
* - $fillable = [translatable field names]
|
|
9
9
|
*/
|
|
10
10
|
import { toPascalCase, toSnakeCase } from './naming-helper.js';
|
|
11
|
-
import { baseFile, userFile } from './types.js';
|
|
11
|
+
import { baseFile, userFile, resolveModularBasePath, resolveModularBaseNamespace } from './types.js';
|
|
12
12
|
/** Generate translation model files for all project schemas with translatable fields. */
|
|
13
13
|
export function generateTranslationModels(reader, config) {
|
|
14
14
|
const files = [];
|
|
@@ -24,7 +24,7 @@ export function generateTranslationModels(reader, config) {
|
|
|
24
24
|
function generateTranslationBaseModel(name, translatableFields, config) {
|
|
25
25
|
const modelName = toPascalCase(name);
|
|
26
26
|
const modelSnake = toSnakeCase(name);
|
|
27
|
-
const baseNamespace = config.models.baseNamespace;
|
|
27
|
+
const baseNamespace = resolveModularBaseNamespace(config, name, 'Models', config.models.baseNamespace);
|
|
28
28
|
const tableName = `${modelSnake}_translations`;
|
|
29
29
|
const fillableLines = translatableFields
|
|
30
30
|
.map(f => ` '${f}',`)
|
|
@@ -65,12 +65,12 @@ ${fillableLines}
|
|
|
65
65
|
];
|
|
66
66
|
}
|
|
67
67
|
`;
|
|
68
|
-
return baseFile(`${
|
|
68
|
+
return baseFile(resolveModularBasePath(config, name, 'Models', `${modelName}TranslationBaseModel.php`, config.models.basePath), content);
|
|
69
69
|
}
|
|
70
70
|
function generateTranslationUserModel(name, config) {
|
|
71
71
|
const modelName = toPascalCase(name);
|
|
72
72
|
const modelNamespace = config.models.namespace;
|
|
73
|
-
const baseNamespace = config.models.baseNamespace;
|
|
73
|
+
const baseNamespace = resolveModularBaseNamespace(config, name, 'Models', config.models.baseNamespace);
|
|
74
74
|
const content = `<?php
|
|
75
75
|
|
|
76
76
|
namespace ${modelNamespace};
|
package/dist/php/types.d.ts
CHANGED
|
@@ -12,6 +12,32 @@ export interface GeneratedFile {
|
|
|
12
12
|
export declare function baseFile(path: string, content: string): GeneratedFile;
|
|
13
13
|
/** Create a user file (created once, skip if exists). */
|
|
14
14
|
export declare function userFile(path: string, content: string): GeneratedFile;
|
|
15
|
+
/** Category of base file for modular path resolution. */
|
|
16
|
+
export type BaseCategory = 'Models' | 'Controllers' | 'Requests' | 'Resources' | 'Services' | 'Enums' | 'Traits' | 'Locales' | 'Policies';
|
|
17
|
+
/**
|
|
18
|
+
* Resolve base file path for a schema based on structure.
|
|
19
|
+
* Modular: app/Modules/{SchemaName}/{category}/{fileName}
|
|
20
|
+
* Legacy: {legacyPath}/{fileName}
|
|
21
|
+
*/
|
|
22
|
+
export declare function resolveModularBasePath(config: PhpConfig, schemaName: string, category: BaseCategory, fileName: string, legacyPath: string): string;
|
|
23
|
+
/**
|
|
24
|
+
* Resolve base namespace for a schema based on structure.
|
|
25
|
+
* Modular: App\Modules\{SchemaName}\{Category}
|
|
26
|
+
* Legacy: {legacyNamespace}
|
|
27
|
+
*/
|
|
28
|
+
export declare function resolveModularBaseNamespace(config: PhpConfig, schemaName: string, category: BaseCategory, legacyNamespace: string): string;
|
|
29
|
+
/**
|
|
30
|
+
* Resolve shared base path (for cross-module files like BaseModel, HasLocalizedDisplayName).
|
|
31
|
+
* Modular: app/Modules/Shared/{category}/{fileName}
|
|
32
|
+
* Legacy: {legacyPath}/{fileName}
|
|
33
|
+
*/
|
|
34
|
+
export declare function resolveSharedBasePath(config: PhpConfig, category: BaseCategory, fileName: string, legacyPath: string): string;
|
|
35
|
+
/**
|
|
36
|
+
* Resolve shared base namespace.
|
|
37
|
+
* Modular: App\Modules\Shared\{Category}
|
|
38
|
+
* Legacy: {legacyNamespace}
|
|
39
|
+
*/
|
|
40
|
+
export declare function resolveSharedBaseNamespace(config: PhpConfig, category: BaseCategory, legacyNamespace: string): string;
|
|
15
41
|
/** Per-target path and namespace override from codegen.laravel config. */
|
|
16
42
|
export interface LaravelPathOverride {
|
|
17
43
|
path?: string;
|
|
@@ -23,6 +49,7 @@ export interface NestedSetOverride {
|
|
|
23
49
|
}
|
|
24
50
|
/** Overrides from codegen.laravel YAML config (all optional). */
|
|
25
51
|
export interface LaravelCodegenOverrides {
|
|
52
|
+
structure?: 'legacy' | 'modular';
|
|
26
53
|
model?: LaravelPathOverride;
|
|
27
54
|
request?: LaravelPathOverride;
|
|
28
55
|
resource?: LaravelPathOverride;
|
|
@@ -36,6 +63,8 @@ export interface LaravelCodegenOverrides {
|
|
|
36
63
|
}
|
|
37
64
|
/** PHP codegen configuration (resolved with defaults). */
|
|
38
65
|
export interface PhpConfig {
|
|
66
|
+
structure: 'legacy' | 'modular';
|
|
67
|
+
modulesPath: string;
|
|
39
68
|
models: {
|
|
40
69
|
namespace: string;
|
|
41
70
|
baseNamespace: string;
|
package/dist/php/types.js
CHANGED
|
@@ -9,6 +9,50 @@ export function baseFile(path, content) {
|
|
|
9
9
|
export function userFile(path, content) {
|
|
10
10
|
return { path, content, overwrite: false, type: 'user' };
|
|
11
11
|
}
|
|
12
|
+
/**
|
|
13
|
+
* Resolve base file path for a schema based on structure.
|
|
14
|
+
* Modular: app/Modules/{SchemaName}/{category}/{fileName}
|
|
15
|
+
* Legacy: {legacyPath}/{fileName}
|
|
16
|
+
*/
|
|
17
|
+
export function resolveModularBasePath(config, schemaName, category, fileName, legacyPath) {
|
|
18
|
+
if (config.structure === 'modular') {
|
|
19
|
+
return `${config.modulesPath}/${schemaName}/${category}/${fileName}`;
|
|
20
|
+
}
|
|
21
|
+
return `${legacyPath}/${fileName}`;
|
|
22
|
+
}
|
|
23
|
+
/**
|
|
24
|
+
* Resolve base namespace for a schema based on structure.
|
|
25
|
+
* Modular: App\Modules\{SchemaName}\{Category}
|
|
26
|
+
* Legacy: {legacyNamespace}
|
|
27
|
+
*/
|
|
28
|
+
export function resolveModularBaseNamespace(config, schemaName, category, legacyNamespace) {
|
|
29
|
+
if (config.structure === 'modular') {
|
|
30
|
+
return pathToNamespace(`${config.modulesPath}/${schemaName}/${category}`);
|
|
31
|
+
}
|
|
32
|
+
return legacyNamespace;
|
|
33
|
+
}
|
|
34
|
+
/**
|
|
35
|
+
* Resolve shared base path (for cross-module files like BaseModel, HasLocalizedDisplayName).
|
|
36
|
+
* Modular: app/Modules/Shared/{category}/{fileName}
|
|
37
|
+
* Legacy: {legacyPath}/{fileName}
|
|
38
|
+
*/
|
|
39
|
+
export function resolveSharedBasePath(config, category, fileName, legacyPath) {
|
|
40
|
+
if (config.structure === 'modular') {
|
|
41
|
+
return `${config.modulesPath}/Shared/${category}/${fileName}`;
|
|
42
|
+
}
|
|
43
|
+
return `${legacyPath}/${fileName}`;
|
|
44
|
+
}
|
|
45
|
+
/**
|
|
46
|
+
* Resolve shared base namespace.
|
|
47
|
+
* Modular: App\Modules\Shared\{Category}
|
|
48
|
+
* Legacy: {legacyNamespace}
|
|
49
|
+
*/
|
|
50
|
+
export function resolveSharedBaseNamespace(config, category, legacyNamespace) {
|
|
51
|
+
if (config.structure === 'modular') {
|
|
52
|
+
return pathToNamespace(`${config.modulesPath}/Shared/${category}`);
|
|
53
|
+
}
|
|
54
|
+
return legacyNamespace;
|
|
55
|
+
}
|
|
12
56
|
/** Convert a file path to a PHP namespace (e.g., app/Models/Omnify → App\Models\Omnify). */
|
|
13
57
|
function pathToNamespace(p) {
|
|
14
58
|
return p
|
|
@@ -49,7 +93,11 @@ export function derivePhpConfig(overrides) {
|
|
|
49
93
|
const serviceNs = overrides?.service?.namespace ?? pathToNamespace(servicePath);
|
|
50
94
|
const routePath = overrides?.route?.path ?? DEFAULT_ROUTE_PATH;
|
|
51
95
|
const nestedsetNs = overrides?.nestedset?.namespace ?? 'Aimeos\\Nestedset';
|
|
96
|
+
const structure = overrides?.structure ?? 'legacy';
|
|
97
|
+
const modulesPath = 'app/Modules';
|
|
52
98
|
return {
|
|
99
|
+
structure,
|
|
100
|
+
modulesPath,
|
|
53
101
|
models: {
|
|
54
102
|
namespace: modelNs,
|
|
55
103
|
baseNamespace: `${modelNs}\\Base`,
|