@izumisy-tailor/tailor-data-viewer 0.3.0 → 0.3.1

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.
@@ -64,7 +64,6 @@ interface TableMetadata {
64
64
  readonly name: string;
65
65
  readonly pluralForm: string;
66
66
  readonly description?: string;
67
- readonly readAllowedRoles: readonly string[];
68
67
  readonly fields: readonly FieldMetadata[];
69
68
  /** Relations (manyToOne, oneToOne, and oneToMany) */
70
69
  readonly relations?: readonly RelationMetadata[];
@@ -89,7 +88,6 @@ interface ProcessedTable {
89
88
  pluralForm: string;
90
89
  originalName: string;
91
90
  description?: string;
92
- readAllowedRoles: string[];
93
91
  fields: FieldMetadata[];
94
92
  relations: RelationMetadata[];
95
93
  }
@@ -29,26 +29,6 @@ function toCamelCase(str) {
29
29
  return str.charAt(0).toLowerCase() + str.slice(1);
30
30
  }
31
31
  /**
32
- * Extract allowed roles from gql permission policies
33
- * Only extracts roles from 'read' action policies with 'allow' permit
34
- */
35
- function extractReadAllowedRoles(gqlPermission) {
36
- if (!gqlPermission) return [];
37
- const roles = /* @__PURE__ */ new Set();
38
- for (const policy of gqlPermission) {
39
- if (policy.permit !== "allow") continue;
40
- const actions = policy.actions;
41
- if (!actions.includes("all") && !actions.includes("read")) continue;
42
- for (const condition of policy.conditions) {
43
- if (!Array.isArray(condition) || condition.length < 3) continue;
44
- const [left, operator, right] = condition;
45
- if (typeof left === "string" && operator === "in" && typeof right === "object" && right !== null && "user" in right && right.user === "roles") roles.add(left);
46
- if (typeof right === "string" && operator === "in" && typeof left === "object" && left !== null && "user" in left && left.user === "roles") roles.add(right);
47
- }
48
- }
49
- return Array.from(roles);
50
- }
51
- /**
52
32
  * Creates a custom generator that extracts table metadata for Data View
53
33
  */
54
34
  function dataViewerMetadataGenerator(options = {}) {
@@ -100,13 +80,11 @@ function dataViewerMetadataGenerator(options = {}) {
100
80
  };
101
81
  fields.push(fieldMetadata);
102
82
  }
103
- const readAllowedRoles = extractReadAllowedRoles(type.permissions.gql);
104
83
  return {
105
84
  name: toCamelCase(type.name),
106
85
  pluralForm: toCamelCase(type.pluralForm),
107
86
  originalName: type.name,
108
87
  description: type.description,
109
- readAllowedRoles,
110
88
  fields,
111
89
  relations
112
90
  };
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@izumisy-tailor/tailor-data-viewer",
3
3
  "private": false,
4
- "version": "0.3.0",
4
+ "version": "0.3.1",
5
5
  "type": "module",
6
6
  "description": "Flexible data viewer component for Tailor Platform",
7
7
  "files": [
@@ -414,7 +414,6 @@ describe("useCollectionVariables", () => {
414
414
  task: {
415
415
  name: "task",
416
416
  pluralForm: "tasks",
417
- readAllowedRoles: [],
418
417
  fields: [
419
418
  { name: "id", type: "uuid", required: true },
420
419
  { name: "title", type: "string", required: true },
@@ -22,7 +22,6 @@ import type { TableMetadata } from "../../generator/metadata-generator";
22
22
  type TestTable = {
23
23
  readonly name: "test";
24
24
  readonly pluralForm: "tests";
25
- readonly readAllowedRoles: readonly [];
26
25
  readonly fields: readonly [
27
26
  { readonly name: "id"; readonly type: "uuid"; readonly required: true },
28
27
  {
@@ -82,9 +81,13 @@ type AssertNumberField = TestQuery extends {
82
81
  : never;
83
82
  export const assertNumberField: AssertNumberField = true;
84
83
 
85
- // ✅ Enum fields produce in/nin with string arrays
84
+ // ✅ Enum fields produce literal union types from enumValues
86
85
  type AssertEnumField = TestQuery extends {
87
- status?: { eq?: string; in?: string[]; nin?: string[] };
86
+ status?: {
87
+ eq?: "active" | "inactive";
88
+ in?: ("active" | "inactive")[];
89
+ nin?: ("active" | "inactive")[];
90
+ };
88
91
  }
89
92
  ? true
90
93
  : never;
@@ -75,7 +75,6 @@ describe("inferColumns()", () => {
75
75
  const metadata = {
76
76
  name: "task",
77
77
  pluralForm: "tasks",
78
- readAllowedRoles: [],
79
78
  fields: [
80
79
  { name: "id", type: "uuid", required: true },
81
80
  { name: "title", type: "string", required: true },
@@ -204,7 +203,6 @@ describe("inferColumns() with metadata", () => {
204
203
  task: {
205
204
  name: "task",
206
205
  pluralForm: "tasks",
207
- readAllowedRoles: [],
208
206
  fields: [
209
207
  { name: "id", type: "uuid", required: true },
210
208
  { name: "title", type: "string", required: true },
@@ -370,7 +368,6 @@ describe("createColumnHelper()", () => {
370
368
  const metadata = {
371
369
  name: "order",
372
370
  pluralForm: "orders",
373
- readAllowedRoles: [],
374
371
  fields: [
375
372
  { name: "id", type: "uuid", required: true },
376
373
  { name: "name", type: "string", required: true },
@@ -390,7 +387,6 @@ describe("createColumnHelper()", () => {
390
387
  const metadata = {
391
388
  name: "order",
392
389
  pluralForm: "orders",
393
- readAllowedRoles: [],
394
390
  fields: [
395
391
  { name: "id", type: "uuid", required: true },
396
392
  { name: "name", type: "string", required: true },
@@ -274,6 +274,23 @@ type FieldTypeToTSType = {
274
274
  enum: string;
275
275
  };
276
276
 
277
+ /**
278
+ * Resolves the value type for a field, narrowing enum fields to their
279
+ * literal union when `enumValues` is present in the metadata.
280
+ *
281
+ * - enum field with `enumValues: readonly ["OPEN", "CLOSED"]` → `"OPEN" | "CLOSED"`
282
+ * - enum field without `enumValues` → `string` (fallback)
283
+ * - all other field types → `FieldTypeToTSType[T]` (unchanged)
284
+ */
285
+ type ResolveFieldValueType<
286
+ F,
287
+ T extends keyof FieldTypeToTSType,
288
+ > = T extends "enum"
289
+ ? F extends { readonly enumValues: readonly (infer V extends string)[] }
290
+ ? V
291
+ : string
292
+ : FieldTypeToTSType[T];
293
+
277
294
  /**
278
295
  * Resolves the value type for a filter operator.
279
296
  * `in`/`nin` operators accept arrays, `between` accepts `{ min, max }`,
@@ -324,7 +341,7 @@ export type BuildQueryVariables<TTable extends TableMetadata> = {
324
341
  }
325
342
  ? FieldTypeToFilterConfigType[T] extends infer FCT extends
326
343
  FilterConfig["type"]
327
- ? FilterInputForFieldType<FCT, FieldTypeToTSType[T]>
344
+ ? FilterInputForFieldType<FCT, ResolveFieldValueType<F, T>>
328
345
  : never
329
346
  : never;
330
347
  };
@@ -86,7 +86,6 @@ export interface TableMetadata {
86
86
  readonly name: string;
87
87
  readonly pluralForm: string;
88
88
  readonly description?: string;
89
- readonly readAllowedRoles: readonly string[];
90
89
  readonly fields: readonly FieldMetadata[];
91
90
  /** Relations (manyToOne, oneToOne, and oneToMany) */
92
91
  readonly relations?: readonly RelationMetadata[];
@@ -112,7 +111,6 @@ interface ProcessedTable {
112
111
  pluralForm: string;
113
112
  originalName: string; // PascalCase name for relation lookup
114
113
  description?: string;
115
- readAllowedRoles: string[];
116
114
  fields: FieldMetadata[];
117
115
  relations: RelationMetadata[];
118
116
  }
@@ -154,63 +152,6 @@ function toCamelCase(str: string): string {
154
152
  return str.charAt(0).toLowerCase() + str.slice(1);
155
153
  }
156
154
 
157
- /**
158
- * Extract allowed roles from gql permission policies
159
- * Only extracts roles from 'read' action policies with 'allow' permit
160
- */
161
- function extractReadAllowedRoles(
162
- gqlPermission?: readonly {
163
- conditions: readonly unknown[];
164
- actions: readonly ["all"] | readonly string[];
165
- permit: "allow" | "deny";
166
- description?: string;
167
- }[],
168
- ): string[] {
169
- if (!gqlPermission) return [];
170
-
171
- const roles = new Set<string>();
172
-
173
- for (const policy of gqlPermission) {
174
- // Only process 'allow' policies that include 'read' action
175
- if (policy.permit !== "allow") continue;
176
- const actions = policy.actions as readonly string[];
177
- if (!actions.includes("all") && !actions.includes("read")) continue;
178
-
179
- // Extract roles from conditions
180
- for (const condition of policy.conditions) {
181
- if (!Array.isArray(condition) || condition.length < 3) continue;
182
-
183
- const [left, operator, right] = condition;
184
-
185
- // Check for pattern: ["ROLE_NAME", "in", { user: "roles" }]
186
- if (
187
- typeof left === "string" &&
188
- operator === "in" &&
189
- typeof right === "object" &&
190
- right !== null &&
191
- "user" in right &&
192
- (right as { user: string }).user === "roles"
193
- ) {
194
- roles.add(left);
195
- }
196
-
197
- // Check for pattern: [{ user: "roles" }, "in", "ROLE_NAME"] (reversed)
198
- if (
199
- typeof right === "string" &&
200
- operator === "in" &&
201
- typeof left === "object" &&
202
- left !== null &&
203
- "user" in left &&
204
- (left as { user: string }).user === "roles"
205
- ) {
206
- roles.add(right);
207
- }
208
- }
209
- }
210
-
211
- return Array.from(roles);
212
- }
213
-
214
155
  /**
215
156
  * Parsed field type from TailorDB
216
157
  */
@@ -402,15 +343,11 @@ export function dataViewerMetadataGenerator(
402
343
  fields.push(fieldMetadata);
403
344
  }
404
345
 
405
- // Extract read allowed roles from gql permission
406
- const readAllowedRoles = extractReadAllowedRoles(type.permissions.gql);
407
-
408
346
  return {
409
347
  name: toCamelCase(type.name),
410
348
  pluralForm: toCamelCase(type.pluralForm),
411
349
  originalName: type.name,
412
350
  description: type.description,
413
- readAllowedRoles,
414
351
  fields,
415
352
  relations,
416
353
  };