@omnifyjp/ts 5.8.3 → 5.8.4
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/php/controller-generator.js +22 -5
- package/dist/php/factory-generator.js +9 -2
- package/dist/php/model-generator.js +22 -5
- package/dist/php/policy-generator.js +9 -3
- package/dist/php/request-generator.js +2 -2
- package/dist/php/resource-generator.js +2 -2
- package/dist/php/schema-config-generator.js +9 -2
- package/dist/php/service-generator.js +11 -3
- package/dist/php/service-provider-generator.js +12 -4
- package/dist/php/types.d.ts +44 -0
- package/dist/php/types.js +18 -1
- package/package.json +1 -1
|
@@ -26,11 +26,28 @@ function generateBaseController(name, schema, reader, config) {
|
|
|
26
26
|
const lookup = api.lookup ?? true;
|
|
27
27
|
const bulkDelete = api.bulkDelete ?? false;
|
|
28
28
|
const restore = api.restore ?? (schema.options?.softDelete ?? false);
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
29
|
+
// Issue #98 v5.8.4 / v5.8.5: cross-layer imports must mirror where
|
|
30
|
+
// the imported file actually lives. BASE layers (Models, Services
|
|
31
|
+
// base, Controllers base) are ALWAYS group-nested in legacy structure.
|
|
32
|
+
// EDITABLE layers (Requests, Resources) are nested only when the
|
|
33
|
+
// target layer's `userEditableGroupByFolder` is `true` — Laravel-
|
|
34
|
+
// canonical defaults to flat. Modular structure already isolates
|
|
35
|
+
// per-schema so all paths skip group nesting.
|
|
36
|
+
const groupNestBase = (ns) => config.structure === 'modular'
|
|
37
|
+
? ns
|
|
38
|
+
: nestByGroup({ path: '', namespace: ns }, schema.group).namespace;
|
|
39
|
+
const groupNestEditable = (ns, layer) => config.structure === 'modular'
|
|
40
|
+
? ns
|
|
41
|
+
: (layer.userEditableGroupByFolder ? nestByGroup({ path: '', namespace: ns }, schema.group).namespace : ns);
|
|
42
|
+
const baseNs = config.structure === 'modular'
|
|
43
|
+
? resolveModularBaseNamespace(config, name, 'Controllers', config.controllers.baseNamespace)
|
|
44
|
+
: groupNestBase(config.controllers.baseNamespace);
|
|
45
|
+
const modelNs = groupNestBase(config.models.namespace);
|
|
46
|
+
const serviceBaseNs = config.structure === 'modular'
|
|
47
|
+
? resolveModularBaseNamespace(config, name, 'Services', config.services.baseNamespace)
|
|
48
|
+
: groupNestBase(config.services.baseNamespace);
|
|
49
|
+
const requestNs = groupNestEditable(config.requests.namespace, config.requests);
|
|
50
|
+
const resourceNs = groupNestEditable(config.resources.namespace, config.resources);
|
|
34
51
|
// Build imports
|
|
35
52
|
const imports = [
|
|
36
53
|
`use App\\Http\\Controllers\\Controller;`,
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
*/
|
|
4
4
|
import { toPascalCase } from './naming-helper.js';
|
|
5
5
|
import { toFaker, compoundFaker, associationFaker } from './faker-mapper.js';
|
|
6
|
-
import { userFile } from './types.js';
|
|
6
|
+
import { userFile, nestByGroup } from './types.js';
|
|
7
7
|
/** Generate Factory classes for all project-owned visible object schemas. */
|
|
8
8
|
export function generateFactories(reader, config) {
|
|
9
9
|
const files = [];
|
|
@@ -17,7 +17,14 @@ export function generateFactories(reader, config) {
|
|
|
17
17
|
}
|
|
18
18
|
function generateFactory(name, schema, reader, schemas, config) {
|
|
19
19
|
const modelName = toPascalCase(name);
|
|
20
|
-
|
|
20
|
+
// Issue #98 v5.8.4: legacy structure groups Models by folder, so the
|
|
21
|
+
// factory's `use ${modelNamespace}\\${modelName}` import must include
|
|
22
|
+
// the schema's group too — otherwise the factory references a flat
|
|
23
|
+
// path that no longer holds the model file. Modular structure
|
|
24
|
+
// already isolates per-schema so it skips the nesting.
|
|
25
|
+
const modelNamespace = config.structure === 'modular'
|
|
26
|
+
? config.models.namespace
|
|
27
|
+
: nestByGroup({ path: '', namespace: config.models.namespace }, schema.group).namespace;
|
|
21
28
|
const factoryNamespace = config.factories.namespace;
|
|
22
29
|
const properties = (schema.properties ?? {});
|
|
23
30
|
const expandedProperties = reader.getExpandedProperties(name);
|
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
import { toPascalCase, toSnakeCase, toCamelCase, pluralize } 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, resolveModularBasePath, resolveModularBaseNamespace, resolveSharedBaseNamespace, resolveGlobalTraitNamespace, resolveGlobalEnumNamespace, resolveBaseClass, resolveEditableClass, nestByGroup, } from './types.js';
|
|
7
|
+
import { baseFile, userFile, resolveModularBasePath, resolveModularBaseNamespace, resolveSharedBaseNamespace, resolveGlobalTraitNamespace, resolveGlobalEnumNamespace, resolveBaseClass, resolveEditableClass, nestByGroup, nestEditableByGroup, } from './types.js';
|
|
8
8
|
import { enumClassName } from './enum-generator.js';
|
|
9
9
|
/** Generate base model and user model for all project-owned object schemas,
|
|
10
10
|
* plus user models for package schemas (extending the package model). */
|
|
@@ -42,6 +42,13 @@ function generateBaseModel(name, schema, reader, config) {
|
|
|
42
42
|
// below) is the PARENT class string (BaseModel / Authenticatable).
|
|
43
43
|
// Issue #98 v5.8+: apply group-by-folder nesting in legacy structure
|
|
44
44
|
// so 100+ schemas produce a navigable tree mirroring schemas/<group>/.
|
|
45
|
+
// v5.8.5: pivot schemas (`kind: pivot`) override group → all pivot
|
|
46
|
+
// models live under a dedicated `Pivot/` subfolder regardless of the
|
|
47
|
+
// YAML group, mirroring the dedicated `Translation/` subfolder. Devs
|
|
48
|
+
// rarely interact with pivot models directly (Eloquent uses them
|
|
49
|
+
// implicitly), so consolidating them keeps the main model namespace
|
|
50
|
+
// clean.
|
|
51
|
+
const isPivot = schema.kind === 'pivot';
|
|
45
52
|
let baseDescriptor;
|
|
46
53
|
let baseNamespace;
|
|
47
54
|
if (config.structure === 'modular') {
|
|
@@ -54,7 +61,9 @@ function generateBaseModel(name, schema, reader, config) {
|
|
|
54
61
|
}
|
|
55
62
|
else {
|
|
56
63
|
const raw = resolveBaseClass(config.models, modelName, 'BaseModel');
|
|
57
|
-
const nested =
|
|
64
|
+
const nested = isPivot
|
|
65
|
+
? { path: `${raw.path}/Pivot`, namespace: `${raw.fqn.substring(0, raw.fqn.lastIndexOf('\\'))}\\Pivot` }
|
|
66
|
+
: nestByGroup({ path: raw.path, namespace: raw.fqn.substring(0, raw.fqn.lastIndexOf('\\')) }, schema.group);
|
|
58
67
|
baseDescriptor = { className: raw.className, path: nested.path, fqn: `${nested.namespace}\\${raw.className}` };
|
|
59
68
|
baseNamespace = nested.namespace;
|
|
60
69
|
}
|
|
@@ -221,7 +230,11 @@ function generateUserModel(name, schema, config, hasNestedSet = false) {
|
|
|
221
230
|
// than the base (e.g. `app/Models/<Name>.php` while base is at
|
|
222
231
|
// `app/Omnify/Models/<Name>.php`). resolveEditableClass +
|
|
223
232
|
// resolveBaseClass keep the extends-clause + use-import in sync.
|
|
224
|
-
// Issue #98 v5.8
|
|
233
|
+
// Issue #98 v5.8.5: pivot schemas always nest under `Pivot/` on
|
|
234
|
+
// both base AND editable sides regardless of `userEditableGroupByFolder`.
|
|
235
|
+
// Pivots are infrastructure — keeping them out of the main namespace
|
|
236
|
+
// mirrors how Laravel devs treat `Illuminate\Database\Eloquent\Relations\Pivot`.
|
|
237
|
+
const isPivot = schema.kind === 'pivot';
|
|
225
238
|
let editable;
|
|
226
239
|
let base;
|
|
227
240
|
if (config.structure === 'modular') {
|
|
@@ -230,10 +243,14 @@ function generateUserModel(name, schema, config, hasNestedSet = false) {
|
|
|
230
243
|
}
|
|
231
244
|
else {
|
|
232
245
|
const editRaw = resolveEditableClass(config.models, modelName);
|
|
233
|
-
const editNested =
|
|
246
|
+
const editNested = isPivot
|
|
247
|
+
? { path: `${editRaw.path}/Pivot`, namespace: `${editRaw.namespace}\\Pivot` }
|
|
248
|
+
: nestEditableByGroup(config.models, { path: editRaw.path, namespace: editRaw.namespace }, schema.group);
|
|
234
249
|
editable = { className: editRaw.className, fileName: editRaw.fileName, namespace: editNested.namespace, path: editNested.path, fqn: `${editNested.namespace}\\${editRaw.className}` };
|
|
235
250
|
const baseRaw = resolveBaseClass(config.models, modelName, 'BaseModel');
|
|
236
|
-
const baseNs =
|
|
251
|
+
const baseNs = isPivot
|
|
252
|
+
? `${baseRaw.fqn.substring(0, baseRaw.fqn.lastIndexOf('\\'))}\\Pivot`
|
|
253
|
+
: nestByGroup({ path: baseRaw.path, namespace: baseRaw.fqn.substring(0, baseRaw.fqn.lastIndexOf('\\')) }, schema.group).namespace;
|
|
237
254
|
base = { className: baseRaw.className, fqn: `${baseNs}\\${baseRaw.className}` };
|
|
238
255
|
}
|
|
239
256
|
const factoryNamespace = config.factories.namespace;
|
|
@@ -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, resolveModularBasePath, resolveModularBaseNamespace, resolveBaseClass, resolveEditableClass, nestByGroup } from './types.js';
|
|
8
|
+
import { baseFile, userFile, resolveModularBasePath, resolveModularBaseNamespace, resolveBaseClass, resolveEditableClass, nestByGroup, nestEditableByGroup } from './types.js';
|
|
9
9
|
// ============================================================================
|
|
10
10
|
// Action mapping: Omnify → Laravel
|
|
11
11
|
// ============================================================================
|
|
@@ -46,7 +46,13 @@ function generateForSchema(name, schema, reader, config) {
|
|
|
46
46
|
function generateBasePolicyClass(name, schema, reader, config) {
|
|
47
47
|
const modelName = toPascalCase(name);
|
|
48
48
|
const baseNamespace = resolveModularBaseNamespace(config, name, 'Policies', config.policies.baseNamespace);
|
|
49
|
-
|
|
49
|
+
// Issue #98 v5.8.4: legacy structure groups Models by folder. The
|
|
50
|
+
// policy's `use ${modelNamespace}\\${modelName}` import must include
|
|
51
|
+
// the schema's group too, otherwise the policy fails to autoload at
|
|
52
|
+
// runtime when Laravel resolves it from the gate registration.
|
|
53
|
+
const modelNamespace = config.structure === 'modular'
|
|
54
|
+
? config.models.namespace
|
|
55
|
+
: nestByGroup({ path: '', namespace: config.models.namespace }, schema.group).namespace;
|
|
50
56
|
const policies = schema.policies;
|
|
51
57
|
const hasSoftDelete = schema.options?.softDelete ?? false;
|
|
52
58
|
const needsCidrHelper = policiesUseCidr(policies);
|
|
@@ -122,7 +128,7 @@ function generateUserPolicyClass(name, schema, config) {
|
|
|
122
128
|
const baseNs = nestByGroup({ path: baseRaw.path, namespace: baseRaw.fqn.substring(0, baseRaw.fqn.lastIndexOf('\\')) }, schema.group).namespace;
|
|
123
129
|
baseDescriptor = { className: baseRaw.className, fqn: `${baseNs}\\${baseRaw.className}` };
|
|
124
130
|
const editRaw = resolveEditableClass(config.policies, modelName, 'Policy');
|
|
125
|
-
const editNested =
|
|
131
|
+
const editNested = nestEditableByGroup(config.policies, { path: editRaw.path, namespace: editRaw.namespace }, schema.group);
|
|
126
132
|
editable = { className: editRaw.className, fileName: editRaw.fileName, namespace: editNested.namespace, path: editNested.path };
|
|
127
133
|
}
|
|
128
134
|
// Issue #98: alias on class-name collision (flatBase + userEditablePath).
|
|
@@ -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, resolveModularBasePath, resolveModularBaseNamespace, resolveBaseClass, resolveEditableClass, nestByGroup } from './types.js';
|
|
6
|
+
import { baseFile, userFile, resolveModularBasePath, resolveModularBaseNamespace, resolveBaseClass, resolveEditableClass, nestByGroup, nestEditableByGroup } from './types.js';
|
|
7
7
|
/**
|
|
8
8
|
* Resolve the Laravel validation rule type ('integer', 'uuid', or 'string') for
|
|
9
9
|
* a foreign key column based on the target schema's primary key type.
|
|
@@ -294,7 +294,7 @@ function generateUserRequest(name, schema, config, action) {
|
|
|
294
294
|
const baseNs = nestByGroup({ path: baseRaw.path, namespace: baseRaw.fqn.substring(0, baseRaw.fqn.lastIndexOf('\\')) }, schema.group).namespace;
|
|
295
295
|
baseDescriptor = { className: baseRaw.className, fqn: `${baseNs}\\${baseRaw.className}` };
|
|
296
296
|
const editRaw = resolveEditableClass(config.requests, modelName, `${action}Request`);
|
|
297
|
-
const editNested =
|
|
297
|
+
const editNested = nestEditableByGroup(config.requests, { path: editRaw.path, namespace: editRaw.namespace }, schema.group);
|
|
298
298
|
editable = { className: editRaw.className, fileName: editRaw.fileName, namespace: editNested.namespace, path: editNested.path };
|
|
299
299
|
}
|
|
300
300
|
// Issue #98: alias on class-name collision (flatBase + userEditablePath).
|
|
@@ -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, resolveModularBasePath, resolveModularBaseNamespace, resolveBaseClass, resolveEditableClass, nestByGroup } from './types.js';
|
|
6
|
+
import { baseFile, userFile, resolveModularBasePath, resolveModularBaseNamespace, resolveBaseClass, resolveEditableClass, nestByGroup, nestEditableByGroup } 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 = [];
|
|
@@ -158,7 +158,7 @@ function generateUserResource(name, schema, config) {
|
|
|
158
158
|
const baseNs = nestByGroup({ path: baseRaw.path, namespace: baseRaw.fqn.substring(0, baseRaw.fqn.lastIndexOf('\\')) }, schema.group).namespace;
|
|
159
159
|
baseDescriptor = { className: baseRaw.className, fqn: `${baseNs}\\${baseRaw.className}` };
|
|
160
160
|
const editRaw = resolveEditableClass(config.resources, modelName, 'Resource');
|
|
161
|
-
const editNested =
|
|
161
|
+
const editNested = nestEditableByGroup(config.resources, { path: editRaw.path, namespace: editRaw.namespace }, schema.group);
|
|
162
162
|
editable = { className: editRaw.className, fileName: editRaw.fileName, namespace: editNested.namespace, path: editNested.path };
|
|
163
163
|
}
|
|
164
164
|
// Issue #98: alias on class-name collision (flatBase + userEditablePath).
|
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
* Only includes properties that have searchable/filterable/sortable flags.
|
|
6
6
|
*/
|
|
7
7
|
import { toPascalCase, toSnakeCase } from './naming-helper.js';
|
|
8
|
-
import { baseFile } from './types.js';
|
|
8
|
+
import { baseFile, nestByGroup } from './types.js';
|
|
9
9
|
/** Generate the omnify-schemas config file. */
|
|
10
10
|
export function generateSchemaConfig(reader, config) {
|
|
11
11
|
const apiSchemas = reader.getSchemasWithApi();
|
|
@@ -64,9 +64,16 @@ function generateSchemaEntry(name, schema, reader, config) {
|
|
|
64
64
|
const propsBlock = propLines.length > 0
|
|
65
65
|
? `\n 'properties' => [\n${propLines.join('\n')}\n ],`
|
|
66
66
|
: `\n 'properties' => [],`;
|
|
67
|
+
// Issue #98 v5.8.4: Query Engine resolves `model` via reflection, so
|
|
68
|
+
// the FQN must reflect the actual file location (which now includes
|
|
69
|
+
// the schema's group folder for legacy structure). Modular structure
|
|
70
|
+
// already isolates per-schema so it skips the nesting.
|
|
71
|
+
const modelNs = config.structure === 'modular'
|
|
72
|
+
? config.models.namespace
|
|
73
|
+
: nestByGroup({ path: '', namespace: config.models.namespace }, schema.group).namespace;
|
|
67
74
|
return ` '${modelName}' => [
|
|
68
75
|
'table' => '${tableName}',
|
|
69
|
-
'model' => \\${
|
|
76
|
+
'model' => \\${modelNs}\\${modelName}::class,
|
|
70
77
|
'softDelete' => ${softDelete ? 'true' : 'false'},
|
|
71
78
|
'perPage' => ${perPage},${propsBlock}
|
|
72
79
|
],
|
|
@@ -13,7 +13,7 @@
|
|
|
13
13
|
* eagerCount}` keys are deprecated and emit warnings at generate time.
|
|
14
14
|
*/
|
|
15
15
|
import { toPascalCase, toSnakeCase } from './naming-helper.js';
|
|
16
|
-
import { baseFile, userFile, resolveModularBasePath, resolveModularBaseNamespace, resolveBaseClass, resolveEditableClass, nestByGroup } from './types.js';
|
|
16
|
+
import { baseFile, userFile, resolveModularBasePath, resolveModularBaseNamespace, resolveBaseClass, resolveEditableClass, nestByGroup, nestEditableByGroup } from './types.js';
|
|
17
17
|
// ============================================================================
|
|
18
18
|
// Public entry point
|
|
19
19
|
// ============================================================================
|
|
@@ -510,7 +510,15 @@ function generateBaseService(name, schema, reader, config) {
|
|
|
510
510
|
const baseNs = config.structure === 'modular'
|
|
511
511
|
? resolveModularBaseNamespace(config, name, 'Services', config.services.baseNamespace)
|
|
512
512
|
: nestByGroup({ path: '', namespace: config.services.baseNamespace }, schema.group).namespace;
|
|
513
|
-
|
|
513
|
+
// Issue #98 v5.8.4: cross-layer Model imports must include the
|
|
514
|
+
// schema's group folder so they resolve to where Models actually
|
|
515
|
+
// live now. Pre-fix the service base emitted
|
|
516
|
+
// `use App\Omnify\Models\Banner;` while the model file was at
|
|
517
|
+
// `app/Omnify/Models/Cms/Banner.php` — autoload failed at runtime
|
|
518
|
+
// for every consumer (TypeError + missing-file include).
|
|
519
|
+
const modelNs = config.structure === 'modular'
|
|
520
|
+
? config.models.namespace
|
|
521
|
+
: nestByGroup({ path: '', namespace: config.models.namespace }, schema.group).namespace;
|
|
514
522
|
// Build imports
|
|
515
523
|
const imports = [
|
|
516
524
|
`use ${modelNs}\\${modelName};`,
|
|
@@ -1784,7 +1792,7 @@ function generateUserService(name, schema, config) {
|
|
|
1784
1792
|
const baseNs = nestByGroup({ path: baseRaw.path, namespace: baseRaw.fqn.substring(0, baseRaw.fqn.lastIndexOf('\\')) }, schema.group).namespace;
|
|
1785
1793
|
baseDescriptor = { className: baseRaw.className, fqn: `${baseNs}\\${baseRaw.className}` };
|
|
1786
1794
|
const editRaw = resolveEditableClass(config.services, modelName, 'Service');
|
|
1787
|
-
const editNested =
|
|
1795
|
+
const editNested = nestEditableByGroup(config.services, { path: editRaw.path, namespace: editRaw.namespace }, schema.group);
|
|
1788
1796
|
editable = { className: editRaw.className, fileName: editRaw.fileName, namespace: editNested.namespace, path: editNested.path };
|
|
1789
1797
|
}
|
|
1790
1798
|
// Group nesting already applied via nestByGroup above; no additional
|
|
@@ -2,15 +2,23 @@
|
|
|
2
2
|
* Port of AppServiceProviderGenerator.php — generates OmnifyServiceProvider.
|
|
3
3
|
*/
|
|
4
4
|
import { toPascalCase } from './naming-helper.js';
|
|
5
|
-
import { baseFile } from './types.js';
|
|
5
|
+
import { baseFile, nestByGroup } from './types.js';
|
|
6
6
|
/** Generate the OmnifyServiceProvider for the application. */
|
|
7
7
|
export function generateServiceProvider(reader, config) {
|
|
8
8
|
const modelNamespace = config.models.namespace;
|
|
9
|
-
// Build morph map entries (project-owned schemas only)
|
|
9
|
+
// Build morph map entries (project-owned schemas only). Issue #98 v5.8.4:
|
|
10
|
+
// each schema's actual model FQN includes its group folder, so the
|
|
11
|
+
// morph map must echo that — pre-fix every entry pointed to the flat
|
|
12
|
+
// `App\Omnify\Models\<Name>::class` and Laravel's morphMap resolved to
|
|
13
|
+
// a non-existent class for every grouped schema, breaking polymorphic
|
|
14
|
+
// relationships project-wide.
|
|
10
15
|
const morphEntries = [];
|
|
11
|
-
for (const name of Object.
|
|
16
|
+
for (const [name, schema] of Object.entries(reader.getProjectVisibleObjectSchemas())) {
|
|
12
17
|
const modelName = toPascalCase(name);
|
|
13
|
-
|
|
18
|
+
const ns = config.structure === 'modular'
|
|
19
|
+
? modelNamespace
|
|
20
|
+
: nestByGroup({ path: '', namespace: modelNamespace }, schema.group).namespace;
|
|
21
|
+
morphEntries.push(` '${modelName}' => \\${ns}\\${modelName}::class,`);
|
|
14
22
|
}
|
|
15
23
|
// Add File to morph map when any schema uses File type
|
|
16
24
|
if (reader.hasFileProperties()) {
|
package/dist/php/types.d.ts
CHANGED
|
@@ -113,6 +113,26 @@ export interface LaravelPathOverride {
|
|
|
113
113
|
* isolates generated code (e.g. `app/Omnify/Models/`).
|
|
114
114
|
*/
|
|
115
115
|
flatBase?: boolean;
|
|
116
|
+
/**
|
|
117
|
+
* Issue #98 v5.8.5: per-layer toggle for whether the USER-EDITABLE
|
|
118
|
+
* stub is grouped by the schema's parent folder. The base layer is
|
|
119
|
+
* always grouped (canonical layout — domain-organized regenerated
|
|
120
|
+
* code), but Laravel ecosystem code (`app/Models/`, `app/Services/`,
|
|
121
|
+
* `app/Http/Requests/`, `app/Http/Resources/`) is canonically FLAT —
|
|
122
|
+
* `App\Models\User`, not `App\Models\Auth\User`. `config/auth.php`,
|
|
123
|
+
* Sanctum traits, factory discovery and dozens of ecosystem packages
|
|
124
|
+
* assume the flat shape.
|
|
125
|
+
*
|
|
126
|
+
* Default: `false` (Laravel-canonical flat editable). The grouped
|
|
127
|
+
* base + flat editable layout is what new `composer create-project
|
|
128
|
+
* laravel/laravel` apps produce, and the use-statement in the editable
|
|
129
|
+
* stub still aliases the GROUPED base FQN — group is encoded in the
|
|
130
|
+
* `use ... as ...Base` import, not the editable's namespace.
|
|
131
|
+
*
|
|
132
|
+
* Projects that adopted v5.8.x and want to keep their grouped editable
|
|
133
|
+
* layout flip this to `true` per layer.
|
|
134
|
+
*/
|
|
135
|
+
userEditableGroupByFolder?: boolean;
|
|
116
136
|
}
|
|
117
137
|
/** Nested set package configuration. */
|
|
118
138
|
export interface NestedSetOverride {
|
|
@@ -225,6 +245,15 @@ export interface BaseEditableLayer {
|
|
|
225
245
|
* extends `\{namespace}\{Schema}` (no `BaseModel` indirection). Issue #96.
|
|
226
246
|
*/
|
|
227
247
|
flatBase: boolean;
|
|
248
|
+
/**
|
|
249
|
+
* Issue #98 v5.8.5: when `true`, the user-editable layer is also
|
|
250
|
+
* grouped by the schema's parent folder (mirrors the base layer).
|
|
251
|
+
* Default `false` — Laravel-canonical flat layout (`app/Models/User.php`,
|
|
252
|
+
* not `app/Models/Auth/User.php`). Group is encoded only in the base
|
|
253
|
+
* layer + the `use ... as Base` import inside the editable stub.
|
|
254
|
+
* The base layer is unaffected — it is always grouped.
|
|
255
|
+
*/
|
|
256
|
+
userEditableGroupByFolder: boolean;
|
|
228
257
|
}
|
|
229
258
|
/** PHP codegen configuration (resolved with defaults). */
|
|
230
259
|
export interface PhpConfig {
|
|
@@ -347,6 +376,21 @@ export declare function resolveEditableClass(layer: BaseEditableLayer, schemaNam
|
|
|
347
376
|
path: string;
|
|
348
377
|
fqn: string;
|
|
349
378
|
};
|
|
379
|
+
/**
|
|
380
|
+
* Issue #98 v5.8.5: gate group nesting for the user-editable layer on
|
|
381
|
+
* `layer.userEditableGroupByFolder`. Default flat (Laravel-canonical) —
|
|
382
|
+
* `app/Models/User.php`, `App\Models\User`. Opt-in to mirror-base via
|
|
383
|
+
* `userEditableGroupByFolder: true` per layer. Auxiliary subfolders
|
|
384
|
+
* (Translation/, Pivot/, Enum/) are imposed elsewhere and are NOT
|
|
385
|
+
* affected by this flag — they always nest.
|
|
386
|
+
*/
|
|
387
|
+
export declare function nestEditableByGroup(layer: BaseEditableLayer, loc: {
|
|
388
|
+
path: string;
|
|
389
|
+
namespace: string;
|
|
390
|
+
}, group: string | undefined): {
|
|
391
|
+
path: string;
|
|
392
|
+
namespace: string;
|
|
393
|
+
};
|
|
350
394
|
/**
|
|
351
395
|
* Derive full PHP config from optional overrides.
|
|
352
396
|
* All paths and namespaces fall back to sensible defaults.
|
package/dist/php/types.js
CHANGED
|
@@ -197,7 +197,11 @@ nsFromPath) {
|
|
|
197
197
|
: path;
|
|
198
198
|
const userEditableNamespace = override?.userEditableNamespace
|
|
199
199
|
?? (override?.userEditablePath ? nsFromPath(userEditablePath) : namespace);
|
|
200
|
-
|
|
200
|
+
// Issue #98 v5.8.5: the user-editable layer is FLAT (Laravel-canonical)
|
|
201
|
+
// by default. Project explicitly opts back into the v5.8.x grouped
|
|
202
|
+
// editable shape via `userEditableGroupByFolder: true` per layer.
|
|
203
|
+
const userEditableGroupByFolder = override?.userEditableGroupByFolder ?? false;
|
|
204
|
+
return { namespace, baseNamespace, path, basePath, userEditablePath, userEditableNamespace, flatBase, userEditableGroupByFolder };
|
|
201
205
|
}
|
|
202
206
|
/**
|
|
203
207
|
* Class-name + file-name resolver for the BASE class of a layer. Returns
|
|
@@ -234,6 +238,19 @@ export function resolveEditableClass(layer, schemaName, classSuffix = '') {
|
|
|
234
238
|
fqn: `${layer.userEditableNamespace}\\${className}`,
|
|
235
239
|
};
|
|
236
240
|
}
|
|
241
|
+
/**
|
|
242
|
+
* Issue #98 v5.8.5: gate group nesting for the user-editable layer on
|
|
243
|
+
* `layer.userEditableGroupByFolder`. Default flat (Laravel-canonical) —
|
|
244
|
+
* `app/Models/User.php`, `App\Models\User`. Opt-in to mirror-base via
|
|
245
|
+
* `userEditableGroupByFolder: true` per layer. Auxiliary subfolders
|
|
246
|
+
* (Translation/, Pivot/, Enum/) are imposed elsewhere and are NOT
|
|
247
|
+
* affected by this flag — they always nest.
|
|
248
|
+
*/
|
|
249
|
+
export function nestEditableByGroup(layer, loc, group) {
|
|
250
|
+
if (!layer.userEditableGroupByFolder)
|
|
251
|
+
return loc;
|
|
252
|
+
return nestByGroup(loc, group);
|
|
253
|
+
}
|
|
237
254
|
// Default paths.
|
|
238
255
|
//
|
|
239
256
|
// Hybrid projects (manual team code + Omnify codegen) need Omnify-generated
|