datagrok-tools 6.7.1 → 6.7.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/.turbo/turbo-build.log
CHANGED
package/CHANGELOG.md
CHANGED
|
@@ -1,12 +1,17 @@
|
|
|
1
1
|
# Datagrok-tools changelog
|
|
2
2
|
|
|
3
|
-
## 6.7.
|
|
3
|
+
## 6.7.2 (WIP)
|
|
4
|
+
|
|
5
|
+
* `grok publish` marks a bundled package for servers older than 1.28.0, which detect one only by a `webpack.config.js` in the archive; the marker is generated at publish time and never written to the package folder.
|
|
6
|
+
|
|
7
|
+
## 6.7.1 (2026-09-15)
|
|
4
8
|
|
|
5
9
|
* `grok login <server>` — keypair authentication, the replacement for the developer key. Generates an EC P-256 key, registers only its public half (in the browser, or with a one-shot `--code` from Profile > Public keys...), and keeps the private half in `~/.grok/keys/<alias>.json`. Logging in signs a server-issued nonce, so nothing reusable crosses the wire; keys can carry an expiry (`--expires`) and are revoked one at a time. `grok publish`, `grok test`, `grok stresstest` and `grok s` use it automatically whenever one is configured for the server, and fall back to the developer key otherwise. For CI, `GROK_PRIVATE_KEY` holds the private JWK (raw or base64) instead of a config file. Needs a server from 1.28 on; see https://datagrok.ai/help/govern/access-control/keypair-authentication
|
|
6
10
|
* `grok s token` — prints a session token for the configured server, so shell scripts stop curling `/users/login/dev` with a long-lived key.
|
|
7
11
|
* `grok config add` — `--key` is now optional: a server reached with a keypair has no developer key to record.
|
|
8
12
|
* Against a server older than 1.28 — which has no keypair endpoints and refuses their paths before routing — the CLI names the version needed instead of reporting a bare 401, and falls back to the developer key when one is still configured for that server.
|
|
9
13
|
* `grok login` reports its progress step by step (spinner on a terminal, one line per step in a log), including while it waits for the browser approval.
|
|
14
|
+
* `grok s push/migrate` — a migrated entity is stamped in its `metaParams` with `migrated_from` (the source stand URL) and `migrated_on`, so on the target it is clear the entity came from another stand. Written wherever the entity already carries `metaParams` (as `sync_id` is) and stripped before the idempotency comparison, so a re-push of an unchanged entity still reads as identical.
|
|
10
15
|
|
|
11
16
|
## 6.6.0 (2026-09-13)
|
|
12
17
|
|
package/bin/commands/publish.js
CHANGED
|
@@ -4,6 +4,8 @@ var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefau
|
|
|
4
4
|
Object.defineProperty(exports, "__esModule", {
|
|
5
5
|
value: true
|
|
6
6
|
});
|
|
7
|
+
exports.BUNDLE_MARKER_NAME = exports.BUNDLE_MARKER = void 0;
|
|
8
|
+
exports.predatesBundleDetection = predatesBundleDetection;
|
|
7
9
|
exports.processPackage = processPackage;
|
|
8
10
|
exports.publish = publish;
|
|
9
11
|
var _archiver = _interopRequireDefault(require("archiver"));
|
|
@@ -487,6 +489,21 @@ async function fallbackImage(img, host, devKey, registry, version, contentHash)
|
|
|
487
489
|
requestedVersion: img.imageTag
|
|
488
490
|
};
|
|
489
491
|
}
|
|
492
|
+
const BUNDLE_MARKER_NAME = exports.BUNDLE_MARKER_NAME = 'webpack.config.js';
|
|
493
|
+
const BUNDLE_MARKER = exports.BUNDLE_MARKER = '// Generated by `grok publish` for servers before 1.28.0, which detect a ' + 'bundled\n// package by this file. The bundle itself is built by @datagrok/build-config.\nmodule.exports = {};\n';
|
|
494
|
+
function predatesBundleDetection(version) {
|
|
495
|
+
const [major, minor, patch] = (version ?? '').split('.').map(Number);
|
|
496
|
+
if ([major, minor, patch].some(isNaN)) return true;
|
|
497
|
+
return major < 1 || major === 1 && minor < 28;
|
|
498
|
+
}
|
|
499
|
+
async function serverPredatesBundleDetection(host) {
|
|
500
|
+
try {
|
|
501
|
+
const resp = await (0, _nodeFetch.default)(`${host}/info/server`);
|
|
502
|
+
return predatesBundleDetection((await resp.json())?.Version);
|
|
503
|
+
} catch {
|
|
504
|
+
return true;
|
|
505
|
+
}
|
|
506
|
+
}
|
|
490
507
|
async function processPackage(debug, rebuild, host, devKey, packageName, dropDb, suffix, hostAlias, registry, rebuildDocker, skipDockerRebuild) {
|
|
491
508
|
// Validate server connectivity and dev key
|
|
492
509
|
let timestamps = {};
|
|
@@ -612,6 +629,13 @@ async function processPackage(debug, rebuild, host, devKey, packageName, dropDb,
|
|
|
612
629
|
if (userInfo) dockerVersion = userInfo.login;
|
|
613
630
|
}
|
|
614
631
|
await processDockerImages(packageName, dockerVersion, registry, devKey, host, rebuildDocker ?? false, zip, localTimestamps, debug, skipDockerRebuild ?? false, generatedDockerDirs);
|
|
632
|
+
const bundledWithoutMarker = !rebuild && _fs.default.existsSync('dist/package.js') && !_fs.default.existsSync(BUNDLE_MARKER_NAME);
|
|
633
|
+
if (bundledWithoutMarker && (await serverPredatesBundleDetection(host))) {
|
|
634
|
+
zip.append(BUNDLE_MARKER, {
|
|
635
|
+
name: BUNDLE_MARKER_NAME
|
|
636
|
+
});
|
|
637
|
+
localTimestamps[BUNDLE_MARKER_NAME] = new Date().toUTCString();
|
|
638
|
+
}
|
|
615
639
|
zip.append(JSON.stringify(localTimestamps), {
|
|
616
640
|
name: 'timestamps.json'
|
|
617
641
|
});
|
|
@@ -35,8 +35,12 @@ function normalize(type, json) {
|
|
|
35
35
|
if (copy.package) copy.package = {
|
|
36
36
|
id: copy.package.id
|
|
37
37
|
};
|
|
38
|
-
// The
|
|
39
|
-
if (copy.metaParams)
|
|
38
|
+
// The stamps are written by the pusher, so they must not make an unchanged entity look different.
|
|
39
|
+
if (copy.metaParams) {
|
|
40
|
+
delete copy.metaParams.sync_id;
|
|
41
|
+
delete copy.metaParams.migrated_from;
|
|
42
|
+
delete copy.metaParams.migrated_on;
|
|
43
|
+
}
|
|
40
44
|
_registry.TYPES[type]?.strip?.(copy);
|
|
41
45
|
return sortKeys(copy);
|
|
42
46
|
}
|
|
@@ -43,9 +43,12 @@ export function normalize(type: string, json: any): any {
|
|
|
43
43
|
delete copy[k];
|
|
44
44
|
if (copy.package)
|
|
45
45
|
copy.package = {id: copy.package.id};
|
|
46
|
-
// The
|
|
47
|
-
if (copy.metaParams)
|
|
46
|
+
// The stamps are written by the pusher, so they must not make an unchanged entity look different.
|
|
47
|
+
if (copy.metaParams) {
|
|
48
48
|
delete copy.metaParams.sync_id;
|
|
49
|
+
delete copy.metaParams.migrated_from;
|
|
50
|
+
delete copy.metaParams.migrated_on;
|
|
51
|
+
}
|
|
49
52
|
TYPES[type]?.strip?.(copy);
|
|
50
53
|
return sortKeys(copy);
|
|
51
54
|
}
|
|
@@ -433,7 +433,14 @@ async function saveOne(dapi, bundle, op, rows, idmap, deferred, missing) {
|
|
|
433
433
|
const spec = _registry.TYPES[op.type];
|
|
434
434
|
const payload = (0, _bundle.stripPrivate)(JSON.parse(JSON.stringify(op.json)));
|
|
435
435
|
const targetId = payload.id ?? op.id;
|
|
436
|
-
if (payload.metaParams && typeof payload.metaParams === 'object')
|
|
436
|
+
if (payload.metaParams && typeof payload.metaParams === 'object') {
|
|
437
|
+
payload.metaParams.sync_id = op.id;
|
|
438
|
+
const from = bundle.manifest?.source?.url;
|
|
439
|
+
if (from) {
|
|
440
|
+
payload.metaParams.migrated_from = from;
|
|
441
|
+
payload.metaParams.migrated_on = new Date().toISOString();
|
|
442
|
+
}
|
|
443
|
+
}
|
|
437
444
|
|
|
438
445
|
// The server encrypts and masks password-class parameters itself, so target-side
|
|
439
446
|
// secrets go in as plain parameters and never touch the bundle.
|
|
@@ -378,8 +378,14 @@ async function saveOne(dapi: NodeDapi, bundle: Bundle, op: Op, rows: Row[], idma
|
|
|
378
378
|
const spec = TYPES[op.type];
|
|
379
379
|
const payload = stripPrivate(JSON.parse(JSON.stringify(op.json)));
|
|
380
380
|
const targetId = payload.id ?? op.id;
|
|
381
|
-
if (payload.metaParams && typeof payload.metaParams === 'object')
|
|
381
|
+
if (payload.metaParams && typeof payload.metaParams === 'object') {
|
|
382
382
|
payload.metaParams.sync_id = op.id;
|
|
383
|
+
const from = bundle.manifest?.source?.url;
|
|
384
|
+
if (from) {
|
|
385
|
+
payload.metaParams.migrated_from = from;
|
|
386
|
+
payload.metaParams.migrated_on = new Date().toISOString();
|
|
387
|
+
}
|
|
388
|
+
}
|
|
383
389
|
|
|
384
390
|
// The server encrypts and masks password-class parameters itself, so target-side
|
|
385
391
|
// secrets go in as plain parameters and never touch the bundle.
|
package/package.json
CHANGED
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
"type": "git",
|
|
5
5
|
"url": "https://github.com/datagrok-ai/public.git"
|
|
6
6
|
},
|
|
7
|
-
"version": "6.7.
|
|
7
|
+
"version": "6.7.2",
|
|
8
8
|
"description": "Utility to upload and publish packages to Datagrok",
|
|
9
9
|
"homepage": "https://github.com/datagrok-ai/public/tree/master/tools#readme",
|
|
10
10
|
"dependencies": {
|