@omnifyjp/ts 5.8.13 → 5.8.14

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.
@@ -7,7 +7,25 @@
7
7
  import { SchemaReader } from './schema-reader.js';
8
8
  import type { GeneratedFile, PhpConfig } from './types.js';
9
9
  import type { SchemaDefinition, SingleCondition } from '../types.js';
10
- /** Generate Laravel Policy classes for all schemas that have policies. */
10
+ /** Generate Laravel Policy classes for project-owned visible schemas.
11
+ *
12
+ * Issue #98 v5.8.14: every `kind: object` schema now gets a generated
13
+ * policy base + editable stub by default — Laravel's policy
14
+ * auto-discovery (`App\\Models\\<Name>` → `App\\Policies\\<Name>Policy`)
15
+ * works out of the box without per-project Gate::policy(...) wiring.
16
+ *
17
+ * Skip rules:
18
+ * - `kind: pivot` — pivots have no API surface
19
+ * - `options.policy: false` — explicit per-schema opt-out
20
+ *
21
+ * Two code paths per schema:
22
+ * - Explicit Cedar-style `policies: [...]` → existing rule-based body
23
+ * generator (forbid / permit / when conditions).
24
+ * - No `policies:` declared → standard CRUD scaffolding (viewAny /
25
+ * view / create / update / delete + restore / forceDelete on
26
+ * softDelete). Default body: `return true;`. Project secures by
27
+ * overriding the method in the editable child.
28
+ */
11
29
  export declare function generatePolicies(reader: SchemaReader, config: PhpConfig): GeneratedFile[];
12
30
  /** Convert a single condition to a PHP expression. */
13
31
  export declare function conditionToPhp(cond: SingleCondition, schema: SchemaDefinition, reader: SchemaReader): string;
@@ -24,11 +24,31 @@ const RECORD_ACTIONS = new Set(['view', 'edit', 'delete']);
24
24
  // ============================================================================
25
25
  // Public API
26
26
  // ============================================================================
27
- /** Generate Laravel Policy classes for all schemas that have policies. */
27
+ /** Generate Laravel Policy classes for project-owned visible schemas.
28
+ *
29
+ * Issue #98 v5.8.14: every `kind: object` schema now gets a generated
30
+ * policy base + editable stub by default — Laravel's policy
31
+ * auto-discovery (`App\\Models\\<Name>` → `App\\Policies\\<Name>Policy`)
32
+ * works out of the box without per-project Gate::policy(...) wiring.
33
+ *
34
+ * Skip rules:
35
+ * - `kind: pivot` — pivots have no API surface
36
+ * - `options.policy: false` — explicit per-schema opt-out
37
+ *
38
+ * Two code paths per schema:
39
+ * - Explicit Cedar-style `policies: [...]` → existing rule-based body
40
+ * generator (forbid / permit / when conditions).
41
+ * - No `policies:` declared → standard CRUD scaffolding (viewAny /
42
+ * view / create / update / delete + restore / forceDelete on
43
+ * softDelete). Default body: `return true;`. Project secures by
44
+ * overriding the method in the editable child.
45
+ */
28
46
  export function generatePolicies(reader, config) {
29
47
  const files = [];
30
48
  for (const [name, schema] of Object.entries(reader.getProjectVisibleObjectSchemas())) {
31
- if (!schema.policies || schema.policies.length === 0)
49
+ if (schema.kind === 'pivot')
50
+ continue;
51
+ if (schema.options?.policy === false)
32
52
  continue;
33
53
  files.push(...generateForSchema(name, schema, reader, config));
34
54
  }
@@ -59,24 +79,36 @@ function generateBasePolicyClass(name, schema, reader, config) {
59
79
  : (config.models.userEditableGroupByFolder
60
80
  ? nestByGroup({ path: '', namespace: config.models.userEditableNamespace }, schema.group).namespace
61
81
  : config.models.userEditableNamespace);
62
- const policies = schema.policies;
82
+ // Issue #98 v5.8.14: when no Cedar-style `policies:` array is defined,
83
+ // emit the standard CRUD scaffold with `return true;` bodies.
84
+ // The project secures the policy by overriding methods in the
85
+ // editable child (e.g. `return $user->hasPermission('manage.banner');`).
86
+ const policies = schema.policies ?? [];
87
+ const hasExplicitPolicies = policies.length > 0;
63
88
  const hasSoftDelete = schema.options?.softDelete ?? false;
64
- const needsCidrHelper = policiesUseCidr(policies);
65
- // Collect all actions that have policies
66
- const expandedPolicies = expandWildcards(policies);
89
+ const needsCidrHelper = hasExplicitPolicies ? policiesUseCidr(policies) : false;
90
+ // Collect all actions that have policies (only relevant for the
91
+ // explicit-policy path; standard CRUD doesn't need wildcard expansion).
92
+ const expandedPolicies = hasExplicitPolicies ? expandWildcards(policies) : policies;
67
93
  // Build methods
68
94
  const methods = [];
69
95
  for (const action of ALL_ACTIONS) {
70
96
  const methodName = ACTION_METHOD_MAP[action];
71
97
  const hasRecord = RECORD_ACTIONS.has(action);
72
- const body = generateMethodBody(action, expandedPolicies, schema, reader, hasRecord);
98
+ const body = hasExplicitPolicies
99
+ ? generateMethodBody(action, expandedPolicies, schema, reader, hasRecord)
100
+ : ' return true;';
73
101
  methods.push(buildMethod(methodName, modelName, hasRecord, body));
74
102
  }
75
103
  // SoftDelete: restore + forceDelete
76
104
  if (hasSoftDelete) {
77
- const restoreBody = generateMethodBody('delete', expandedPolicies, schema, reader);
105
+ const restoreBody = hasExplicitPolicies
106
+ ? generateMethodBody('delete', expandedPolicies, schema, reader)
107
+ : ' return true;';
78
108
  methods.push(buildMethod('restore', modelName, true, restoreBody));
79
- const forceDeleteBody = generateMethodBody('delete', expandedPolicies, schema, reader);
109
+ const forceDeleteBody = hasExplicitPolicies
110
+ ? generateMethodBody('delete', expandedPolicies, schema, reader)
111
+ : ' return true;';
80
112
  methods.push(buildMethod('forceDelete', modelName, true, forceDeleteBody));
81
113
  }
82
114
  const cidrHelper = needsCidrHelper ? buildCidrHelper() : '';
package/dist/types.d.ts CHANGED
@@ -208,6 +208,17 @@ export interface SchemaOptions {
208
208
  * generate time).
209
209
  */
210
210
  readonly service?: ServiceOptions | false;
211
+ /**
212
+ * Per-schema opt-out for the auto-generated Policy. Issue #98 v5.8.14:
213
+ * every `kind: object` schema gets a generated policy base + editable
214
+ * stub by default. Set `policy: false` on schemas that should NOT have
215
+ * an authorization policy (translation tables, internal sidecars, etc).
216
+ * Cedar-style ABAC `policies:` array on the root schema definition
217
+ * still drives the generated method bodies when present; otherwise the
218
+ * generator emits a standard 5-method CRUD scaffold with
219
+ * `return true;` bodies for the project to override in the editable.
220
+ */
221
+ readonly policy?: false;
211
222
  /** Schema-level default ordering — generates a global Eloquent scope. Issue #40. */
212
223
  readonly defaultOrder?: readonly OrderByItem[];
213
224
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@omnifyjp/ts",
3
- "version": "5.8.13",
3
+ "version": "5.8.14",
4
4
  "description": "TypeScript model type generator from Omnify schemas.json",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",