@omnifyjp/omnify 5.8.9 → 5.8.11

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.9",
3
+ "version": "5.8.11",
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.9",
40
- "@omnifyjp/omnify-darwin-x64": "5.8.9",
41
- "@omnifyjp/omnify-linux-x64": "5.8.9",
42
- "@omnifyjp/omnify-linux-arm64": "5.8.9",
43
- "@omnifyjp/omnify-win32-x64": "5.8.9"
39
+ "@omnifyjp/omnify-darwin-arm64": "5.8.11",
40
+ "@omnifyjp/omnify-darwin-x64": "5.8.11",
41
+ "@omnifyjp/omnify-linux-x64": "5.8.11",
42
+ "@omnifyjp/omnify-linux-arm64": "5.8.11",
43
+ "@omnifyjp/omnify-win32-x64": "5.8.11"
44
44
  }
45
45
  }
@@ -42,7 +42,13 @@ function generateBaseController(name, schema, reader, config) {
42
42
  const baseNs = config.structure === 'modular'
43
43
  ? resolveModularBaseNamespace(config, name, 'Controllers', config.controllers.baseNamespace)
44
44
  : groupNestBase(config.controllers.baseNamespace);
45
- const modelNs = groupNestBase(config.models.namespace);
45
+ // Issue #98 v5.8.11: controller base methods type-hint the
46
+ // USER-EDITABLE Model — same reasoning as the service-generator
47
+ // signature fix. Without this, the controller's `show` /
48
+ // `update` / `destroy` route bindings resolve as base instances
49
+ // and every project-owned service / policy that takes the
50
+ // editable type fails with TypeError.
51
+ const modelNs = groupNestEditable(config.models.userEditableNamespace, config.models);
46
52
  const serviceBaseNs = config.structure === 'modular'
47
53
  ? resolveModularBaseNamespace(config, name, 'Services', config.services.baseNamespace)
48
54
  : groupNestBase(config.services.baseNamespace);
@@ -579,48 +579,46 @@ function buildCasts(properties, expandedProperties, propertyOrder, reader, confi
579
579
  return casts.map(c => ` ${c}`).join('\n') + '\n';
580
580
  }
581
581
  /**
582
- * Issue #98 v5.8.6: resolve the FQCN namespace of a related Model
583
- * for inline `belongsTo / hasMany / belongsToMany / morphTo` references.
584
- * The namespace must match the TARGET's CANONICAL CLASS LOCATION:
582
+ * Issue #98 v5.8.10: resolve the FQCN namespace of a related Model for
583
+ * inline `belongsTo / hasMany / belongsToMany / morphTo` references.
584
+ * Relations must resolve to the USER-EDITABLE class — that's what
585
+ * services / controllers / tests / seeders type-hint against, and what
586
+ * `<Target>::factory()` returns since v5.8.9. Pre-fix relations pointed
587
+ * at the BASE class FQN, so loaded relations were base instances and
588
+ * every downstream type-hinted call failed with `TypeError`. Same root
589
+ * cause + fix as the factory `$model` issue.
585
590
  *
586
- * 1. Package schemas return the package's namespace verbatim
587
- * (already handled by reader.resolveModelNamespace).
588
- * 2. Pivot schemas always nest under `Pivot/` regardless of any
589
- * group / flat flag (matches the dedicated `Pivot/` folder
590
- * enforced for pivot models).
591
- * 3. flatBase: true the BASE class is the user's canonical class
592
- * (no `*BaseModel` suffix, lives at the grouped path). Nest by
593
- * group so the FQCN matches the grouped base.
594
- * 4. flatBase: false + userEditableGroupByFolder: true — the editable
595
- * mirrors the base group. Nest by group so the FQCN matches the
596
- * grouped editable.
597
- * 5. flatBase: false + userEditableGroupByFolder: false (Laravel-
598
- * canonical default) — the editable is FLAT. Don't nest; the
599
- * FQCN matches the flat editable's location.
600
- *
601
- * Pre-v5.8.6 every relation emitted `\${modelNamespace}\${target}::class`
602
- * (flat) regardless of where the target's file actually lived. Grouped
603
- * projects (especially flatBase) hit `ErrorException: include(... no
604
- * such file)` on every cross-Model reference.
591
+ * Resolution rules (mirror `factory-generator.ts:resolveEditableModelNamespace`):
592
+ * 1. Package schemas — return the package's model namespace verbatim
593
+ * (we don't generate editable stubs for package schemas).
594
+ * 2. Pivot schemas nest under `<editableNs>\Pivot` regardless of
595
+ * any group / flag (matches the dedicated `Pivot/` subfolder).
596
+ * 3. `userEditableGroupByFolder: true` + target has group nest by
597
+ * group so the FQCN matches where the editable file lives.
598
+ * 4. Default flat editable namespace (Laravel-canonical
599
+ * `App\Models\<Name>`).
605
600
  */
606
601
  function resolveRelatedModelNamespace(target, modelNamespace, config, reader) {
607
- const baseNs = reader.resolveModelNamespace(target, modelNamespace);
608
- // Package schemasleave as-is.
609
- if (baseNs !== modelNamespace)
610
- return baseNs;
602
+ // Package schemas use their own model namespace (we don't generate
603
+ // editable stubs for them relations dispatch to the package class).
604
+ const packageNs = reader.resolveModelNamespace(target, modelNamespace);
605
+ if (packageNs !== modelNamespace)
606
+ return packageNs;
607
+ // Modular structure: editable shares per-Schema modular path.
608
+ if (config.structure === 'modular') {
609
+ return config.models.namespace;
610
+ }
611
611
  const targetSchema = reader.getSchema(target);
612
612
  if (!targetSchema)
613
- return baseNs;
613
+ return config.models.userEditableNamespace;
614
+ const editableNs = config.models.userEditableNamespace;
614
615
  if (targetSchema.kind === 'pivot') {
615
- return `${baseNs}\\Pivot`;
616
+ return `${editableNs}\\Pivot`;
616
617
  }
617
- // Nest by group when EITHER flatBase is on (base is canonical, grouped)
618
- // OR the editable explicitly mirrors the base group.
619
- const shouldNestByGroup = config.models.flatBase || config.models.userEditableGroupByFolder;
620
- if (shouldNestByGroup && targetSchema.group) {
621
- return `${baseNs}\\${toPascalCase(targetSchema.group)}`;
618
+ if (config.models.userEditableGroupByFolder && targetSchema.group) {
619
+ return `${editableNs}\\${toPascalCase(targetSchema.group)}`;
622
620
  }
623
- return baseNs;
621
+ return editableNs;
624
622
  }
625
623
  function buildRelations(schemaName, properties, propertyOrder, modelNamespace, reader, config) {
626
624
  const methods = [];
@@ -510,15 +510,24 @@ 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
- // 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).
513
+ // Issue #98 v5.8.11: service base methods type-hint the USER-EDITABLE
514
+ // Model class (`App\Models\Banner`), NOT the grouped base
515
+ // (`App\Omnify\Models\Cms\Banner`). PHP signature contravariance:
516
+ // when the user-editable child service overrides a base method,
517
+ // PHP requires the override's parameter type to be the SAME or
518
+ // WIDER than the parent's. The user-editable class is what app code
519
+ // type-hints against everywhere else (factory $model since v5.8.9,
520
+ // relations since v5.8.10, controllers, tests). Without this fix,
521
+ // every override of `find / create / update / delete` on every
522
+ // editable service blew up with a Fatal compile error.
523
+ // Modular structure: per-Schema isolation — base + editable share ns.
524
+ // Pivot schemas don't have services (kind:object only), so the only
525
+ // shape adjustment is `userEditableGroupByFolder` group nesting.
519
526
  const modelNs = config.structure === 'modular'
520
527
  ? config.models.namespace
521
- : nestByGroup({ path: '', namespace: config.models.namespace }, schema.group).namespace;
528
+ : (config.models.userEditableGroupByFolder
529
+ ? nestByGroup({ path: '', namespace: config.models.userEditableNamespace }, schema.group).namespace
530
+ : config.models.userEditableNamespace);
522
531
  // Build imports
523
532
  const imports = [
524
533
  `use ${modelNs}\\${modelName};`,