@qikdev/mcp 6.7.7 → 6.8.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.
@@ -0,0 +1,408 @@
1
+ /**
2
+ * Schema-based validation for content payloads.
3
+ * Fetches content type schemas from the glossary API and validates/coerces payloads.
4
+ */
5
+ import { ConfigManager } from "../config.js";
6
+ // ============================================================================
7
+ // CACHE
8
+ // ============================================================================
9
+ const CACHE_TTL_MS = 5 * 60 * 1000; // 5 minutes
10
+ const schemaCache = {
11
+ index: null,
12
+ schemas: new Map()
13
+ };
14
+ function isCacheValid(entry) {
15
+ return entry !== null && (Date.now() - entry.fetchedAt) < CACHE_TTL_MS;
16
+ }
17
+ // ============================================================================
18
+ // SCHEMA FETCHING
19
+ // ============================================================================
20
+ async function getConfig() {
21
+ const configManager = new ConfigManager();
22
+ const config = await configManager.loadConfig();
23
+ if (!config) {
24
+ throw new Error('Qik MCP server not configured');
25
+ }
26
+ return config;
27
+ }
28
+ async function fetchGlossaryIndex() {
29
+ if (isCacheValid(schemaCache.index)) {
30
+ return schemaCache.index.data;
31
+ }
32
+ const config = await getConfig();
33
+ const response = await fetch(`${config.apiUrl || 'https://api.qik.dev'}/glossary/ai`, {
34
+ headers: {
35
+ 'Authorization': `Bearer ${config.accessToken}`,
36
+ 'Content-Type': 'application/json',
37
+ }
38
+ });
39
+ if (!response.ok) {
40
+ throw new Error(`Failed to fetch glossary: ${response.status}`);
41
+ }
42
+ const data = await response.json();
43
+ schemaCache.index = { data, fetchedAt: Date.now() };
44
+ return data;
45
+ }
46
+ export async function getContentTypeSchema(typeKey) {
47
+ // Check cache
48
+ const cached = schemaCache.schemas.get(typeKey) || null;
49
+ if (isCacheValid(cached)) {
50
+ return cached.data;
51
+ }
52
+ try {
53
+ // Get glossary index
54
+ const index = await fetchGlossaryIndex();
55
+ // Find the content type
56
+ const contentType = index.find(ct => ct.key === typeKey);
57
+ if (!contentType) {
58
+ return null; // Unknown content type
59
+ }
60
+ // Fetch detailed schema
61
+ const config = await getConfig();
62
+ const schemaUrl = contentType.urls.documentation.url;
63
+ const response = await fetch(schemaUrl, {
64
+ headers: {
65
+ 'Authorization': `Bearer ${config.accessToken}`,
66
+ 'Content-Type': 'application/json',
67
+ }
68
+ });
69
+ if (!response.ok) {
70
+ throw new Error(`Failed to fetch schema for ${typeKey}: ${response.status}`);
71
+ }
72
+ const schema = await response.json();
73
+ schemaCache.schemas.set(typeKey, { data: schema, fetchedAt: Date.now() });
74
+ return schema;
75
+ }
76
+ catch (error) {
77
+ console.error(`Error fetching schema for ${typeKey}:`, error);
78
+ return null;
79
+ }
80
+ }
81
+ // ============================================================================
82
+ // TYPE COERCION
83
+ // ============================================================================
84
+ /**
85
+ * Try to parse a string as JSON
86
+ */
87
+ function tryParseJson(value) {
88
+ const trimmed = value.trim();
89
+ if ((trimmed.startsWith('{') && trimmed.endsWith('}')) ||
90
+ (trimmed.startsWith('[') && trimmed.endsWith(']'))) {
91
+ try {
92
+ return JSON.parse(value);
93
+ }
94
+ catch {
95
+ return null;
96
+ }
97
+ }
98
+ return null;
99
+ }
100
+ /**
101
+ * Coerce a value to boolean
102
+ */
103
+ function coerceToBoolean(value) {
104
+ if (typeof value === 'boolean') {
105
+ return { value };
106
+ }
107
+ if (typeof value === 'string') {
108
+ const lower = value.toLowerCase().trim();
109
+ if (['true', 'yes', '1', 'on'].includes(lower)) {
110
+ return { value: true };
111
+ }
112
+ if (['false', 'no', '0', 'off', ''].includes(lower)) {
113
+ return { value: false };
114
+ }
115
+ return { value, error: `Cannot convert "${value}" to boolean` };
116
+ }
117
+ if (typeof value === 'number') {
118
+ return { value: value !== 0 };
119
+ }
120
+ return { value: Boolean(value) };
121
+ }
122
+ /**
123
+ * Coerce a value to date (ISO string)
124
+ */
125
+ function coerceToDate(value) {
126
+ if (value instanceof Date) {
127
+ return { value: value.toISOString() };
128
+ }
129
+ if (typeof value === 'string') {
130
+ const date = new Date(value);
131
+ if (!isNaN(date.getTime())) {
132
+ return { value: value }; // Keep original string if valid
133
+ }
134
+ return { value, error: `Cannot parse "${value}" as date` };
135
+ }
136
+ if (typeof value === 'number') {
137
+ const date = new Date(value);
138
+ if (!isNaN(date.getTime())) {
139
+ return { value: date.toISOString() };
140
+ }
141
+ }
142
+ return { value, error: `Cannot convert to date` };
143
+ }
144
+ /**
145
+ * Coerce a value to the expected type based on field definition
146
+ */
147
+ export function coerceValue(value, field) {
148
+ // Handle null/undefined
149
+ if (value === null || value === undefined) {
150
+ return { value };
151
+ }
152
+ // First, try to parse JSON strings (LLM sends nested objects as strings)
153
+ if (typeof value === 'string' && field.type !== 'string') {
154
+ const parsed = tryParseJson(value);
155
+ if (parsed !== null) {
156
+ value = parsed;
157
+ }
158
+ }
159
+ // Handle array wrapping based on field cardinality
160
+ const isArrayField = field.maximum === 0 || (field.maximum !== undefined && field.maximum > 1);
161
+ switch (field.type) {
162
+ case 'string':
163
+ case 'email':
164
+ case 'url':
165
+ if (typeof value !== 'string') {
166
+ return { value: String(value) };
167
+ }
168
+ return { value };
169
+ case 'number':
170
+ if (typeof value === 'number') {
171
+ return { value };
172
+ }
173
+ if (typeof value === 'string') {
174
+ // Handle currency formatting (remove $, commas, etc.)
175
+ const cleaned = value.replace(/[$,\s]/g, '');
176
+ const num = parseFloat(cleaned);
177
+ if (!isNaN(num)) {
178
+ return { value: num };
179
+ }
180
+ return { value, error: `Cannot convert "${value}" to number` };
181
+ }
182
+ return { value, error: `Cannot convert to number` };
183
+ case 'integer':
184
+ if (typeof value === 'number') {
185
+ return { value: Math.round(value) };
186
+ }
187
+ if (typeof value === 'string') {
188
+ const int = parseInt(value, 10);
189
+ if (!isNaN(int)) {
190
+ return { value: int };
191
+ }
192
+ return { value, error: `Cannot convert "${value}" to integer` };
193
+ }
194
+ return { value, error: `Cannot convert to integer` };
195
+ case 'boolean':
196
+ return coerceToBoolean(value);
197
+ case 'date':
198
+ return coerceToDate(value);
199
+ case 'reference':
200
+ // References should be arrays of IDs (or single ID for maximum: 1)
201
+ if (Array.isArray(value)) {
202
+ // Recursively coerce array items (handle stringified arrays)
203
+ const coerced = value.map(v => {
204
+ if (typeof v === 'string') {
205
+ const parsed = tryParseJson(v);
206
+ return parsed !== null ? parsed : v;
207
+ }
208
+ return v;
209
+ });
210
+ return { value: coerced };
211
+ }
212
+ if (typeof value === 'string') {
213
+ // Single ID - wrap in array if needed
214
+ if (isArrayField) {
215
+ return { value: [value] };
216
+ }
217
+ return { value };
218
+ }
219
+ return { value };
220
+ case 'object':
221
+ // Already handled JSON parsing above
222
+ if (typeof value === 'object') {
223
+ return { value };
224
+ }
225
+ return { value, error: `Expected object for field "${field.title}"` };
226
+ case 'group':
227
+ // Visual-only field, no data
228
+ return { value: undefined };
229
+ default:
230
+ return { value };
231
+ }
232
+ }
233
+ // ============================================================================
234
+ // FIELD VALIDATION
235
+ // ============================================================================
236
+ function isEmpty(value) {
237
+ if (value === null || value === undefined)
238
+ return true;
239
+ if (value === '')
240
+ return true;
241
+ if (Array.isArray(value) && value.length === 0)
242
+ return true;
243
+ return false;
244
+ }
245
+ /**
246
+ * Validate a field value against its definition
247
+ */
248
+ export function validateField(value, field) {
249
+ const errors = [];
250
+ // Skip group fields (visual only)
251
+ if (field.type === 'group') {
252
+ return errors;
253
+ }
254
+ // Required check
255
+ if (field.minimum !== undefined && field.minimum >= 1) {
256
+ if (isEmpty(value)) {
257
+ errors.push(`"${field.title}" is required`);
258
+ return errors; // No point continuing
259
+ }
260
+ }
261
+ // Skip further validation if empty and optional
262
+ if (isEmpty(value)) {
263
+ return errors;
264
+ }
265
+ // Cardinality check
266
+ const values = Array.isArray(value) ? value : [value];
267
+ if (field.maximum === 1 && values.length > 1) {
268
+ errors.push(`"${field.title}" accepts only one value (received ${values.length})`);
269
+ }
270
+ if (field.maximum !== undefined && field.maximum > 1 && values.length > field.maximum) {
271
+ errors.push(`"${field.title}" accepts at most ${field.maximum} values (received ${values.length})`);
272
+ }
273
+ // Options validation (for select/button widgets)
274
+ if (field.options && field.options.length > 0) {
275
+ const validValues = new Set(field.options.map(o => o.value));
276
+ for (const v of values) {
277
+ if (!validValues.has(v)) {
278
+ const optionsList = field.options.map(o => o.value).join(', ');
279
+ errors.push(`"${field.title}" value "${v}" is not valid. Options: ${optionsList}`);
280
+ }
281
+ }
282
+ }
283
+ return errors;
284
+ }
285
+ // ============================================================================
286
+ // MAIN VALIDATION FUNCTION
287
+ // ============================================================================
288
+ // System fields that shouldn't be validated
289
+ const SYSTEM_FIELDS = new Set(['_id', 'meta', 'organisation', 'createdAt', 'updatedAt']);
290
+ /**
291
+ * Validate and coerce a payload against a content type schema.
292
+ */
293
+ export async function validateAndCoercePayload(typeKey, payload, options = {}) {
294
+ const result = {
295
+ valid: true,
296
+ errors: [],
297
+ warnings: [],
298
+ coercedPayload: {}
299
+ };
300
+ // Try to get schema
301
+ let schema = null;
302
+ try {
303
+ schema = await getContentTypeSchema(typeKey);
304
+ }
305
+ catch (error) {
306
+ result.warnings.push(`Could not fetch schema: ${error.message}`);
307
+ }
308
+ // If no schema, pass through with JSON string parsing only
309
+ if (!schema) {
310
+ result.warnings.push(`Content type "${typeKey}" not found in glossary - skipping validation`);
311
+ result.coercedPayload = parsePayloadJsonStrings(payload);
312
+ return result;
313
+ }
314
+ // Build a map of field keys for quick lookup
315
+ const fieldMap = new Map();
316
+ for (const field of schema.fields) {
317
+ if (field.key) {
318
+ fieldMap.set(field.key, field);
319
+ }
320
+ }
321
+ // Process all fields in the payload
322
+ for (const [key, value] of Object.entries(payload)) {
323
+ // Skip system fields
324
+ if (SYSTEM_FIELDS.has(key)) {
325
+ // Still parse JSON strings in system fields
326
+ result.coercedPayload[key] = parseValueJsonStrings(value);
327
+ continue;
328
+ }
329
+ const field = fieldMap.get(key);
330
+ if (!field) {
331
+ // Unknown field - pass through with JSON parsing
332
+ result.coercedPayload[key] = parseValueJsonStrings(value);
333
+ continue;
334
+ }
335
+ // Coerce the value
336
+ const coerced = coerceValue(value, field);
337
+ if (coerced.error) {
338
+ result.warnings.push(`${field.title}: ${coerced.error}`);
339
+ }
340
+ result.coercedPayload[key] = coerced.value;
341
+ // Validate the coerced value
342
+ const fieldErrors = validateField(coerced.value, field);
343
+ result.errors.push(...fieldErrors);
344
+ }
345
+ // Check for missing required fields (only for non-partial validation)
346
+ if (!options.partial) {
347
+ for (const field of schema.fields) {
348
+ if (field.type === 'group')
349
+ continue;
350
+ if (!field.key)
351
+ continue;
352
+ if (field.minimum !== undefined && field.minimum >= 1) {
353
+ if (!(field.key in payload)) {
354
+ result.errors.push(`"${field.title}" is required`);
355
+ }
356
+ }
357
+ }
358
+ }
359
+ result.valid = result.errors.length === 0;
360
+ return result;
361
+ }
362
+ // ============================================================================
363
+ // HELPER FUNCTIONS
364
+ // ============================================================================
365
+ /**
366
+ * Recursively parse JSON strings in a value
367
+ */
368
+ function parseValueJsonStrings(value) {
369
+ if (value === null || value === undefined) {
370
+ return value;
371
+ }
372
+ if (typeof value === 'string') {
373
+ const parsed = tryParseJson(value);
374
+ if (parsed !== null) {
375
+ return parseValueJsonStrings(parsed);
376
+ }
377
+ return value;
378
+ }
379
+ if (Array.isArray(value)) {
380
+ return value.map(v => parseValueJsonStrings(v));
381
+ }
382
+ if (typeof value === 'object') {
383
+ const result = {};
384
+ for (const [k, v] of Object.entries(value)) {
385
+ result[k] = parseValueJsonStrings(v);
386
+ }
387
+ return result;
388
+ }
389
+ return value;
390
+ }
391
+ /**
392
+ * Parse JSON strings throughout a payload object
393
+ */
394
+ function parsePayloadJsonStrings(payload) {
395
+ const result = {};
396
+ for (const [key, value] of Object.entries(payload)) {
397
+ result[key] = parseValueJsonStrings(value);
398
+ }
399
+ return result;
400
+ }
401
+ /**
402
+ * Clear the schema cache (useful for testing)
403
+ */
404
+ export function clearSchemaCache() {
405
+ schemaCache.index = null;
406
+ schemaCache.schemas.clear();
407
+ }
408
+ //# sourceMappingURL=schema-validator.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"schema-validator.js","sourceRoot":"","sources":["../../../src/tools/schema-validator.ts"],"names":[],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"update.d.ts","sourceRoot":"","sources":["../../../src/tools/update.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,oCAAoC,CAAC;AAG1D,eAAO,MAAM,iBAAiB,EAAE,IAyC/B,CAAC;AAEF,wBAAsB,mBAAmB,CAAC,IAAI,EAAE,GAAG,GAAG,OAAO,CAAC;IAAE,OAAO,EAAE,KAAK,CAAC;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAE,CAAC,CAAA;CAAE,CAAC,CAgDhH"}
1
+ {"version":3,"file":"update.d.ts","sourceRoot":"","sources":["../../../src/tools/update.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,oCAAoC,CAAC;AAI1D,eAAO,MAAM,iBAAiB,EAAE,IAgD/B,CAAC;AAEF,wBAAsB,mBAAmB,CAAC,IAAI,EAAE,GAAG,GAAG,OAAO,CAAC;IAAE,OAAO,EAAE,KAAK,CAAC;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAE,CAAC,CAAA;CAAE,CAAC,CAqFhH"}
@@ -1,4 +1,5 @@
1
1
  import { ConfigManager } from "../config.js";
2
+ import { validateAndCoercePayload } from "./schema-validator.js";
2
3
  export const updateContentTool = {
3
4
  name: "update_content",
4
5
  description: `Update existing content items in Qik.
@@ -10,8 +11,10 @@ export const updateContentTool = {
10
11
 
11
12
  **Optional:**
12
13
  - updateMethod: "patch" (default) for partial updates, "put" for full replacement
14
+ - typeKey: Content type key for schema validation (e.g., 'article', 'profile'). If provided, payload will be validated and coerced against the schema.
13
15
 
14
16
  All other properties are passed directly to the API as the update payload.
17
+ The MCP server will automatically validate and coerce values if typeKey is provided.
15
18
 
16
19
  **Tags Shorthand:**
17
20
  Pass \`tags: ['green', 'red']\` as string names and the backend auto-creates tags.
@@ -20,6 +23,7 @@ Pass \`tags: ['green', 'red']\` as string names and the backend auto-creates tag
20
23
  \`\`\`json
21
24
  {
22
25
  "contentId": "abc123",
26
+ "typeKey": "article",
23
27
  "title": "Updated Title",
24
28
  "tags": ["featured", "breaking"]
25
29
  }
@@ -31,6 +35,10 @@ Pass \`tags: ['green', 'red']\` as string names and the backend auto-creates tag
31
35
  type: "string",
32
36
  description: "The ID of the content item to update"
33
37
  },
38
+ typeKey: {
39
+ type: "string",
40
+ description: "Content type key for schema validation (e.g., 'article', 'profile')"
41
+ },
34
42
  updateMethod: {
35
43
  type: "string",
36
44
  enum: ["patch", "put"],
@@ -48,11 +56,42 @@ export async function handleUpdateContent(args) {
48
56
  if (!config) {
49
57
  throw new Error('Qik MCP server not configured. Run setup first.');
50
58
  }
51
- const { contentId, updateMethod, ...payload } = args;
59
+ const { contentId, typeKey, updateMethod, ...rawPayload } = args;
52
60
  if (!contentId) {
53
61
  throw new Error('contentId is required');
54
62
  }
55
63
  const method = (updateMethod || 'patch').toUpperCase();
64
+ const isPartialUpdate = method === 'PATCH';
65
+ let payload;
66
+ // If typeKey is provided, validate and coerce using schema
67
+ if (typeKey) {
68
+ const validation = await validateAndCoercePayload(typeKey, rawPayload, {
69
+ partial: isPartialUpdate // For PATCH, only validate fields that are present
70
+ });
71
+ // Return validation errors if any
72
+ if (!validation.valid) {
73
+ let errorMessage = `**Validation failed for ${typeKey}:**\n\n`;
74
+ errorMessage += validation.errors.map(e => `- ${e}`).join('\n');
75
+ if (validation.warnings.length > 0) {
76
+ errorMessage += `\n\n**Warnings:**\n${validation.warnings.map(w => `- ${w}`).join('\n')}`;
77
+ }
78
+ return {
79
+ content: [{
80
+ type: "text",
81
+ text: errorMessage
82
+ }]
83
+ };
84
+ }
85
+ // Log warnings if any (but proceed with request)
86
+ if (validation.warnings.length > 0) {
87
+ console.warn(`Validation warnings for ${typeKey}:`, validation.warnings);
88
+ }
89
+ payload = validation.coercedPayload;
90
+ }
91
+ else {
92
+ // No typeKey provided - just do basic JSON string parsing
93
+ payload = parsePayloadJsonStrings(rawPayload);
94
+ }
56
95
  const response = await fetch(`${config.apiUrl || 'https://api.qik.dev'}/content/${contentId}`, {
57
96
  method,
58
97
  headers: {
@@ -82,4 +121,43 @@ export async function handleUpdateContent(args) {
82
121
  };
83
122
  }
84
123
  }
124
+ /**
125
+ * Basic JSON string parsing for payloads without schema validation
126
+ */
127
+ function parsePayloadJsonStrings(payload) {
128
+ const result = {};
129
+ for (const [key, value] of Object.entries(payload)) {
130
+ result[key] = parseValueJsonStrings(value);
131
+ }
132
+ return result;
133
+ }
134
+ function parseValueJsonStrings(value) {
135
+ if (value === null || value === undefined) {
136
+ return value;
137
+ }
138
+ if (typeof value === 'string') {
139
+ const trimmed = value.trim();
140
+ if ((trimmed.startsWith('{') && trimmed.endsWith('}')) ||
141
+ (trimmed.startsWith('[') && trimmed.endsWith(']'))) {
142
+ try {
143
+ return parseValueJsonStrings(JSON.parse(value));
144
+ }
145
+ catch {
146
+ return value;
147
+ }
148
+ }
149
+ return value;
150
+ }
151
+ if (Array.isArray(value)) {
152
+ return value.map(v => parseValueJsonStrings(v));
153
+ }
154
+ if (typeof value === 'object') {
155
+ const result = {};
156
+ for (const [k, v] of Object.entries(value)) {
157
+ result[k] = parseValueJsonStrings(v);
158
+ }
159
+ return result;
160
+ }
161
+ return value;
162
+ }
85
163
  //# sourceMappingURL=update.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"update.js","sourceRoot":"","sources":["../../../src/tools/update.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,aAAa,EAAE,MAAM,cAAc,CAAC;AAE7C,MAAM,CAAC,MAAM,iBAAiB,GAAS;IACrC,IAAI,EAAE,gBAAgB;IACtB,WAAW,EAAE;;;;;;;;;;;;;;;;;;;;;;OAsBR;IACL,WAAW,EAAE;QACX,IAAI,EAAE,QAAQ;QACd,UAAU,EAAE;YACV,SAAS,EAAE;gBACT,IAAI,EAAE,QAAQ;gBACd,WAAW,EAAE,sCAAsC;aACpD;YACD,YAAY,EAAE;gBACZ,IAAI,EAAE,QAAQ;gBACd,IAAI,EAAE,CAAC,OAAO,EAAE,KAAK,CAAC;gBACtB,WAAW,EAAE,mEAAmE;aACjF;SACF;QACD,QAAQ,EAAE,CAAC,WAAW,CAAC;QACvB,oBAAoB,EAAE,IAAI;KAC3B;CACF,CAAC;AAEF,MAAM,CAAC,KAAK,UAAU,mBAAmB,CAAC,IAAS;IACjD,IAAI,CAAC;QACH,MAAM,aAAa,GAAG,IAAI,aAAa,EAAE,CAAC;QAC1C,MAAM,MAAM,GAAG,MAAM,aAAa,CAAC,UAAU,EAAE,CAAC;QAEhD,IAAI,CAAC,MAAM,EAAE,CAAC;YACZ,MAAM,IAAI,KAAK,CAAC,iDAAiD,CAAC,CAAC;QACrE,CAAC;QAED,MAAM,EAAE,SAAS,EAAE,YAAY,EAAE,GAAG,OAAO,EAAE,GAAG,IAAI,CAAC;QAErD,IAAI,CAAC,SAAS,EAAE,CAAC;YACf,MAAM,IAAI,KAAK,CAAC,uBAAuB,CAAC,CAAC;QAC3C,CAAC;QAED,MAAM,MAAM,GAAG,CAAC,YAAY,IAAI,OAAO,CAAC,CAAC,WAAW,EAAE,CAAC;QAEvD,MAAM,QAAQ,GAAG,MAAM,KAAK,CAAC,GAAG,MAAM,CAAC,MAAM,IAAI,qBAAqB,YAAY,SAAS,EAAE,EAAE;YAC7F,MAAM;YACN,OAAO,EAAE;gBACP,eAAe,EAAE,UAAU,MAAM,CAAC,WAAW,EAAE;gBAC/C,cAAc,EAAE,kBAAkB;aACnC;YACD,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,OAAO,CAAC;SAC9B,CAAC,CAAC;QAEH,IAAI,CAAC,QAAQ,CAAC,EAAE,EAAE,CAAC;YACjB,MAAM,SAAS,GAAG,MAAM,QAAQ,CAAC,IAAI,EAAE,CAAC;YACxC,MAAM,IAAI,KAAK,CAAC,QAAQ,QAAQ,CAAC,MAAM,KAAK,SAAS,EAAE,CAAC,CAAC;QAC3D,CAAC;QAED,MAAM,IAAI,GAAG,MAAM,QAAQ,CAAC,IAAI,EAAE,CAAC;QAEnC,OAAO;YACL,OAAO,EAAE,CAAC;oBACR,IAAI,EAAE,MAAM;oBACZ,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,IAAI,EAAE,IAAI,EAAE,CAAC,CAAC;iBACpC,CAAC;SACH,CAAC;IAEJ,CAAC;IAAC,OAAO,KAAU,EAAE,CAAC;QACpB,OAAO;YACL,OAAO,EAAE,CAAC;oBACR,IAAI,EAAE,MAAM;oBACZ,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,EAAE,KAAK,EAAE,KAAK,CAAC,OAAO,EAAE,EAAE,IAAI,EAAE,CAAC,CAAC;iBACxD,CAAC;SACH,CAAC;IACJ,CAAC;AACH,CAAC"}
1
+ {"version":3,"file":"update.js","sourceRoot":"","sources":["../../../src/tools/update.ts"],"names":[],"mappings":"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"}
@@ -40,5 +40,41 @@ export declare function hasPermission(userSession: UserSession, permission: stri
40
40
  export declare function getAvailableScopes(userSession: UserSession, permission: string): string[];
41
41
  export declare function hasPermissionInScope(userSession: UserSession, permission: string, scopeId: string): boolean;
42
42
  export declare function getScopeTitle(userSession: UserSession, scopeId: string): string;
43
+ export declare function hasAnyPermission(userSession: UserSession, permissions: string[]): boolean;
44
+ export declare function hasFieldPermission(userSession: UserSession, basePermission: string): boolean;
45
+ export interface PermissionCheck {
46
+ permission: string;
47
+ alternatives?: string[];
48
+ description: string;
49
+ }
50
+ export declare function checkPermissions(userSession: UserSession, required: PermissionCheck[]): {
51
+ hasAll: boolean;
52
+ missing: PermissionCheck[];
53
+ };
54
+ export declare function formatPermissionError(operation: string, missing: PermissionCheck[]): string;
55
+ export declare const WORKFLOW_PERMISSIONS: {
56
+ view: ({
57
+ permission: string;
58
+ alternatives: string[];
59
+ description: string;
60
+ } | {
61
+ permission: string;
62
+ description: string;
63
+ alternatives?: never;
64
+ })[];
65
+ edit: ({
66
+ permission: string;
67
+ alternatives: string[];
68
+ description: string;
69
+ } | {
70
+ permission: string;
71
+ description: string;
72
+ alternatives?: never;
73
+ })[];
74
+ create: {
75
+ permission: string;
76
+ description: string;
77
+ }[];
78
+ };
43
79
  export declare function getUserSessionData(): Promise<UserSession>;
44
80
  //# sourceMappingURL=user.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"user.d.ts","sourceRoot":"","sources":["../../../src/tools/user.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,oCAAoC,CAAC;AAG1D,MAAM,WAAW,gBAAgB;IAC/B,KAAK,EAAE,MAAM,CAAC;IACd,GAAG,EAAE,MAAM,CAAC;IACZ,QAAQ,EAAE,CAAC,MAAM,GAAG;QAAE,GAAG,EAAE,MAAM,CAAC;QAAC,CAAC,GAAG,EAAE,MAAM,GAAG,GAAG,CAAA;KAAE,CAAC,EAAE,CAAC;IAC3D,WAAW,EAAE,MAAM,EAAE,CAAC;CACvB;AAED,MAAM,WAAW,WAAW;IAC1B,GAAG,EAAE,MAAM,CAAC;IACZ,YAAY,CAAC,EAAE;QACb,GAAG,EAAE,MAAM,CAAC;QACZ,KAAK,EAAE,MAAM,CAAC;QACd,MAAM,EAAE,MAAM,CAAC;KAChB,CAAC;IACF,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,IAAI,CAAC,EAAE;QACL,IAAI,EAAE,MAAM,CAAC;QACb,IAAI,EAAE,MAAM,CAAC;KACd,CAAC;IACF,WAAW,EAAE;QACX,CAAC,OAAO,EAAE,MAAM,GAAG,gBAAgB,CAAC;KACrC,CAAC;IACF,kBAAkB,CAAC,EAAE,GAAG,EAAE,CAAC;IAC3B,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,CAAC,GAAG,EAAE,MAAM,GAAG,GAAG,CAAC;CACpB;AAED,eAAO,MAAM,kBAAkB,EAAE,IAOhC,CAAC;AAEF,wBAAsB,oBAAoB,IAAI,OAAO,CAAC;IAAE,OAAO,EAAE,KAAK,CAAC;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAE,CAAC,CAAA;CAAE,CAAC,CAqCxG;AAGD,wBAAgB,aAAa,CAAC,WAAW,EAAE,WAAW,EAAE,UAAU,EAAE,MAAM,GAAG,OAAO,CAiBnF;AAGD,wBAAgB,kBAAkB,CAAC,WAAW,EAAE,WAAW,EAAE,UAAU,EAAE,MAAM,GAAG,MAAM,EAAE,CA+BzF;AAGD,wBAAgB,oBAAoB,CAAC,WAAW,EAAE,WAAW,EAAE,UAAU,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,OAAO,CAW3G;AAGD,wBAAgB,aAAa,CAAC,WAAW,EAAE,WAAW,EAAE,OAAO,EAAE,MAAM,GAAG,MAAM,CAO/E;AAGD,wBAAsB,kBAAkB,IAAI,OAAO,CAAC,WAAW,CAAC,CAoB/D"}
1
+ {"version":3,"file":"user.d.ts","sourceRoot":"","sources":["../../../src/tools/user.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,oCAAoC,CAAC;AAG1D,MAAM,WAAW,gBAAgB;IAC/B,KAAK,EAAE,MAAM,CAAC;IACd,GAAG,EAAE,MAAM,CAAC;IACZ,QAAQ,EAAE,CAAC,MAAM,GAAG;QAAE,GAAG,EAAE,MAAM,CAAC;QAAC,CAAC,GAAG,EAAE,MAAM,GAAG,GAAG,CAAA;KAAE,CAAC,EAAE,CAAC;IAC3D,WAAW,EAAE,MAAM,EAAE,CAAC;CACvB;AAED,MAAM,WAAW,WAAW;IAC1B,GAAG,EAAE,MAAM,CAAC;IACZ,YAAY,CAAC,EAAE;QACb,GAAG,EAAE,MAAM,CAAC;QACZ,KAAK,EAAE,MAAM,CAAC;QACd,MAAM,EAAE,MAAM,CAAC;KAChB,CAAC;IACF,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,IAAI,CAAC,EAAE;QACL,IAAI,EAAE,MAAM,CAAC;QACb,IAAI,EAAE,MAAM,CAAC;KACd,CAAC;IACF,WAAW,EAAE;QACX,CAAC,OAAO,EAAE,MAAM,GAAG,gBAAgB,CAAC;KACrC,CAAC;IACF,kBAAkB,CAAC,EAAE,GAAG,EAAE,CAAC;IAC3B,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,CAAC,GAAG,EAAE,MAAM,GAAG,GAAG,CAAC;CACpB;AAED,eAAO,MAAM,kBAAkB,EAAE,IAOhC,CAAC;AAEF,wBAAsB,oBAAoB,IAAI,OAAO,CAAC;IAAE,OAAO,EAAE,KAAK,CAAC;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAE,CAAC,CAAA;CAAE,CAAC,CAqCxG;AAGD,wBAAgB,aAAa,CAAC,WAAW,EAAE,WAAW,EAAE,UAAU,EAAE,MAAM,GAAG,OAAO,CAiBnF;AAGD,wBAAgB,kBAAkB,CAAC,WAAW,EAAE,WAAW,EAAE,UAAU,EAAE,MAAM,GAAG,MAAM,EAAE,CA+BzF;AAGD,wBAAgB,oBAAoB,CAAC,WAAW,EAAE,WAAW,EAAE,UAAU,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,OAAO,CAW3G;AAGD,wBAAgB,aAAa,CAAC,WAAW,EAAE,WAAW,EAAE,OAAO,EAAE,MAAM,GAAG,MAAM,CAO/E;AAGD,wBAAgB,gBAAgB,CAAC,WAAW,EAAE,WAAW,EAAE,WAAW,EAAE,MAAM,EAAE,GAAG,OAAO,CAOzF;AAGD,wBAAgB,kBAAkB,CAAC,WAAW,EAAE,WAAW,EAAE,cAAc,EAAE,MAAM,GAAG,OAAO,CAuB5F;AAGD,MAAM,WAAW,eAAe;IAC9B,UAAU,EAAE,MAAM,CAAC;IACnB,YAAY,CAAC,EAAE,MAAM,EAAE,CAAC;IACxB,WAAW,EAAE,MAAM,CAAC;CACrB;AAED,wBAAgB,gBAAgB,CAAC,WAAW,EAAE,WAAW,EAAE,QAAQ,EAAE,eAAe,EAAE,GAAG;IACvF,MAAM,EAAE,OAAO,CAAC;IAChB,OAAO,EAAE,eAAe,EAAE,CAAC;CAC5B,CAoBA;AAGD,wBAAgB,qBAAqB,CAAC,SAAS,EAAE,MAAM,EAAE,OAAO,EAAE,eAAe,EAAE,GAAG,MAAM,CAe3F;AAGD,eAAO,MAAM,oBAAoB;;;;;;;;;;;;;;;;;;;;;;;CAYhC,CAAC;AAGF,wBAAsB,kBAAkB,IAAI,OAAO,CAAC,WAAW,CAAC,CAoB/D"}