@reformer/builder-plugin-api 1.0.0-beta.1
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 +21 -0
- package/README.md +206 -0
- package/dist/index.d.ts +147 -0
- package/dist/index.js +76 -0
- package/dist/internal.d.ts +78 -0
- package/dist/internal.js +289 -0
- package/dist/permissions-BWlsUVPs.js +551 -0
- package/dist/plugin/bundled-modules.d.ts +25 -0
- package/dist/plugin/layout.d.ts +27 -0
- package/dist/plugin/manifest-parser.d.ts +54 -0
- package/dist/plugin/manifest.d.ts +320 -0
- package/dist/plugin/messages-bundle.d.ts +24 -0
- package/dist/plugin/permissions.d.ts +48 -0
- package/dist/plugin/plugin-exports.d.ts +10 -0
- package/dist/plugin/runtime-modules.d.ts +20 -0
- package/dist/plugin/storage.d.ts +70 -0
- package/dist/plugin/types.d.ts +136 -0
- package/dist/primitives/capability.d.ts +72 -0
- package/dist/primitives/command.d.ts +262 -0
- package/dist/primitives/disposable.d.ts +23 -0
- package/dist/primitives/event.d.ts +38 -0
- package/dist/primitives/extension-point.d.ts +53 -0
- package/dist/primitives/module-path.d.ts +21 -0
- package/dist/primitives/resource.d.ts +159 -0
- package/dist/primitives/semver.d.ts +93 -0
- package/dist/primitives/service.d.ts +68 -0
- package/dist/primitives/when-context.d.ts +69 -0
- package/dist/primitives/when-expr.d.ts +177 -0
- package/dist/resource-clipboard-Bdk_Is5N.js +381 -0
- package/dist/runtime-modules-CiUDFMIn.js +597 -0
- package/dist/services/context-keys.d.ts +52 -0
- package/dist/services/diagnostics/fixes.d.ts +40 -0
- package/dist/services/diagnostics/service.d.ts +34 -0
- package/dist/services/diagnostics/types.d.ts +148 -0
- package/dist/services/document-models.d.ts +20 -0
- package/dist/services/documents.d.ts +94 -0
- package/dist/services/host-messages.d.ts +10 -0
- package/dist/services/i18n.d.ts +43 -0
- package/dist/services/modules.d.ts +49 -0
- package/dist/services/notifications.d.ts +56 -0
- package/dist/services/plugin-settings.d.ts +10 -0
- package/dist/services/plugins-catalog.d.ts +58 -0
- package/dist/services/preview.d.ts +163 -0
- package/dist/services/prompt.d.ts +111 -0
- package/dist/services/resource-clipboard.d.ts +28 -0
- package/dist/services/selection.d.ts +46 -0
- package/dist/services/settings.d.ts +44 -0
- package/dist/services/theme.d.ts +15 -0
- package/dist/services/validation/types.d.ts +98 -0
- package/dist/services/workspace-files.d.ts +84 -0
- package/dist/services/workspace-resources.d.ts +41 -0
- package/dist/services/workspace-save.d.ts +18 -0
- package/dist/tooling.d.ts +28 -0
- package/dist/tooling.js +35 -0
- package/dist/ui/contributions/decorations.d.ts +55 -0
- package/dist/ui/contributions/editors.d.ts +58 -0
- package/dist/ui/contributions/plugin-settings.d.ts +54 -0
- package/dist/ui/keyboard/keybinding-rules.d.ts +48 -0
- package/dist/ui/keyboard/keybindings.d.ts +55 -0
- package/dist/ui/keyboard/keymap.d.ts +81 -0
- package/dist/ui/keyboard/scope.d.ts +38 -0
- package/dist/ui/menu/editor-menu.d.ts +25 -0
- package/dist/ui/menu/menu.d.ts +228 -0
- package/dist/ui/menu/palette.d.ts +36 -0
- package/dist/ui/menu/resource-menu.d.ts +45 -0
- package/dist/ui/slots.d.ts +113 -0
- package/dist/ui/useActiveDocument.d.ts +5 -0
- package/dist/ui/useLocale.d.ts +9 -0
- package/dist/ui/useTranslate.d.ts +4 -0
- package/dist/workspace/document.d.ts +42 -0
- package/dist/workspace/model/editor-view-states.d.ts +29 -0
- package/dist/workspace/model/model-document.d.ts +86 -0
- package/dist/workspace/model/provider.d.ts +140 -0
- package/dist/workspace/model/text-editor-focus.d.ts +22 -0
- package/dist/workspace/resource-names.d.ts +92 -0
- package/dist/workspace/write-options.d.ts +36 -0
- package/package.json +69 -0
|
@@ -0,0 +1,163 @@
|
|
|
1
|
+
import { Capability } from '../primitives/capability.js';
|
|
2
|
+
import { Disposable } from '../primitives/disposable.js';
|
|
3
|
+
import { ExtensionPoint } from '../primitives/extension-point.js';
|
|
4
|
+
import { ResourceId } from '../primitives/resource.js';
|
|
5
|
+
import { TextRange } from './diagnostics/types.js';
|
|
6
|
+
import { NodeId } from '../workspace/model/provider.js';
|
|
7
|
+
import { DocumentRef } from './validation/types.js';
|
|
8
|
+
/**
|
|
9
|
+
* Что поверхность умеет. Каждый признак отвечает на вопрос, который обязаны задать ДО
|
|
10
|
+
* монтирования: правило выбора ранжирует по ним поверхности и сверяет их с правами источника.
|
|
11
|
+
*/
|
|
12
|
+
export interface PreviewCapabilities {
|
|
13
|
+
/** Можно ли трогать форму: вводить значения, нажимать кнопки. */
|
|
14
|
+
readonly interactive: boolean;
|
|
15
|
+
/** Выбор узла кликом. */
|
|
16
|
+
readonly hitTest: boolean;
|
|
17
|
+
/** Принимает ли дроп с палитры. */
|
|
18
|
+
readonly dragSource: boolean;
|
|
19
|
+
/** Исполняет ли код документа. Только по этому признаку работает запрет по источнику. */
|
|
20
|
+
readonly executesCode: boolean;
|
|
21
|
+
/** Тот же realm, что у оболочки. Исполняющая поверхность обязана отвечать `true`. */
|
|
22
|
+
readonly sameRealm: boolean;
|
|
23
|
+
}
|
|
24
|
+
/** На чём споткнулись. */
|
|
25
|
+
export type PreviewProblemPhase =
|
|
26
|
+
/** Документ не разобрался в схему формы. */
|
|
27
|
+
'schema'
|
|
28
|
+
/** Импорт не привязался. */
|
|
29
|
+
| 'resolve'
|
|
30
|
+
/** Движок транспиляции отказался. */
|
|
31
|
+
| 'transpile'
|
|
32
|
+
/** Модуль исполнился и бросил. */
|
|
33
|
+
| 'evaluate'
|
|
34
|
+
/** Сборка формы или отрисовка. */
|
|
35
|
+
| 'render';
|
|
36
|
+
/**
|
|
37
|
+
* Сбой превью — данные, а не исключение.
|
|
38
|
+
*
|
|
39
|
+
* `resource` и `range` — адрес для службы диагностик: по ним находка становится подчёркиванием
|
|
40
|
+
* в редакторе того файла, где чинить. Оба необязательны: сбой без файла относится к документу.
|
|
41
|
+
*/
|
|
42
|
+
export interface PreviewProblem {
|
|
43
|
+
readonly file: string;
|
|
44
|
+
readonly phase: PreviewProblemPhase;
|
|
45
|
+
readonly message: string;
|
|
46
|
+
readonly resource?: ResourceId;
|
|
47
|
+
readonly range?: TextRange;
|
|
48
|
+
}
|
|
49
|
+
/** Значения модели формы. Форма приходит из схемы, и сузить её нечем. */
|
|
50
|
+
export type PreviewValues = Record<string, unknown>;
|
|
51
|
+
/** Мок-данные формы: значения модели и значения источников. Авторский артефакт. */
|
|
52
|
+
export interface PreviewMock {
|
|
53
|
+
readonly model: Record<string, unknown>;
|
|
54
|
+
readonly dataSources: Record<string, unknown>;
|
|
55
|
+
}
|
|
56
|
+
/**
|
|
57
|
+
* Собранная форма в объёме, нужном наблюдателю (панели модели): модель и реестр. Шире — значит
|
|
58
|
+
* дать наблюдателю пересобирать форму, а этим занята поверхность.
|
|
59
|
+
*/
|
|
60
|
+
export interface PreviewFormHandle {
|
|
61
|
+
readonly model: unknown;
|
|
62
|
+
readonly registry?: unknown;
|
|
63
|
+
}
|
|
64
|
+
/**
|
|
65
|
+
* Что поверхность получает на монтирование.
|
|
66
|
+
*
|
|
67
|
+
* Схема — метод, а не поле: документ правят, пока превью открыто, и поверхность обязана читать
|
|
68
|
+
* то, что есть СЕЙЧАС. `null` — документ не разобрался; это законное состояние, а не ошибка.
|
|
69
|
+
*/
|
|
70
|
+
export interface PreviewContext {
|
|
71
|
+
readonly doc: DocumentRef;
|
|
72
|
+
/**
|
|
73
|
+
* Модель документа, как её разобрал провайдер (`doc.providerId`), либо `null`. Ссылка
|
|
74
|
+
* стабильна, пока документ не менялся. Форму знает поверхность и сужает её сама.
|
|
75
|
+
*/
|
|
76
|
+
schema(): unknown;
|
|
77
|
+
onDidChangeSchema(cb: () => void): Disposable;
|
|
78
|
+
/** Выделенные узлы — те же адреса, которыми оперирует редактор документа. */
|
|
79
|
+
selection(): readonly NodeId[];
|
|
80
|
+
onDidChangeSelection(cb: () => void): Disposable;
|
|
81
|
+
/** Обратная связь хит-теста: поверхность сообщает, куда ткнули. */
|
|
82
|
+
select(ids: readonly NodeId[]): void;
|
|
83
|
+
/** Мок-данные или `null`, если автор их не задавал (тогда поверхность синтезирует свои). */
|
|
84
|
+
mock(): PreviewMock | null;
|
|
85
|
+
/** Что человек успел ввести в прежнюю сборку этой формы; `undefined` — не начинали. */
|
|
86
|
+
values(): PreviewValues | undefined;
|
|
87
|
+
/**
|
|
88
|
+
* Отдать значения на хранение: перед пересборкой формы и при размонтировании. Не позовёт
|
|
89
|
+
* поверхность — потеряет набранное человеком, и никто, кроме него, этого не заметит.
|
|
90
|
+
*/
|
|
91
|
+
keepValues(values: PreviewValues): void;
|
|
92
|
+
/** Отдать собранную форму наблюдателям; `null` — формы сейчас нет. Необязателен. */
|
|
93
|
+
publishForm?(form: PreviewFormHandle | null): void;
|
|
94
|
+
/** Куда уходят находки сборки. Список от одного `source` ЗАМЕЩАЕТСЯ целиком. */
|
|
95
|
+
report(source: string, problems: readonly PreviewProblem[]): void;
|
|
96
|
+
}
|
|
97
|
+
/** Поверхность превью — вклад в точку {@link PreviewSurfacePoint}. */
|
|
98
|
+
export interface PreviewSurface {
|
|
99
|
+
/** Уникален среди поверхностей: он же имя источника диагностик. */
|
|
100
|
+
readonly id: string;
|
|
101
|
+
/**
|
|
102
|
+
* Берётся ли поверхность за такой документ. Синхронная и дешёвая, решает по адресу, виду
|
|
103
|
+
* и провайдеру модели — содержимого здесь нет, выбор не должен стоить разбора текста.
|
|
104
|
+
*/
|
|
105
|
+
applies(doc: DocumentRef): boolean;
|
|
106
|
+
readonly capabilities: PreviewCapabilities;
|
|
107
|
+
mount(host: HTMLElement, ctx: PreviewContext): Disposable;
|
|
108
|
+
/**
|
|
109
|
+
* Имя для человека, УЖЕ переведённое. Функция, а не ключ: словарь принадлежит внёсшему
|
|
110
|
+
* плагину, а спрашивает имя чужой (живой вид редактора). Нет — показывают `id`.
|
|
111
|
+
*/
|
|
112
|
+
title?(): string;
|
|
113
|
+
}
|
|
114
|
+
/** Точка расширения поверхностей превью. Заполняется только вкладами. */
|
|
115
|
+
export declare const PreviewSurfacePoint: ExtensionPoint<PreviewSurface>;
|
|
116
|
+
/**
|
|
117
|
+
* Что живой вид даёт поверхности: схему из МОДЕЛИ редактора (буфер перерисовывается с задержкой,
|
|
118
|
+
* пока печатают), выделение и обратную связь хит-теста. Остальное достраивает провайдер.
|
|
119
|
+
*/
|
|
120
|
+
export interface LiveSurfaceContext {
|
|
121
|
+
/** Разобранная модель документа; `null` — не разбирается. Ссылка обязана быть стабильной. */
|
|
122
|
+
schema(): unknown;
|
|
123
|
+
onDidChangeSchema(cb: () => void): Disposable;
|
|
124
|
+
selection(): readonly NodeId[];
|
|
125
|
+
onDidChangeSelection(cb: () => void): Disposable;
|
|
126
|
+
select(ids: readonly NodeId[]): void;
|
|
127
|
+
}
|
|
128
|
+
/** Чем нарисован документ — в объёме, которым живой вид принимает решения. */
|
|
129
|
+
export interface LiveSurfaceInfo {
|
|
130
|
+
readonly id: string;
|
|
131
|
+
/** Уже переведённое имя. */
|
|
132
|
+
readonly title: string;
|
|
133
|
+
readonly hitTest: boolean;
|
|
134
|
+
readonly sameRealm: boolean;
|
|
135
|
+
readonly executesCode: boolean;
|
|
136
|
+
/** Уже переведённая причина, по которой выбрана не самая способная поверхность. */
|
|
137
|
+
readonly notice: string | null;
|
|
138
|
+
}
|
|
139
|
+
/**
|
|
140
|
+
* Живой вид: выбрать поверхность для документа по общему правилу и смонтировать её.
|
|
141
|
+
*
|
|
142
|
+
* Одно правило на всех, кто показывает документ, — поэтому «чем нарисована эта форма» имеет
|
|
143
|
+
* один ответ, где бы её ни показывали, а введённые значения и находки не раздваиваются.
|
|
144
|
+
*/
|
|
145
|
+
export interface PreviewLiveService {
|
|
146
|
+
/** Есть ли кому рисовать вовсе. */
|
|
147
|
+
available(): boolean;
|
|
148
|
+
/** Чем будет нарисован документ; `null` — показывать нечем. */
|
|
149
|
+
chosen(documentId: ResourceId): LiveSurfaceInfo | null;
|
|
150
|
+
/** Смонтировать поверхность в элемент; `null` — не за что было взяться. */
|
|
151
|
+
mount(documentId: ResourceId, element: HTMLElement, ctx: LiveSurfaceContext): Disposable | null;
|
|
152
|
+
/** Состав поверхностей для этого документа изменился. */
|
|
153
|
+
onDidChange(documentId: ResourceId, cb: () => void): Disposable;
|
|
154
|
+
/** Форма, которую опубликовала смонтированная поверхность; `null` — формы нет. */
|
|
155
|
+
formOf(documentId: ResourceId): PreviewFormHandle | null;
|
|
156
|
+
/** Опубликованная форма документа сменилась. */
|
|
157
|
+
onDidChangeForm(documentId: ResourceId, cb: () => void): Disposable;
|
|
158
|
+
}
|
|
159
|
+
/**
|
|
160
|
+
* Живой вид превью. Провайдер — плагин превью (`reformer.preview`), потребители — редакторы
|
|
161
|
+
* любых стеков. Необязателен у каждого потребителя: превью выключаемо.
|
|
162
|
+
*/
|
|
163
|
+
export declare const PreviewLiveCapability: Capability<PreviewLiveService>;
|
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
import { Disposable } from '../primitives/disposable.js';
|
|
2
|
+
/** Проверка введённого значения: ключ сообщения об ошибке или `null`, если всё хорошо. */
|
|
3
|
+
export type PromptValidator = (value: string) => string | null;
|
|
4
|
+
/** Общая часть запроса: заголовок и необязательное пояснение — ключами i18n. */
|
|
5
|
+
export interface PromptRequestBase {
|
|
6
|
+
/** Ключ i18n заголовка. */
|
|
7
|
+
readonly titleKey: string;
|
|
8
|
+
/** Ключ i18n пояснения под заголовком. */
|
|
9
|
+
readonly descriptionKey?: string;
|
|
10
|
+
/** Параметры подстановки для заголовка и пояснения (имя файла, число записей). */
|
|
11
|
+
readonly params?: Readonly<Record<string, unknown>>;
|
|
12
|
+
/**
|
|
13
|
+
* Чей это словарь. Тот же приём, что у заголовков команд в палитре: ключ сам по себе
|
|
14
|
+
* не говорит, где его искать, и без владельца запрос плагина показывал бы маркер промаха.
|
|
15
|
+
*/
|
|
16
|
+
readonly pluginId?: string;
|
|
17
|
+
}
|
|
18
|
+
/** Запрос строки. */
|
|
19
|
+
export interface PromptInputRequest extends PromptRequestBase {
|
|
20
|
+
readonly kind: 'input';
|
|
21
|
+
/** Начальное значение поля. */
|
|
22
|
+
readonly value?: string;
|
|
23
|
+
/** Ключ i18n подписи поля — для скринридера и для метки над полем. */
|
|
24
|
+
readonly labelKey?: string;
|
|
25
|
+
/** Ключ i18n подписи кнопки подтверждения; без него оболочка возьмёт свою. */
|
|
26
|
+
readonly confirmKey?: string;
|
|
27
|
+
/** Ключ i18n подписи кнопки отмены; без него оболочка возьмёт свою. */
|
|
28
|
+
readonly cancelKey?: string;
|
|
29
|
+
/**
|
|
30
|
+
* Что выделить при открытии.
|
|
31
|
+
*
|
|
32
|
+
* `stem` — имя без расширения: переименовывая `schema.json`, человек меняет `schema`,
|
|
33
|
+
* и выделять точку с расширением значило бы заставлять его каждый раз их дописывать.
|
|
34
|
+
*/
|
|
35
|
+
readonly select?: 'all' | 'stem';
|
|
36
|
+
readonly validate?: PromptValidator;
|
|
37
|
+
}
|
|
38
|
+
/** Запрос подтверждения. */
|
|
39
|
+
export interface PromptConfirmRequest extends PromptRequestBase {
|
|
40
|
+
readonly kind: 'confirm';
|
|
41
|
+
readonly confirmKey?: string;
|
|
42
|
+
readonly cancelKey?: string;
|
|
43
|
+
/** Опасное действие: оболочка покажет подтверждение красным. */
|
|
44
|
+
readonly tone?: 'default' | 'danger';
|
|
45
|
+
}
|
|
46
|
+
/** Пункт выбора из списка. */
|
|
47
|
+
export interface PromptPickItem {
|
|
48
|
+
/** Уникален в пределах запроса; его и возвращает {@link PromptService.pick}. */
|
|
49
|
+
readonly id: string;
|
|
50
|
+
/** Готовая строка: пункты — данные, а не сообщения. */
|
|
51
|
+
readonly label: string;
|
|
52
|
+
/** Пояснение справа: дата, раздел. Участвует в поиске — как пояснение пункта палитры. */
|
|
53
|
+
readonly description?: string;
|
|
54
|
+
}
|
|
55
|
+
/** Выбор из списка. */
|
|
56
|
+
export interface PromptPickRequest extends PromptRequestBase {
|
|
57
|
+
readonly kind: 'pick';
|
|
58
|
+
/**
|
|
59
|
+
* Пункты в порядке показа. Порядок — решение спрашивающего (у недавних это свежесть):
|
|
60
|
+
* поиск его не пересчитывает, пока пункты совпадают с запросом одинаково.
|
|
61
|
+
*/
|
|
62
|
+
readonly items: readonly PromptPickItem[];
|
|
63
|
+
/** Ключ i18n подсказки в поле поиска. */
|
|
64
|
+
readonly placeholderKey?: string;
|
|
65
|
+
/** Ключ i18n текста для пустого списка; без него оболочка возьмёт свой. */
|
|
66
|
+
readonly emptyKey?: string;
|
|
67
|
+
/**
|
|
68
|
+
* Кнопка «убрать» на каждом пункте — «Remove from Recently Opened» из VS Code.
|
|
69
|
+
*
|
|
70
|
+
* Зовёт её оболочка, и окно при этом остаётся открытым: человек чистит список, а не выбирает.
|
|
71
|
+
* Пункт исчезает сразу, не дожидаясь `run`: ответ хранилища ничего не меняет в том, что
|
|
72
|
+
* человек уже увидел. Отказ `run` уходит в консоль.
|
|
73
|
+
*/
|
|
74
|
+
readonly remove?: {
|
|
75
|
+
/** Ключ i18n подписи кнопки — для скринридера и всплывающей подсказки. */
|
|
76
|
+
readonly labelKey: string;
|
|
77
|
+
run(id: string): void | Promise<void>;
|
|
78
|
+
};
|
|
79
|
+
}
|
|
80
|
+
export type PromptRequest = PromptInputRequest | PromptConfirmRequest | PromptPickRequest;
|
|
81
|
+
/** Запрос, ждущий ответа: то, что оболочка сейчас рисует. */
|
|
82
|
+
export type PendingPrompt = PromptRequest & {
|
|
83
|
+
/** Выдаётся службой; годится React-ключом и адресом ответа. */
|
|
84
|
+
readonly id: string;
|
|
85
|
+
};
|
|
86
|
+
/** Ответ на запрос: строка либо согласие; отмена — всегда `null`. */
|
|
87
|
+
export type PromptAnswer = string | boolean | null;
|
|
88
|
+
export interface PromptService {
|
|
89
|
+
/** Спрашивает строку. `null` — отменили. */
|
|
90
|
+
input(request: Omit<PromptInputRequest, 'kind'>): Promise<string | null>;
|
|
91
|
+
/** Спрашивает согласие. Отмена — `false`: несделанное действие и есть отказ. */
|
|
92
|
+
confirm(request: Omit<PromptConfirmRequest, 'kind'>): Promise<boolean>;
|
|
93
|
+
/** Спрашивает выбор из списка. Ответ — `id` пункта; отмена — `null`. */
|
|
94
|
+
pick(request: Omit<PromptPickRequest, 'kind'>): Promise<string | null>;
|
|
95
|
+
/**
|
|
96
|
+
* Текущий запрос или `null`. Ссылка стабильна между изменениями — условие
|
|
97
|
+
* `useSyncExternalStore`.
|
|
98
|
+
*/
|
|
99
|
+
current(): PendingPrompt | null;
|
|
100
|
+
/**
|
|
101
|
+
* Отвечает на текущий запрос. Отвечает ОБОЛОЧКА, а не спрашивающий.
|
|
102
|
+
*
|
|
103
|
+
* Идентификатор обязателен: между отрисовкой и нажатием запрос мог смениться (команда
|
|
104
|
+
* отменила его, плагин выключили), и ответ «да» ушёл бы не тому вопросу.
|
|
105
|
+
*/
|
|
106
|
+
resolve(id: string, answer: PromptAnswer): void;
|
|
107
|
+
/** Снимает все ожидающие запросы отменой: закрытие проекта, выключение плагина. */
|
|
108
|
+
cancelAll(): void;
|
|
109
|
+
observe(cb: () => void): Disposable;
|
|
110
|
+
}
|
|
111
|
+
export declare const PromptServiceToken: import('../index.js').ServiceToken<PromptService>;
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import { Disposable } from '../primitives/disposable.js';
|
|
2
|
+
import { ResourceId } from '../primitives/resource.js';
|
|
3
|
+
/**
|
|
4
|
+
* Что сделали с записями.
|
|
5
|
+
*
|
|
6
|
+
* Различать обязательно: копия оставляет оригинал на месте, перенос — нет. Сейчас вставка
|
|
7
|
+
* умеет только копирование, но вид хранится с самого начала, потому что добавить его позже
|
|
8
|
+
* означало бы, что уже написанные вклады меню знают о буфере не всё.
|
|
9
|
+
*/
|
|
10
|
+
export type ClipboardMode = 'copy' | 'cut';
|
|
11
|
+
/** Снимок буфера. Ссылка стабильна между изменениями — условие `useSyncExternalStore`. */
|
|
12
|
+
export interface ClipboardState {
|
|
13
|
+
readonly mode: ClipboardMode;
|
|
14
|
+
readonly items: readonly ResourceId[];
|
|
15
|
+
}
|
|
16
|
+
export interface ResourceClipboardService {
|
|
17
|
+
/** Кладёт записи в буфер, заменяя предыдущее содержимое. Пустой список очищает буфер. */
|
|
18
|
+
copy(items: readonly ResourceId[]): void;
|
|
19
|
+
/** То же, но с пометкой «вырезано»: вставка обязана перенести, а не скопировать. */
|
|
20
|
+
cut(items: readonly ResourceId[]): void;
|
|
21
|
+
clear(): void;
|
|
22
|
+
/** Содержимое буфера; пустой список — буфер пуст. */
|
|
23
|
+
get(): ClipboardState;
|
|
24
|
+
/** Сколько записей лежит в буфере. Нужен предикатам применимости — им хватает числа. */
|
|
25
|
+
size(): number;
|
|
26
|
+
observe(cb: () => void): Disposable;
|
|
27
|
+
}
|
|
28
|
+
export declare const ResourceClipboardServiceToken: import('../index.js').ServiceToken<ResourceClipboardService>;
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
import { Disposable } from '../primitives/disposable.js';
|
|
2
|
+
import { ResourceId } from '../primitives/resource.js';
|
|
3
|
+
import { NodeId } from '../workspace/model/provider.js';
|
|
4
|
+
/**
|
|
5
|
+
* Общий канал выделения.
|
|
6
|
+
*
|
|
7
|
+
* Читающая и пишущая половины намеренно НЕ разведены (в отличие от документа и ручки правки
|
|
8
|
+
* в моделях): выделение — не правка, право выбрать узел есть у всех, кто узел показывает,
|
|
9
|
+
* и разделение здесь означало бы, что превью надо выдавать отдельную привилегию на то,
|
|
10
|
+
* что оно и так делает своим кликом.
|
|
11
|
+
*/
|
|
12
|
+
export interface SelectionService {
|
|
13
|
+
/**
|
|
14
|
+
* Выделение ресурса; пустой список, если никто ничего не выбирал.
|
|
15
|
+
*
|
|
16
|
+
* Между изменениями возвращает ТУ ЖЕ ссылку. Это не экономия: снимок читает
|
|
17
|
+
* `useSyncExternalStore`, который сравнивает по ссылке и падает с «The result of
|
|
18
|
+
* getSnapshot should be cached» на новом массиве при каждом вызове. Та же дисциплина,
|
|
19
|
+
* что у службы диагностик и у реестра вкладов.
|
|
20
|
+
*/
|
|
21
|
+
get(resource: ResourceId): readonly NodeId[];
|
|
22
|
+
/**
|
|
23
|
+
* Записывает выделение ресурса целиком.
|
|
24
|
+
*
|
|
25
|
+
* Замещение, а не добавление: писать сюда будут стороны, каждая из которых знает своё
|
|
26
|
+
* состояние полностью, и «добавить один узел» означало бы, что снятие выделения нельзя
|
|
27
|
+
* выразить вовсе. Пустой список — законная запись со смыслом «ничего не выбрано».
|
|
28
|
+
*
|
|
29
|
+
* Совпадающее по содержимому значение НЕ порождает уведомления: обе стороны пишут сюда
|
|
30
|
+
* своё состояние на каждое движение, и эхо чужой записи обязано затухать само, иначе
|
|
31
|
+
* два подписчика, отражающих выделение друг друга, крутились бы вечно.
|
|
32
|
+
*/
|
|
33
|
+
set(resource: ResourceId, ids: readonly NodeId[]): void;
|
|
34
|
+
/** Выделение ресурса изменилось. Полезная нагрузка — какого именно. */
|
|
35
|
+
onDidChange(cb: (resource: ResourceId) => void): Disposable;
|
|
36
|
+
/**
|
|
37
|
+
* Забывает выделение ресурса.
|
|
38
|
+
*
|
|
39
|
+
* Отличается от `set(resource, [])` только намерением и потому существует отдельно:
|
|
40
|
+
* пустой список — это «человек снял выделение» (о нём сообщают), а `forget` — «ресурса
|
|
41
|
+
* больше нет в работе». Уведомление он тоже шлёт: подписчик, держащий копию, обязан
|
|
42
|
+
* узнать, что копия больше ничего не отражает.
|
|
43
|
+
*/
|
|
44
|
+
forget(resource: ResourceId): void;
|
|
45
|
+
}
|
|
46
|
+
export declare const SelectionServiceToken: import('../index.js').ServiceToken<SelectionService>;
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import { Disposable } from '../primitives/disposable.js';
|
|
2
|
+
/** Куда пишется значение. Читается всегда из обеих: `workspace` перекрывает `user`. */
|
|
3
|
+
export type SettingsScope = 'user' | 'workspace';
|
|
4
|
+
/** То, что видит плагин. */
|
|
5
|
+
export interface SettingsService {
|
|
6
|
+
/**
|
|
7
|
+
* Действующее значение: `workspace` → `user` → умолчание вклада → `undefined`.
|
|
8
|
+
*
|
|
9
|
+
* Тип не проверяется в рантайме: в хранилище лежит то, что туда положили прошлые версии
|
|
10
|
+
* приложения. Потребитель, для которого чужое значение опасно, обязан его провалидировать —
|
|
11
|
+
* так делает служба темы.
|
|
12
|
+
*/
|
|
13
|
+
get<T>(key: string): T | undefined;
|
|
14
|
+
/**
|
|
15
|
+
* Записывает значение. Без `scope` область берётся из префикса ключа
|
|
16
|
+
* ({@link scopeForKey}); явный `scope` позволяет перекрыть глобальную настройку
|
|
17
|
+
* в рабочей области — ради этого слои и существуют.
|
|
18
|
+
*
|
|
19
|
+
* `value === undefined` снимает запись именно этой области, и значение проваливается
|
|
20
|
+
* на слой ниже. Без этого «workspace перекрывает user» было бы дверью в одну сторону:
|
|
21
|
+
* перекрыть можно, вернуться к глобальному значению нельзя.
|
|
22
|
+
*
|
|
23
|
+
* Кэш и подписчики обновляются сразу, до того как хранилище подтвердит запись, — иначе
|
|
24
|
+
* переключатель в интерфейсе ждал бы IndexedDB. Если запись отказала, кэш откатывается,
|
|
25
|
+
* подписчики уведомляются повторно, а отказ пробрасывается вызывающему.
|
|
26
|
+
*/
|
|
27
|
+
set<T>(key: string, value: T, scope?: SettingsScope): Promise<void>;
|
|
28
|
+
/**
|
|
29
|
+
* Уведомление о смене **действующего** значения ключа.
|
|
30
|
+
*
|
|
31
|
+
* Запись, перекрытая более сильной областью, уведомления не вызывает: подписчик реагирует
|
|
32
|
+
* на то, что вернёт `get`, а перерисовка ради того же самого значения — просто трата кадра.
|
|
33
|
+
*/
|
|
34
|
+
onDidChange(cb: (key: string) => void): Disposable;
|
|
35
|
+
/**
|
|
36
|
+
* Объявляет умолчание вклада. `dispose()` снимает его — вместе с плагином.
|
|
37
|
+
*
|
|
38
|
+
* Повторное объявление того же ключа — ошибка, а не замена: два умолчания на один ключ
|
|
39
|
+
* означают, что действующее значение зависит от порядка активации плагинов, а он ничего
|
|
40
|
+
* не значит.
|
|
41
|
+
*/
|
|
42
|
+
registerDefault<T>(key: string, value: T): Disposable;
|
|
43
|
+
}
|
|
44
|
+
export declare const SettingsServiceToken: import('../index.js').ServiceToken<SettingsService>;
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { Disposable } from '../primitives/disposable.js';
|
|
2
|
+
/** Тема, которая реально применена. Третьего состояния у оболочки нет. */
|
|
3
|
+
export type ThemeKind = 'light' | 'dark';
|
|
4
|
+
/** Что выбрал пользователь. `system` — «следуй за системой», а не «светлая». */
|
|
5
|
+
export type ThemePreference = ThemeKind | 'system';
|
|
6
|
+
export interface ThemeService {
|
|
7
|
+
/** Применённая тема: то, что сейчас на корневом элементе. */
|
|
8
|
+
readonly theme: ThemeKind;
|
|
9
|
+
/** Выбор пользователя. `system` означает «действующая тема берётся у системы». */
|
|
10
|
+
readonly preference: ThemePreference;
|
|
11
|
+
/** Записывает выбор в настройки; тема применяется сразу, не дожидаясь хранилища. */
|
|
12
|
+
setPreference(preference: ThemePreference): Promise<void>;
|
|
13
|
+
onDidChange(cb: (theme: ThemeKind) => void): Disposable;
|
|
14
|
+
}
|
|
15
|
+
export declare const ThemeServiceToken: import('../index.js').ServiceToken<ThemeService>;
|
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
import { ResourceId, ResourceRef } from '../../primitives/resource.js';
|
|
2
|
+
import { Diagnostic } from '../diagnostics/types.js';
|
|
3
|
+
import { DocumentKind } from '../../workspace/document.js';
|
|
4
|
+
/**
|
|
5
|
+
* То, что валидатор знает о документе, ещё ничего не прочитав.
|
|
6
|
+
*
|
|
7
|
+
* Все поля — из уже открытого документа (`Document` присваивается сюда структурно). Методов
|
|
8
|
+
* здесь нет намеренно: {@link ValidatorContribution.applies} обязан отвечать по адресу и виду,
|
|
9
|
+
* а не по содержимому — иначе выбор валидаторов стоил бы разбора текста на каждой правке,
|
|
10
|
+
* причём каждому кандидату своего.
|
|
11
|
+
*/
|
|
12
|
+
export interface DocumentRef {
|
|
13
|
+
readonly id: ResourceId;
|
|
14
|
+
readonly ref: ResourceRef;
|
|
15
|
+
readonly kind: DocumentKind;
|
|
16
|
+
/**
|
|
17
|
+
* Провайдер модели, который взялся за документ (`DocumentModelProvider.id`); есть только
|
|
18
|
+
* у `kind: 'model'`.
|
|
19
|
+
*
|
|
20
|
+
* Без него «чей это документ» узнавалось по медиатипу, а `.json` бывает схемой ЛЮБОГО
|
|
21
|
+
* стека: валидатор и поверхность превью одного стека брались бы за документы другого.
|
|
22
|
+
* Провайдер же отвечает на этот вопрос пробой содержимого ещё при открытии — дёшево и один
|
|
23
|
+
* раз, и здесь его ответ только читают.
|
|
24
|
+
*/
|
|
25
|
+
readonly providerId?: string;
|
|
26
|
+
}
|
|
27
|
+
/**
|
|
28
|
+
* Что валидатору дают на проход.
|
|
29
|
+
*
|
|
30
|
+
* `text()` и `model()` — методы, а не поля: контекст переживает один проход, но проход бывает
|
|
31
|
+
* отложенным (дорогой уровень), и читать состояние надо в момент чтения, а не в момент сборки
|
|
32
|
+
* контекста.
|
|
33
|
+
*/
|
|
34
|
+
export interface ValidateContext {
|
|
35
|
+
readonly doc: DocumentRef;
|
|
36
|
+
/** Текст буфера — ровно то, что видит человек и что уйдёт в файл при сохранении. */
|
|
37
|
+
text(): string;
|
|
38
|
+
/**
|
|
39
|
+
* Модель документа, **согласованная с буфером**, либо `undefined`.
|
|
40
|
+
*
|
|
41
|
+
* `undefined` означает одно из трёх: документ текстовый (провайдера модели нет), буфер
|
|
42
|
+
* не разобрался (расхождение), или модель есть, но она устарела. Все три случая для
|
|
43
|
+
* валидатора одинаковы: доверять можно только тексту, и если ему нужна структура — он
|
|
44
|
+
* разбирает текст сам и сам отвечает за ошибку разбора.
|
|
45
|
+
*
|
|
46
|
+
* Отдавать УСТАРЕВШУЮ модель было бы хуже, чем не отдавать ничего: диагностика указывала бы
|
|
47
|
+
* на узлы, которых в тексте перед человеком уже нет.
|
|
48
|
+
*/
|
|
49
|
+
model(): unknown;
|
|
50
|
+
}
|
|
51
|
+
/**
|
|
52
|
+
* Вклад валидатора.
|
|
53
|
+
*
|
|
54
|
+
* Оба метода необязательны, но хотя бы один обязан быть — вклад без обоих просто ничего
|
|
55
|
+
* не делает, и оркестратор его молча пропускает.
|
|
56
|
+
*/
|
|
57
|
+
export interface ValidatorContribution {
|
|
58
|
+
/**
|
|
59
|
+
* Уникален среди валидаторов: он же — имя источника в службе диагностик, по которому
|
|
60
|
+
* замещаются прошлые находки.
|
|
61
|
+
*/
|
|
62
|
+
readonly id: string;
|
|
63
|
+
/** Берётся ли этот валидатор за такой документ. Синхронный и дешёвый — см. {@link DocumentRef}. */
|
|
64
|
+
applies(doc: DocumentRef): boolean;
|
|
65
|
+
/**
|
|
66
|
+
* Быстрая проверка. **СИНХРОННАЯ** — на ней стоит гейт ассистента.
|
|
67
|
+
*
|
|
68
|
+
* Возвращает полный список своих находок: не «что изменилось», а «что я вижу сейчас».
|
|
69
|
+
* Пустой массив — законный ответ «чисто», и именно он снимает исправленную ошибку.
|
|
70
|
+
*/
|
|
71
|
+
validate?(ctx: ValidateContext): readonly Diagnostic[];
|
|
72
|
+
/**
|
|
73
|
+
* Дорогая проверка: запускается с задержкой, отменяется следующей правкой, результат
|
|
74
|
+
* вливается отдельным источником.
|
|
75
|
+
*
|
|
76
|
+
* Обязана уважать `signal`: оркестратор отменённый результат **отбросит**, но работу,
|
|
77
|
+
* которую валидатор продолжает делать в отменённом проходе, за него никто не остановит.
|
|
78
|
+
*/
|
|
79
|
+
validateAsync?(ctx: ValidateContext, signal: AbortSignal): Promise<readonly Diagnostic[]>;
|
|
80
|
+
}
|
|
81
|
+
/**
|
|
82
|
+
* Точка расширения валидаторов.
|
|
83
|
+
*
|
|
84
|
+
* Заполняется только плагинами: разбор и проверка содержимого — предметное знание, и в Host
|
|
85
|
+
* оно означало бы, что второй формат придётся вносить правкой ядра.
|
|
86
|
+
*/
|
|
87
|
+
export declare const ValidatorPoint: import('../../internal.js').ExtensionPoint<ValidatorContribution>;
|
|
88
|
+
/**
|
|
89
|
+
* Суффикс источника дорогого уровня.
|
|
90
|
+
*
|
|
91
|
+
* Видимый, а не скрытый: имя источника попадает в интерфейс и в лог, и «почему у меня два
|
|
92
|
+
* источника от одного валидатора» должно читаться из самого имени.
|
|
93
|
+
*/
|
|
94
|
+
export declare const ASYNC_SOURCE_SUFFIX = "#async";
|
|
95
|
+
/** Имя источника быстрого уровня — сам идентификатор валидатора. */
|
|
96
|
+
export declare function fastSource(validatorId: string): string;
|
|
97
|
+
/** Имя источника дорогого уровня — идентификатор плюс {@link ASYNC_SOURCE_SUFFIX}. */
|
|
98
|
+
export declare function asyncSource(validatorId: string): string;
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
import { Capability } from '../primitives/capability.js';
|
|
2
|
+
import { Disposable } from '../primitives/disposable.js';
|
|
3
|
+
import { ResourceId, ResourceRef } from '../primitives/resource.js';
|
|
4
|
+
export interface WorkspaceFilesService {
|
|
5
|
+
/**
|
|
6
|
+
* Каталог, в котором лежит ресурс. Для ресурса в корне источника — сам корень.
|
|
7
|
+
*
|
|
8
|
+
* Нужен каждому, чьё состояние принадлежит КАТАЛОГУ, а не файлу: у превью значения формы
|
|
9
|
+
* и находки сборки общие на форму и её сайдкары.
|
|
10
|
+
*/
|
|
11
|
+
parentOf(id: ResourceId): ResourceId;
|
|
12
|
+
/** Адрес внутри каталога: `resolve(dir, 'validation.ts')`. Сегменты приписываются по одному. */
|
|
13
|
+
resolve(dir: ResourceId, ...segments: readonly string[]): ResourceId;
|
|
14
|
+
/**
|
|
15
|
+
* Адрес по пути ОТ КОРНЯ ИСТОЧНИКА, в котором лежит опорный ресурс.
|
|
16
|
+
*
|
|
17
|
+
* Нужен импортам и ссылкам вида `src/forms/credit`: они записаны от корня проекта,
|
|
18
|
+
* а опорой служит любой ресурс того же источника.
|
|
19
|
+
*/
|
|
20
|
+
fromRoot(anchor: ResourceId, path: string): ResourceId;
|
|
21
|
+
/**
|
|
22
|
+
* Корень открытого проекта или `null`, если проекта нет.
|
|
23
|
+
*
|
|
24
|
+
* Отдельный вопрос, а не «parentOf до упора»: корень знает рабочая область, и подниматься
|
|
25
|
+
* к нему перебором значило бы гадать, где остановиться.
|
|
26
|
+
*/
|
|
27
|
+
projectRoot(): ResourceId | null;
|
|
28
|
+
/**
|
|
29
|
+
* Есть ли такой ресурс. Отказ источника — это `false`, а не исключение: спрашивают об этом,
|
|
30
|
+
* чтобы не затереть чужой файл, и «не знаю» здесь хуже, чем «нет».
|
|
31
|
+
*/
|
|
32
|
+
exists(id: ResourceId): Promise<boolean>;
|
|
33
|
+
/** Один уровень каталога. Отказ листинга — пустой список: «здесь ничего не нашлось». */
|
|
34
|
+
list(dir: ResourceId): Promise<readonly ResourceRef[]>;
|
|
35
|
+
/** Текст ресурса из рабочей копии; `null` — нет проекта, нет ресурса или он не читается текстом. */
|
|
36
|
+
readText(id: ResourceId): Promise<string | null>;
|
|
37
|
+
/**
|
|
38
|
+
* Примет ли ИСТОЧНИК этого ресурса запись. Без проекта — `false`.
|
|
39
|
+
*
|
|
40
|
+
* Не то же, что «есть ли право у плагина»: право одно на всех и выражено самой дверью
|
|
41
|
+
* записи. Это вопрос к источнику — каталог мог быть открыт только на чтение, — и задают
|
|
42
|
+
* его ДО работы: генерация обязана сказать «сюда писать нельзя» до первого напечатанного
|
|
43
|
+
* файла, а не после половины.
|
|
44
|
+
*/
|
|
45
|
+
canWrite(id: ResourceId): boolean;
|
|
46
|
+
/**
|
|
47
|
+
* Разрешает ли ИСТОЧНИК этого ресурса исполнять его код. Без проекта — `false`.
|
|
48
|
+
*
|
|
49
|
+
* Близнец {@link canWrite} и по той же причине вопрос к источнику, а не к плагину: сайдкары
|
|
50
|
+
* формы — это код, и придёт он оттуда же, откуда схема. Задают его поверхности превью,
|
|
51
|
+
* которые компилируют и исполняют файлы рабочей копии; `false` для них — отказ, а не повод
|
|
52
|
+
* исполнять «на всякий случай».
|
|
53
|
+
*/
|
|
54
|
+
executesCode(id: ResourceId): boolean;
|
|
55
|
+
/**
|
|
56
|
+
* Перечитать каталог: в нём появились или исчезли записи мимо интерфейса.
|
|
57
|
+
*
|
|
58
|
+
* Дерево проекта читает уровни ЛЕНИВО и помнит прочитанное, поэтому каталог, созданный
|
|
59
|
+
* записью плагина, сам в нём не появится. Это не «сбросить кэш на всякий случай»: зовёт
|
|
60
|
+
* это тот, кто ТОЛЬКО ЧТО записал, и знает, куда именно.
|
|
61
|
+
*/
|
|
62
|
+
refresh(dir: ResourceId): Promise<void>;
|
|
63
|
+
/**
|
|
64
|
+
* ТЕКСТ ресурсов рабочей копии изменился или они исчезли.
|
|
65
|
+
*
|
|
66
|
+
* В `changed` — только такие адреса: «загрузился» и «сохранился» текста не меняют, и тот,
|
|
67
|
+
* кто держит находки по этим файлам, стёр бы их на каждое сохранение. Подписка переживает
|
|
68
|
+
* смену проекта: служба существует с запуска, а проект открывают и закрывают.
|
|
69
|
+
*/
|
|
70
|
+
onDidChange(cb: (changed: readonly ResourceId[]) => void): Disposable;
|
|
71
|
+
}
|
|
72
|
+
/**
|
|
73
|
+
* Возможность «записи рабочей области».
|
|
74
|
+
*
|
|
75
|
+
* Провайдер — оболочка (`./host-capabilities`): рабочая область существует с запуска и
|
|
76
|
+
* отвечает без проекта — `null`, `false`, пустым списком, — как и служба документов рядом.
|
|
77
|
+
*
|
|
78
|
+
* Версия `1.1.0`: к исходной добавлены {@link WorkspaceFilesService.executesCode} и
|
|
79
|
+
* {@link WorkspaceFilesService.onDidChange} — ими поверхности превью перестали зависеть от порта,
|
|
80
|
+
* который собирала оболочка. Растит её тот, кто интерфейс меняет.
|
|
81
|
+
*/
|
|
82
|
+
export declare const WorkspaceFilesCapability: Capability<WorkspaceFilesService>;
|
|
83
|
+
/** Токен службы — ТОТ ЖЕ объект: возможность расширяет токен, второго реестра нет. */
|
|
84
|
+
export declare const WorkspaceFilesServiceToken: Capability<WorkspaceFilesService>;
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import { Capability } from '../primitives/capability.js';
|
|
2
|
+
import { ResourceId } from '../primitives/resource.js';
|
|
3
|
+
/**
|
|
4
|
+
* Итог пакетной операции: что получилось и что нет.
|
|
5
|
+
*
|
|
6
|
+
* Пакетные операции НЕ всё-или-ничего: удаление десяти файлов, где один занят чужим
|
|
7
|
+
* процессом, обязано удалить девять и назвать десятый. Откатить уже удалённое всё равно
|
|
8
|
+
* нечем, а отказ целиком заставил бы человека повторять то, что уже сделано.
|
|
9
|
+
*/
|
|
10
|
+
export interface WorkspaceBatchResult {
|
|
11
|
+
readonly done: readonly ResourceId[];
|
|
12
|
+
readonly failed: readonly {
|
|
13
|
+
readonly id: ResourceId;
|
|
14
|
+
readonly error: unknown;
|
|
15
|
+
}[];
|
|
16
|
+
}
|
|
17
|
+
export interface WorkspaceResourcesService {
|
|
18
|
+
/**
|
|
19
|
+
* Умеет ли движок выбрать каталог вообще.
|
|
20
|
+
*
|
|
21
|
+
* Ответ не меняется за время жизни вкладки: это про браузер (File System Access),
|
|
22
|
+
* а не про состояние. Спрашивают его, чтобы не показывать кнопку, которая ничего не делает.
|
|
23
|
+
*/
|
|
24
|
+
canOpenProject(): boolean;
|
|
25
|
+
/** Показывает человеку выбор каталога и открывает проект. `false` — не выбрали. */
|
|
26
|
+
openProject(): Promise<boolean>;
|
|
27
|
+
createFile(dir: ResourceId, name: string, text?: string): Promise<ResourceId>;
|
|
28
|
+
createDirectory(dir: ResourceId, name: string): Promise<ResourceId>;
|
|
29
|
+
rename(id: ResourceId, name: string): Promise<ResourceId>;
|
|
30
|
+
move(id: ResourceId, dir: ResourceId): Promise<ResourceId>;
|
|
31
|
+
remove(ids: readonly ResourceId[]): Promise<WorkspaceBatchResult>;
|
|
32
|
+
copy(ids: readonly ResourceId[], dir: ResourceId): Promise<WorkspaceBatchResult>;
|
|
33
|
+
}
|
|
34
|
+
/**
|
|
35
|
+
* Возможность «правка записей проекта».
|
|
36
|
+
*
|
|
37
|
+
* Провайдер — оболочка. Версия `1.0.0` — исходная; растит её тот, кто меняет интерфейс.
|
|
38
|
+
*/
|
|
39
|
+
export declare const WorkspaceResourcesCapability: Capability<WorkspaceResourcesService>;
|
|
40
|
+
/** Токен службы — ТОТ ЖЕ объект: возможность расширяет токен, второго реестра нет. */
|
|
41
|
+
export declare const WorkspaceResourcesServiceToken: Capability<WorkspaceResourcesService>;
|