@bscotch/blork-shared
Advanced tools
Comparing version 0.10.0 to 0.11.0
import { BaseError } from './errors.js'; | ||
import { Events } from './events.js'; | ||
import { CommentData, CommentPatch } from './types.comments.js'; | ||
@@ -35,4 +36,12 @@ import { TaskData, TaskPatch, TaskPost } from './types.tasks.js'; | ||
} | ||
export declare class BlorkClient { | ||
export type BlorkRequest = [url: string | URL, options: RequestInit]; | ||
export declare class BlorkClient extends Events<{ | ||
response: Res; | ||
request: BlorkRequest; | ||
}> { | ||
readonly options: BlorkClientOptions; | ||
protected remoteVersions: { | ||
server?: string; | ||
site?: string; | ||
}; | ||
constructor(options: BlorkClientOptions); | ||
@@ -76,2 +85,4 @@ withOptions(options: Partial<BlorkClient['options']>): BlorkClient; | ||
updateTaskDoneState(taskId: string, done: boolean): Promise<TaskData>; | ||
updateTaskLockedState(taskId: string, locked: boolean): Promise<TaskData>; | ||
updateTaskBackloggedState(taskId: string, backlogged: boolean): Promise<TaskData>; | ||
addTaskBlocker(taskId: string, blockerId: string): Promise<TaskData>; | ||
@@ -94,7 +105,7 @@ removeTaskBlocker(taskId: string, blockerId: string): Promise<TaskData>; | ||
updateTemplate(templateId: string, patch: TaskTemplatePatch): Promise<{ | ||
creator: string; | ||
createdAt: Date; | ||
updatedAt: Date; | ||
creator: string; | ||
description: string; | ||
name: string; | ||
description: string; | ||
template: string; | ||
@@ -137,4 +148,8 @@ templateId: string; | ||
get code(): string | number | undefined; | ||
get serverVersion(): { | ||
server: string | null; | ||
site: string | null; | ||
}; | ||
static from(response: Response): Promise<Res>; | ||
} | ||
//# sourceMappingURL=client.d.ts.map |
import { z } from 'zod'; | ||
import { BaseError } from './errors.js'; | ||
import { Events } from './events.js'; | ||
import { stringSchema } from './types.lib.js'; | ||
import { taskPatchBlockSchema, taskPatchDescriptionSchema, taskPatchDoneSchema, taskPatchHoursSchema, taskPatchLinkSchema, taskPatchMoveSchema, taskPatchOwnerSchema, taskPatchSchema, taskPatchSnoozeSchema, taskPatchStarredSchema, taskPatchTaggedSchema, taskPatchTitleSchema, taskPatchUnblockSchema, taskPatchUnlinkSchema, taskPostSchema, taskSchema, } from './types.tasks.js'; | ||
import { taskPatchBackloggedSchema, taskPatchBlockSchema, taskPatchDescriptionSchema, taskPatchDoneSchema, taskPatchHoursSchema, taskPatchLinkSchema, taskPatchLockedSchema, taskPatchMoveSchema, taskPatchNonownerSchema, taskPatchOwnerSchema, taskPatchSchema, taskPatchSnoozeSchema, taskPatchStarredSchema, taskPatchTaggedSchema, taskPatchTitleSchema, taskPatchUnblockSchema, taskPatchUnlinkSchema, taskPostSchema, taskSchema, } from './types.tasks.js'; | ||
import { taskTemplatePatchSchema, taskTemplatePostSchema, taskTemplateSchema, } from './types.templates.js'; | ||
import { safeUserOrGroupDataSchema, userAccessNewTokenSchema, userDataSchema, userGroupDataSchema, userGroupPatchMembersSchema, userLoginPostSchema, userOrGroupDataSchema, userPatchPinsSchema, userPostSchema, } from './types.users.js'; | ||
export class BlorkClient { | ||
export class BlorkClient extends Events { | ||
options; | ||
remoteVersions = {}; | ||
constructor(options) { | ||
super(); | ||
this.options = options; | ||
@@ -69,9 +72,21 @@ } | ||
} | ||
const response = await this.fetch(fullUrl, { | ||
method, | ||
body, | ||
headers: headers, | ||
credentials: 'include', | ||
}); | ||
const request = [ | ||
fullUrl, | ||
{ | ||
method, | ||
body, | ||
headers: headers, | ||
credentials: 'include', | ||
}, | ||
]; | ||
this.emit('request', request); | ||
const response = await this.fetch(request[0], request[1]); | ||
if (response.headers.get('Blork-Server-Version')) { | ||
this.remoteVersions.server = response.headers.get('Blork-Server-Version'); | ||
} | ||
if (response.headers.get('Blork-Site-Version')) { | ||
this.remoteVersions.site = response.headers.get('Blork-Site-Version'); | ||
} | ||
const res = await Res.from(response); | ||
this.emit('response', res); | ||
if (options?.assertStatus) { | ||
@@ -119,3 +134,6 @@ assertStatus(res, options.assertStatus, this.options.errorClass); | ||
const task = (await this.request('PATCH', `/api/tasks/${encodeURIComponent(taskId)}`, { | ||
body: taskPatchOwnerSchema.parse({ kind: 'set-nonowners', nonowners }), | ||
body: taskPatchNonownerSchema.parse({ | ||
kind: 'set-nonowners', | ||
nonowners, | ||
}), | ||
assertStatus: 200, | ||
@@ -177,2 +195,19 @@ })).body.result; | ||
} | ||
async updateTaskLockedState(taskId, locked) { | ||
const task = (await this.request('PATCH', `/api/tasks/${encodeURIComponent(taskId)}`, { | ||
body: taskPatchLockedSchema.parse({ kind: 'set-locked', locked }), | ||
assertStatus: 200, | ||
})).body.result; | ||
return taskSchema.parse(task); | ||
} | ||
async updateTaskBackloggedState(taskId, backlogged) { | ||
const task = (await this.request('PATCH', `/api/tasks/${encodeURIComponent(taskId)}`, { | ||
body: taskPatchBackloggedSchema.parse({ | ||
kind: 'set-backlogged', | ||
backlogged, | ||
}), | ||
assertStatus: 200, | ||
})).body.result; | ||
return taskSchema.parse(task); | ||
} | ||
async addTaskBlocker(taskId, blockerId) { | ||
@@ -428,2 +463,8 @@ const task = (await this.request('PATCH', `/api/tasks/${encodeURIComponent(taskId)}`, { | ||
} | ||
get serverVersion() { | ||
return { | ||
server: this.response.headers.get('Blork-Server-Version'), | ||
site: this.response.headers.get('Blork-Site-Version'), | ||
}; | ||
} | ||
static async from(response) { | ||
@@ -430,0 +471,0 @@ const res = new Res(); |
@@ -7,2 +7,3 @@ import { Events } from './events.js'; | ||
export * from './events.js'; | ||
export * from './html.js'; | ||
export * from './markdown.js'; | ||
@@ -9,0 +10,0 @@ export * from './search.js'; |
@@ -6,2 +6,3 @@ import { Events } from './events.js'; | ||
export * from './events.js'; | ||
export * from './html.js'; | ||
export * from './markdown.js'; | ||
@@ -8,0 +9,0 @@ export * from './search.js'; |
@@ -12,3 +12,4 @@ export interface InlineMarkdownOptions { | ||
paragraphs?: 'inline' | 'truncate'; | ||
allowHtml?: boolean; | ||
}): string; | ||
//# sourceMappingURL=markdown.d.ts.map |
@@ -0,3 +1,3 @@ | ||
import { escapeHtml } from './html.js'; | ||
export function inlineMarkdownToHtml(markdown, options = {}) { | ||
let lefts = []; | ||
options.paragraphs ||= 'inline'; | ||
@@ -14,2 +14,7 @@ if (options.paragraphs === 'inline') { | ||
} | ||
// Remove any html | ||
if (!options.allowHtml) { | ||
markdown = escapeHtml(markdown); | ||
} | ||
let lefts = []; | ||
let html = `<span>`; | ||
@@ -16,0 +21,0 @@ for (let i = 0; i < markdown.length; i++) { |
@@ -212,2 +212,5 @@ import uFuzzy from '@leeoniya/ufuzzy'; | ||
} | ||
else if (term === 'locked') { | ||
return !!task.locked; | ||
} | ||
else if (term === 'description') { | ||
@@ -214,0 +217,0 @@ return !!task.description; |
@@ -19,2 +19,3 @@ import { durationStringToHours, entries } from './util.js'; | ||
done: ['done', 'completed', 'complete', 'checked', 'finished'], | ||
locked: ['locked', 'lock', 'folder'], | ||
files: ['file', 'files', 'attachment', 'attachments'], | ||
@@ -21,0 +22,0 @@ description: descriptionFilterAliases, |
@@ -17,3 +17,3 @@ export interface BlorkQuery { | ||
export type BlorkFilterKind = 'text' | 'title' | 'description' | 'comments' | 'id' | 'owner' | 'has' | 'hours' | 'unknown'; | ||
export type BlorkHasTermName = 'star' | 'tag' | 'done' | 'snooze' | 'block' | 'files' | 'description' | 'title' | 'comments' | 'hours' | 'unknown'; | ||
export type BlorkHasTermName = 'star' | 'tag' | 'done' | 'locked' | 'snooze' | 'block' | 'files' | 'description' | 'title' | 'comments' | 'hours' | 'unknown'; | ||
export interface BlorkQueryHasTerm { | ||
@@ -20,0 +20,0 @@ term: BlorkHasTermName; |
@@ -56,3 +56,4 @@ import { CommentData, TaskData, UserData, UserDataSafe } from './index.js'; | ||
updateChildren: Map<string, string[]>; | ||
blockers: Set<string>; | ||
incompleteBlockers: Set<string>; | ||
lockedBlockers: Set<string>; | ||
} | ||
@@ -75,2 +76,11 @@ /** | ||
/** | ||
* Tasks are lockable if all of their parents are locked (or root), | ||
* and if they are not already complete. | ||
*/ | ||
export declare function taskIsLockable(cache: TaskCache, taskId: string): boolean; | ||
/** | ||
* A task is unlockable if it is locked and all of its children are unlocked. | ||
*/ | ||
export declare function taskIsUnlockable(cache: TaskCache, taskId: string): boolean; | ||
/** | ||
* If the task or any of its ancestors are starred, return true. | ||
@@ -77,0 +87,0 @@ */ |
@@ -155,3 +155,4 @@ import { assert } from './errors.js'; | ||
// to complete the deletion. | ||
const blockers = new Set(); | ||
const incompleteBlockers = new Set(); | ||
const lockedBlockers = new Set(); | ||
const updateParents = new Map(); | ||
@@ -187,4 +188,7 @@ const updateChildren = new Map(); | ||
if (taskId !== taskIdToDelete && !task.done) { | ||
blockers.add(taskId); | ||
incompleteBlockers.add(taskId); | ||
} | ||
else if (task.locked) { | ||
lockedBlockers.add(taskId); | ||
} | ||
for (const childId of task.children) { | ||
@@ -206,7 +210,8 @@ evaluateForDeletion(childId, taskId); | ||
return { | ||
allowed: blockers.size === 0, | ||
allowed: !incompleteBlockers.size && !lockedBlockers.size, | ||
delete: tasksToDelete, | ||
updateParents, | ||
updateChildren, | ||
blockers, | ||
incompleteBlockers, | ||
lockedBlockers, | ||
}; | ||
@@ -249,2 +254,38 @@ } | ||
/** | ||
* Tasks are lockable if all of their parents are locked (or root), | ||
* and if they are not already complete. | ||
*/ | ||
export function taskIsLockable(cache, taskId) { | ||
const task = cache.get(taskId); | ||
if (!task) | ||
return false; | ||
if (task.done) | ||
return false; | ||
// Only lockable if all parents are locked | ||
for (const parentId of task.parents) { | ||
if (parentId === rootTaskId) | ||
continue; | ||
const parent = cache.get(parentId); | ||
if (!parent || !parent.locked) | ||
return false; | ||
} | ||
return true; | ||
} | ||
/** | ||
* A task is unlockable if it is locked and all of its children are unlocked. | ||
*/ | ||
export function taskIsUnlockable(cache, taskId) { | ||
if (taskId === rootTaskId) | ||
return false; | ||
const task = cache.get(taskId); | ||
if (!task || !task.locked) | ||
return false; | ||
for (const childId of task.children) { | ||
const child = cache.get(childId); | ||
if (!child || child.locked) | ||
return false; | ||
} | ||
return true; | ||
} | ||
/** | ||
* If the task or any of its ancestors are starred, return true. | ||
@@ -303,2 +344,4 @@ */ | ||
} | ||
if (task.backlogged) | ||
return false; | ||
if (taskIsSnoozed(task)) | ||
@@ -466,2 +509,3 @@ return false; | ||
const isDoable = !task.done && | ||
!task.locked && | ||
isMine && | ||
@@ -468,0 +512,0 @@ // all children are done |
@@ -14,6 +14,6 @@ export declare const taskUrlAreas: readonly ["card", "tree", "pins", "doables", "done", "search"]; | ||
/** | ||
* When `where` is 'card', this is the pointer for the Card we want to focus. Conceptually distinct from 'task', which is the pointer we want to focus (could be inside the card, could be elsewhere prior to opening Card View) | ||
* When `where` is 'card' or 'pin', this is the pointer for the subtree root. Conceptually distinct from 'task', which is the pointer we want to focus (could be inside the card, could be elsewhere prior to opening Card View) | ||
* Defaults to the task pointer. | ||
*/ | ||
card?: string[]; | ||
subtree?: string[]; | ||
/** | ||
@@ -20,0 +20,0 @@ * When `where` is 'search', this is the search query used that led to this task. When present, if the task is not found in the search results that part |
@@ -28,3 +28,3 @@ import { assert } from './errors.js'; | ||
if (options.where === 'card') { | ||
card = [...(options.card || focus)]; | ||
card = [...(options.subtree || focus)]; | ||
assert(card.length && card[0] === rootTaskId, 'Card must start with root task'); | ||
@@ -50,7 +50,9 @@ // Remove the root element since it's inferrable | ||
} | ||
// Remove the root task from the pointer and card since they are inferrable | ||
if (card?.[0] === rootTaskId) | ||
card.shift(); | ||
if (focus[0] === rootTaskId) | ||
focus.shift(); | ||
// If in pins view, add the subtree as a param | ||
if (options.where === 'pins' && | ||
options.subtree && | ||
options.subtree.length > 1 && | ||
!stringArraysAreSame(options.subtree, focus)) { | ||
url.searchParams.set('subtree', options.subtree.slice(1).join('/')); | ||
} | ||
if (options.search?.trim()) { | ||
@@ -77,7 +79,7 @@ url.searchParams.set('search', options.search); | ||
const pathParts = url.pathname.split('/').slice(2); | ||
options.card = [rootTaskId, ...(pathParts || [])]; | ||
options.subtree = [rootTaskId, ...(pathParts || [])]; | ||
options.where = 'card'; | ||
if (!url.searchParams.get('focus')) { | ||
// Then we're focusing the card itself implicitly | ||
options.focus = [...options.card]; | ||
options.focus = [...options.subtree]; | ||
} | ||
@@ -89,2 +91,8 @@ } | ||
} | ||
if (options.where === 'pins') { | ||
// Then we need to get the subtree | ||
const subtree = url.searchParams.get('subtree')?.split('/') || []; | ||
subtree.unshift(rootTaskId); | ||
options.subtree = subtree; | ||
} | ||
const search = url.searchParams.get('search'); | ||
@@ -100,4 +108,4 @@ if (search) { | ||
options.where = 'card'; | ||
options.card = parts.card.split('/'); | ||
options.focus = options.card; | ||
options.subtree = parts.card.split('/'); | ||
options.focus = options.subtree; | ||
} | ||
@@ -104,0 +112,0 @@ else if (parts.tree) { |
@@ -113,8 +113,11 @@ import { assert } from './errors.js'; | ||
} | ||
else if (tag.match(/^#(tag(ged)?|label(ed)?)$/)) { | ||
else if (tag.match(/^#(?:tag(?:ged)?|label(?:ed)?)$/)) { | ||
newTask.tagged = true; | ||
} | ||
else if (tag.match(/^#star(red)?$/)) { | ||
else if (tag.match(/^#star(?:red)?$/)) { | ||
newTask.starred = true; | ||
} | ||
else if (tag.match(/^#(?:lock(?:ed)?|folder)$/)) { | ||
newTask.locked = true; | ||
} | ||
} | ||
@@ -121,0 +124,0 @@ } |
@@ -21,2 +21,4 @@ import { z } from 'zod'; | ||
creator: z.ZodString; | ||
locked: z.ZodNullable<z.ZodOptional<z.ZodBoolean>>; | ||
backlogged: z.ZodNullable<z.ZodOptional<z.ZodBoolean>>; | ||
done: z.ZodNullable<z.ZodDefault<z.ZodBoolean>>; | ||
@@ -95,2 +97,4 @@ taskId: z.ZodString; | ||
description?: string | null | undefined; | ||
locked?: boolean | null | undefined; | ||
backlogged?: boolean | null | undefined; | ||
hours?: number | null | undefined; | ||
@@ -130,2 +134,4 @@ starred?: boolean | null | undefined; | ||
description?: string | null | undefined; | ||
locked?: boolean | null | undefined; | ||
backlogged?: boolean | null | undefined; | ||
hours?: number | null | undefined; | ||
@@ -167,2 +173,4 @@ starred?: boolean | null | undefined; | ||
description?: string | null | undefined; | ||
locked?: boolean | null | undefined; | ||
backlogged?: boolean | null | undefined; | ||
hours?: number | null | undefined; | ||
@@ -199,2 +207,3 @@ starred?: boolean | null | undefined; | ||
done?: boolean; | ||
locked?: boolean; | ||
starred?: boolean; | ||
@@ -303,2 +312,24 @@ tagged?: boolean; | ||
}>; | ||
export type TaskPatchLocked = z.infer<typeof taskPatchLockedSchema>; | ||
export declare const taskPatchLockedSchema: z.ZodObject<{ | ||
kind: z.ZodLiteral<"set-locked">; | ||
locked: z.ZodBoolean; | ||
}, "strip", z.ZodTypeAny, { | ||
kind: "set-locked"; | ||
locked: boolean; | ||
}, { | ||
kind: "set-locked"; | ||
locked: boolean; | ||
}>; | ||
export type TaskPatchBacklogged = z.infer<typeof taskPatchBackloggedSchema>; | ||
export declare const taskPatchBackloggedSchema: z.ZodObject<{ | ||
kind: z.ZodLiteral<"set-backlogged">; | ||
backlogged: z.ZodBoolean; | ||
}, "strip", z.ZodTypeAny, { | ||
kind: "set-backlogged"; | ||
backlogged: boolean; | ||
}, { | ||
kind: "set-backlogged"; | ||
backlogged: boolean; | ||
}>; | ||
export type TaskPatchHours = z.infer<typeof taskPatchHoursSchema>; | ||
@@ -447,2 +478,20 @@ export declare const taskPatchHoursSchema: z.ZodObject<{ | ||
}>, z.ZodObject<{ | ||
kind: z.ZodLiteral<"set-locked">; | ||
locked: z.ZodBoolean; | ||
}, "strip", z.ZodTypeAny, { | ||
kind: "set-locked"; | ||
locked: boolean; | ||
}, { | ||
kind: "set-locked"; | ||
locked: boolean; | ||
}>, z.ZodObject<{ | ||
kind: z.ZodLiteral<"set-backlogged">; | ||
backlogged: z.ZodBoolean; | ||
}, "strip", z.ZodTypeAny, { | ||
kind: "set-backlogged"; | ||
backlogged: boolean; | ||
}, { | ||
kind: "set-backlogged"; | ||
backlogged: boolean; | ||
}>, z.ZodObject<{ | ||
kind: z.ZodLiteral<"set-hours">; | ||
@@ -570,2 +619,4 @@ hours: z.ZodNullable<z.ZodNumber>; | ||
creator: z.ZodString; | ||
locked: z.ZodNullable<z.ZodOptional<z.ZodBoolean>>; | ||
backlogged: z.ZodNullable<z.ZodOptional<z.ZodBoolean>>; | ||
done: z.ZodNullable<z.ZodDefault<z.ZodBoolean>>; | ||
@@ -644,2 +695,4 @@ taskId: z.ZodString; | ||
description?: string | null | undefined; | ||
locked?: boolean | null | undefined; | ||
backlogged?: boolean | null | undefined; | ||
hours?: number | null | undefined; | ||
@@ -679,2 +732,4 @@ starred?: boolean | null | undefined; | ||
description?: string | null | undefined; | ||
locked?: boolean | null | undefined; | ||
backlogged?: boolean | null | undefined; | ||
hours?: number | null | undefined; | ||
@@ -716,2 +771,4 @@ starred?: boolean | null | undefined; | ||
description?: string | null | undefined; | ||
locked?: boolean | null | undefined; | ||
backlogged?: boolean | null | undefined; | ||
hours?: number | null | undefined; | ||
@@ -757,2 +814,4 @@ starred?: boolean | null | undefined; | ||
description?: string | null | undefined; | ||
locked?: boolean | null | undefined; | ||
backlogged?: boolean | null | undefined; | ||
hours?: number | null | undefined; | ||
@@ -801,2 +860,4 @@ starred?: boolean | null | undefined; | ||
creator: z.ZodString; | ||
locked: z.ZodNullable<z.ZodOptional<z.ZodBoolean>>; | ||
backlogged: z.ZodNullable<z.ZodOptional<z.ZodBoolean>>; | ||
done: z.ZodNullable<z.ZodDefault<z.ZodBoolean>>; | ||
@@ -875,2 +936,4 @@ taskId: z.ZodString; | ||
description?: string | null | undefined; | ||
locked?: boolean | null | undefined; | ||
backlogged?: boolean | null | undefined; | ||
hours?: number | null | undefined; | ||
@@ -910,2 +973,4 @@ starred?: boolean | null | undefined; | ||
description?: string | null | undefined; | ||
locked?: boolean | null | undefined; | ||
backlogged?: boolean | null | undefined; | ||
hours?: number | null | undefined; | ||
@@ -947,2 +1012,4 @@ starred?: boolean | null | undefined; | ||
description?: string | null | undefined; | ||
locked?: boolean | null | undefined; | ||
backlogged?: boolean | null | undefined; | ||
hours?: number | null | undefined; | ||
@@ -988,2 +1055,4 @@ starred?: boolean | null | undefined; | ||
description?: string | null | undefined; | ||
locked?: boolean | null | undefined; | ||
backlogged?: boolean | null | undefined; | ||
hours?: number | null | undefined; | ||
@@ -990,0 +1059,0 @@ starred?: boolean | null | undefined; |
@@ -39,2 +39,8 @@ import { z } from 'zod'; | ||
creator: stringSchema, | ||
locked: z.boolean().optional().nullable(), | ||
backlogged: z | ||
.boolean() | ||
.optional() | ||
.nullable() | ||
.describe('Backlog tasks prevent all of their subtasks from appearing in Doables. Only locked tasks can flagged as a backlog.'), | ||
done: z.boolean().default(false).nullable(), | ||
@@ -67,2 +73,3 @@ taskId: stringSchema, | ||
done: z.boolean().optional(), | ||
locked: z.boolean().optional(), | ||
starred: z.boolean().optional(), | ||
@@ -118,2 +125,10 @@ tagged: z.boolean().optional(), | ||
}); | ||
export const taskPatchLockedSchema = z.object({ | ||
kind: z.literal('set-locked'), | ||
locked: z.boolean(), | ||
}); | ||
export const taskPatchBackloggedSchema = z.object({ | ||
kind: z.literal('set-backlogged'), | ||
backlogged: z.boolean(), | ||
}); | ||
export const taskPatchHoursSchema = z.object({ | ||
@@ -165,2 +180,4 @@ kind: z.literal('set-hours'), | ||
taskPatchDoneSchema, | ||
taskPatchLockedSchema, | ||
taskPatchBackloggedSchema, | ||
taskPatchHoursSchema, | ||
@@ -167,0 +184,0 @@ taskPatchOwnerSchema, |
@@ -8,8 +8,11 @@ import { z } from 'zod'; | ||
useCtrlToEditTaskTitles: z.ZodOptional<z.ZodBoolean>; | ||
skipSnoozeConfirmation: z.ZodOptional<z.ZodBoolean>; | ||
}, "strip", z.ZodTypeAny, { | ||
useCtrlToOpenCardLinks?: boolean | undefined; | ||
useCtrlToEditTaskTitles?: boolean | undefined; | ||
skipSnoozeConfirmation?: boolean | undefined; | ||
}, { | ||
useCtrlToOpenCardLinks?: boolean | undefined; | ||
useCtrlToEditTaskTitles?: boolean | undefined; | ||
skipSnoozeConfirmation?: boolean | undefined; | ||
}>; | ||
@@ -16,0 +19,0 @@ export type UserGroupData = z.infer<typeof userGroupDataSchema>; |
@@ -8,2 +8,3 @@ import { z } from 'zod'; | ||
useCtrlToEditTaskTitles: z.boolean().optional(), | ||
skipSnoozeConfirmation: z.boolean().optional(), | ||
}); | ||
@@ -10,0 +11,0 @@ const userDataBaseSchema = z.object({ |
@@ -50,2 +50,3 @@ import { UserData, UserGroupData, UserOrGroupData, type UserDataSafe } from './types.users.js'; | ||
*/ | ||
export declare function userIsInGroup(userId: string, groupId: string, users: UserCache): boolean; | ||
export declare function userIsInGroup(userId: string, group: UserOrGroupData): boolean; | ||
@@ -52,0 +53,0 @@ /** |
@@ -69,7 +69,9 @@ /** | ||
} | ||
/** | ||
* Returns true if both userIds are the same, or if the | ||
* userId is found in the group's members. | ||
*/ | ||
export function userIsInGroup(userId, group) { | ||
export function userIsInGroup(userId, group, users) { | ||
if (typeof group === 'string') { | ||
const foundGroup = users?.get(group); | ||
if (!foundGroup) | ||
return false; | ||
group = foundGroup; | ||
} | ||
return (userId === group.userId || | ||
@@ -76,0 +78,0 @@ (isUserGroup(group) && group.userIds?.includes(userId))); |
{ | ||
"name": "@bscotch/blork-shared", | ||
"version": "0.10.0", | ||
"version": "0.11.0", | ||
"description": "Client and shared utilities for Blork projects.", | ||
@@ -5,0 +5,0 @@ "keywords": [], |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
450519
162
7254