@taskless-app/shared 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/LICENSE +24 -0
- package/dist/branding.d.ts +32 -0
- package/dist/branding.js +28 -0
- package/dist/branding.js.map +1 -0
- package/dist/chatMessageKinds.d.ts +2 -0
- package/dist/chatMessageKinds.js +10 -0
- package/dist/chatMessageKinds.js.map +1 -0
- package/dist/designTokens.d.ts +190 -0
- package/dist/designTokens.js +249 -0
- package/dist/designTokens.js.map +1 -0
- package/dist/domain.d.ts +2 -0
- package/dist/domain.js +8 -0
- package/dist/domain.js.map +1 -0
- package/dist/finishChip.d.ts +18 -0
- package/dist/finishChip.js +95 -0
- package/dist/finishChip.js.map +1 -0
- package/dist/gender.d.ts +6 -0
- package/dist/gender.js +11 -0
- package/dist/gender.js.map +1 -0
- package/dist/index.d.ts +18 -0
- package/dist/index.js +19 -0
- package/dist/index.js.map +1 -0
- package/dist/labelColors.d.ts +3 -0
- package/dist/labelColors.js +33 -0
- package/dist/labelColors.js.map +1 -0
- package/dist/notifications.d.ts +36 -0
- package/dist/notifications.js +2 -0
- package/dist/notifications.js.map +1 -0
- package/dist/releaseSources.d.ts +20 -0
- package/dist/releaseSources.js +44 -0
- package/dist/releaseSources.js.map +1 -0
- package/dist/schemas.d.ts +1929 -0
- package/dist/schemas.js +655 -0
- package/dist/schemas.js.map +1 -0
- package/dist/sortWorkflowStates.d.ts +5 -0
- package/dist/sortWorkflowStates.js +18 -0
- package/dist/sortWorkflowStates.js.map +1 -0
- package/dist/statusIcons.d.ts +2 -0
- package/dist/statusIcons.js +40 -0
- package/dist/statusIcons.js.map +1 -0
- package/dist/translit.d.ts +11 -0
- package/dist/translit.js +41 -0
- package/dist/translit.js.map +1 -0
- package/dist/uiTour.d.ts +48 -0
- package/dist/uiTour.js +175 -0
- package/dist/uiTour.js.map +1 -0
- package/dist/userHandle.d.ts +14 -0
- package/dist/userHandle.js +25 -0
- package/dist/userHandle.js.map +1 -0
- package/dist/userHue.d.ts +1 -0
- package/dist/userHue.js +24 -0
- package/dist/userHue.js.map +1 -0
- package/dist/weight.d.ts +11 -0
- package/dist/weight.js +71 -0
- package/dist/weight.js.map +1 -0
- package/dist/workspaceBrand.d.ts +5 -0
- package/dist/workspaceBrand.js +39 -0
- package/dist/workspaceBrand.js.map +1 -0
- package/package.json +32 -0
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
// PRJ-7 Фаза 2 (F2-1): computeFinishChip — единая логика для чипа задачи во
|
|
2
|
+
// всех списках (TaskCard / TaskTable / EntityRowList / Inbox / Today).
|
|
3
|
+
// Dominant signal:
|
|
4
|
+
// 1. pinnedUntil > now → 📌 pin (assignee'ское personal trump)
|
|
5
|
+
// 2. task.deadline → 🗓 standalone deadline
|
|
6
|
+
// 3. иначе → null (chip не рендерим)
|
|
7
|
+
//
|
|
8
|
+
// Возвращает self-contained data structure — UI рендерит как угодно. tone
|
|
9
|
+
// определяет цвет/intensity:
|
|
10
|
+
// "neutral" — нормальный (нейтральный pin)
|
|
11
|
+
// "urgent" — ≤2 дня до события или активный pin
|
|
12
|
+
// "overdue" — дата прошла
|
|
13
|
+
//
|
|
14
|
+
// Импортится фронтом и api (формат ленты, агента).
|
|
15
|
+
function toDate(v) {
|
|
16
|
+
return typeof v === "string" ? new Date(v) : v;
|
|
17
|
+
}
|
|
18
|
+
function pluralizeDays(n) {
|
|
19
|
+
const abs = Math.abs(n);
|
|
20
|
+
const last = abs % 10;
|
|
21
|
+
const tens = Math.floor(abs / 10) % 10;
|
|
22
|
+
if (tens === 1)
|
|
23
|
+
return "дней";
|
|
24
|
+
if (last === 1)
|
|
25
|
+
return "день";
|
|
26
|
+
if (last >= 2 && last <= 4)
|
|
27
|
+
return "дня";
|
|
28
|
+
return "дней";
|
|
29
|
+
}
|
|
30
|
+
function diffDays(target, now) {
|
|
31
|
+
// Date-based diff в локальном TZ юзера. UX'но правильнее: дедлайн
|
|
32
|
+
// «завтра 00:00» = «завтра» даже если до него 4 часа. Тесты должны
|
|
33
|
+
// фиксировать TZ через vitest config (process.env.TZ).
|
|
34
|
+
const a = new Date(target.getFullYear(), target.getMonth(), target.getDate()).getTime();
|
|
35
|
+
const b = new Date(now.getFullYear(), now.getMonth(), now.getDate()).getTime();
|
|
36
|
+
return Math.round((a - b) / (24 * 3600 * 1000));
|
|
37
|
+
}
|
|
38
|
+
function relativeLabel(target, now) {
|
|
39
|
+
const days = diffDays(target, now);
|
|
40
|
+
if (days < 0) {
|
|
41
|
+
const abs = Math.abs(days);
|
|
42
|
+
return { text: `просрочено ${abs}${abs === 1 ? "д" : "д"}`, tone: "overdue" };
|
|
43
|
+
}
|
|
44
|
+
if (days === 0)
|
|
45
|
+
return { text: "сегодня", tone: "urgent" };
|
|
46
|
+
if (days === 1)
|
|
47
|
+
return { text: "завтра", tone: "urgent" };
|
|
48
|
+
if (days <= 7)
|
|
49
|
+
return { text: `через ${days}д`, tone: "urgent" };
|
|
50
|
+
return { text: `через ${days}д`, tone: "neutral" };
|
|
51
|
+
}
|
|
52
|
+
function fullTooltip(prefix, target, now) {
|
|
53
|
+
const days = diffDays(target, now);
|
|
54
|
+
const dateStr = target.toLocaleDateString("ru-RU", { day: "numeric", month: "long" });
|
|
55
|
+
if (days < 0) {
|
|
56
|
+
const abs = Math.abs(days);
|
|
57
|
+
return `${prefix} ${dateStr} — просрочено ${abs} ${pluralizeDays(abs)}`;
|
|
58
|
+
}
|
|
59
|
+
if (days === 0)
|
|
60
|
+
return `${prefix} ${dateStr} — сегодня`;
|
|
61
|
+
if (days === 1)
|
|
62
|
+
return `${prefix} ${dateStr} — завтра`;
|
|
63
|
+
return `${prefix} ${dateStr} — через ${days} ${pluralizeDays(days)}`;
|
|
64
|
+
}
|
|
65
|
+
export function computeFinishChip(task, now = new Date()) {
|
|
66
|
+
// 1. pinnedUntil → assignee'ское personal trump.
|
|
67
|
+
if (task.pinnedUntil) {
|
|
68
|
+
const pinDate = toDate(task.pinnedUntil);
|
|
69
|
+
if (pinDate.getTime() > now.getTime()) {
|
|
70
|
+
const rel = relativeLabel(pinDate, now);
|
|
71
|
+
// Pin всегда urgent tone — даже если до конца недели, это сознательный
|
|
72
|
+
// фокус assignee. Если pin далеко в будущем — neutral, чтобы не кричал.
|
|
73
|
+
const tone = diffDays(pinDate, now) > 7 ? "neutral" : "urgent";
|
|
74
|
+
return {
|
|
75
|
+
icon: "pin",
|
|
76
|
+
label: rel.text === "сегодня" ? "до конца дня" : rel.text,
|
|
77
|
+
tone,
|
|
78
|
+
tooltip: `📌 Закреплено ${fullTooltip("до", pinDate, now)}`,
|
|
79
|
+
};
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
// 2. standalone task.deadline.
|
|
83
|
+
if (task.deadline) {
|
|
84
|
+
const dl = toDate(task.deadline);
|
|
85
|
+
const rel = relativeLabel(dl, now);
|
|
86
|
+
return {
|
|
87
|
+
icon: "deadline",
|
|
88
|
+
label: rel.text,
|
|
89
|
+
tone: rel.tone,
|
|
90
|
+
tooltip: fullTooltip("🗓 Дедлайн", dl, now),
|
|
91
|
+
};
|
|
92
|
+
}
|
|
93
|
+
return null;
|
|
94
|
+
}
|
|
95
|
+
//# sourceMappingURL=finishChip.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"finishChip.js","sourceRoot":"","sources":["../src/finishChip.ts"],"names":[],"mappings":"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"}
|
package/dist/gender.d.ts
ADDED
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
export type Gender = "male" | "female";
|
|
2
|
+
export declare const GENDER_OPTIONS: Gender[];
|
|
3
|
+
export declare const GENDER_LABEL: Record<Gender, string>;
|
|
4
|
+
/** Выбирает форму глагола/прилагательного прошедшего времени по полу.
|
|
5
|
+
* null/undefined → мужской род (дефолт для незаполненного профиля). */
|
|
6
|
+
export declare function genderPast(g: Gender | null | undefined, masc: string, fem: string): string;
|
package/dist/gender.js
ADDED
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
export const GENDER_OPTIONS = ["male", "female"];
|
|
2
|
+
export const GENDER_LABEL = {
|
|
3
|
+
male: "Мужской",
|
|
4
|
+
female: "Женский",
|
|
5
|
+
};
|
|
6
|
+
/** Выбирает форму глагола/прилагательного прошедшего времени по полу.
|
|
7
|
+
* null/undefined → мужской род (дефолт для незаполненного профиля). */
|
|
8
|
+
export function genderPast(g, masc, fem) {
|
|
9
|
+
return g === "female" ? fem : masc;
|
|
10
|
+
}
|
|
11
|
+
//# sourceMappingURL=gender.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"gender.js","sourceRoot":"","sources":["../src/gender.ts"],"names":[],"mappings":"AAKA,MAAM,CAAC,MAAM,cAAc,GAAa,CAAC,MAAM,EAAE,QAAQ,CAAC,CAAC;AAE3D,MAAM,CAAC,MAAM,YAAY,GAA2B;IAClD,IAAI,EAAE,SAAS;IACf,MAAM,EAAE,SAAS;CAClB,CAAC;AAEF;wEACwE;AACxE,MAAM,UAAU,UAAU,CAAC,CAA4B,EAAE,IAAY,EAAE,GAAW;IAChF,OAAO,CAAC,KAAK,QAAQ,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC;AACrC,CAAC"}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
export * from "./schemas.js";
|
|
2
|
+
export * from "./gender.js";
|
|
3
|
+
export * from "./notifications.js";
|
|
4
|
+
export * from "./userHandle.js";
|
|
5
|
+
export * from "./statusIcons.js";
|
|
6
|
+
export * from "./sortWorkflowStates.js";
|
|
7
|
+
export * from "./domain.js";
|
|
8
|
+
export * from "./finishChip.js";
|
|
9
|
+
export * from "./weight.js";
|
|
10
|
+
export * from "./uiTour.js";
|
|
11
|
+
export * from "./translit.js";
|
|
12
|
+
export * from "./branding.js";
|
|
13
|
+
export * from "./workspaceBrand.js";
|
|
14
|
+
export * from "./labelColors.js";
|
|
15
|
+
export * from "./chatMessageKinds.js";
|
|
16
|
+
export * from "./userHue.js";
|
|
17
|
+
export * from "./releaseSources.js";
|
|
18
|
+
export * from "./designTokens.js";
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
export * from "./schemas.js";
|
|
2
|
+
export * from "./gender.js";
|
|
3
|
+
export * from "./notifications.js";
|
|
4
|
+
export * from "./userHandle.js";
|
|
5
|
+
export * from "./statusIcons.js";
|
|
6
|
+
export * from "./sortWorkflowStates.js";
|
|
7
|
+
export * from "./domain.js";
|
|
8
|
+
export * from "./finishChip.js";
|
|
9
|
+
export * from "./weight.js";
|
|
10
|
+
export * from "./uiTour.js";
|
|
11
|
+
export * from "./translit.js";
|
|
12
|
+
export * from "./branding.js";
|
|
13
|
+
export * from "./workspaceBrand.js";
|
|
14
|
+
export * from "./labelColors.js";
|
|
15
|
+
export * from "./chatMessageKinds.js";
|
|
16
|
+
export * from "./userHue.js";
|
|
17
|
+
export * from "./releaseSources.js";
|
|
18
|
+
export * from "./designTokens.js";
|
|
19
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,cAAc,CAAC;AAC7B,cAAc,aAAa,CAAC;AAC5B,cAAc,oBAAoB,CAAC;AACnC,cAAc,iBAAiB,CAAC;AAChC,cAAc,kBAAkB,CAAC;AACjC,cAAc,yBAAyB,CAAC;AACxC,cAAc,aAAa,CAAC;AAC5B,cAAc,iBAAiB,CAAC;AAChC,cAAc,aAAa,CAAC;AAC5B,cAAc,aAAa,CAAC;AAC5B,cAAc,eAAe,CAAC;AAC9B,cAAc,eAAe,CAAC;AAC9B,cAAc,qBAAqB,CAAC;AACpC,cAAc,kBAAkB,CAAC;AACjC,cAAc,uBAAuB,CAAC;AACtC,cAAc,cAAc,CAAC;AAC7B,cAAc,qBAAqB,CAAC;AACpC,cAAc,mBAAmB,CAAC"}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
// TAS-16 (перенесено из web): палитра + детерминированный цвет лейбла по имени.
|
|
2
|
+
// ЕДИНСТВЕННЫЙ источник палитры: web/src/labels/labelPalette.ts реэкспортит её.
|
|
3
|
+
// Раньше палитр было две — авто-цвет брался отсюда (10 цветов), а редактор
|
|
4
|
+
// рисовал свои 12, и цвет #f59e0b не попадал в пикер: у лейбла с ним ни одна
|
|
5
|
+
// плитка не была выбрана. Набор ниже = набор редактора (без почти-белого
|
|
6
|
+
// #f5f5f5, он сливался на светлой теме).
|
|
7
|
+
// Цвет нового лейбла выводится из имени (djb2-хеш % palette.length),
|
|
8
|
+
// чтобы одно и то же имя всегда давало один и тот же цвет.
|
|
9
|
+
export const LABEL_PALETTE = [
|
|
10
|
+
"#64748b", // slate
|
|
11
|
+
"#ef4444", // red
|
|
12
|
+
"#f97316", // orange
|
|
13
|
+
"#eab308", // yellow
|
|
14
|
+
"#84cc16", // lime
|
|
15
|
+
"#22c55e", // green
|
|
16
|
+
"#14b8a6", // teal
|
|
17
|
+
"#3b82f6", // blue
|
|
18
|
+
"#6366f1", // indigo
|
|
19
|
+
"#a855f7", // violet
|
|
20
|
+
"#ec4899", // pink
|
|
21
|
+
"#94a3b8", // slate-light
|
|
22
|
+
];
|
|
23
|
+
/** Детерминированный hex из палитры по имени лейбла (case-insensitive). */
|
|
24
|
+
export function colorForLabelName(name) {
|
|
25
|
+
const key = name.trim().toLowerCase();
|
|
26
|
+
let hash = 5381;
|
|
27
|
+
for (let i = 0; i < key.length; i++) {
|
|
28
|
+
hash = ((hash << 5) + hash + key.charCodeAt(i)) | 0;
|
|
29
|
+
}
|
|
30
|
+
const idx = Math.abs(hash) % LABEL_PALETTE.length;
|
|
31
|
+
return LABEL_PALETTE[idx];
|
|
32
|
+
}
|
|
33
|
+
//# sourceMappingURL=labelColors.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"labelColors.js","sourceRoot":"","sources":["../src/labelColors.ts"],"names":[],"mappings":"AAAA,gFAAgF;AAChF,gFAAgF;AAChF,2EAA2E;AAC3E,6EAA6E;AAC7E,yEAAyE;AACzE,yCAAyC;AACzC,qEAAqE;AACrE,2DAA2D;AAE3D,MAAM,CAAC,MAAM,aAAa,GAAa;IACrC,SAAS,EAAE,QAAQ;IACnB,SAAS,EAAE,MAAM;IACjB,SAAS,EAAE,SAAS;IACpB,SAAS,EAAE,SAAS;IACpB,SAAS,EAAE,OAAO;IAClB,SAAS,EAAE,QAAQ;IACnB,SAAS,EAAE,OAAO;IAClB,SAAS,EAAE,OAAO;IAClB,SAAS,EAAE,SAAS;IACpB,SAAS,EAAE,SAAS;IACpB,SAAS,EAAE,OAAO;IAClB,SAAS,EAAE,cAAc;CAC1B,CAAC;AAEF,2EAA2E;AAC3E,MAAM,UAAU,iBAAiB,CAAC,IAAY;IAC5C,MAAM,GAAG,GAAG,IAAI,CAAC,IAAI,EAAE,CAAC,WAAW,EAAE,CAAC;IACtC,IAAI,IAAI,GAAG,IAAI,CAAC;IAChB,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,GAAG,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;QACpC,IAAI,GAAG,CAAC,CAAC,IAAI,IAAI,CAAC,CAAC,GAAG,IAAI,GAAG,GAAG,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC;IACtD,CAAC;IACD,MAAM,GAAG,GAAG,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,GAAG,aAAa,CAAC,MAAM,CAAC;IAClD,OAAO,aAAa,CAAC,GAAG,CAAE,CAAC;AAC7B,CAAC"}
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
export interface UserNotification {
|
|
2
|
+
/** Persisted DB row id, set when the notification was logged via
|
|
3
|
+
* `notifyUser`/`notifyUsers`. UI uses it to call mark-read. Optional
|
|
4
|
+
* for backwards-compat with legacy callers that don't go through the
|
|
5
|
+
* send helpers (none currently, but keeps the type permissive). */
|
|
6
|
+
id?: string;
|
|
7
|
+
/** Dotted short code like "call.invite", "room.mention". Used by the
|
|
8
|
+
* UI for kind-specific side effects (e.g. bumping a chat badge) and
|
|
9
|
+
* for observability. Not shown to the user. */
|
|
10
|
+
kind: string;
|
|
11
|
+
/** OS notification title and toast heading. Should stand alone. */
|
|
12
|
+
title: string;
|
|
13
|
+
/** Optional body — shown under the title on the OS and as the toast
|
|
14
|
+
* description. */
|
|
15
|
+
body?: string;
|
|
16
|
+
/** Deep-link to the relevant view. Clicking the OS notification or
|
|
17
|
+
* toast lands here. Relative to the app origin. */
|
|
18
|
+
href?: string;
|
|
19
|
+
/** Dedup key. A later notification with the same tag replaces the
|
|
20
|
+
* previous one instead of stacking. */
|
|
21
|
+
tag?: string;
|
|
22
|
+
/** Persistent notification that doesn't auto-close after a few seconds
|
|
23
|
+
* — use for mentions / things we really don't want the user to miss. */
|
|
24
|
+
requireInteraction?: boolean;
|
|
25
|
+
/** Audible re-ping when replacing an existing tag (chrome only — other
|
|
26
|
+
* browsers ignore this). Useful for chat, not for silent updates. */
|
|
27
|
+
renotify?: boolean;
|
|
28
|
+
/** Kind-specific structured extras the UI might need (e.g. roomId for
|
|
29
|
+
* badge bumping). Not shown to the user. */
|
|
30
|
+
data?: Record<string, unknown>;
|
|
31
|
+
/** Bypass the SW's "tab focused → suppress OS notification" dedup. Used
|
|
32
|
+
* by the profile page's test-push button so the user can verify the
|
|
33
|
+
* end-to-end OS path without alt-tabbing first. Don't set this on
|
|
34
|
+
* real notifications — it produces duplicate OS+toast pings. */
|
|
35
|
+
forceShow?: boolean;
|
|
36
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"notifications.js","sourceRoot":"","sources":["../src/notifications.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
export declare const RELEASE_SOURCES: readonly ["ui", "mcp", "agent"];
|
|
3
|
+
export type ReleaseSource = (typeof RELEASE_SOURCES)[number];
|
|
4
|
+
export declare const ReleaseAllowedSources: z.ZodObject<{
|
|
5
|
+
ui: z.ZodBoolean;
|
|
6
|
+
mcp: z.ZodBoolean;
|
|
7
|
+
agent: z.ZodBoolean;
|
|
8
|
+
}, "strip", z.ZodTypeAny, {
|
|
9
|
+
ui: boolean;
|
|
10
|
+
mcp: boolean;
|
|
11
|
+
agent: boolean;
|
|
12
|
+
}, {
|
|
13
|
+
ui: boolean;
|
|
14
|
+
mcp: boolean;
|
|
15
|
+
agent: boolean;
|
|
16
|
+
}>;
|
|
17
|
+
export type ReleaseAllowedSources = z.infer<typeof ReleaseAllowedSources>;
|
|
18
|
+
export declare const DEFAULT_RELEASE_ALLOWED_SOURCES: ReleaseAllowedSources;
|
|
19
|
+
export declare function resolveReleaseAllowedSources(raw: unknown): ReleaseAllowedSources;
|
|
20
|
+
export declare function isReleaseSourceAllowed(raw: unknown, source: ReleaseSource): boolean;
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
// PRJ4-10: откуда разрешено запускать release/deploy-действия проекта
|
|
3
|
+
// (dispatch_workflow / create_tag / create_github_release / push_branch,
|
|
4
|
+
// плюс объединённый POST /projects/:id/release).
|
|
5
|
+
//
|
|
6
|
+
// ui — кнопка в веб-интерфейсе (cookie-сессия живого юзера).
|
|
7
|
+
// mcp — внешний MCP-клиент (Claude Code, Cursor и т.п. через OAuth Bearer).
|
|
8
|
+
// agent — AI-ассистент в чате Taskless, действующий от имени юзера.
|
|
9
|
+
// Самый рискованный источник — по умолчанию ВЫКЛЮЧЕН.
|
|
10
|
+
//
|
|
11
|
+
// Это второй слой поверх RBAC (role >= admin): даже админ не сможет
|
|
12
|
+
// запустить действие через источник, отключённый на проекте.
|
|
13
|
+
export const RELEASE_SOURCES = ["ui", "mcp", "agent"];
|
|
14
|
+
export const ReleaseAllowedSources = z.object({
|
|
15
|
+
ui: z.boolean(),
|
|
16
|
+
mcp: z.boolean(),
|
|
17
|
+
agent: z.boolean(),
|
|
18
|
+
});
|
|
19
|
+
// Дефолт при releaseAllowedSources === null: UI и MCP разрешены,
|
|
20
|
+
// AI-ассистент — нет (самый рискованный путь, opt-in).
|
|
21
|
+
export const DEFAULT_RELEASE_ALLOWED_SOURCES = {
|
|
22
|
+
ui: true,
|
|
23
|
+
mcp: true,
|
|
24
|
+
agent: false,
|
|
25
|
+
};
|
|
26
|
+
// Нормализация значения из БД (Json?) к строгой форме. Любой мусор/частичный
|
|
27
|
+
// объект/null → дефолт (fail-safe: неизвестное = дефолтная политика, не «всё
|
|
28
|
+
// разрешено» и не «всё запрещено»). Отсутствующие ключи добираются из дефолта.
|
|
29
|
+
export function resolveReleaseAllowedSources(raw) {
|
|
30
|
+
if (raw && typeof raw === "object" && !Array.isArray(raw)) {
|
|
31
|
+
const obj = raw;
|
|
32
|
+
return {
|
|
33
|
+
ui: typeof obj.ui === "boolean" ? obj.ui : DEFAULT_RELEASE_ALLOWED_SOURCES.ui,
|
|
34
|
+
mcp: typeof obj.mcp === "boolean" ? obj.mcp : DEFAULT_RELEASE_ALLOWED_SOURCES.mcp,
|
|
35
|
+
agent: typeof obj.agent === "boolean" ? obj.agent : DEFAULT_RELEASE_ALLOWED_SOURCES.agent,
|
|
36
|
+
};
|
|
37
|
+
}
|
|
38
|
+
return { ...DEFAULT_RELEASE_ALLOWED_SOURCES };
|
|
39
|
+
}
|
|
40
|
+
// Разрешён ли конкретный источник для проекта (raw = Project.releaseAllowedSources).
|
|
41
|
+
export function isReleaseSourceAllowed(raw, source) {
|
|
42
|
+
return resolveReleaseAllowedSources(raw)[source];
|
|
43
|
+
}
|
|
44
|
+
//# sourceMappingURL=releaseSources.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"releaseSources.js","sourceRoot":"","sources":["../src/releaseSources.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAExB,sEAAsE;AACtE,yEAAyE;AACzE,iDAAiD;AACjD,EAAE;AACF,kEAAkE;AAClE,gFAAgF;AAChF,sEAAsE;AACtE,gEAAgE;AAChE,EAAE;AACF,oEAAoE;AACpE,6DAA6D;AAC7D,MAAM,CAAC,MAAM,eAAe,GAAG,CAAC,IAAI,EAAE,KAAK,EAAE,OAAO,CAAU,CAAC;AAG/D,MAAM,CAAC,MAAM,qBAAqB,GAAG,CAAC,CAAC,MAAM,CAAC;IAC5C,EAAE,EAAE,CAAC,CAAC,OAAO,EAAE;IACf,GAAG,EAAE,CAAC,CAAC,OAAO,EAAE;IAChB,KAAK,EAAE,CAAC,CAAC,OAAO,EAAE;CACnB,CAAC,CAAC;AAGH,iEAAiE;AACjE,uDAAuD;AACvD,MAAM,CAAC,MAAM,+BAA+B,GAA0B;IACpE,EAAE,EAAE,IAAI;IACR,GAAG,EAAE,IAAI;IACT,KAAK,EAAE,KAAK;CACb,CAAC;AAEF,6EAA6E;AAC7E,6EAA6E;AAC7E,+EAA+E;AAC/E,MAAM,UAAU,4BAA4B,CAAC,GAAY;IACvD,IAAI,GAAG,IAAI,OAAO,GAAG,KAAK,QAAQ,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC;QAC1D,MAAM,GAAG,GAAG,GAA8B,CAAC;QAC3C,OAAO;YACL,EAAE,EAAE,OAAO,GAAG,CAAC,EAAE,KAAK,SAAS,CAAC,CAAC,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC,CAAC,+BAA+B,CAAC,EAAE;YAC7E,GAAG,EAAE,OAAO,GAAG,CAAC,GAAG,KAAK,SAAS,CAAC,CAAC,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,CAAC,+BAA+B,CAAC,GAAG;YACjF,KAAK,EAAE,OAAO,GAAG,CAAC,KAAK,KAAK,SAAS,CAAC,CAAC,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC,CAAC,+BAA+B,CAAC,KAAK;SAC1F,CAAC;IACJ,CAAC;IACD,OAAO,EAAE,GAAG,+BAA+B,EAAE,CAAC;AAChD,CAAC;AAED,qFAAqF;AACrF,MAAM,UAAU,sBAAsB,CAAC,GAAY,EAAE,MAAqB;IACxE,OAAO,4BAA4B,CAAC,GAAG,CAAC,CAAC,MAAM,CAAC,CAAC;AACnD,CAAC"}
|