@omnifyjp/omnify 5.9.0 → 5.9.2
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.9.
|
|
3
|
+
"version": "5.9.2",
|
|
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.9.
|
|
40
|
-
"@omnifyjp/omnify-darwin-x64": "5.9.
|
|
41
|
-
"@omnifyjp/omnify-linux-x64": "5.9.
|
|
42
|
-
"@omnifyjp/omnify-linux-arm64": "5.9.
|
|
43
|
-
"@omnifyjp/omnify-win32-x64": "5.9.
|
|
39
|
+
"@omnifyjp/omnify-darwin-arm64": "5.9.2",
|
|
40
|
+
"@omnifyjp/omnify-darwin-x64": "5.9.2",
|
|
41
|
+
"@omnifyjp/omnify-linux-x64": "5.9.2",
|
|
42
|
+
"@omnifyjp/omnify-linux-arm64": "5.9.2",
|
|
43
|
+
"@omnifyjp/omnify-win32-x64": "5.9.2"
|
|
44
44
|
}
|
|
45
45
|
}
|
|
@@ -115,7 +115,7 @@ function generateBaseModel(name, schema, reader, config) {
|
|
|
115
115
|
// the generated base model.
|
|
116
116
|
const hasAuditLog = reader.isAuditLogEnabled(name);
|
|
117
117
|
const imports = buildImports(baseNamespace, modelName, hasSoftDelete, isAuthenticatable, hasTranslatable, properties, needsUuidTrait, needsUlidTrait, hasNestedSet, config.nestedset.namespace, hasFiles, modelNamespace, localesNamespace, traitsNamespace, sharedModelsNamespace, config, hasAuditLog);
|
|
118
|
-
const docProperties = buildDocProperties(properties, expandedProperties, propertyOrder);
|
|
118
|
+
const docProperties = buildDocProperties(properties, expandedProperties, propertyOrder, reader, config);
|
|
119
119
|
const baseClass = isAuthenticatable ? 'Authenticatable' : 'BaseModel';
|
|
120
120
|
const implementsClause = hasTranslatable ? ' implements TranslatableContract' : '';
|
|
121
121
|
const traits = buildTraits(hasSoftDelete, isAuthenticatable, hasTranslatable, needsUuidTrait, needsUlidTrait, hasNestedSet, hasFiles, hasAuditLog);
|
|
@@ -386,12 +386,14 @@ function buildImports(baseNamespace, modelName, hasSoftDelete, isAuthenticatable
|
|
|
386
386
|
}
|
|
387
387
|
}
|
|
388
388
|
if (hasAuditLog) {
|
|
389
|
-
// HasOmnifyAuditLog is a
|
|
390
|
-
// audit-trait-generator.ts
|
|
391
|
-
//
|
|
392
|
-
//
|
|
389
|
+
// HasOmnifyAuditLog is a GLOBAL Omnify trait emitted by
|
|
390
|
+
// audit-trait-generator.ts at `config.models.baseNamespace\Traits`
|
|
391
|
+
// (e.g. App\Models\Omnify\Base\Traits). The import here must resolve to
|
|
392
|
+
// that SAME global namespace — using the per-model (group) `baseNamespace`
|
|
393
|
+
// (e.g. ...\Base\Logistics) yields `Base\Logistics\Traits\HasOmnifyAuditLog`
|
|
394
|
+
// which does not exist → "Trait not found" fatal on every model load.
|
|
393
395
|
const auditTraitsNs = config
|
|
394
|
-
? resolveGlobalTraitNamespace(config, baseNamespace + '\\Traits')
|
|
396
|
+
? resolveGlobalTraitNamespace(config, config.models.baseNamespace + '\\Traits')
|
|
395
397
|
: (traitsNamespace || baseNamespace + '\\Traits');
|
|
396
398
|
lines.push(`use ${auditTraitsNs}\\HasOmnifyAuditLog;`);
|
|
397
399
|
}
|
|
@@ -407,8 +409,14 @@ function buildImports(baseNamespace, modelName, hasSoftDelete, isAuthenticatable
|
|
|
407
409
|
}
|
|
408
410
|
return lines.join('\n') + '\n';
|
|
409
411
|
}
|
|
410
|
-
function buildDocProperties(properties, expandedProperties, propertyOrder) {
|
|
412
|
+
function buildDocProperties(properties, expandedProperties, propertyOrder, reader, config) {
|
|
411
413
|
const lines = [];
|
|
414
|
+
// Mirror buildCasts: EnumRef columns are cast to their generated enum class,
|
|
415
|
+
// so document them with that class (not `string`) — otherwise static analysis
|
|
416
|
+
// sees a string and rejects `$model->col->value` / enum comparisons.
|
|
417
|
+
const globalEnumNs = config
|
|
418
|
+
? resolveGlobalEnumNamespace(config, config.models.namespace)
|
|
419
|
+
: '';
|
|
412
420
|
for (const propName of propertyOrder) {
|
|
413
421
|
const prop = properties[propName];
|
|
414
422
|
if (!prop)
|
|
@@ -443,6 +451,16 @@ function buildDocProperties(properties, expandedProperties, propertyOrder) {
|
|
|
443
451
|
}
|
|
444
452
|
const nullable = prop['nullable'] ?? false;
|
|
445
453
|
const snakeName = toSnakeCase(propName);
|
|
454
|
+
// EnumRef → document the generated enum class (fully-qualified, matching the
|
|
455
|
+
// cast) only when the referenced enum schema exists; else fall through.
|
|
456
|
+
if (type === 'EnumRef') {
|
|
457
|
+
const enumName = prop['enum'];
|
|
458
|
+
if (typeof enumName === 'string' && reader.getSchema(enumName)?.kind === 'enum' && globalEnumNs) {
|
|
459
|
+
const enumType = `\\${globalEnumNs}\\${enumClassName(enumName)}`;
|
|
460
|
+
lines.push(` * @property ${nullable ? `${enumType}|null` : enumType} $${snakeName}`);
|
|
461
|
+
continue;
|
|
462
|
+
}
|
|
463
|
+
}
|
|
446
464
|
const phpDocType = toPhpDocType(type, nullable);
|
|
447
465
|
lines.push(` * @property ${phpDocType} $${snakeName}`);
|
|
448
466
|
}
|
|
@@ -195,7 +195,7 @@ namespace ${baseNamespace};
|
|
|
195
195
|
use Illuminate\\Foundation\\Http\\FormRequest;${ruleImport}
|
|
196
196
|
use ${localesClass};
|
|
197
197
|
|
|
198
|
-
|
|
198
|
+
class ${modelName}${action}RequestBase extends FormRequest
|
|
199
199
|
{
|
|
200
200
|
/**
|
|
201
201
|
* Determine if the user is authorized to make this request.
|
|
@@ -277,7 +277,10 @@ ${attributeKeysList}
|
|
|
277
277
|
const nested = nestByGroup({ path: raw.path, namespace: '' }, schema.group);
|
|
278
278
|
baseDescriptor = { className: raw.className, path: nested.path };
|
|
279
279
|
}
|
|
280
|
-
|
|
280
|
+
// Issue #114: the request base is the class controllers inject directly
|
|
281
|
+
// (#101) — so it must be CONCRETE, not abstract (an abstract FormRequest is
|
|
282
|
+
// not container-resolvable → BindingResolutionException / HTTP 500).
|
|
283
|
+
const finalContent = content.replace(new RegExp(`class ${modelName}${action}RequestBase\\b`, 'g'), `class ${baseDescriptor.className}`);
|
|
281
284
|
return baseFile(`${baseDescriptor.path}/${baseDescriptor.className}.php`, finalContent);
|
|
282
285
|
}
|
|
283
286
|
function generateUserRequest(name, schema, config, action) {
|
|
@@ -5,9 +5,12 @@ import { SchemaReader } from './schema-reader.js';
|
|
|
5
5
|
import type { GeneratedFile, PhpConfig } from './types.js';
|
|
6
6
|
/** Generate Resource classes for all project-owned visible object schemas.
|
|
7
7
|
*
|
|
8
|
-
* Issue #101 v5.8.23
|
|
9
|
-
*
|
|
10
|
-
*
|
|
11
|
-
*
|
|
8
|
+
* Issue #101 v5.8.23 emitted ONLY the base — but child resources embed a
|
|
9
|
+
* parent relation via `new \App\Http\Resources\<Parent>Resource(...)` (the
|
|
10
|
+
* editable sibling). With the sibling gone, any loaded relation fatals with a
|
|
11
|
+
* "class not found" Error (issue #114). So the editable sibling is re-emitted
|
|
12
|
+
* as a create-if-missing user file (`overwrite: false`): written once, never
|
|
13
|
+
* regenerated (so it is not the scaffolding noise #101 removed), and the
|
|
14
|
+
* cross-resource reference always resolves.
|
|
12
15
|
*/
|
|
13
16
|
export declare function generateResources(reader: SchemaReader, config: PhpConfig): GeneratedFile[];
|
|
@@ -6,10 +6,13 @@ import { isHiddenByDefault, toResourceExpression } from './type-mapper.js';
|
|
|
6
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
|
*
|
|
9
|
-
* Issue #101 v5.8.23
|
|
10
|
-
*
|
|
11
|
-
*
|
|
12
|
-
*
|
|
9
|
+
* Issue #101 v5.8.23 emitted ONLY the base — but child resources embed a
|
|
10
|
+
* parent relation via `new \App\Http\Resources\<Parent>Resource(...)` (the
|
|
11
|
+
* editable sibling). With the sibling gone, any loaded relation fatals with a
|
|
12
|
+
* "class not found" Error (issue #114). So the editable sibling is re-emitted
|
|
13
|
+
* as a create-if-missing user file (`overwrite: false`): written once, never
|
|
14
|
+
* regenerated (so it is not the scaffolding noise #101 removed), and the
|
|
15
|
+
* cross-resource reference always resolves.
|
|
13
16
|
*/
|
|
14
17
|
export function generateResources(reader, config) {
|
|
15
18
|
const files = [];
|
|
@@ -17,6 +20,7 @@ export function generateResources(reader, config) {
|
|
|
17
20
|
if (schema.kind === 'extend')
|
|
18
21
|
continue;
|
|
19
22
|
files.push(generateBaseResource(name, schema, reader, config));
|
|
23
|
+
files.push(generateUserResource(name, schema, config));
|
|
20
24
|
}
|
|
21
25
|
return files;
|
|
22
26
|
}
|