@omnifyjp/omnify 5.8.15 → 5.8.17

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@omnifyjp/omnify",
3
- "version": "5.8.15",
3
+ "version": "5.8.17",
4
4
  "description": "Schema-driven code generation for Laravel, TypeScript, and SQL",
5
5
  "license": "MIT",
6
6
  "repository": {
@@ -36,10 +36,10 @@
36
36
  "zod": "^3.24.0"
37
37
  },
38
38
  "optionalDependencies": {
39
- "@omnifyjp/omnify-darwin-arm64": "5.8.15",
40
- "@omnifyjp/omnify-darwin-x64": "5.8.15",
41
- "@omnifyjp/omnify-linux-x64": "5.8.15",
42
- "@omnifyjp/omnify-linux-arm64": "5.8.15",
43
- "@omnifyjp/omnify-win32-x64": "5.8.15"
39
+ "@omnifyjp/omnify-darwin-arm64": "5.8.17",
40
+ "@omnifyjp/omnify-darwin-x64": "5.8.17",
41
+ "@omnifyjp/omnify-linux-x64": "5.8.17",
42
+ "@omnifyjp/omnify-linux-arm64": "5.8.17",
43
+ "@omnifyjp/omnify-win32-x64": "5.8.17"
44
44
  }
45
45
  }
