@things-factory/ai-dashboard 10.1.213 → 10.1.215
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/client/components/card-dialogs.ts +24 -1
- package/client/components/dashboard-card.ts +24 -70
- package/client/index.ts +2 -0
- package/client/pages/my-dashboard-page.ts +6 -5
- package/client/utils/card-api.ts +3 -2
- package/client/utils/card-words.ts +11 -0
- package/client/utils/examples.ts +15 -0
- package/dist-client/components/card-dialogs.js +22 -1
- package/dist-client/components/card-dialogs.js.map +1 -1
- package/dist-client/components/dashboard-card.d.ts +6 -5
- package/dist-client/components/dashboard-card.js +23 -73
- package/dist-client/components/dashboard-card.js.map +1 -1
- package/dist-client/index.d.ts +1 -0
- package/dist-client/index.js +2 -0
- package/dist-client/index.js.map +1 -1
- package/dist-client/pages/my-dashboard-page.js +6 -5
- package/dist-client/pages/my-dashboard-page.js.map +1 -1
- package/dist-client/tsconfig.tsbuildinfo +1 -1
- package/dist-client/utils/card-api.d.ts +6 -1
- package/dist-client/utils/card-api.js +1 -1
- package/dist-client/utils/card-api.js.map +1 -1
- package/dist-client/utils/card-words.d.ts +14 -0
- package/dist-client/utils/card-words.js +9 -0
- package/dist-client/utils/card-words.js.map +1 -1
- package/dist-client/utils/examples.d.ts +3 -0
- package/dist-client/utils/examples.js +14 -0
- package/dist-client/utils/examples.js.map +1 -0
- package/dist-server/service/card/card-access.d.ts +8 -2
- package/dist-server/service/card/card-access.js +9 -3
- package/dist-server/service/card/card-access.js.map +1 -1
- package/dist-server/service/card/card-definition.d.ts +42 -6
- package/dist-server/service/card/card-definition.js +172 -18
- package/dist-server/service/card/card-definition.js.map +1 -1
- package/dist-server/service/card/card-names.d.ts +5 -0
- package/dist-server/service/card/card-names.js +6 -1
- package/dist-server/service/card/card-names.js.map +1 -1
- package/dist-server/service/card/card-proposal.d.ts +6 -0
- package/dist-server/service/card/card-proposal.js +9 -0
- package/dist-server/service/card/card-proposal.js.map +1 -1
- package/dist-server/service/card/card-resolver.js +24 -5
- package/dist-server/service/card/card-resolver.js.map +1 -1
- package/dist-server/service/card/card-run.js +5 -1
- package/dist-server/service/card/card-run.js.map +1 -1
- package/dist-server/service/card/card-tool.d.ts +66 -8
- package/dist-server/service/card/card-tool.js +88 -17
- package/dist-server/service/card/card-tool.js.map +1 -1
- package/dist-server/service/card/card-types.d.ts +1 -0
- package/dist-server/service/card/card-types.js +8 -4
- package/dist-server/service/card/card-types.js.map +1 -1
- package/dist-server/service/card/dashboard-card.d.ts +2 -0
- package/dist-server/service/card/dashboard-card.js +5 -3
- package/dist-server/service/card/dashboard-card.js.map +1 -1
- package/dist-server/tsconfig.tsbuildinfo +1 -1
- package/package.json +5 -5
- package/server/service/card/card-access.test.ts +62 -7
- package/server/service/card/card-access.ts +12 -5
- package/server/service/card/card-definition.ts +182 -18
- package/server/service/card/card-intent.test.ts +250 -0
- package/server/service/card/card-names.ts +5 -0
- package/server/service/card/card-proposal.ts +10 -1
- package/server/service/card/card-resolver.ts +26 -8
- package/server/service/card/card-run.ts +5 -1
- package/server/service/card/card-tool.ts +91 -20
- package/server/service/card/card-types.ts +7 -4
- package/server/service/card/dashboard-card.ts +5 -3
- package/test/card-menu.test.ts +34 -0
- package/test/translations.test.ts +1 -1
- package/translations/en.json +3 -3
- package/translations/es.json +3 -3
- package/translations/ja.json +3 -3
- package/translations/ko.json +3 -3
- package/translations/ms.json +3 -3
- package/translations/zh.json +3 -3
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
export interface CardShare {
|
|
2
|
-
scope: 'USER' | 'DEPARTMENT' | 'DOMAIN';
|
|
2
|
+
scope: 'USER' | 'DEPARTMENT' | 'ROLE' | 'DOMAIN';
|
|
3
3
|
targetId: string;
|
|
4
4
|
targetName?: string | null;
|
|
5
5
|
}
|
|
@@ -64,6 +64,11 @@ export declare const cardApi: {
|
|
|
64
64
|
name: string;
|
|
65
65
|
}[];
|
|
66
66
|
peopleAvailable: boolean;
|
|
67
|
+
roles: {
|
|
68
|
+
id: string;
|
|
69
|
+
name: string;
|
|
70
|
+
note?: string | null;
|
|
71
|
+
}[];
|
|
67
72
|
}>;
|
|
68
73
|
people: (text: string) => Promise<{
|
|
69
74
|
id: string;
|
|
@@ -19,7 +19,7 @@ export const cardApi = {
|
|
|
19
19
|
run: async (id) => (await ask(`query ($id: String!) { dashboardCardRun(id: $id) }`, { id })).dashboardCardRun,
|
|
20
20
|
preview: async (sessionId, proposalKey) => (await ask(`query ($s: String!, $k: String!) { dashboardCardProposalPreview(sessionId: $s, proposalKey: $k) }`, { s: sessionId, k: proposalKey })).dashboardCardProposalPreview,
|
|
21
21
|
versions: async (id) => (await ask(`query ($id: String!) { dashboardCardVersions(id: $id) { version name definition creatorName createdAt } }`, { id })).dashboardCardVersions,
|
|
22
|
-
shareOptions: async () => (await ask(`query { dashboardShareOptions { domainId domainName departmentsAvailable departments { id name } peopleAvailable } }`)).dashboardShareOptions,
|
|
22
|
+
shareOptions: async () => (await ask(`query { dashboardShareOptions { domainId domainName departmentsAvailable departments { id name } peopleAvailable roles { id name note } } }`)).dashboardShareOptions,
|
|
23
23
|
people: async (text) => (await ask(`query ($text: String!) { dashboardSharePeople(text: $text) { id name note } }`, { text })).dashboardSharePeople,
|
|
24
24
|
saveProposal: async (sessionId, proposalKey) => (await ask(`mutation ($s: String!, $k: String!) { saveDashboardCardProposal(sessionId: $s, proposalKey: $k) }`, { s: sessionId, k: proposalKey }, true)).saveDashboardCardProposal,
|
|
25
25
|
rename: async (id, name) => (await ask(`mutation ($id: String!, $name: String!) { renameDashboardCard(id: $id, name: $name) { id } }`, { id, name }, true)).renameDashboardCard,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"card-api.js","sourceRoot":"","sources":["../../client/utils/card-api.ts"],"names":[],"mappings":"AAAA;;;GAGG;AACH,OAAO,GAAG,MAAM,aAAa,CAAA;AAE7B,OAAO,EAAE,MAAM,EAAE,MAAM,kBAAkB,CAAA;AA8CzC,MAAM,WAAW,GAAG,4HAA4H,CAAA;AAEhJ,KAAK,UAAU,GAAG,CAAI,QAAgB,EAAE,YAAqC,EAAE,EAAE,MAAM,GAAG,KAAK;IAC7F,MAAM,QAAQ,GAAQ,MAAM;QAC1B,CAAC,CAAC,MAAM,MAAM,CAAC,MAAM,CAAC,EAAE,QAAQ,EAAE,GAAG,CAAC,QAAQ,CAAC,EAAE,SAAS,EAAE,CAAC;QAC7D,CAAC,CAAC,MAAM,MAAM,CAAC,KAAK,CAAC,EAAE,KAAK,EAAE,GAAG,CAAC,QAAQ,CAAC,EAAE,SAAS,EAAE,WAAW,EAAE,UAAU,EAAE,CAAC,CAAA;IACpF,IAAI,QAAQ,CAAC,MAAM,EAAE,MAAM;QAAE,MAAM,IAAI,KAAK,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,CAAA;IACxE,OAAO,QAAQ,CAAC,IAAI,CAAA;AACtB,CAAC;AAED,MAAM,CAAC,MAAM,OAAO,GAAG;IACrB,WAAW,EAAE,KAAK,IAAI,EAAE,CAAC,CAAC,MAAM,GAAG,CAAM,sDAAsD,WAAW,QAAQ,CAAC,CAAC,CAAC,WAA0B;IAC/I,OAAO,EAAE,KAAK,EAAE,KAAwB,EAAE,EAAE,CAAC,CAAC,MAAM,GAAG,CAAM,6DAA6D,WAAW,MAAM,EAAE,EAAE,KAAK,EAAE,CAAC,CAAC,CAAC,cAA4B;IACrL,GAAG,EAAE,KAAK,EAAE,EAAU,EAAE,EAAE,CAAC,CAAC,MAAM,GAAG,CAAM,oDAAoD,EAAE,EAAE,EAAE,EAAE,CAAC,CAAC,CAAC,gBAA2B;IACrI,OAAO,EAAE,KAAK,EAAE,SAAiB,EAAE,WAAmB,EAAE,EAAE,CACxD,CAAC,MAAM,GAAG,CAAM,mGAAmG,EAAE,EAAE,CAAC,EAAE,SAAS,EAAE,CAAC,EAAE,WAAW,EAAE,CAAC,CAAC,CAAC,4BAAuC;IACjM,QAAQ,EAAE,KAAK,EAAE,EAAU,EAAE,EAAE,CAC7B,CAAC,MAAM,GAAG,CAAM,2GAA2G,EAAE,EAAE,EAAE,EAAE,CAAC,CAAC,CAAC,qBAMnI;IACL,YAAY,EAAE,KAAK,IAAI,EAAE,CACvB,CAAC,MAAM,GAAG,CAAM,
|
|
1
|
+
{"version":3,"file":"card-api.js","sourceRoot":"","sources":["../../client/utils/card-api.ts"],"names":[],"mappings":"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","sourcesContent":["/*\n * The doors the dashboard screens call (server: card-resolver.ts). One place, so the page, the library and the\n * conversation's card read the same fields.\n */\nimport gql from 'graphql-tag'\n\nimport { client } from '@operato/graphql'\n\nexport interface CardShare {\n scope: 'USER' | 'DEPARTMENT' | 'ROLE' | 'DOMAIN'\n targetId: string\n targetName?: string | null\n}\n\nexport interface CardItem {\n id: string\n name: string\n description?: string | null\n version: number\n definition: any\n access: 'owner' | 'shared'\n ownerName?: string | null\n copiedFromId?: string | null\n placed: boolean\n shares?: CardShare[] | null\n updatedAt?: string | null\n}\n\nexport interface PlaceItem {\n id: string\n order: number\n width: number\n height: number\n card: CardItem\n}\n\nexport interface CardCounts {\n read: number\n total: number\n complete: boolean\n shaped: number\n shown: number\n}\n\nexport interface CardRun {\n block?: any\n issue?: { code: string; params?: Record<string, unknown> }\n counts?: CardCounts\n asOf: string\n source?: { key: string; labelKey?: string }\n}\n\nconst CARD_FIELDS = `id name description version definition access ownerName copiedFromId placed shares { scope targetId targetName } updatedAt`\n\nasync function ask<T>(document: string, variables: Record<string, unknown> = {}, mutate = false): Promise<T> {\n const response: any = mutate\n ? await client.mutate({ mutation: gql(document), variables })\n : await client.query({ query: gql(document), variables, fetchPolicy: 'no-cache' })\n if (response.errors?.length) throw new Error(response.errors[0].message)\n return response.data\n}\n\nexport const cardApi = {\n myDashboard: async () => (await ask<any>(`query { myDashboard { id order width height card { ${CARD_FIELDS} } } }`)).myDashboard as PlaceItem[],\n library: async (which: 'mine' | 'shared') => (await ask<any>(`query ($which: String!) { dashboardCards(which: $which) { ${CARD_FIELDS} } }`, { which })).dashboardCards as CardItem[],\n run: async (id: string) => (await ask<any>(`query ($id: String!) { dashboardCardRun(id: $id) }`, { id })).dashboardCardRun as CardRun,\n preview: async (sessionId: string, proposalKey: string) =>\n (await ask<any>(`query ($s: String!, $k: String!) { dashboardCardProposalPreview(sessionId: $s, proposalKey: $k) }`, { s: sessionId, k: proposalKey })).dashboardCardProposalPreview as CardRun,\n versions: async (id: string) =>\n (await ask<any>(`query ($id: String!) { dashboardCardVersions(id: $id) { version name definition creatorName createdAt } }`, { id })).dashboardCardVersions as {\n version: number\n name: string\n definition: any\n creatorName?: string\n createdAt?: string\n }[],\n shareOptions: async () =>\n (await ask<any>(`query { dashboardShareOptions { domainId domainName departmentsAvailable departments { id name } peopleAvailable roles { id name note } } }`)).dashboardShareOptions as {\n domainId: string\n domainName: string\n departmentsAvailable: boolean\n departments: { id: string; name: string }[]\n peopleAvailable: boolean\n roles: { id: string; name: string; note?: string | null }[]\n },\n people: async (text: string) => (await ask<any>(`query ($text: String!) { dashboardSharePeople(text: $text) { id name note } }`, { text })).dashboardSharePeople as { id: string; name: string; note?: string }[],\n saveProposal: async (sessionId: string, proposalKey: string) =>\n (await ask<any>(`mutation ($s: String!, $k: String!) { saveDashboardCardProposal(sessionId: $s, proposalKey: $k) }`, { s: sessionId, k: proposalKey }, true)).saveDashboardCardProposal as {\n cardId: string\n version: number\n placeId: string\n again?: boolean\n },\n rename: async (id: string, name: string) => (await ask<any>(`mutation ($id: String!, $name: String!) { renameDashboardCard(id: $id, name: $name) { id } }`, { id, name }, true)).renameDashboardCard,\n restore: async (id: string, version: number) => (await ask<any>(`mutation ($id: String!, $v: Int!) { restoreDashboardCardVersion(id: $id, version: $v) { id } }`, { id, v: version }, true)).restoreDashboardCardVersion,\n copy: async (id: string) => (await ask<any>(`mutation ($id: String!) { copyDashboardCard(id: $id) { id } }`, { id }, true)).copyDashboardCard,\n remove: async (id: string) => (await ask<any>(`mutation ($id: String!) { deleteDashboardCard(id: $id) }`, { id }, true)).deleteDashboardCard,\n share: async (id: string, shares: CardShare[]) =>\n (await ask<any>(`mutation ($id: String!, $shares: [DashboardCardShareInput!]!) { shareDashboardCard(id: $id, shares: $shares) { ${CARD_FIELDS} } }`, { id, shares }, true)).shareDashboardCard as CardItem,\n place: async (cardId: string) => (await ask<any>(`mutation ($id: String!) { placeDashboardCard(cardId: $id) { id } }`, { id: cardId }, true)).placeDashboardCard,\n unplace: async (id: string) => (await ask<any>(`mutation ($id: String!) { removeDashboardPlace(id: $id) }`, { id }, true)).removeDashboardPlace,\n arrange: async (places: { id: string; order: number; width: number; height: number }[]) =>\n (await ask<any>(`mutation ($places: [DashboardPlaceInput!]!) { arrangeDashboard(places: $places) }`, { places }, true)).arrangeDashboard\n}\n\n/** Told when a card is saved, copied, placed or removed elsewhere - an open dashboard reads itself again. */\nexport const DASHBOARD_CHANGED = 'ai-dashboard-changed'\n\nexport function dashboardChanged(): void {\n window.dispatchEvent(new CustomEvent(DASHBOARD_CHANGED))\n}\n"]}
|
|
@@ -1,5 +1,19 @@
|
|
|
1
1
|
import type { CardItem, CardRun } from './card-api.js';
|
|
2
2
|
export type Translate = (key: string, options?: Record<string, unknown>) => string;
|
|
3
|
+
/** The axis of a saved card - the server's `CARD_AXIS` (card-names.ts); a test holds the two equal. */
|
|
4
|
+
export declare const CARD_AXIS = "dashboard-card";
|
|
5
|
+
/**
|
|
6
|
+
* A card picked to change, as the conversation is handed it (`askAssistant({ selection })`): its key
|
|
7
|
+
* `dashboard-card:<uuid>`, like any picked row - the bare uuid named no record, and the change failed on it (2026-10-25).
|
|
8
|
+
*/
|
|
9
|
+
export declare function cardSelection(card: Pick<CardItem, 'id' | 'name'>, title: string): {
|
|
10
|
+
title: string;
|
|
11
|
+
list: string;
|
|
12
|
+
records: {
|
|
13
|
+
id: string;
|
|
14
|
+
label: string;
|
|
15
|
+
}[];
|
|
16
|
+
};
|
|
3
17
|
/** The refusals a card names in the reader's words - others are said by their code. */
|
|
4
18
|
export declare const KNOWN_ISSUES: readonly ["door-closed", "not-found", "list-missing", "query-failed", "condition-unreadable", "mixed-currency-order", "too-many-series", "too-many-figures", "unknown-read", "not-a-card-source", "unknown-list", "unknown-column", "unknown-condition"];
|
|
5
19
|
/** Why a card is not drawn - one sentence, and whether it is the reader's access (shown calmly, not as a fault). */
|
|
@@ -1,3 +1,12 @@
|
|
|
1
|
+
/** The axis of a saved card - the server's `CARD_AXIS` (card-names.ts); a test holds the two equal. */
|
|
2
|
+
export const CARD_AXIS = 'dashboard-card';
|
|
3
|
+
/**
|
|
4
|
+
* A card picked to change, as the conversation is handed it (`askAssistant({ selection })`): its key
|
|
5
|
+
* `dashboard-card:<uuid>`, like any picked row - the bare uuid named no record, and the change failed on it (2026-10-25).
|
|
6
|
+
*/
|
|
7
|
+
export function cardSelection(card, title) {
|
|
8
|
+
return { title, list: 'dashboardCards', records: [{ id: `${CARD_AXIS}:${card.id}`, label: card.name }] };
|
|
9
|
+
}
|
|
1
10
|
/** The refusals a card names in the reader's words - others are said by their code. */
|
|
2
11
|
export const KNOWN_ISSUES = [
|
|
3
12
|
'door-closed',
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"card-words.js","sourceRoot":"","sources":["../../client/utils/card-words.ts"],"names":[],"mappings":"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","sourcesContent":["/*\n * What a card says besides its block - why it is not drawn, how much of its source it was drawn from, when it was\n * read, what it reads (ADR-0160 decisions 4, 6). Pure - tested without a browser.\n */\nimport type { CardItem, CardRun } from './card-api.js'\n\nexport type Translate = (key: string, options?: Record<string, unknown>) => string\n\n/** The refusals a card names in the reader's words - others are said by their code. */\nexport const KNOWN_ISSUES = [\n 'door-closed',\n 'not-found',\n 'list-missing',\n 'query-failed',\n 'condition-unreadable',\n 'mixed-currency-order',\n 'too-many-series',\n 'too-many-figures',\n 'unknown-read',\n 'not-a-card-source',\n 'unknown-list',\n 'unknown-column',\n 'unknown-condition'\n] as const\n\n/** Why a card is not drawn - one sentence, and whether it is the reader's access (shown calmly, not as a fault). */\nexport function issueLine(run: CardRun, t: Translate): { text: string; access: boolean } | undefined {\n const issue = run.issue\n if (!issue) return undefined\n const code = issue.code\n const known = (KNOWN_ISSUES as readonly string[]).includes(code)\n const params = { ...(issue.params ?? {}), code } as Record<string, unknown>\n if (Array.isArray(params.currencies)) params.currencies = (params.currencies as string[]).join(', ')\n return {\n text: t(known ? `ai-dashboard.issue.${code}` : 'ai-dashboard.issue.other', { ...params, defaultValue: known ? code : 'This card cannot be drawn ({code}).' }),\n access: code === 'door-closed'\n }\n}\n\n/** How much of its source a card was drawn from - said only when it was not all of it. */\nexport function partialLine(run: CardRun, t: Translate): string | undefined {\n const counts = run.counts\n if (!counts || counts.complete) return undefined\n return t('ai-dashboard.card.partial', { read: counts.read.toLocaleString(), total: counts.total.toLocaleString(), defaultValue: 'Drawn from {read} of {total} rows - sums and ranks are of those.' })\n}\n\n/** A table or chart with no row to draw - said in words, never an empty axis. A number of nothing is 0, and drawn. */\nexport function drawsNothing(run: CardRun): boolean {\n return !run.issue && !!run.block && run.block.kind !== 'metrics' && (run.counts?.shown ?? 0) === 0\n}\n\n/** The day relative periods were read for, and the time it was read. */\nexport function readLine(run: CardRun, readAt: Date, t: Translate, locale?: string): string {\n const time = readAt.toLocaleTimeString(locale || undefined, { hour: '2-digit', minute: '2-digit' })\n return t('ai-dashboard.card.read-at', { day: run.asOf, time, defaultValue: 'as of {day} · read {time}' })\n}\n\n/** Who a card came from, for a card shared with the reader; whom it is shared with, for its owner. */\nexport function ownershipLine(card: CardItem, t: Translate): string | undefined {\n if (card.access === 'shared') return t('ai-dashboard.card.shared-by', { name: card.ownerName ?? '', defaultValue: 'shared by {name}' })\n const shares = card.shares ?? []\n if (!shares.length) return undefined\n const names = shares.map(one => (one.scope === 'DOMAIN' ? t('ai-dashboard.share.everyone', { defaultValue: 'everyone' }) : one.targetName || one.targetId))\n return t('ai-dashboard.card.shared-with', { names: names.slice(0, 3).join(', ') + (names.length > 3 ? ` +${names.length - 3}` : ''), defaultValue: 'shared with {names}' })\n}\n\n/** The kind of drawing a definition asks for - the icon a card and the library show. */\nexport function viewIcon(definition: any): string {\n return ({ number: 'pin', table: 'table_rows', bar: 'bar_chart', line: 'show_chart' } as Record<string, string>)[definition?.view?.kind] ?? 'dashboard'\n}\n\n/** Moves one place in a list of places and gives every place its order again - what arranging sends. */\nexport function movedPlaces<P extends { id: string; order: number }>(places: readonly P[], id: string, step: -1 | 1): P[] {\n const list = [...places].sort((a, b) => a.order - b.order)\n const at = list.findIndex(one => one.id === id)\n const to = at + step\n if (at < 0 || to < 0 || to >= list.length) return list.map((one, order) => ({ ...one, order }))\n ;[list[at], list[to]] = [list[to], list[at]]\n return list.map((one, order) => ({ ...one, order }))\n}\n"]}
|
|
1
|
+
{"version":3,"file":"card-words.js","sourceRoot":"","sources":["../../client/utils/card-words.ts"],"names":[],"mappings":"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","sourcesContent":["/*\n * What a card says besides its block - why it is not drawn, how much of its source it was drawn from, when it was\n * read, what it reads (ADR-0160 decisions 4, 6). Pure - tested without a browser.\n */\nimport type { CardItem, CardRun } from './card-api.js'\n\nexport type Translate = (key: string, options?: Record<string, unknown>) => string\n\n/** The axis of a saved card - the server's `CARD_AXIS` (card-names.ts); a test holds the two equal. */\nexport const CARD_AXIS = 'dashboard-card'\n\n/**\n * A card picked to change, as the conversation is handed it (`askAssistant({ selection })`): its key\n * `dashboard-card:<uuid>`, like any picked row - the bare uuid named no record, and the change failed on it (2026-10-25).\n */\nexport function cardSelection(card: Pick<CardItem, 'id' | 'name'>, title: string) {\n return { title, list: 'dashboardCards', records: [{ id: `${CARD_AXIS}:${card.id}`, label: card.name }] }\n}\n\n/** The refusals a card names in the reader's words - others are said by their code. */\nexport const KNOWN_ISSUES = [\n 'door-closed',\n 'not-found',\n 'list-missing',\n 'query-failed',\n 'condition-unreadable',\n 'mixed-currency-order',\n 'too-many-series',\n 'too-many-figures',\n 'unknown-read',\n 'not-a-card-source',\n 'unknown-list',\n 'unknown-column',\n 'unknown-condition'\n] as const\n\n/** Why a card is not drawn - one sentence, and whether it is the reader's access (shown calmly, not as a fault). */\nexport function issueLine(run: CardRun, t: Translate): { text: string; access: boolean } | undefined {\n const issue = run.issue\n if (!issue) return undefined\n const code = issue.code\n const known = (KNOWN_ISSUES as readonly string[]).includes(code)\n const params = { ...(issue.params ?? {}), code } as Record<string, unknown>\n if (Array.isArray(params.currencies)) params.currencies = (params.currencies as string[]).join(', ')\n return {\n text: t(known ? `ai-dashboard.issue.${code}` : 'ai-dashboard.issue.other', { ...params, defaultValue: known ? code : 'This card cannot be drawn ({code}).' }),\n access: code === 'door-closed'\n }\n}\n\n/** How much of its source a card was drawn from - said only when it was not all of it. */\nexport function partialLine(run: CardRun, t: Translate): string | undefined {\n const counts = run.counts\n if (!counts || counts.complete) return undefined\n return t('ai-dashboard.card.partial', { read: counts.read.toLocaleString(), total: counts.total.toLocaleString(), defaultValue: 'Drawn from {read} of {total} rows - sums and ranks are of those.' })\n}\n\n/** A table or chart with no row to draw - said in words, never an empty axis. A number of nothing is 0, and drawn. */\nexport function drawsNothing(run: CardRun): boolean {\n return !run.issue && !!run.block && run.block.kind !== 'metrics' && (run.counts?.shown ?? 0) === 0\n}\n\n/** The day relative periods were read for, and the time it was read. */\nexport function readLine(run: CardRun, readAt: Date, t: Translate, locale?: string): string {\n const time = readAt.toLocaleTimeString(locale || undefined, { hour: '2-digit', minute: '2-digit' })\n return t('ai-dashboard.card.read-at', { day: run.asOf, time, defaultValue: 'as of {day} · read {time}' })\n}\n\n/** Who a card came from, for a card shared with the reader; whom it is shared with, for its owner. */\nexport function ownershipLine(card: CardItem, t: Translate): string | undefined {\n if (card.access === 'shared') return t('ai-dashboard.card.shared-by', { name: card.ownerName ?? '', defaultValue: 'shared by {name}' })\n const shares = card.shares ?? []\n if (!shares.length) return undefined\n const names = shares.map(one => (one.scope === 'DOMAIN' ? t('ai-dashboard.share.everyone', { defaultValue: 'everyone' }) : one.targetName || one.targetId))\n return t('ai-dashboard.card.shared-with', { names: names.slice(0, 3).join(', ') + (names.length > 3 ? ` +${names.length - 3}` : ''), defaultValue: 'shared with {names}' })\n}\n\n/** The kind of drawing a definition asks for - the icon a card and the library show. */\nexport function viewIcon(definition: any): string {\n return ({ number: 'pin', table: 'table_rows', bar: 'bar_chart', line: 'show_chart' } as Record<string, string>)[definition?.view?.kind] ?? 'dashboard'\n}\n\n/** Moves one place in a list of places and gives every place its order again - what arranging sends. */\nexport function movedPlaces<P extends { id: string; order: number }>(places: readonly P[], id: string, step: -1 | 1): P[] {\n const list = [...places].sort((a, b) => a.order - b.order)\n const at = list.findIndex(one => one.id === id)\n const to = at + step\n if (at < 0 || to < 0 || to >= list.length) return list.map((one, order) => ({ ...one, order }))\n ;[list[at], list[to]] = [list[to], list[at]]\n return list.map((one, order) => ({ ...one, order }))\n}\n"]}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* The requests an empty dashboard offers - the application's, in its own words (i18n keys), since only it knows what
|
|
3
|
+
* its reads hold: the receivables in an office, the output by operation in a plant. None: the dashboard offers only
|
|
4
|
+
* the library and the conversation beside it.
|
|
5
|
+
*/
|
|
6
|
+
let keys = [];
|
|
7
|
+
/** Called once from the application's client bootstrap. */
|
|
8
|
+
export function setDashboardExamples(examples) {
|
|
9
|
+
keys = [...examples];
|
|
10
|
+
}
|
|
11
|
+
export function dashboardExamples() {
|
|
12
|
+
return keys;
|
|
13
|
+
}
|
|
14
|
+
//# sourceMappingURL=examples.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"examples.js","sourceRoot":"","sources":["../../client/utils/examples.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AACH,IAAI,IAAI,GAAa,EAAE,CAAA;AAEvB,2DAA2D;AAC3D,MAAM,UAAU,oBAAoB,CAAC,QAA2B;IAC9D,IAAI,GAAG,CAAC,GAAG,QAAQ,CAAC,CAAA;AACtB,CAAC;AAED,MAAM,UAAU,iBAAiB;IAC/B,OAAO,IAAI,CAAA;AACb,CAAC","sourcesContent":["/*\n * The requests an empty dashboard offers - the application's, in its own words (i18n keys), since only it knows what\n * its reads hold: the receivables in an office, the output by operation in a plant. None: the dashboard offers only\n * the library and the conversation beside it.\n */\nlet keys: string[] = []\n\n/** Called once from the application's client bootstrap. */\nexport function setDashboardExamples(examples: readonly string[]): void {\n keys = [...examples]\n}\n\nexport function dashboardExamples(): readonly string[] {\n return keys\n}\n"]}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
export type CardAccess = 'owner' | 'shared';
|
|
2
2
|
export interface CardShareRow {
|
|
3
|
-
scope: 'USER' | 'DEPARTMENT' | 'DOMAIN' | string;
|
|
3
|
+
scope: 'USER' | 'DEPARTMENT' | 'ROLE' | 'DOMAIN' | string;
|
|
4
4
|
targetId: string;
|
|
5
5
|
}
|
|
6
6
|
export interface CardViewer {
|
|
@@ -8,6 +8,8 @@ export interface CardViewer {
|
|
|
8
8
|
domainId: string;
|
|
9
9
|
/** The departments of the viewer's active employee records - none where the organization module is not there. */
|
|
10
10
|
departmentIds: readonly string[];
|
|
11
|
+
/** The roles the viewer holds in the domain, the ones it inherits included - a role share reaches whoever holds it. */
|
|
12
|
+
roleIds?: readonly string[];
|
|
11
13
|
}
|
|
12
14
|
export declare function cardAccessOf(card: {
|
|
13
15
|
ownerId?: string | null;
|
|
@@ -25,8 +27,12 @@ export declare function departmentsOfEmployees(records: readonly {
|
|
|
25
27
|
id?: string | null;
|
|
26
28
|
} | null;
|
|
27
29
|
}[] | null | undefined): string[];
|
|
28
|
-
/**
|
|
30
|
+
/**
|
|
31
|
+
* A share the owner may give - a known scope with a target; the domain scope names the owner's own domain, a role one
|
|
32
|
+
* of the domain's roles (`roleIds`, the ones it inherits included).
|
|
33
|
+
*/
|
|
29
34
|
export declare function shareRefusal(share: CardShareRow, owner: {
|
|
30
35
|
domainId: string;
|
|
31
36
|
departmentsAvailable: boolean;
|
|
37
|
+
roleIds?: readonly string[];
|
|
32
38
|
}): string | undefined;
|
|
@@ -18,7 +18,8 @@ function cardAccessOf(card, viewer, shares) {
|
|
|
18
18
|
return 'owner';
|
|
19
19
|
const shared = shares.some(share => (share.scope === 'USER' && share.targetId === viewer.userId) ||
|
|
20
20
|
(share.scope === 'DOMAIN' && share.targetId === viewer.domainId) ||
|
|
21
|
-
(share.scope === 'DEPARTMENT' && viewer.departmentIds.includes(share.targetId))
|
|
21
|
+
(share.scope === 'DEPARTMENT' && viewer.departmentIds.includes(share.targetId)) ||
|
|
22
|
+
(share.scope === 'ROLE' && (viewer.roleIds ?? []).includes(share.targetId)));
|
|
22
23
|
return shared ? 'shared' : undefined;
|
|
23
24
|
}
|
|
24
25
|
/**
|
|
@@ -30,9 +31,12 @@ function cardAccessOf(card, viewer, shares) {
|
|
|
30
31
|
function departmentsOfEmployees(records) {
|
|
31
32
|
return [...new Set((records ?? []).filter(one => one?.active === true && one.department?.id).map(one => one.department.id))];
|
|
32
33
|
}
|
|
33
|
-
/**
|
|
34
|
+
/**
|
|
35
|
+
* A share the owner may give - a known scope with a target; the domain scope names the owner's own domain, a role one
|
|
36
|
+
* of the domain's roles (`roleIds`, the ones it inherits included).
|
|
37
|
+
*/
|
|
34
38
|
function shareRefusal(share, owner) {
|
|
35
|
-
if (!['USER', 'DEPARTMENT', 'DOMAIN'].includes(share.scope))
|
|
39
|
+
if (!['USER', 'DEPARTMENT', 'ROLE', 'DOMAIN'].includes(share.scope))
|
|
36
40
|
return 'unknown-scope';
|
|
37
41
|
if (!share.targetId)
|
|
38
42
|
return 'no-target';
|
|
@@ -40,6 +44,8 @@ function shareRefusal(share, owner) {
|
|
|
40
44
|
return 'another-domain';
|
|
41
45
|
if (share.scope === 'DEPARTMENT' && !owner.departmentsAvailable)
|
|
42
46
|
return 'no-departments';
|
|
47
|
+
if (share.scope === 'ROLE' && !(owner.roleIds ?? []).includes(share.targetId))
|
|
48
|
+
return 'unknown-role';
|
|
43
49
|
return undefined;
|
|
44
50
|
}
|
|
45
51
|
//# sourceMappingURL=card-access.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"card-access.js","sourceRoot":"","sources":["../../../server/service/card/card-access.ts"],"names":[],"mappings":";AAAA;;;;;;;GAOG;;
|
|
1
|
+
{"version":3,"file":"card-access.js","sourceRoot":"","sources":["../../../server/service/card/card-access.ts"],"names":[],"mappings":";AAAA;;;;;;;GAOG;;AAkBH,oCAWC;AAQD,wDAEC;AAMD,oCAOC;AAlCD,SAAgB,YAAY,CAAC,IAA2D,EAAE,MAAkB,EAAE,MAA+B;IAC3I,IAAI,CAAC,MAAM,CAAC,MAAM,IAAI,CAAC,MAAM,CAAC,QAAQ,IAAI,IAAI,CAAC,QAAQ,KAAK,MAAM,CAAC,QAAQ;QAAE,OAAO,SAAS,CAAA;IAC7F,IAAI,IAAI,CAAC,OAAO,KAAK,MAAM,CAAC,MAAM;QAAE,OAAO,OAAO,CAAA;IAClD,MAAM,MAAM,GAAG,MAAM,CAAC,IAAI,CACxB,KAAK,CAAC,EAAE,CACN,CAAC,KAAK,CAAC,KAAK,KAAK,MAAM,IAAI,KAAK,CAAC,QAAQ,KAAK,MAAM,CAAC,MAAM,CAAC;QAC5D,CAAC,KAAK,CAAC,KAAK,KAAK,QAAQ,IAAI,KAAK,CAAC,QAAQ,KAAK,MAAM,CAAC,QAAQ,CAAC;QAChE,CAAC,KAAK,CAAC,KAAK,KAAK,YAAY,IAAI,MAAM,CAAC,aAAa,CAAC,QAAQ,CAAC,KAAK,CAAC,QAAQ,CAAC,CAAC;QAC/E,CAAC,KAAK,CAAC,KAAK,KAAK,MAAM,IAAI,CAAC,MAAM,CAAC,OAAO,IAAI,EAAE,CAAC,CAAC,QAAQ,CAAC,KAAK,CAAC,QAAQ,CAAC,CAAC,CAC9E,CAAA;IACD,OAAO,MAAM,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,SAAS,CAAA;AACtC,CAAC;AAED;;;;;GAKG;AACH,SAAgB,sBAAsB,CAAC,OAA8G;IACnJ,OAAO,CAAC,GAAG,IAAI,GAAG,CAAC,CAAC,OAAO,IAAI,EAAE,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,IAAI,IAAI,GAAG,CAAC,UAAU,EAAE,EAAE,CAAC,CAAC,GAAG,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,CAAC,UAAW,CAAC,EAAG,CAAC,CAAC,CAAC,CAAA;AAChI,CAAC;AAED;;;GAGG;AACH,SAAgB,YAAY,CAAC,KAAmB,EAAE,KAAuF;IACvI,IAAI,CAAC,CAAC,MAAM,EAAE,YAAY,EAAE,MAAM,EAAE,QAAQ,CAAC,CAAC,QAAQ,CAAC,KAAK,CAAC,KAAK,CAAC;QAAE,OAAO,eAAe,CAAA;IAC3F,IAAI,CAAC,KAAK,CAAC,QAAQ;QAAE,OAAO,WAAW,CAAA;IACvC,IAAI,KAAK,CAAC,KAAK,KAAK,QAAQ,IAAI,KAAK,CAAC,QAAQ,KAAK,KAAK,CAAC,QAAQ;QAAE,OAAO,gBAAgB,CAAA;IAC1F,IAAI,KAAK,CAAC,KAAK,KAAK,YAAY,IAAI,CAAC,KAAK,CAAC,oBAAoB;QAAE,OAAO,gBAAgB,CAAA;IACxF,IAAI,KAAK,CAAC,KAAK,KAAK,MAAM,IAAI,CAAC,CAAC,KAAK,CAAC,OAAO,IAAI,EAAE,CAAC,CAAC,QAAQ,CAAC,KAAK,CAAC,QAAQ,CAAC;QAAE,OAAO,cAAc,CAAA;IACpG,OAAO,SAAS,CAAA;AAClB,CAAC","sourcesContent":["/*\n * Who may use a card (ADR-0160 decisions 6, 7) - the first of the two checks; the data's own door is the second, asked\n * when the card is run. Using a card means reading its definition and running it as oneself: a share gives the\n * definition, never the data behind it. Asked again on every read, run, placing and copy - a share withdrawn is gone\n * at once, whatever is still placed.\n *\n * Pure - the rule is tested without a database.\n */\n\nexport type CardAccess = 'owner' | 'shared'\n\nexport interface CardShareRow {\n scope: 'USER' | 'DEPARTMENT' | 'ROLE' | 'DOMAIN' | string\n targetId: string\n}\n\nexport interface CardViewer {\n userId: string\n domainId: string\n /** The departments of the viewer's active employee records - none where the organization module is not there. */\n departmentIds: readonly string[]\n /** The roles the viewer holds in the domain, the ones it inherits included - a role share reaches whoever holds it. */\n roleIds?: readonly string[]\n}\n\nexport function cardAccessOf(card: { ownerId?: string | null; domainId?: string | null }, viewer: CardViewer, shares: readonly CardShareRow[]): CardAccess | undefined {\n if (!viewer.userId || !viewer.domainId || card.domainId !== viewer.domainId) return undefined\n if (card.ownerId === viewer.userId) return 'owner'\n const shared = shares.some(\n share =>\n (share.scope === 'USER' && share.targetId === viewer.userId) ||\n (share.scope === 'DOMAIN' && share.targetId === viewer.domainId) ||\n (share.scope === 'DEPARTMENT' && viewer.departmentIds.includes(share.targetId)) ||\n (share.scope === 'ROLE' && (viewer.roleIds ?? []).includes(share.targetId))\n )\n return shared ? 'shared' : undefined\n}\n\n/**\n * The departments a person belongs to for sharing - their employee records that are active (`active = true`; an\n * unset `active` is not taken, as the assistant's people read takes only `active eq true`), each record's department.\n * A person with several records belongs to each record's department. Nothing is guessed: a record without a\n * department adds none.\n */\nexport function departmentsOfEmployees(records: readonly { active?: boolean | null; department?: { id?: string | null } | null }[] | null | undefined): string[] {\n return [...new Set((records ?? []).filter(one => one?.active === true && one.department?.id).map(one => one.department!.id!))]\n}\n\n/**\n * A share the owner may give - a known scope with a target; the domain scope names the owner's own domain, a role one\n * of the domain's roles (`roleIds`, the ones it inherits included).\n */\nexport function shareRefusal(share: CardShareRow, owner: { domainId: string; departmentsAvailable: boolean; roleIds?: readonly string[] }): string | undefined {\n if (!['USER', 'DEPARTMENT', 'ROLE', 'DOMAIN'].includes(share.scope)) return 'unknown-scope'\n if (!share.targetId) return 'no-target'\n if (share.scope === 'DOMAIN' && share.targetId !== owner.domainId) return 'another-domain'\n if (share.scope === 'DEPARTMENT' && !owner.departmentsAvailable) return 'no-departments'\n if (share.scope === 'ROLE' && !(owner.roleIds ?? []).includes(share.targetId)) return 'unknown-role'\n return undefined\n}\n"]}
|
|
@@ -2,7 +2,9 @@ import type { DetailList, DetailRead, ReadColumn, ReadTarget } from '@things-fac
|
|
|
2
2
|
export declare const CARD_SCHEMA_VERSION = 1;
|
|
3
3
|
export declare const VIEW_KINDS: readonly ["number", "table", "bar", "line"];
|
|
4
4
|
export type ViewKind = (typeof VIEW_KINDS)[number];
|
|
5
|
-
export declare const MATCH_OPS: readonly ["eq", "ne", "gt", "gte", "lt", "lte"];
|
|
5
|
+
export declare const MATCH_OPS: readonly ["eq", "ne", "gt", "gte", "lt", "lte", "in", "not_in"];
|
|
6
|
+
/** The operators whose value is a list - one of these values, none of them. */
|
|
7
|
+
export declare const LIST_OPS: readonly ["in", "not_in"];
|
|
6
8
|
export type MatchOp = (typeof MATCH_OPS)[number];
|
|
7
9
|
/** The rows a table shows, and the points a chart draws, at most (ADR-0160 decision 4). */
|
|
8
10
|
export declare const MAX_TABLE_ROWS = 200;
|
|
@@ -21,7 +23,8 @@ export interface CardSourceRef {
|
|
|
21
23
|
export interface CardMatch {
|
|
22
24
|
column: string;
|
|
23
25
|
op: MatchOp;
|
|
24
|
-
|
|
26
|
+
/** A list for `in` and `not_in` (status not_in [APPROVED, REJECTED, WITHDRAWN]); one value otherwise. */
|
|
27
|
+
value: string | number | boolean | (string | number)[];
|
|
25
28
|
}
|
|
26
29
|
export interface CardRows {
|
|
27
30
|
match?: CardMatch[];
|
|
@@ -60,6 +63,10 @@ export interface SourceCondition {
|
|
|
60
63
|
description?: string;
|
|
61
64
|
/** A detail read's argument its query cannot run without. */
|
|
62
65
|
required?: boolean;
|
|
66
|
+
/** A string condition that holds a month as YYYY-MM - it takes a relative month (this-month, -5m). */
|
|
67
|
+
format?: 'month';
|
|
68
|
+
/** It takes several values at once - a list read's statuses (`status: [..]`, `statusNot: [..]`). */
|
|
69
|
+
many?: boolean;
|
|
63
70
|
}
|
|
64
71
|
/** What a card may read from one declaration - the same whichever kind of read it is. */
|
|
65
72
|
export interface CardSource {
|
|
@@ -73,6 +80,8 @@ export interface CardSource {
|
|
|
73
80
|
target?: ReadTarget;
|
|
74
81
|
detail?: DetailRead;
|
|
75
82
|
list?: DetailList;
|
|
83
|
+
/** The rows are the viewer's own, whoever looks (내 지출결의, 나의 전략 업무) - ReadTarget.mine · DetailRead.mine. */
|
|
84
|
+
mine?: boolean;
|
|
76
85
|
}
|
|
77
86
|
/** The source a reference names - or why there is none. */
|
|
78
87
|
export declare function sourceOf(ref: CardSourceRef | undefined, readTargetOf: (key: string) => ReadTarget | undefined, detailReadOf: (key: string) => DetailRead | undefined): {
|
|
@@ -81,16 +90,20 @@ export declare function sourceOf(ref: CardSourceRef | undefined, readTargetOf: (
|
|
|
81
90
|
};
|
|
82
91
|
export declare const isRelativeDate: (value: unknown) => boolean;
|
|
83
92
|
export declare const isRelativePeriod: (value: unknown) => boolean;
|
|
93
|
+
export declare const isRelativeMonth: (value: unknown) => boolean;
|
|
84
94
|
/** Today in a time zone - `YYYY-MM-DD`; the system's zone when the domain names none or one the runtime does not know. */
|
|
85
95
|
export declare function todayIn(timeZone: string | undefined, now?: Date): string;
|
|
86
96
|
/** A relative date as a day, from `today` - weeks start on Monday, an end is that last day (a range's `to` takes the whole day). */
|
|
87
97
|
export declare function resolveRelativeDate(value: string, today: string): string;
|
|
98
|
+
/** A relative month as YYYY-MM, from `today` - `this-year-start` is this year's January. */
|
|
99
|
+
export declare function resolveRelativeMonth(value: string, today: string): string;
|
|
88
100
|
/**
|
|
89
|
-
* The relative values of a definition's conditions, as of `today
|
|
90
|
-
* month
|
|
91
|
-
*
|
|
101
|
+
* The relative values of a definition's conditions, as of `today` - each by what its condition holds (`conditions`):
|
|
102
|
+
* a month as YYYY-MM, a day, an integer year or month. A year and a month are read from one month: with a month token
|
|
103
|
+
* in the same conditions, `this-year` is that month's year - January's `last-month` with `this-year` is last December,
|
|
104
|
+
* never this year's December.
|
|
92
105
|
*/
|
|
93
|
-
export declare function resolveWhere(where: Record<string, unknown> | undefined, today: string): Record<string, unknown>;
|
|
106
|
+
export declare function resolveWhere(where: Record<string, unknown> | undefined, today: string, conditions?: readonly SourceCondition[]): Record<string, unknown>;
|
|
94
107
|
/** The columns the rows have after `rows` - a grouped card's group column, its count and its sums. */
|
|
95
108
|
export declare function shapedColumnNames(source: CardSource, rows: CardRows | undefined): Map<string, ReadColumn>;
|
|
96
109
|
/**
|
|
@@ -98,3 +111,26 @@ export declare function shapedColumnNames(source: CardSource, rows: CardRows | u
|
|
|
98
111
|
* repairs: a definition the model wrote wrong is sent back with what the source has.
|
|
99
112
|
*/
|
|
100
113
|
export declare function checkDefinition(definition: CardDefinition | undefined, source: CardSource): CardIssue[];
|
|
114
|
+
export type PeriodUnit = 'day' | 'week' | 'month' | 'months' | 'year';
|
|
115
|
+
/** The periods a text says - none for a text without one. */
|
|
116
|
+
export declare function periodsNamed(text: string | undefined): PeriodUnit[];
|
|
117
|
+
/** The viewer as the definition may name them by mistake - their user id, name and e-mail. */
|
|
118
|
+
export interface ViewerNames {
|
|
119
|
+
id?: string;
|
|
120
|
+
name?: string;
|
|
121
|
+
email?: string;
|
|
122
|
+
}
|
|
123
|
+
/**
|
|
124
|
+
* Whether a card means what its name says, and reads as whoever looks at it. Issues, never repairs:
|
|
125
|
+
* - a period in the name or line (이번 달, 최근 6개월) with no condition of that period - it would sum all time;
|
|
126
|
+
* - a period said relatively but held to fixed days - it would stop being "this month" next month;
|
|
127
|
+
* - a filter on the viewer's own name or id: a read of the viewer's own rows needs none (it is theirs whoever looks),
|
|
128
|
+
* and another read filtered by one person shows that person to everyone the card is shared with - the viewer's own
|
|
129
|
+
* read (`mine`) is the source instead.
|
|
130
|
+
* `mineSources` are the reads of one's own rows the model may use instead (cardSources).
|
|
131
|
+
*/
|
|
132
|
+
export declare function checkCardIntent(card: {
|
|
133
|
+
name?: string;
|
|
134
|
+
description?: string;
|
|
135
|
+
definition: CardDefinition;
|
|
136
|
+
}, source: CardSource, viewer?: ViewerNames, mineSources?: string[]): CardIssue[];
|