ose-plugin 0.1.0 → 0.1.2
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/README.md +37 -10
- package/bin/ose-plugin.mjs +9 -3
- package/create.mjs +5 -3
- package/pack.mjs +203 -0
- package/package.json +2 -1
- package/templates/theme/README.md +3 -1
- package/templates/widget/README.md +4 -3
- package/validate.mjs +3 -3
package/README.md
CHANGED
|
@@ -7,9 +7,10 @@
|
|
|
7
7
|
|
|
8
8
|
| Файл | Зачем |
|
|
9
9
|
|---|---|
|
|
10
|
-
| `bin/ose-plugin.mjs` | единая команда `npx ose-plugin create` / `
|
|
10
|
+
| `bin/ose-plugin.mjs` | единая команда `npx ose-plugin create` / `check` / `pack` |
|
|
11
11
|
| `create.mjs` | создаёт рабочий пакет виджета или темы |
|
|
12
12
|
| `validate.mjs` | проверяет пакет по тем же правилам, что `src-tauri/src/plugins.rs` |
|
|
13
|
+
| `pack.mjs` | собирает пакет в zip для установки из панели |
|
|
13
14
|
| `index.d.ts` | типы `window.OSE`, `BaseWidget`, событий и манифестов |
|
|
14
15
|
| `schema/` | JSON-схемы `widget.json` и `theme.json` для редактора |
|
|
15
16
|
| `templates/` | то, из чего `create` собирает пакет |
|
|
@@ -32,10 +33,13 @@ npx ose-plugin create plain --theme --name "Plain"
|
|
|
32
33
|
# проверить готовый пакет или весь каталог
|
|
33
34
|
npx ose-plugin check hello
|
|
34
35
|
npx ose-plugin check config/plugins
|
|
36
|
+
|
|
37
|
+
# собрать архив для установки из панели
|
|
38
|
+
npx ose-plugin pack hello
|
|
35
39
|
```
|
|
36
40
|
|
|
37
|
-
В репозитории OSE то же самое без сети: `node sdk/create.mjs
|
|
38
|
-
`node sdk/validate.mjs`.
|
|
41
|
+
В репозитории OSE то же самое без сети: `node sdk/create.mjs`,
|
|
42
|
+
`node sdk/validate.mjs` и `node sdk/pack.mjs`.
|
|
39
43
|
|
|
40
44
|
### Команды
|
|
41
45
|
|
|
@@ -58,16 +62,30 @@ npx ose-plugin check config/plugins
|
|
|
58
62
|
|
|
59
63
|
Код возврата `1` — есть ошибки; предупреждения его не меняют.
|
|
60
64
|
|
|
61
|
-
|
|
62
|
-
|
|
65
|
+
`ose-plugin pack <папка>`:
|
|
66
|
+
|
|
67
|
+
| Параметр | Что делает |
|
|
68
|
+
|---|---|
|
|
69
|
+
| `<папка>` | папка готового пакета; сначала прогоняется та же проверка, что у `check` |
|
|
70
|
+
| `--out <файл>` | куда положить архив; по умолчанию `<id>.zip` в текущем каталоге |
|
|
71
|
+
|
|
72
|
+
В архив не попадают `node_modules`, `.git` и служебные файлы Finder и Windows.
|
|
73
|
+
Манифест лежит в корне архива.
|
|
74
|
+
|
|
75
|
+
Пакет сразу рабочий: скопируйте папку в каталог пакетов или поставьте архив
|
|
76
|
+
через «Настройки → Пакеты» → «Установить из ZIP», обновите страницу панели
|
|
77
|
+
(или источник в OBS) и добавьте карточку из библиотеки.
|
|
63
78
|
|
|
64
79
|
- разработка (`npm run tauri:dev`) — `config/plugins/<id>/`;
|
|
65
80
|
- установленное приложение — каталог данных `com.openstreamenvironment.app`
|
|
66
81
|
(Windows: `%APPDATA%\com.openstreamenvironment.app\plugins\`).
|
|
67
82
|
|
|
68
|
-
Манифесты
|
|
69
|
-
|
|
70
|
-
|
|
83
|
+
Манифесты перечитываются, когда панель или оверлей запрашивают `/api/plugins`
|
|
84
|
+
при загрузке страницы. После установки или правки `widget.json`/`theme.json`
|
|
85
|
+
перезапуск приложения не нужен: панель при возврате фокуса заметит новый список
|
|
86
|
+
и сама перезагрузит страницу; источник в OBS обновите вручную — оверлей не
|
|
87
|
+
трогаем, чтобы не рвать эфир. Код и CSS сервер отдаёт с диска, поэтому правки
|
|
88
|
+
видны сразу после обновления.
|
|
71
89
|
|
|
72
90
|
## Виджет
|
|
73
91
|
|
|
@@ -282,8 +300,8 @@ npx ose-plugin check <папка> --json # для скриптов и CI
|
|
|
282
300
|
|
|
283
301
|
## Если пакет не появился
|
|
284
302
|
|
|
285
|
-
-
|
|
286
|
-
|
|
303
|
+
- Обновите страницу панели или источник в OBS: панель замечает новый список
|
|
304
|
+
при возврате фокуса и перезагружается сама; оверлей обновляют вручную.
|
|
287
305
|
- Папка должна называться так же, как `id`, и лежать в каталоге пакетов; в ней
|
|
288
306
|
ровно один манифест — `widget.json` **или** `theme.json`.
|
|
289
307
|
- Ошибки загрузки пишутся в терминал приложения (`[ose] пакет <id>: …`) и
|
|
@@ -313,3 +331,12 @@ npm publish
|
|
|
313
331
|
Версию поднимайте в `sdk/package.json` (semver), после — коммит в репозиторий.
|
|
314
332
|
Версия SDK не связана с версией приложения: контракт пакетов держится на
|
|
315
333
|
`apiVersion: 1`, а не на номере npm-пакета.
|
|
334
|
+
|
|
335
|
+
Имя пакета и имя команды в `bin` должны совпадать: `npx` первым словом ищет
|
|
336
|
+
пакет, поэтому `npx ose-plugin` сработает только у пакета `ose-plugin`. Если на
|
|
337
|
+
аккаунте включена 2FA, публикуйте с `--otp=<код>` или automation-токеном —
|
|
338
|
+
иначе npm оставит версию в очереди и следующая попытка получит 409.
|
|
339
|
+
|
|
340
|
+
После публикации проверьте `npx --yes ose-plugin@latest --help`, а старое имя
|
|
341
|
+
пакета пометьте `npm deprecate` (или `npm unpublish` в первые 72 часа), чтобы в
|
|
342
|
+
поиске не висели два одинаковых SDK.
|
package/bin/ose-plugin.mjs
CHANGED
|
@@ -1,15 +1,17 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
|
|
3
3
|
/*
|
|
4
|
-
Одна команда для SDK: `npx ose-plugin create` и `
|
|
4
|
+
Одна команда для SDK: `npx ose-plugin create`, `check` и `pack`.
|
|
5
5
|
|
|
6
|
-
Разделение на подкоманды — чтобы установленный пакет не требовал помнить
|
|
7
|
-
имени: `create` собирает заготовку, `check` проверяет манифест и
|
|
6
|
+
Разделение на подкоманды — чтобы установленный пакет не требовал помнить три
|
|
7
|
+
имени: `create` собирает заготовку, `check` проверяет манифест и файлы,
|
|
8
|
+
`pack` кладёт пакет в zip для установки из панели.
|
|
8
9
|
*/
|
|
9
10
|
|
|
10
11
|
import process from "node:process";
|
|
11
12
|
|
|
12
13
|
import { main as create } from "../create.mjs";
|
|
14
|
+
import { main as pack } from "../pack.mjs";
|
|
13
15
|
import { main as check } from "../validate.mjs";
|
|
14
16
|
|
|
15
17
|
const USAGE = [
|
|
@@ -17,6 +19,7 @@ const USAGE = [
|
|
|
17
19
|
"",
|
|
18
20
|
" ose-plugin create <id> [--theme] [--name «Имя»] [--dir <каталог>] [--force]",
|
|
19
21
|
" ose-plugin check [<папка | каталог>] [--json] (по умолчанию — текущая папка)",
|
|
22
|
+
" ose-plugin pack <папка> [--out <файл>] — zip для «Установить из ZIP»",
|
|
20
23
|
"",
|
|
21
24
|
"Документация: https://github.com/Halantar-git/open-stream-environment/tree/main/sdk",
|
|
22
25
|
].join("\n");
|
|
@@ -31,6 +34,9 @@ switch (command) {
|
|
|
31
34
|
case "validate":
|
|
32
35
|
check(rest.length > 0 ? rest : ["."]);
|
|
33
36
|
break;
|
|
37
|
+
case "pack":
|
|
38
|
+
pack(rest);
|
|
39
|
+
break;
|
|
34
40
|
case undefined:
|
|
35
41
|
case "help":
|
|
36
42
|
case "--help":
|
package/create.mjs
CHANGED
|
@@ -4,8 +4,8 @@
|
|
|
4
4
|
Создать заготовку пакета виджета или темы.
|
|
5
5
|
|
|
6
6
|
Заготовка — рабочий пакет, а не пустой скелет: его можно сразу положить в
|
|
7
|
-
config/plugins
|
|
8
|
-
остаётся переписать код, стили и схему настроек.
|
|
7
|
+
config/plugins и увидеть карточку в библиотеке после обновления страницы.
|
|
8
|
+
Дальше остаётся переписать код, стили и схему настроек.
|
|
9
9
|
|
|
10
10
|
Использование:
|
|
11
11
|
npx ose-plugin create <id> [параметры]
|
|
@@ -152,8 +152,10 @@ function main(argv) {
|
|
|
152
152
|
}
|
|
153
153
|
console.log("Дальше:");
|
|
154
154
|
console.log(" 1. Скопируйте папку в config/plugins/ (разработка) или в каталог данных приложения.");
|
|
155
|
-
console.log(" 2.
|
|
155
|
+
console.log(" 2. Обновите страницу панели — манифесты перечитываются при загрузке.");
|
|
156
|
+
console.log(" Оверлей в OBS обновите вручную, чтобы не рвать эфир.");
|
|
156
157
|
console.log(` 3. Проверка после правок: npx ose-plugin check «${target}»`);
|
|
158
|
+
console.log(` 4. Архив для установки: npx ose-plugin pack «${target}»`);
|
|
157
159
|
}
|
|
158
160
|
|
|
159
161
|
export { main };
|
package/pack.mjs
ADDED
|
@@ -0,0 +1,203 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
/*
|
|
4
|
+
Собрать пакет в zip для установки из панели («Настройки → Пакеты»).
|
|
5
|
+
|
|
6
|
+
Архив — обычный zip без внешних зависимостей: пакет собирается из папки, а
|
|
7
|
+
в него не попадают служебные файлы Finder и Windows, `node_modules` и `.git`.
|
|
8
|
+
Манифест кладётся в корень, поэтому архив принимается и плоским, и вместе с
|
|
9
|
+
одноимённой папкой.
|
|
10
|
+
|
|
11
|
+
Использование:
|
|
12
|
+
npx ose-plugin pack <папка пакета> [--out <файл>]
|
|
13
|
+
node sdk/pack.mjs <папка пакета> [--out <файл>] — в репозитории OSE
|
|
14
|
+
|
|
15
|
+
Код возврата 1 — пакет не прошёл проверку или архив не собрался.
|
|
16
|
+
*/
|
|
17
|
+
|
|
18
|
+
import fs from "node:fs";
|
|
19
|
+
import path from "node:path";
|
|
20
|
+
import process from "node:process";
|
|
21
|
+
import zlib from "node:zlib";
|
|
22
|
+
import { fileURLToPath } from "node:url";
|
|
23
|
+
|
|
24
|
+
import { validatePackage } from "./validate.mjs";
|
|
25
|
+
|
|
26
|
+
// Мусор, который не должен уезжать в архив: зависимости, служебные каталоги
|
|
27
|
+
// системы контроля версий и файлы Finder/Windows.
|
|
28
|
+
const SKIP = new Set(["node_modules", ".git", ".svn", "__MACOSX"]);
|
|
29
|
+
|
|
30
|
+
const USAGE = [
|
|
31
|
+
"Использование: ose-plugin pack <папка пакета> [--out <файл>]",
|
|
32
|
+
" --out <файл> — куда положить архив (по умолчанию <id>.zip в текущем каталоге)",
|
|
33
|
+
].join("\n");
|
|
34
|
+
|
|
35
|
+
const CRC_TABLE = (() => {
|
|
36
|
+
const table = new Uint32Array(256);
|
|
37
|
+
for (let index = 0; index < 256; index += 1) {
|
|
38
|
+
let value = index;
|
|
39
|
+
for (let bit = 0; bit < 8; bit += 1) {
|
|
40
|
+
value = value & 1 ? 0xedb88320 ^ (value >>> 1) : value >>> 1;
|
|
41
|
+
}
|
|
42
|
+
table[index] = value >>> 0;
|
|
43
|
+
}
|
|
44
|
+
return table;
|
|
45
|
+
})();
|
|
46
|
+
|
|
47
|
+
function crc32(buffer) {
|
|
48
|
+
let crc = 0xffffffff;
|
|
49
|
+
for (const byte of buffer) crc = CRC_TABLE[(crc ^ byte) & 0xff] ^ (crc >>> 8);
|
|
50
|
+
return (crc ^ 0xffffffff) >>> 0;
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
/** Файлы пакета: относительные пути с «/» — так их понимает приложение. */
|
|
54
|
+
function collect(dir, base = "", out = []) {
|
|
55
|
+
const entries = fs.readdirSync(dir, { withFileTypes: true }).sort((a, b) => a.name.localeCompare(b.name));
|
|
56
|
+
for (const entry of entries) {
|
|
57
|
+
const name = entry.name;
|
|
58
|
+
if (SKIP.has(name) || name === ".DS_Store" || name === "Thumbs.db" || name.startsWith("._")) continue;
|
|
59
|
+
const full = path.join(dir, name);
|
|
60
|
+
const relative = base ? `${base}/${name}` : name;
|
|
61
|
+
if (entry.isDirectory()) collect(full, relative, out);
|
|
62
|
+
else if (entry.isFile()) out.push({ relative, full });
|
|
63
|
+
}
|
|
64
|
+
return out;
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
/*
|
|
68
|
+
Минимальный zip: локальные заголовки, центральный каталог и конец каталога.
|
|
69
|
+
Deflate берётся только когда он правда уменьшает файл — иначе файл кладётся
|
|
70
|
+
как есть, и архив читается любым распаковщиком.
|
|
71
|
+
*/
|
|
72
|
+
function zip(files) {
|
|
73
|
+
const parts = [];
|
|
74
|
+
const central = [];
|
|
75
|
+
let offset = 0;
|
|
76
|
+
|
|
77
|
+
for (const file of files) {
|
|
78
|
+
const data = fs.readFileSync(file.full);
|
|
79
|
+
const deflated = zlib.deflateRawSync(data);
|
|
80
|
+
const packed = deflated.length < data.length;
|
|
81
|
+
const body = packed ? deflated : data;
|
|
82
|
+
const name = Buffer.from(file.relative, "utf8");
|
|
83
|
+
const checksum = crc32(data);
|
|
84
|
+
|
|
85
|
+
const local = Buffer.alloc(30);
|
|
86
|
+
local.writeUInt32LE(0x04034b50, 0);
|
|
87
|
+
local.writeUInt16LE(20, 4);
|
|
88
|
+
local.writeUInt16LE(0x0800, 6); // имена в UTF-8
|
|
89
|
+
local.writeUInt16LE(packed ? 8 : 0, 8);
|
|
90
|
+
local.writeUInt16LE(0, 10);
|
|
91
|
+
local.writeUInt16LE(0x21, 12);
|
|
92
|
+
local.writeUInt32LE(checksum, 14);
|
|
93
|
+
local.writeUInt32LE(body.length, 18);
|
|
94
|
+
local.writeUInt32LE(data.length, 22);
|
|
95
|
+
local.writeUInt16LE(name.length, 26);
|
|
96
|
+
local.writeUInt16LE(0, 28);
|
|
97
|
+
parts.push(local, name, body);
|
|
98
|
+
|
|
99
|
+
const header = Buffer.alloc(46);
|
|
100
|
+
header.writeUInt32LE(0x02014b50, 0);
|
|
101
|
+
header.writeUInt16LE(20, 4);
|
|
102
|
+
header.writeUInt16LE(20, 6);
|
|
103
|
+
header.writeUInt16LE(0x0800, 8);
|
|
104
|
+
header.writeUInt16LE(packed ? 8 : 0, 10);
|
|
105
|
+
header.writeUInt16LE(0, 12);
|
|
106
|
+
header.writeUInt16LE(0x21, 14);
|
|
107
|
+
header.writeUInt32LE(checksum, 16);
|
|
108
|
+
header.writeUInt32LE(body.length, 20);
|
|
109
|
+
header.writeUInt32LE(data.length, 24);
|
|
110
|
+
header.writeUInt16LE(name.length, 28);
|
|
111
|
+
header.writeUInt16LE(0, 30);
|
|
112
|
+
header.writeUInt16LE(0, 32);
|
|
113
|
+
header.writeUInt16LE(0, 34);
|
|
114
|
+
header.writeUInt16LE(0, 36);
|
|
115
|
+
header.writeUInt32LE((0o100644 << 16) >>> 0, 38);
|
|
116
|
+
header.writeUInt32LE(offset, 42);
|
|
117
|
+
central.push(header, name);
|
|
118
|
+
|
|
119
|
+
offset += local.length + name.length + body.length;
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
const centralSize = central.reduce((sum, part) => sum + part.length, 0);
|
|
123
|
+
const end = Buffer.alloc(22);
|
|
124
|
+
end.writeUInt32LE(0x06054b50, 0);
|
|
125
|
+
end.writeUInt16LE(0, 4);
|
|
126
|
+
end.writeUInt16LE(0, 6);
|
|
127
|
+
end.writeUInt16LE(files.length, 8);
|
|
128
|
+
end.writeUInt16LE(files.length, 10);
|
|
129
|
+
end.writeUInt32LE(centralSize, 12);
|
|
130
|
+
end.writeUInt32LE(offset, 16);
|
|
131
|
+
end.writeUInt16LE(0, 20);
|
|
132
|
+
|
|
133
|
+
return Buffer.concat([...parts, ...central, end]);
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
function fail(message) {
|
|
137
|
+
console.error(`[OSE] ${message}`);
|
|
138
|
+
process.exitCode = 1;
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
export function main(argv) {
|
|
142
|
+
if (argv.includes("--help") || argv.includes("-h")) {
|
|
143
|
+
console.log(USAGE);
|
|
144
|
+
return;
|
|
145
|
+
}
|
|
146
|
+
const options = { target: "", out: "" };
|
|
147
|
+
for (let index = 0; index < argv.length; index += 1) {
|
|
148
|
+
const arg = argv[index];
|
|
149
|
+
if (arg === "--out") {
|
|
150
|
+
const value = argv[index + 1];
|
|
151
|
+
if (!value || value.startsWith("--")) {
|
|
152
|
+
fail("у --out нет значения");
|
|
153
|
+
return;
|
|
154
|
+
}
|
|
155
|
+
options.out = value;
|
|
156
|
+
index += 1;
|
|
157
|
+
} else if (arg.startsWith("--")) {
|
|
158
|
+
fail(`неизвестный параметр: ${arg}`);
|
|
159
|
+
return;
|
|
160
|
+
} else if (!options.target) {
|
|
161
|
+
options.target = arg;
|
|
162
|
+
} else {
|
|
163
|
+
fail("нужна одна папка пакета");
|
|
164
|
+
return;
|
|
165
|
+
}
|
|
166
|
+
}
|
|
167
|
+
if (!options.target) {
|
|
168
|
+
console.log(USAGE);
|
|
169
|
+
process.exitCode = 1;
|
|
170
|
+
return;
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
const folder = path.resolve(options.target);
|
|
174
|
+
if (!fs.existsSync(folder) || !fs.statSync(folder).isDirectory()) {
|
|
175
|
+
fail(`нет папки пакета: ${options.target}`);
|
|
176
|
+
return;
|
|
177
|
+
}
|
|
178
|
+
// Архив с ошибкой в манифесте приложение всё равно отвергнет — лучше сказать
|
|
179
|
+
// об этом сразу, а не после установки.
|
|
180
|
+
const report = validatePackage(folder);
|
|
181
|
+
if (report.errors.length > 0) {
|
|
182
|
+
report.errors.forEach((error) => console.error(`[OSE] ошибка: ${error}`));
|
|
183
|
+
process.exitCode = 1;
|
|
184
|
+
return;
|
|
185
|
+
}
|
|
186
|
+
report.warnings.forEach((warning) => console.log(`[OSE] предупреждение: ${warning}`));
|
|
187
|
+
|
|
188
|
+
const files = collect(folder);
|
|
189
|
+
if (files.length === 0) {
|
|
190
|
+
fail("в папке нет файлов");
|
|
191
|
+
return;
|
|
192
|
+
}
|
|
193
|
+
const id = path.basename(folder);
|
|
194
|
+
const out = options.out ? path.resolve(options.out) : path.join(process.cwd(), `${id}.zip`);
|
|
195
|
+
const archive = zip(files);
|
|
196
|
+
fs.writeFileSync(out, archive);
|
|
197
|
+
console.log(`[OSE] Архив готов: ${out} (файлов: ${files.length}, ${archive.length} байт)`);
|
|
198
|
+
console.log("Установка: «Настройки → Пакеты» → «Установить из ZIP».");
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
if (process.argv[1] && path.resolve(process.argv[1]) === fileURLToPath(import.meta.url)) {
|
|
202
|
+
main(process.argv.slice(2));
|
|
203
|
+
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "ose-plugin",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.2",
|
|
4
4
|
"description": "Scaffold and validate Open Stream Environment widget and theme packages, with types for window.OSE.",
|
|
5
5
|
"license": "GPL-3.0-or-later",
|
|
6
6
|
"type": "module",
|
|
@@ -11,6 +11,7 @@
|
|
|
11
11
|
"bin",
|
|
12
12
|
"create.mjs",
|
|
13
13
|
"validate.mjs",
|
|
14
|
+
"pack.mjs",
|
|
14
15
|
"index.d.ts",
|
|
15
16
|
"schema",
|
|
16
17
|
"templates",
|
|
@@ -9,7 +9,9 @@
|
|
|
9
9
|
|
|
10
10
|
## Установка
|
|
11
11
|
|
|
12
|
-
Скопируйте папку `{{id}}` в каталог пакетов
|
|
12
|
+
Скопируйте папку `{{id}}` в каталог пакетов — перезапуск приложения не нужен:
|
|
13
|
+
панель сама перезагрузится, когда вернёте ей фокус, а источник в OBS обновите
|
|
14
|
+
вручную:
|
|
13
15
|
|
|
14
16
|
- разработка (`npm run tauri:dev`) — `config/plugins/` в корне репозитория;
|
|
15
17
|
- установленное приложение — каталог данных `com.openstreamenvironment.app`
|
|
@@ -10,14 +10,15 @@
|
|
|
10
10
|
|
|
11
11
|
## Установка
|
|
12
12
|
|
|
13
|
-
Скопируйте папку `{{id}}` в каталог пакетов
|
|
14
|
-
|
|
13
|
+
Скопируйте папку `{{id}}` в каталог пакетов — перезапуск приложения не нужен:
|
|
14
|
+
панель сама перезагрузится, когда вернёте ей фокус, а источник в OBS обновите
|
|
15
|
+
вручную:
|
|
15
16
|
|
|
16
17
|
- разработка (`npm run tauri:dev`) — `config/plugins/` в корне репозитория;
|
|
17
18
|
- установленное приложение — каталог данных `com.openstreamenvironment.app`
|
|
18
19
|
(Windows: `%APPDATA%\com.openstreamenvironment.app\plugins\`).
|
|
19
20
|
|
|
20
|
-
После
|
|
21
|
+
После обновления страницы виджет появится в колонке виджетов под своим именем.
|
|
21
22
|
|
|
22
23
|
## Проверка
|
|
23
24
|
|
package/validate.mjs
CHANGED
|
@@ -3,9 +3,9 @@
|
|
|
3
3
|
/*
|
|
4
4
|
Проверка пакета виджета или темы до установки.
|
|
5
5
|
|
|
6
|
-
Правила повторяют src-tauri/src/plugins.rs: приложение
|
|
7
|
-
|
|
8
|
-
|
|
6
|
+
Правила повторяют src-tauri/src/plugins.rs: приложение перечитывает манифесты
|
|
7
|
+
при загрузке страницы и отвергает пакет, который их не проходит. Ошибку лучше
|
|
8
|
+
увидеть здесь, чем в терминале приложения и пустой карточкой.
|
|
9
9
|
|
|
10
10
|
Использование:
|
|
11
11
|
npx ose-plugin check <папка пакета | каталог пакетов> [--json]
|