@@ -46,7 +46,7 @@ function generateBaseResource(name, schema, reader, config) {
46
46
  if (isHiddenByDefault(type) || hidden)
47
47
  continue;
48
48
  if (type === 'Association') {
49
- addAssociationFields(propName, prop, fields, resourceNamespace, modelNamespace, reader);
49
+ addAssociationFields(propName, prop, fields, resourceNamespace, modelNamespace, reader, config);
50
50
  continue;
51
51
  }
52
52
  if (expandedProperties[propName]) {
@@ -193,27 +193,38 @@ class ${editable.className} extends ${baseAlias}
193
193
  `;
194
194
  return userFile(`${editable.path}/${editable.fileName}`, content);
195
195
  }
196
- function addAssociationFields(propName, prop, fields, resourceNamespace, modelNamespace, reader) {
196
+ function addAssociationFields(propName, prop, fields, resourceNamespace, modelNamespace, reader, config) {
197
197
  const relation = prop['relation'] ?? '';
198
198
  const target = prop['target'] ?? '';
199
199
  const methodName = toCamelCase(propName);
200
- // Resolve resource namespace for the target (null if package without resource ns)
201
- // Issue #98 v5.8.12: nest the resource FQCN by the TARGET schema's
202
- // group folder so the inline `new \<ns>\<Name>Resource(...)` ref
203
- // matches where the target Resource file actually lives. Pre-fix
204
- // every cross-resource ref emitted FLAT (`use App\Omnify\Resources\PaymentProviderResource`)
205
- // while the file lived at `App\Omnify\Resources\Payments\PaymentProviderResource`
206
- // PHP autoload failed at runtime on every base resource that
207
- // referenced a sibling resource (whenLoaded relation).
208
- const rawTargetResNs = target ? reader.resolveResourceNamespace(target, resourceNamespace) : resourceNamespace;
209
- let targetResNs = rawTargetResNs;
210
- if (rawTargetResNs && rawTargetResNs === resourceNamespace) {
211
- // Project-owned target: nest by the target's group so the FQCN
212
- // matches the grouped base resource. Package targets keep their
213
- // own namespace.
200
+ // Resolve resource namespace for the target.
201
+ // Issue #98 v5.8.12 / #99 v5.8.17: cross-resource refs match where
202
+ // the target Resource file actually lives. Same pattern as the
203
+ // v5.8.10/11 model + service / controller fixes point at the
204
+ // EDITABLE so app code consistently resolves the same class:
205
+ // 1. Package target keep the package's resource namespace.
206
+ // 2. Project target on modular structure use the resource
207
+ // namespace as-is (modular has its own per-schema isolation).
208
+ // 3. `userEditableGroupByFolder: true` nest editable namespace
209
+ // by group so the FQCN matches the grouped editable file.
210
+ // 4. Default (flat editable) use the editable namespace as-is.
211
+ // v4 projects with `resource.namespace: App\\Http\\Resources`
212
+ // single-tier flat layout (#99) hit this path and stay flat.
213
+ const packageResNs = target ? reader.resolveResourceNamespace(target, resourceNamespace) : resourceNamespace;
214
+ let targetResNs = packageResNs;
215
+ if (packageResNs && packageResNs === resourceNamespace) {
216
+ // Project-owned target: switch to editable namespace + apply
217
+ // optional group nesting. Modular structure aligns base + editable
218
+ // on the same namespace so this is a no-op.
219
+ const editableNs = config.resources.userEditableNamespace || resourceNamespace;
214
220
  const targetSchema = target ? reader.getSchema(target) : undefined;
215
- if (targetSchema?.group) {
216
- targetResNs = `${rawTargetResNs}\\${toPascalCase(targetSchema.group)}`;
221
+ if (config.structure !== 'modular'
222
+ && config.resources.userEditableGroupByFolder
223
+ && targetSchema?.group) {
224
+ targetResNs = `${editableNs}\\${toPascalCase(targetSchema.group)}`;
225
+ }
226
+ else {
227
+ targetResNs = editableNs;
217
228
  }
218
229
  }
219
230
  // If target is a package schema without a resource namespace, use simple whenLoaded
@@ -5,24 +5,42 @@ import { toPascalCase } from './naming-helper.js';
5
5
  import { baseFile, nestByGroup } from './types.js';
6
6
  /** Generate the OmnifyServiceProvider for the application. */
7
7
  export function generateServiceProvider(reader, config) {
8
+ // Issue #98 v5.8.16: morph map entries point at the USER-EDITABLE
9
+ // class FQN, NOT the BASE. Same fix as v5.8.9 factory \$model,
10
+ // v5.8.10 model relations, v5.8.11 service / controller signatures —
11
+ // every layer that produces / type-hints model instances now uses
12
+ // the editable. Without this, Eloquent's `getMorphClass()` lookup
13
+ // misses (factory + relation output is `App\Models\<Name>`, but
14
+ // morph map keys point at `App\Omnify\Models\<Group>\<Name>`)
15
+ // and the runtime throws ClassMorphViolationException on every
16
+ // polymorphic relation in the project.
8
17
  const modelNamespace = config.models.namespace;
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.
18
+ const editableNamespace = config.models.userEditableNamespace;
19
+ const editableGrouped = config.models.userEditableGroupByFolder;
20
+ // Build morph map entries (project-owned schemas only).
15
21
  const morphEntries = [];
16
22
  for (const [name, schema] of Object.entries(reader.getProjectVisibleObjectSchemas())) {
17
23
  const modelName = toPascalCase(name);
18
- const ns = config.structure === 'modular'
19
- ? modelNamespace
20
- : nestByGroup({ path: '', namespace: modelNamespace }, schema.group).namespace;
24
+ let ns;
25
+ if (config.structure === 'modular') {
26
+ ns = modelNamespace;
27
+ }
28
+ else if (schema.kind === 'pivot') {
29
+ // Pivot models always live under `<editableNs>\Pivot` (issue #98 v5.8.5).
30
+ ns = `${editableNamespace}\\Pivot`;
31
+ }
32
+ else if (editableGrouped) {
33
+ ns = nestByGroup({ path: '', namespace: editableNamespace }, schema.group).namespace;
34
+ }
35
+ else {
36
+ ns = editableNamespace;
37
+ }
21
38
  morphEntries.push(` '${modelName}' => \\${ns}\\${modelName}::class,`);
22
39
  }
23
- // Add File to morph map when any schema uses File type
40
+ // Add File to morph map when any schema uses File type. File is a
41
+ // shared / global model — uses the editable namespace too.
24
42
  if (reader.hasFileProperties()) {
25
- morphEntries.push(` 'File' => \\${modelNamespace}\\File::class,`);
43
+ morphEntries.push(` 'File' => \\${editableNamespace}\\File::class,`);
26
44
  }
27
45
  morphEntries.sort();
28
46
  const morphMapContent = morphEntries.join('\n');