odant-work 1.0.12 → 1.0.13
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/#system/certs/russian_trusted_root_ca.pem +33 -0
- package/#system/mail.json.example +9 -0
- package/#system/package-manifest.json +986 -0
- package/#system/sandbox.json +19 -0
- package/#system/settings.json.example +3 -0
- package/package.json +1 -1
- package/run.mjs +78 -11
- package/scripts/check-ignored-code.mjs +25 -1
- package/sources/data/api.js +1071 -0
- package/sources/data/choices.js +125 -0
- package/sources/data/classes.js +412 -0
- package/sources/data/db.js +383 -0
- package/sources/data/errors.js +15 -0
- package/sources/data/expr.js +456 -0
- package/sources/data/objects.js +950 -0
- package/sources/data/posting.js +657 -0
- package/sources/data/print.js +524 -0
- package/sources/data/progress.md +526 -0
- package/sources/data/readme.md +77 -0
- package/sources/data/reports.js +1033 -0
- package/sources/data/schema.js +586 -0
- package/sources/data/scope.js +281 -0
- package/sources/data/sql-inspector.js +892 -0
- package/sources/data/time.js +67 -0
- package/sources/data/workspace.js +152 -0
- package/sources/host/auto-updater.js +52 -10
- package/.vscode/launch.json +0 -32
- package/.vscode/settings.json +0 -2
- package/.vscode/tasks.json +0 -65
- package/ORGANIZATIONS//320/221/320/270/320/267/320/275/320/265/321/201 /320/230/320/275/321/202/320/265/321/200 /320/241/320/276/321/204/321/202/orders/$structure/video/IMG_8524.MP4 +0 -0
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
{
|
|
2
|
+
"enabled": true,
|
|
3
|
+
"docker": { "socketPath": null, "host": null, "port": null },
|
|
4
|
+
"image": "work-computer:latest",
|
|
5
|
+
"images": ["work-computer:latest", "python:3.12-slim", "node:22-slim"],
|
|
6
|
+
"workdir": "/workspace",
|
|
7
|
+
"user": "",
|
|
8
|
+
"limits": { "memoryMb": 1024, "cpus": 1, "pids": 256 },
|
|
9
|
+
"maxPerUser": 2,
|
|
10
|
+
"maxRunning": 4,
|
|
11
|
+
"idleStopMin": 10,
|
|
12
|
+
"execTimeoutSec": 120,
|
|
13
|
+
"maxReadBytes": 1000000,
|
|
14
|
+
"maxWriteBytes": 200000,
|
|
15
|
+
"maxOutput": 200000,
|
|
16
|
+
"network": { "egressName": "work-egress", "sandboxName": "work-sandbox", "ttlMin": 15 },
|
|
17
|
+
"graphical": ["work-computer:latest"],
|
|
18
|
+
"displayWaitSec": 30
|
|
19
|
+
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "odant-work",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.13",
|
|
4
4
|
"description": "ODANT-WORK — платформа цифровой организации (встроенная система учёта, документооборот, управление процессами и приватный мультимодальный ИИ)",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "sources/work.js",
|
package/run.mjs
CHANGED
|
@@ -23,19 +23,36 @@ function readVersion(file) {
|
|
|
23
23
|
|
|
24
24
|
/**
|
|
25
25
|
* Нужна ли установка зависимостей.
|
|
26
|
-
*
|
|
27
|
-
*
|
|
28
|
-
*
|
|
26
|
+
* 1) Проверяем, разрешаются ли все dependencies из package.json через import.meta.resolve
|
|
27
|
+
* (учитывает как локальный node_modules, так и поднятый родительский node_modules при установке через npm/npx).
|
|
28
|
+
* 2) Если рядом есть package-lock.json (репозиторий Git/SVN), дополнительно сверяем версии package.json и package-lock.json.
|
|
29
29
|
*/
|
|
30
30
|
function isPackageActual() {
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
31
|
+
try {
|
|
32
|
+
const pkgFile = path.join(currentDirectory, 'package.json');
|
|
33
|
+
if (!fs.existsSync(pkgFile))
|
|
34
|
+
return false;
|
|
35
|
+
const pkg = JSON.parse(fs.readFileSync(pkgFile, 'utf8'));
|
|
36
|
+
const deps = Object.keys(pkg.dependencies || {});
|
|
37
|
+
for (const dep of deps) {
|
|
38
|
+
try {
|
|
39
|
+
import.meta.resolve(dep);
|
|
40
|
+
}
|
|
41
|
+
catch {
|
|
42
|
+
return false;
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
const lockFile = path.join(currentDirectory, 'package-lock.json');
|
|
46
|
+
if (fs.existsSync(lockFile)) {
|
|
47
|
+
const lockVersion = readVersion(lockFile);
|
|
48
|
+
if (pkg.version && lockVersion && pkg.version !== lockVersion)
|
|
49
|
+
return false;
|
|
50
|
+
}
|
|
51
|
+
return true;
|
|
52
|
+
}
|
|
53
|
+
catch {
|
|
37
54
|
return false;
|
|
38
|
-
|
|
55
|
+
}
|
|
39
56
|
}
|
|
40
57
|
|
|
41
58
|
if (!isPackageActual()) {
|
|
@@ -60,12 +77,62 @@ if (!isPackageActual()) {
|
|
|
60
77
|
await npmInstall;
|
|
61
78
|
}
|
|
62
79
|
|
|
80
|
+
const workRoot = path.resolve(process.cwd());
|
|
81
|
+
const pkgRoot = path.resolve(currentDirectory);
|
|
82
|
+
|
|
83
|
+
/**
|
|
84
|
+
* Если запуск выполнен через `npx odant-work` или из `node_modules/odant-work` в рабочей папке (например, D:\WORK),
|
|
85
|
+
* автоматически разворачиваем или безопасно обновляем рабочую директорию из установленного пакета.
|
|
86
|
+
*/
|
|
87
|
+
if (workRoot !== pkgRoot) {
|
|
88
|
+
const pkgVersion = readVersion(path.join(pkgRoot, 'package.json'));
|
|
89
|
+
const manifestVersion = readVersion(path.join(workRoot, '#system', 'package-manifest.json'));
|
|
90
|
+
const hasServerTree = fs.existsSync(path.join(workRoot, '$server', '$folder'));
|
|
91
|
+
if (!hasServerTree || (pkgVersion && manifestVersion !== pkgVersion)) {
|
|
92
|
+
const { applyUpdateFromDirectory } = await import('./sources/host/auto-updater.js');
|
|
93
|
+
const report = applyUpdateFromDirectory({
|
|
94
|
+
sourceDir: pkgRoot,
|
|
95
|
+
rootDir: workRoot,
|
|
96
|
+
newVersion: pkgVersion || '',
|
|
97
|
+
});
|
|
98
|
+
console.log(`[WORK] Рабочая директория синхронизирована с пакетом odant-work@${report.toVersion} (${workRoot})`);
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
/**
|
|
103
|
+
* При первом запуске в чистой папке автоматически засеваем демонстрационную базу Маслоторг,
|
|
104
|
+
* если класс организации присутствует, а файла work.db ещё нет.
|
|
105
|
+
*/
|
|
106
|
+
const maslotorgClass = path.join(workRoot, 'ORGANIZATIONS', 'Маслоторг', '$base', 'class.js');
|
|
107
|
+
const maslotorgDb = path.join(workRoot, 'ORGANIZATIONS', 'Маслоторг', '$base', '#system', 'work.db');
|
|
108
|
+
if (!process.env.WORK_TEST && fs.existsSync(maslotorgClass) && !fs.existsSync(maslotorgDb)) {
|
|
109
|
+
try {
|
|
110
|
+
const { openDataDb } = await import('./sources/data/db.js');
|
|
111
|
+
const { refreshClasses } = await import('./sources/data/classes.js');
|
|
112
|
+
const { queryObjects } = await import('./sources/data/objects.js');
|
|
113
|
+
const { seedDemo, seedDemoOperations } = await import('./scripts/demo-seed.mjs');
|
|
114
|
+
const prefix = '/ORGANIZATIONS/Маслоторг/MODULES/Register';
|
|
115
|
+
const orgBase = '/ORGANIZATIONS/Маслоторг';
|
|
116
|
+
const db = await openDataDb(maslotorgDb);
|
|
117
|
+
await refreshClasses(db, workRoot);
|
|
118
|
+
if (!queryObjects(db, { cid: `${prefix}/CATALOGS/Виды нормативов`, limit: 1 }).total) {
|
|
119
|
+
const ids = seedDemo(db, { prefix });
|
|
120
|
+
seedDemoOperations(db, ids, { prefix, orgBase });
|
|
121
|
+
console.log('[WORK] Инициализирована демонстрационная база данных /ORGANIZATIONS/Маслоторг.');
|
|
122
|
+
}
|
|
123
|
+
db.close();
|
|
124
|
+
}
|
|
125
|
+
catch (err) {
|
|
126
|
+
console.warn('[WORK] Не удалось засеять демо-базу Маслоторг:', err?.message || err);
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
|
|
63
130
|
/**
|
|
64
131
|
* Если предыдущий экземпляр `run.mjs` остался висеть в фоне и держит порт 8001 / STUN 3478,
|
|
65
132
|
* аккуратно завершаем его перед стартом нового экземпляра.
|
|
66
133
|
*/
|
|
67
134
|
async function releasePreviousInstance() {
|
|
68
|
-
const pidFile = path.join(
|
|
135
|
+
const pidFile = path.join(workRoot, '#system', 'run.pid');
|
|
69
136
|
try {
|
|
70
137
|
if (fs.existsSync(pidFile)) {
|
|
71
138
|
const oldPid = Number(fs.readFileSync(pidFile, 'utf8').trim());
|
|
@@ -66,4 +66,28 @@ if (ignored.length) {
|
|
|
66
66
|
console.error(' ' + f);
|
|
67
67
|
process.exit(1);
|
|
68
68
|
}
|
|
69
|
-
|
|
69
|
+
|
|
70
|
+
// Проверяем также .npmignore через npm pack --dry-run --json (кроме tests и license-server)
|
|
71
|
+
const NPM_CODE_ROOTS = new Set(['$server', 'sources', 'oda', 'scripts', 'rules', 'MODELS', 'NODES', 'SERVICES']);
|
|
72
|
+
const npmCandidates = candidates.filter(f => {
|
|
73
|
+
const top = f.split('/')[0];
|
|
74
|
+
return NPM_CODE_ROOTS.has(top) || !f.includes('/');
|
|
75
|
+
});
|
|
76
|
+
const npmCmd = process.platform === 'win32' ? 'npm.cmd' : 'npm';
|
|
77
|
+
const packRes = spawnSync(npmCmd, ['pack', '--dry-run', '--json'], { cwd: ROOT, encoding: 'utf-8', shell: process.platform === 'win32' });
|
|
78
|
+
if (!packRes.error && packRes.status === 0 && packRes.stdout) {
|
|
79
|
+
try {
|
|
80
|
+
const packJson = JSON.parse(packRes.stdout);
|
|
81
|
+
const packedLower = new Set((packJson[0]?.files || []).map(f => String(f.path || '').toLowerCase()));
|
|
82
|
+
const missingFromNpm = npmCandidates.filter(f => !packedLower.has(f.toLowerCase()));
|
|
83
|
+
if (missingFromNpm.length) {
|
|
84
|
+
console.error('check-ignored-code: ФАЙЛЫ КОДА ПОДПАДАЮТ ПОД .npmignore и НЕ попадут в пакет npm:');
|
|
85
|
+
for (const f of missingFromNpm)
|
|
86
|
+
console.error(' ' + f);
|
|
87
|
+
process.exit(1);
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
catch { /* ignore json parse error */ }
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
console.log('Код не игнорируется (.gitignore и .npmignore): ' + candidates.length + ' файлов проверено, потерь нет.');
|