@memoryengine/client 0.1.0
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/dist/index.d.ts +71 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +213 -0
- package/dist/index.js.map +1 -0
- package/dist/schemas/auth.d.ts +69 -0
- package/dist/schemas/auth.d.ts.map +1 -0
- package/dist/schemas/auth.js +55 -0
- package/dist/schemas/auth.js.map +1 -0
- package/dist/schemas/engram.d.ts +141 -0
- package/dist/schemas/engram.d.ts.map +1 -0
- package/dist/schemas/engram.js +140 -0
- package/dist/schemas/engram.js.map +1 -0
- package/dist/schemas/fields.d.ts +18 -0
- package/dist/schemas/fields.d.ts.map +1 -0
- package/dist/schemas/fields.js +28 -0
- package/dist/schemas/fields.js.map +1 -0
- package/dist/schemas/index.d.ts +9 -0
- package/dist/schemas/index.d.ts.map +1 -0
- package/dist/schemas/index.js +14 -0
- package/dist/schemas/index.js.map +1 -0
- package/dist/schemas/principal.d.ts +150 -0
- package/dist/schemas/principal.d.ts.map +1 -0
- package/dist/schemas/principal.js +119 -0
- package/dist/schemas/principal.js.map +1 -0
- package/dist/schemas/rpc.d.ts +1312 -0
- package/dist/schemas/rpc.d.ts.map +1 -0
- package/dist/schemas/rpc.js +137 -0
- package/dist/schemas/rpc.js.map +1 -0
- package/package.json +38 -0
- package/src/index.ts +415 -0
- package/src/schemas/auth.ts +79 -0
- package/src/schemas/engram.test.ts +59 -0
- package/src/schemas/engram.ts +194 -0
- package/src/schemas/fields.test.ts +38 -0
- package/src/schemas/fields.ts +35 -0
- package/src/schemas/index.ts +15 -0
- package/src/schemas/principal.ts +178 -0
- package/src/schemas/rpc.ts +291 -0
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
import { describe, expect, test } from "bun:test";
|
|
2
|
+
import { temporalQuerySchema } from "./engram";
|
|
3
|
+
|
|
4
|
+
describe("temporalQuerySchema", () => {
|
|
5
|
+
test("accepts empty object", () => {
|
|
6
|
+
expect(temporalQuerySchema.safeParse({}).success).toBe(true);
|
|
7
|
+
});
|
|
8
|
+
|
|
9
|
+
test("accepts single contains filter", () => {
|
|
10
|
+
const result = temporalQuerySchema.safeParse({
|
|
11
|
+
contains: "2024-01-01T00:00:00Z",
|
|
12
|
+
});
|
|
13
|
+
expect(result.success).toBe(true);
|
|
14
|
+
});
|
|
15
|
+
|
|
16
|
+
test("accepts single overlaps filter", () => {
|
|
17
|
+
const result = temporalQuerySchema.safeParse({
|
|
18
|
+
overlaps: ["2024-01-01T00:00:00Z", "2024-12-31T23:59:59Z"],
|
|
19
|
+
});
|
|
20
|
+
expect(result.success).toBe(true);
|
|
21
|
+
});
|
|
22
|
+
|
|
23
|
+
test("accepts single within filter", () => {
|
|
24
|
+
const result = temporalQuerySchema.safeParse({
|
|
25
|
+
within: ["2024-01-01T00:00:00Z", "2024-12-31T23:59:59Z"],
|
|
26
|
+
});
|
|
27
|
+
expect(result.success).toBe(true);
|
|
28
|
+
});
|
|
29
|
+
|
|
30
|
+
test("rejects contains + overlaps", () => {
|
|
31
|
+
const result = temporalQuerySchema.safeParse({
|
|
32
|
+
contains: "2024-01-01T00:00:00Z",
|
|
33
|
+
overlaps: ["2024-01-01T00:00:00Z", "2024-12-31T23:59:59Z"],
|
|
34
|
+
});
|
|
35
|
+
expect(result.success).toBe(false);
|
|
36
|
+
if (!result.success) {
|
|
37
|
+
expect(result.error.issues[0]?.message).toContain(
|
|
38
|
+
"exactly one of: contains, overlaps, within",
|
|
39
|
+
);
|
|
40
|
+
}
|
|
41
|
+
});
|
|
42
|
+
|
|
43
|
+
test("rejects contains + within", () => {
|
|
44
|
+
const result = temporalQuerySchema.safeParse({
|
|
45
|
+
contains: "2024-01-01T00:00:00Z",
|
|
46
|
+
within: ["2024-01-01T00:00:00Z", "2024-12-31T23:59:59Z"],
|
|
47
|
+
});
|
|
48
|
+
expect(result.success).toBe(false);
|
|
49
|
+
});
|
|
50
|
+
|
|
51
|
+
test("rejects all three filters", () => {
|
|
52
|
+
const result = temporalQuerySchema.safeParse({
|
|
53
|
+
contains: "2024-01-01T00:00:00Z",
|
|
54
|
+
overlaps: ["2024-01-01T00:00:00Z", "2024-06-30T23:59:59Z"],
|
|
55
|
+
within: ["2024-01-01T00:00:00Z", "2024-12-31T23:59:59Z"],
|
|
56
|
+
});
|
|
57
|
+
expect(result.success).toBe(false);
|
|
58
|
+
});
|
|
59
|
+
});
|
|
@@ -0,0 +1,194 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Engram schemas - shared between server and client
|
|
3
|
+
*
|
|
4
|
+
* Server: imports schemas for validation
|
|
5
|
+
* Client: imports inferred types for type safety
|
|
6
|
+
*/
|
|
7
|
+
import { z } from "zod";
|
|
8
|
+
import {
|
|
9
|
+
contentField,
|
|
10
|
+
idField,
|
|
11
|
+
metaField,
|
|
12
|
+
treeField,
|
|
13
|
+
treeFilterField,
|
|
14
|
+
} from "./fields";
|
|
15
|
+
|
|
16
|
+
// ===== Input Schemas =====
|
|
17
|
+
|
|
18
|
+
export const temporalSchema = z
|
|
19
|
+
.object({
|
|
20
|
+
start: z.string().describe("ISO timestamp for start of time range"),
|
|
21
|
+
end: z
|
|
22
|
+
.string()
|
|
23
|
+
.optional()
|
|
24
|
+
.describe("ISO timestamp for end (omit for point-in-time)"),
|
|
25
|
+
})
|
|
26
|
+
.describe("Time range for the memory");
|
|
27
|
+
|
|
28
|
+
export const temporalQuerySchema = z
|
|
29
|
+
.object({
|
|
30
|
+
contains: z
|
|
31
|
+
.string()
|
|
32
|
+
.optional()
|
|
33
|
+
.describe("Find memories containing this point in time"),
|
|
34
|
+
overlaps: z
|
|
35
|
+
.tuple([z.string(), z.string()])
|
|
36
|
+
.optional()
|
|
37
|
+
.describe("[start, end] - find memories overlapping this range"),
|
|
38
|
+
within: z
|
|
39
|
+
.tuple([z.string(), z.string()])
|
|
40
|
+
.optional()
|
|
41
|
+
.describe("[start, end] - find memories fully within this range"),
|
|
42
|
+
})
|
|
43
|
+
.refine(
|
|
44
|
+
(data) => {
|
|
45
|
+
const defined = [data.contains, data.overlaps, data.within].filter(
|
|
46
|
+
(v) => v !== undefined,
|
|
47
|
+
);
|
|
48
|
+
return defined.length <= 1;
|
|
49
|
+
},
|
|
50
|
+
{
|
|
51
|
+
message:
|
|
52
|
+
"Temporal filter must use exactly one of: contains, overlaps, within",
|
|
53
|
+
},
|
|
54
|
+
)
|
|
55
|
+
.describe("Temporal filter for search");
|
|
56
|
+
|
|
57
|
+
export const createEngramSchema = z.object({
|
|
58
|
+
id: idField.optional(),
|
|
59
|
+
content: contentField,
|
|
60
|
+
meta: metaField.optional(),
|
|
61
|
+
tree: treeField
|
|
62
|
+
.optional()
|
|
63
|
+
.describe(
|
|
64
|
+
"Hierarchical path (e.g., work.projects.me). Defaults to root path when omitted",
|
|
65
|
+
),
|
|
66
|
+
temporal: temporalSchema.optional(),
|
|
67
|
+
});
|
|
68
|
+
|
|
69
|
+
export const batchCreateEngramSchema = z.object({
|
|
70
|
+
engrams: z.array(createEngramSchema).max(1000),
|
|
71
|
+
});
|
|
72
|
+
|
|
73
|
+
export const updateEngramSchema = z.object({
|
|
74
|
+
id: idField,
|
|
75
|
+
content: contentField.optional(),
|
|
76
|
+
meta: metaField.optional(),
|
|
77
|
+
tree: treeField.optional(),
|
|
78
|
+
temporal: temporalSchema.optional(),
|
|
79
|
+
});
|
|
80
|
+
|
|
81
|
+
export const getEngramSchema = z.object({
|
|
82
|
+
id: idField,
|
|
83
|
+
});
|
|
84
|
+
|
|
85
|
+
export const deleteEngramSchema = z.object({
|
|
86
|
+
id: idField,
|
|
87
|
+
});
|
|
88
|
+
|
|
89
|
+
export const mvEngramSchema = z.object({
|
|
90
|
+
source: treeField.min(1),
|
|
91
|
+
destination: treeField,
|
|
92
|
+
dry_run: z.boolean().optional().default(false),
|
|
93
|
+
});
|
|
94
|
+
|
|
95
|
+
export const mvEngramResultSchema = z.object({
|
|
96
|
+
moved: z.number().int(),
|
|
97
|
+
source: z.string(),
|
|
98
|
+
destination: z.string(),
|
|
99
|
+
});
|
|
100
|
+
|
|
101
|
+
export const searchEngramSchema = z
|
|
102
|
+
.object({
|
|
103
|
+
semantic: z.string().optional(),
|
|
104
|
+
fulltext: z.string().optional(),
|
|
105
|
+
meta: metaField.optional(),
|
|
106
|
+
tree: treeFilterField.optional(),
|
|
107
|
+
temporal: temporalQuerySchema.optional(),
|
|
108
|
+
limit: z.number().int().positive().max(1000).optional().default(100),
|
|
109
|
+
candidateLimit: z
|
|
110
|
+
.number()
|
|
111
|
+
.int()
|
|
112
|
+
.positive()
|
|
113
|
+
.min(1)
|
|
114
|
+
.max(1000)
|
|
115
|
+
.optional()
|
|
116
|
+
.default(30),
|
|
117
|
+
hybrid: z
|
|
118
|
+
.object({
|
|
119
|
+
weights: z
|
|
120
|
+
.object({
|
|
121
|
+
fulltext: z
|
|
122
|
+
.number()
|
|
123
|
+
.min(0)
|
|
124
|
+
.max(1)
|
|
125
|
+
.optional()
|
|
126
|
+
.describe("Weight for BM25 keyword matching (0-1)"),
|
|
127
|
+
semantic: z
|
|
128
|
+
.number()
|
|
129
|
+
.min(0)
|
|
130
|
+
.max(1)
|
|
131
|
+
.optional()
|
|
132
|
+
.describe("Weight for semantic similarity (0-1)"),
|
|
133
|
+
})
|
|
134
|
+
.optional()
|
|
135
|
+
.describe("Weights for hybrid search ranking (RRF)"),
|
|
136
|
+
})
|
|
137
|
+
.optional(),
|
|
138
|
+
})
|
|
139
|
+
.refine(
|
|
140
|
+
(data) =>
|
|
141
|
+
data.semantic || data.fulltext || data.meta || data.tree || data.temporal,
|
|
142
|
+
{ message: "At least one search criterion required" },
|
|
143
|
+
);
|
|
144
|
+
|
|
145
|
+
// ===== Output Schemas =====
|
|
146
|
+
|
|
147
|
+
export const engramSchema = z.object({
|
|
148
|
+
id: idField,
|
|
149
|
+
content: contentField,
|
|
150
|
+
meta: metaField,
|
|
151
|
+
tree: treeField,
|
|
152
|
+
temporal: z.string().nullable(),
|
|
153
|
+
has_embedding: z.boolean().optional(),
|
|
154
|
+
created_at: z.string(),
|
|
155
|
+
updated_at: z.string().nullable(),
|
|
156
|
+
});
|
|
157
|
+
|
|
158
|
+
export const engramWithScoreSchema = engramSchema.extend({
|
|
159
|
+
score: z.number(),
|
|
160
|
+
});
|
|
161
|
+
|
|
162
|
+
export const searchEngramResultSchema = z.object({
|
|
163
|
+
results: z.array(engramWithScoreSchema),
|
|
164
|
+
total: z.number(),
|
|
165
|
+
limit: z.number(),
|
|
166
|
+
});
|
|
167
|
+
|
|
168
|
+
export const batchCreateResultSchema = z.object({
|
|
169
|
+
ids: z.array(z.uuidv7()),
|
|
170
|
+
});
|
|
171
|
+
|
|
172
|
+
export const deleteResultSchema = z.object({
|
|
173
|
+
success: z.literal(true),
|
|
174
|
+
});
|
|
175
|
+
|
|
176
|
+
// ===== Inferred Types (auto-generated from schemas) =====
|
|
177
|
+
|
|
178
|
+
export type Temporal = z.infer<typeof temporalSchema>;
|
|
179
|
+
export type TemporalQuery = z.infer<typeof temporalQuerySchema>;
|
|
180
|
+
|
|
181
|
+
export type CreateEngramParams = z.infer<typeof createEngramSchema>;
|
|
182
|
+
export type BatchCreateEngramParams = z.infer<typeof batchCreateEngramSchema>;
|
|
183
|
+
export type UpdateEngramParams = z.infer<typeof updateEngramSchema>;
|
|
184
|
+
export type GetEngramParams = z.infer<typeof getEngramSchema>;
|
|
185
|
+
export type DeleteEngramParams = z.infer<typeof deleteEngramSchema>;
|
|
186
|
+
export type SearchEngramParams = z.infer<typeof searchEngramSchema>;
|
|
187
|
+
|
|
188
|
+
export type Engram = z.infer<typeof engramSchema>;
|
|
189
|
+
export type EngramWithScore = z.infer<typeof engramWithScoreSchema>;
|
|
190
|
+
export type SearchEngramResult = z.infer<typeof searchEngramResultSchema>;
|
|
191
|
+
export type BatchCreateResult = z.infer<typeof batchCreateResultSchema>;
|
|
192
|
+
export type DeleteResult = z.infer<typeof deleteResultSchema>;
|
|
193
|
+
export type MvEngramParams = z.infer<typeof mvEngramSchema>;
|
|
194
|
+
export type MvEngramResult = z.infer<typeof mvEngramResultSchema>;
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import { describe, expect, test } from "bun:test";
|
|
2
|
+
import { treeFilterField } from "./fields";
|
|
3
|
+
|
|
4
|
+
describe("treeFilterField", () => {
|
|
5
|
+
test("accepts ltxtquery with plain labels", () => {
|
|
6
|
+
expect(treeFilterField.safeParse("knowledge & postgresql").success).toBe(
|
|
7
|
+
true,
|
|
8
|
+
);
|
|
9
|
+
});
|
|
10
|
+
|
|
11
|
+
test("accepts ltxtquery with underscored labels", () => {
|
|
12
|
+
expect(treeFilterField.safeParse("reference & sql_commands").success).toBe(
|
|
13
|
+
true,
|
|
14
|
+
);
|
|
15
|
+
});
|
|
16
|
+
|
|
17
|
+
test("accepts ltxtquery with negation", () => {
|
|
18
|
+
expect(treeFilterField.safeParse("api & !draft").success).toBe(true);
|
|
19
|
+
});
|
|
20
|
+
|
|
21
|
+
test("rejects ltxtquery with dotted path", () => {
|
|
22
|
+
const result = treeFilterField.safeParse("work.knowledge & postgresql");
|
|
23
|
+
expect(result.success).toBe(false);
|
|
24
|
+
if (!result.success) {
|
|
25
|
+
expect(result.error.issues[0]?.message).toContain(
|
|
26
|
+
"ltxtquery matches labels, not paths",
|
|
27
|
+
);
|
|
28
|
+
}
|
|
29
|
+
});
|
|
30
|
+
|
|
31
|
+
test("accepts lquery pattern (no &)", () => {
|
|
32
|
+
expect(treeFilterField.safeParse("work.*").success).toBe(true);
|
|
33
|
+
});
|
|
34
|
+
|
|
35
|
+
test("accepts exact ltree path (no &)", () => {
|
|
36
|
+
expect(treeFilterField.safeParse("work.projects.api").success).toBe(true);
|
|
37
|
+
});
|
|
38
|
+
});
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Shared field validators - single source of truth
|
|
3
|
+
*
|
|
4
|
+
* Both shared schemas and MCP tool schemas import from here.
|
|
5
|
+
* This prevents drift in core validation logic (e.g., uuidv7, content min length).
|
|
6
|
+
*/
|
|
7
|
+
import { z } from "zod";
|
|
8
|
+
|
|
9
|
+
/** UUIDv7 for all engram IDs */
|
|
10
|
+
export const idField = z.uuidv7();
|
|
11
|
+
|
|
12
|
+
/** Memory content - non-empty string */
|
|
13
|
+
export const contentField = z.string().min(1);
|
|
14
|
+
|
|
15
|
+
/** Metadata - arbitrary key-value pairs */
|
|
16
|
+
export const metaField = z.record(z.string(), z.unknown());
|
|
17
|
+
|
|
18
|
+
/** Tree path - dot-separated hierarchy (write contexts) */
|
|
19
|
+
export const treeField = z.string();
|
|
20
|
+
|
|
21
|
+
/** Tree filter - ltree path, lquery pattern, or ltxtquery label search */
|
|
22
|
+
export const treeFilterField = z.string().refine(
|
|
23
|
+
(val) => {
|
|
24
|
+
if (!val.includes("&")) return true;
|
|
25
|
+
const words = val
|
|
26
|
+
.replace(/[&|!()]/g, " ")
|
|
27
|
+
.split(/\s+/)
|
|
28
|
+
.filter(Boolean);
|
|
29
|
+
return words.every((w) => !w.includes("."));
|
|
30
|
+
},
|
|
31
|
+
{
|
|
32
|
+
message:
|
|
33
|
+
'ltxtquery matches labels, not paths. Use individual labels with & (e.g., "knowledge & postgresql"), not dot-separated paths (e.g., "work.knowledge & postgresql").',
|
|
34
|
+
},
|
|
35
|
+
);
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Shared schemas - import from here in both server and client
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
// Auth schemas and types
|
|
6
|
+
export * from "./auth";
|
|
7
|
+
// Engram schemas and types
|
|
8
|
+
export * from "./engram";
|
|
9
|
+
// Shared field validators (single source of truth)
|
|
10
|
+
export * from "./fields";
|
|
11
|
+
// Principal schemas and types
|
|
12
|
+
export * from "./principal";
|
|
13
|
+
|
|
14
|
+
// RPC contract and type utilities
|
|
15
|
+
export * from "./rpc";
|
|
@@ -0,0 +1,178 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Principal management schemas - shared between server and client
|
|
3
|
+
*/
|
|
4
|
+
import { z } from "zod";
|
|
5
|
+
import { principalSchema, successSchema } from "./auth";
|
|
6
|
+
|
|
7
|
+
// ===== Input Schemas =====
|
|
8
|
+
|
|
9
|
+
export const getPrincipalSchema = z.object({
|
|
10
|
+
name: z.string().min(1),
|
|
11
|
+
});
|
|
12
|
+
|
|
13
|
+
export const createPrincipalSchema = z.object({
|
|
14
|
+
name: z.string().min(1),
|
|
15
|
+
email: z.email().optional(),
|
|
16
|
+
password: z.string().min(8).optional(),
|
|
17
|
+
superuser: z.boolean().optional(),
|
|
18
|
+
createrole: z.boolean().optional(),
|
|
19
|
+
can_login: z.boolean().optional(),
|
|
20
|
+
});
|
|
21
|
+
|
|
22
|
+
export const deletePrincipalSchema = z.object({
|
|
23
|
+
name: z.string().min(1),
|
|
24
|
+
});
|
|
25
|
+
|
|
26
|
+
export const setPasswordSchema = z.object({
|
|
27
|
+
name: z.string().min(1),
|
|
28
|
+
password: z.string().min(8),
|
|
29
|
+
});
|
|
30
|
+
|
|
31
|
+
// ===== Tree Grant Schemas =====
|
|
32
|
+
|
|
33
|
+
const treeActionSchema = z.enum(["read", "create", "update", "delete"]);
|
|
34
|
+
|
|
35
|
+
export const grantTreeAccessSchema = z.object({
|
|
36
|
+
principal_name: z.string().min(1),
|
|
37
|
+
tree_path: z.string(),
|
|
38
|
+
actions: z.array(treeActionSchema).min(1),
|
|
39
|
+
with_grant_option: z.boolean().optional(),
|
|
40
|
+
});
|
|
41
|
+
|
|
42
|
+
export const revokeTreeAccessSchema = z.object({
|
|
43
|
+
principal_name: z.string().min(1),
|
|
44
|
+
tree_path: z.string(),
|
|
45
|
+
});
|
|
46
|
+
|
|
47
|
+
export const listTreeGrantsSchema = z.object({
|
|
48
|
+
principal_name: z.string().min(1).optional(),
|
|
49
|
+
});
|
|
50
|
+
|
|
51
|
+
export const checkTreeAccessSchema = z.object({
|
|
52
|
+
tree_path: z.string(),
|
|
53
|
+
action: treeActionSchema,
|
|
54
|
+
});
|
|
55
|
+
|
|
56
|
+
// ===== Role Membership Schemas =====
|
|
57
|
+
|
|
58
|
+
export const addRoleMemberSchema = z.object({
|
|
59
|
+
role_name: z.string().min(1),
|
|
60
|
+
member_name: z.string().min(1),
|
|
61
|
+
with_admin_option: z.boolean().optional(),
|
|
62
|
+
});
|
|
63
|
+
|
|
64
|
+
export const removeRoleMemberSchema = z.object({
|
|
65
|
+
role_name: z.string().min(1),
|
|
66
|
+
member_name: z.string().min(1),
|
|
67
|
+
});
|
|
68
|
+
|
|
69
|
+
export const listRoleMembersSchema = z.object({
|
|
70
|
+
role_name: z.string().min(1),
|
|
71
|
+
});
|
|
72
|
+
|
|
73
|
+
export const listRolesForPrincipalSchema = z.object({
|
|
74
|
+
principal_name: z.string().min(1).optional(),
|
|
75
|
+
});
|
|
76
|
+
|
|
77
|
+
// ===== Tree Ownership Schemas =====
|
|
78
|
+
|
|
79
|
+
export const setTreeOwnerSchema = z.object({
|
|
80
|
+
tree_path: z.string(),
|
|
81
|
+
principal_name: z.string().min(1),
|
|
82
|
+
});
|
|
83
|
+
|
|
84
|
+
export const removeTreeOwnerSchema = z.object({
|
|
85
|
+
tree_path: z.string(),
|
|
86
|
+
});
|
|
87
|
+
|
|
88
|
+
export const getTreeOwnerSchema = z.object({
|
|
89
|
+
tree_path: z.string(),
|
|
90
|
+
});
|
|
91
|
+
|
|
92
|
+
export const listTreeOwnersSchema = z.object({
|
|
93
|
+
principal_name: z.string().min(1).optional(),
|
|
94
|
+
});
|
|
95
|
+
|
|
96
|
+
// ===== Output Schemas =====
|
|
97
|
+
|
|
98
|
+
export const principalListItemSchema = z.object({
|
|
99
|
+
id: z.uuidv7(),
|
|
100
|
+
email: z.email().nullable(),
|
|
101
|
+
name: z.string(),
|
|
102
|
+
superuser: z.boolean(),
|
|
103
|
+
createrole: z.boolean(),
|
|
104
|
+
can_login: z.boolean(),
|
|
105
|
+
created_at: z.string(),
|
|
106
|
+
});
|
|
107
|
+
|
|
108
|
+
export const principalDetailSchema = principalSchema.extend({
|
|
109
|
+
created_at: z.string(),
|
|
110
|
+
});
|
|
111
|
+
|
|
112
|
+
export const treeGrantSchema = z.object({
|
|
113
|
+
id: z.uuidv7(),
|
|
114
|
+
principal_id: z.uuidv7(),
|
|
115
|
+
tree_path: z.string(),
|
|
116
|
+
actions: z.array(z.string()),
|
|
117
|
+
with_grant_option: z.boolean(),
|
|
118
|
+
granted_by: z.uuidv7().nullable(),
|
|
119
|
+
created_at: z.string(),
|
|
120
|
+
});
|
|
121
|
+
|
|
122
|
+
export const roleMemberSchema = z.object({
|
|
123
|
+
id: z.uuidv7(),
|
|
124
|
+
name: z.string(),
|
|
125
|
+
email: z.email().nullable(),
|
|
126
|
+
superuser: z.boolean(),
|
|
127
|
+
can_login: z.boolean(),
|
|
128
|
+
with_admin_option: z.boolean(),
|
|
129
|
+
created_at: z.string(),
|
|
130
|
+
});
|
|
131
|
+
|
|
132
|
+
export const principalRoleSchema = z.object({
|
|
133
|
+
id: z.uuidv7(),
|
|
134
|
+
name: z.string(),
|
|
135
|
+
created_at: z.string(),
|
|
136
|
+
});
|
|
137
|
+
|
|
138
|
+
export const treeOwnerSchema = z.object({
|
|
139
|
+
tree_path: z.string(),
|
|
140
|
+
principal_id: z.uuidv7(),
|
|
141
|
+
principal_name: z.string(),
|
|
142
|
+
created_by: z.uuidv7().nullable(),
|
|
143
|
+
created_at: z.string(),
|
|
144
|
+
});
|
|
145
|
+
|
|
146
|
+
// Re-export success schema for convenience
|
|
147
|
+
export { successSchema };
|
|
148
|
+
|
|
149
|
+
// ===== Inferred Types =====
|
|
150
|
+
|
|
151
|
+
export type GetPrincipalParams = z.infer<typeof getPrincipalSchema>;
|
|
152
|
+
export type CreatePrincipalParams = z.infer<typeof createPrincipalSchema>;
|
|
153
|
+
export type DeletePrincipalParams = z.infer<typeof deletePrincipalSchema>;
|
|
154
|
+
export type SetPasswordParams = z.infer<typeof setPasswordSchema>;
|
|
155
|
+
|
|
156
|
+
export type GrantTreeAccessParams = z.infer<typeof grantTreeAccessSchema>;
|
|
157
|
+
export type RevokeTreeAccessParams = z.infer<typeof revokeTreeAccessSchema>;
|
|
158
|
+
export type ListTreeGrantsParams = z.infer<typeof listTreeGrantsSchema>;
|
|
159
|
+
export type CheckTreeAccessParams = z.infer<typeof checkTreeAccessSchema>;
|
|
160
|
+
|
|
161
|
+
export type AddRoleMemberParams = z.infer<typeof addRoleMemberSchema>;
|
|
162
|
+
export type RemoveRoleMemberParams = z.infer<typeof removeRoleMemberSchema>;
|
|
163
|
+
export type ListRoleMembersParams = z.infer<typeof listRoleMembersSchema>;
|
|
164
|
+
export type ListRolesForPrincipalParams = z.infer<
|
|
165
|
+
typeof listRolesForPrincipalSchema
|
|
166
|
+
>;
|
|
167
|
+
|
|
168
|
+
export type SetTreeOwnerParams = z.infer<typeof setTreeOwnerSchema>;
|
|
169
|
+
export type RemoveTreeOwnerParams = z.infer<typeof removeTreeOwnerSchema>;
|
|
170
|
+
export type GetTreeOwnerParams = z.infer<typeof getTreeOwnerSchema>;
|
|
171
|
+
export type ListTreeOwnersParams = z.infer<typeof listTreeOwnersSchema>;
|
|
172
|
+
|
|
173
|
+
export type PrincipalListItem = z.infer<typeof principalListItemSchema>;
|
|
174
|
+
export type PrincipalDetail = z.infer<typeof principalDetailSchema>;
|
|
175
|
+
export type TreeGrant = z.infer<typeof treeGrantSchema>;
|
|
176
|
+
export type RoleMember = z.infer<typeof roleMemberSchema>;
|
|
177
|
+
export type PrincipalRole = z.infer<typeof principalRoleSchema>;
|
|
178
|
+
export type TreeOwner = z.infer<typeof treeOwnerSchema>;
|