datagrok-tools 6.7.9 → 6.7.10
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/.devcontainer/Dockerfile.pkg_dev +1 -1
- package/.turbo/turbo-build.log +2 -2
- package/CHANGELOG.md +22 -1
- package/CLAUDE.md +1 -0
- package/GROK_S.md +69 -1
- package/README.md +14 -0
- package/bin/commands/api.js +29 -8
- package/bin/commands/check.js +43 -1
- package/bin/commands/connect-folder.js +411 -0
- package/bin/commands/help.js +66 -0
- package/bin/commands/publish.js +6 -0
- package/bin/commands/server-observe.js +335 -7
- package/bin/commands/server.js +65 -5
- package/bin/commands/src.js +458 -0
- package/bin/grok.js +9 -5
- package/bin/utils/connect-folder/docker.js +244 -0
- package/bin/utils/connect-folder/docker.ts +259 -0
- package/bin/utils/ent-helpers.js +1 -1
- package/bin/utils/node-dapi.js +29 -7
- package/bin/utils/server-client.js +8 -1
- package/bin/utils/test-utils.js +54 -2
- package/package.json +1 -1
- package/plugins/func-gen-plugin.js +1 -1
- package/vitest.config.mts +4 -0
package/.turbo/turbo-build.log
CHANGED
package/CHANGELOG.md
CHANGED
|
@@ -1,6 +1,27 @@
|
|
|
1
1
|
# Datagrok-tools changelog
|
|
2
2
|
|
|
3
|
-
##
|
|
3
|
+
## 6.7.10 (2026-11-06)
|
|
4
|
+
|
|
5
|
+
* Added `grok src`: git recipes across the repos of the datagrok umbrella (`clone`, `add`, `sparse`, `switch`, `status`, `pull`, `at`, `bump`, `wt add`, `doctor`)
|
|
6
|
+
* Kept positionals, `--url` and `--dir` verbatim (`1.10` no longer becomes 1.1), and an explicit boolean such as `--force` now reaches every command instead of being dropped
|
|
7
|
+
* Added `grok s o groups list|get|add|set|rm|put|reset`, `endpoints list|rm`, `logs match '<filter>'` (with `--space`) and `logs activations [stop]`: log groups and endpoints of Settings > Logger
|
|
8
|
+
* `grok publish`: A local container build that fails for the host platform on Apple Silicon is retried for linux/amd64, so a package whose base image has no arm64 variant (the Chembl ChEMBL database) builds
|
|
9
|
+
* `grok test`: A package built on u2 or ems runs with u2 strict — a u2 misuse throws a `U2UsageError` naming the fix, and one the page caught and logged fails the run when it is the package's own (a stack frame in its bundle, or none to tell; another package's prints as a warning); `U2_STRICT=report` lists them instead without failing
|
|
10
|
+
* `grok check`: A package built on u2 or ems fails on a problem of u2's consumer check whatever its version (a 0.x package only printed it), so a CSS rule over a new `.u2-*` class or `[data-u2…]` attribute fails the check
|
|
11
|
+
* Added `grok s o problems severity <id|kind:key> <info|warning|critical|none>`: pins the severity a problem's raises use (`none` unpins it)
|
|
12
|
+
* Added `grok connect-folder`: connects a local folder as a connection, served from a Docker container; the agent image tag is pulled on every connect, so a moved tag replaces a stale local agent
|
|
13
|
+
* `grok connect-folder`: Runs only the Docker Hub `datagrok/proxy_storage` agent image whatever image the server names; `--image` runs another, such as a copy in a private registry
|
|
14
|
+
* Added `grok s ... --log [<spec>]` on every `grok s` command (`grok s o` included): its requests share a `datlas-log-id`, every server instance keeps what they log at the spec (`verbose`, `standard`, levels, debug flags or `all`) in memory only, and at the end the command gathers it and prints it to stderr
|
|
15
|
+
* Added `grok s functions run ... --debug`: a debug call (`?debug=true`) whose own log, a query's stages as the query debugger shows them, is kept and printed the same way
|
|
16
|
+
* Added `grok s o logs request <logId>`: gathers what the requests of one `--log` command logged
|
|
17
|
+
* `grok s status`: server build, uptime, DB pool and HTTP connections from `/info/server`; for admins also the requests in flight (`?extended=true`)
|
|
18
|
+
* `grok api`: Fixed double plurals in table accessors (`categorieses` → `categories`)
|
|
19
|
+
* Build: Fixed `package-api.ts` of a decorator package lagging one build behind `package.g.ts`
|
|
20
|
+
* Added a `restore` arm per soft-delete table to the `<Schema>TransactionOp` that `grok api` generates, so the typed `transaction()` accepts the restore ops the server runs
|
|
21
|
+
* Made `grok api` type a required column with a `default` as optional on `<Table>Insert`: the server fills it when an insert omits it
|
|
22
|
+
* Fixed `grok api` emitting a choices type that does not compile, or holds a different value, when a choice contains `'` or `\`
|
|
23
|
+
|
|
24
|
+
## 6.7.9 (2026-10-16)
|
|
4
25
|
|
|
5
26
|
* Upgraded Puppeteer to v25, which drops the vulnerable `extract-zip` and `basic-ftp` transitive dependencies; Node.js 22.12+ is now required
|
|
6
27
|
* `grok add app --domain`, `grok api --ui`: scaffold against `@datagrok-libraries/ems`
|
package/CLAUDE.md
CHANGED
|
@@ -33,6 +33,7 @@ The CLI uses a modular command pattern. Each command is a separate module that:
|
|
|
33
33
|
- `claude.ts` - Launch a Dockerized dev environment with Datagrok + Claude Code
|
|
34
34
|
- `migrate.ts` - Update legacy packages
|
|
35
35
|
- `init.ts` - Apply configuration to existing packages
|
|
36
|
+
- `src.ts` - Git recipes across the repos of the datagrok umbrella (`grok src`)
|
|
36
37
|
|
|
37
38
|
The commands `api`, `check`, `link`, `publish`, and `test` support the `--all` flag to run recursively across all packages in the current directory.
|
|
38
39
|
|
package/GROK_S.md
CHANGED
|
@@ -36,6 +36,7 @@ browser or a logged-in session.
|
|
|
36
36
|
| See what fields an entity type has | `grok s describe connections` |
|
|
37
37
|
| Hit any undocumented endpoint | `grok s raw GET /users/current` / `raw POST <path> --data '{...}'` |
|
|
38
38
|
| Check server + per-module health | `grok s healthcheck [--module <name>]` |
|
|
39
|
+
| Server build, uptime, DB pool, requests in flight | `grok s status` |
|
|
39
40
|
| Problems, alerts, problem rules, logger settings, errors, cloud logs | `grok s observe problems list --alert-status open` (alias `grok s o`) |
|
|
40
41
|
| Bulk operations in one round-trip | `grok s batch <entity> <verb> --json items.json` |
|
|
41
42
|
| Move entities dev to prod (bundle, or instance to instance) | `grok s pull ... --out ./bundle` / `grok s migrate ... --from dev --to prod` |
|
|
@@ -217,6 +218,7 @@ grants inherited through the entity's project links (`inherited: true`).
|
|
|
217
218
|
grok s functions run 'Chem:smilesToMw("CCO")' # positional args
|
|
218
219
|
grok s functions run 'Pkg:fn({smiles:"CCO", radius:2})' # named args
|
|
219
220
|
grok s functions run Pkg:fn --json params.json # big input from a file
|
|
221
|
+
grok s functions run 'MyPkg:MyQuery()' --debug # a debug call: the query's own log on stderr
|
|
220
222
|
```
|
|
221
223
|
|
|
222
224
|
The server binds arguments by parameter name, so positional values are mapped onto the
|
|
@@ -497,6 +499,20 @@ module the server does not report exits 1. Requires a valid dev key (standard `g
|
|
|
497
499
|
For an anonymous liveness probe — load balancer, k8s readiness — hit `/admin/health` directly;
|
|
498
500
|
it's on the server's unauthenticated allowlist.
|
|
499
501
|
|
|
502
|
+
### Server status
|
|
503
|
+
|
|
504
|
+
```bash
|
|
505
|
+
grok s status # build, uptime, DB pool, HTTP connections
|
|
506
|
+
grok s status --output json # {server, extended}
|
|
507
|
+
grok s status --output quiet # just the version
|
|
508
|
+
```
|
|
509
|
+
|
|
510
|
+
Reads `GET /info/server` and `GET /info/server?extended=true`: `Version`, `Branch`, `Commit`,
|
|
511
|
+
build `Date`, `Uptime`, `Requests` served, `Used Connections` / `Pool Connections` of the DB pool,
|
|
512
|
+
`Isolate`, `Service network`, `webRoot`, and the `Http Server` connection counts. For an admin the
|
|
513
|
+
extended call replaces the active-connection count with the requests in flight per endpoint
|
|
514
|
+
(`{"GET /api/...": n}`), printed as a table; for anyone else the two responses are the same.
|
|
515
|
+
|
|
500
516
|
## Problems, logging and errors (`grok s observe`, alias `grok s o`)
|
|
501
517
|
|
|
502
518
|
Thin commands over the server's routes; `grok s observe` with no command prints every verb and option.
|
|
@@ -506,6 +522,7 @@ grok s o problems list --alert-status open # the open alerts; --
|
|
|
506
522
|
grok s o problems get 'health:Jupyter@<server>' # by id or kind:key; history <id> for its records
|
|
507
523
|
grok s o problems status connection:<connection id> --data '{"status": "muted", "reason": "maintenance", "until": "2026-10-04T06:00:00Z"}'
|
|
508
524
|
grok s o problems ack 'health:Jupyter@<server>' --reason x # resolve <id> --reason ... closes the alert
|
|
525
|
+
grok s o problems severity dashboard:<project id> critical --reason 'board meeting' # pin; none unpins
|
|
509
526
|
grok s o rules get > rules.json # Settings > Alerts problem rules; rules put --json rules.json
|
|
510
527
|
grok s o rules test # evaluates the saved rules once, now
|
|
511
528
|
grok s o logger get exportSettings # the logger settings, or one path of them
|
|
@@ -525,16 +542,67 @@ grok s o logs archive list --prefix cw/ --since 1d # keys in the log a
|
|
|
525
542
|
grok s o logs archive read <key> # one archived object decoded to events
|
|
526
543
|
grok s o logs container # docker containers and their status
|
|
527
544
|
grok s o logs container scripting-python_1 --since 1h --grep 'Kernel (started|shutdown)' # one container's log lines
|
|
545
|
+
grok s o logs match 'level in (error, warning) and not text ~ ResizeObserver' --since 2h # what a log filter matches
|
|
546
|
+
grok s o logs match --level error --package Chembl --grep 'time(d )?out' # flags add conditions joined by and; --grep is a regex
|
|
547
|
+
grok s o logs match --level audit --space Chem # audit of entities in the Chem space and its subspaces (case-sensitive)
|
|
548
|
+
grok s o logs match 'space startsWith Chem: or space endsWith :Assays' # space: the entity's space path; = ~ =~ startsWith endsWith
|
|
549
|
+
grok s o groups # log groups (Settings > Logger): name, kind, levels, filter, where to
|
|
550
|
+
grok s o groups add --name Chembl --levels error,warning --filter 'package = Chembl' --to db,grafana:otlp
|
|
551
|
+
grok s o groups set Chembl --when 'level = error and package = Chembl' --scope session --for 15m --before 60s --flags db
|
|
552
|
+
grok s o groups set Chembl --enabled false # only the flags given change; groups rm Chembl deletes it
|
|
553
|
+
grok s o groups put --json groups.json # replace every log group (the GROK_PARAMETERS settings.logger.logGroups shape)
|
|
554
|
+
grok s o groups reset # back to the default groups; the audit group can only be switched off, not removed
|
|
555
|
+
grok s o endpoints # where groups can send records; endpoints rm grafana
|
|
556
|
+
grok s o logs activations # triggered groups on now; logs activations stop <group id> <key>
|
|
528
557
|
```
|
|
529
558
|
|
|
530
559
|
Problems need `ManageAlerts`, errors, another session's timeline and `logs cloud`/`logs archive` `ViewTelemetry`,
|
|
531
|
-
`rules test` both, logger and rules changes
|
|
560
|
+
`rules test` both, logger and rules changes, `groups`/`endpoints` changes, `logs activations stop` and `logs capture`
|
|
561
|
+
`EditPluginsSettings`; `logs match` and `logs activations` need `ViewTelemetry`, and changing the audit group or an
|
|
562
|
+
endpoint it sends to also needs `EditAuditLogging`. `logs match` takes the whole filter as one quoted argument; `--grep`
|
|
563
|
+
is a regex and `--space` matches the space and its subspaces, both case-sensitive, as `=~` is. `groups add|set|rm`
|
|
564
|
+
need a server that returns its default log groups; on an older one, replace them all with `groups put`. `capture` is an expiring
|
|
532
565
|
`userGroupSettings` entry with `saveHttpRequests` on (seeded from the All Users entry, with `usage` saved); on an entry
|
|
533
566
|
that already expires later it keeps that time. `capture stop` removes only an expiring entry that holds nothing but the
|
|
534
567
|
capture; for any other entry use `logger set --user <login> --remove`. Read what it recorded with
|
|
535
568
|
`timeline --session <id>`. `logs container` reads the container's latest `--limit` lines (20000) and only then cuts `--since`/`--from`/`--to` (UTC, matched across the container's own offset) and `--grep`, so a window older than those lines comes back empty: raise `--limit`. `logs archive list --since` filters only the page the server returned (`--limit`), so narrow
|
|
536
569
|
the listing with `--prefix` first. `logs` read with the server's AWS role, or with `--connection <id>`. In durations `m` means minutes (in `grok s pull --since` it means months).
|
|
537
570
|
|
|
571
|
+
### Logging one command (`--log`)
|
|
572
|
+
|
|
573
|
+
`logger set --user` changes what a user logs for a while; `--log` makes the server keep what the
|
|
574
|
+
requests of one command log, and prints it at the end. It works on every `grok s` command, `grok s o`
|
|
575
|
+
included:
|
|
576
|
+
|
|
577
|
+
```bash
|
|
578
|
+
grok s functions run UsageAnalysis:Groups --log # verbose: every level
|
|
579
|
+
grok s functions run UsageAnalysis:Groups --log verbose,db # and every SQL statement (the db debug flag)
|
|
580
|
+
grok s users list --log debug,storage,credentials # levels and flags; flags alone add debug
|
|
581
|
+
grok s functions run 'MyPkg:MyQuery()' --debug # the query's own debug log, plus errors and warnings
|
|
582
|
+
grok s users list --log --output json 2>log.jsonl # one JSON object per record
|
|
583
|
+
```
|
|
584
|
+
|
|
585
|
+
Every request of the command carries one `datlas-log-id` (a new UUID per command) and the spec in
|
|
586
|
+
`datlas-log`. A command is often several requests, and each can land on a different isolate and
|
|
587
|
+
server instance: each keeps what its request logged at the spec in memory, in a buffer for that id.
|
|
588
|
+
Those records never reach the database, the console or a sync destination, and what the server logs
|
|
589
|
+
the usual way does not change. When the command ends, `GET /log/requests/<logId>` gathers the
|
|
590
|
+
buffers from every isolate of every instance over the message queue, hands them over and forgets
|
|
591
|
+
them; the CLI prints them to stderr, so stdout keeps the result. The gather also adds what the
|
|
592
|
+
server saved the usual way for the command's session at the levels of the spec (errors, warnings, audit),
|
|
593
|
+
skipping copies of records it already has, so an instance that died before it could answer still
|
|
594
|
+
shows its saved errors. A buffer nobody gathers is dropped after an hour. No permission is needed; another user's id takes `ViewTelemetry`.
|
|
595
|
+
`grok s o logs request <logId>` gathers one id by hand.
|
|
596
|
+
|
|
597
|
+
The spec is comma-separated: `verbose`, `standard`, the levels (`error`, `warning`, `info`, `debug`,
|
|
598
|
+
`audit`, `usage`) and the debug flags of the logger settings (`db`, `socket`, `storage`, `credentials`,
|
|
599
|
+
`docker`, `auth`, ... or `all`).
|
|
600
|
+
|
|
601
|
+
`functions run --debug` sends `?debug=true`: the call runs as a debug call (not cached), the way the
|
|
602
|
+
query debugger in the UI runs it, and its own log (connection, the query's stages) is kept with the
|
|
603
|
+
rest; without `--log` the spec is `error,warning`. Only what runs in Datlas is kept: a script that
|
|
604
|
+
runs on a queue worker adds nothing here.
|
|
605
|
+
|
|
538
606
|
## Describing an entity type
|
|
539
607
|
|
|
540
608
|
```bash
|
package/README.md
CHANGED
|
@@ -151,3 +151,17 @@ For more information on configuring connections, refer to the [Connections](http
|
|
|
151
151
|
| debug | Sets a debug breakpoint before each test execution, allowing you to debug the test. Only works in `gui` mode |
|
|
152
152
|
|
|
153
153
|
- `link` command is used for public plugins development to link `datagrok-api` and libraries.
|
|
154
|
+
- `connect-folder` makes a local folder a Datagrok connection. A folder agent in Docker dials out to the server (no
|
|
155
|
+
inbound port) with a key of its own that can only serve this folder; your keypair (`grok login <server>` first)
|
|
156
|
+
never leaves the machine. Connecting the same folder again resumes the same connection. Requires Docker and the
|
|
157
|
+
"Connect local folders" permission.
|
|
158
|
+
|
|
159
|
+
```shell
|
|
160
|
+
grok connect-folder <folder> [--host <alias>] [--read-only] [--foreground] [--image <ref>] [--force]
|
|
161
|
+
grok connect-folder list [--host <alias>] [--output json]
|
|
162
|
+
grok connect-folder start|stop|logs <connection> [-f]
|
|
163
|
+
grok connect-folder rm <connection>
|
|
164
|
+
```
|
|
165
|
+
|
|
166
|
+
`<connection>` is the connection name, a connection id prefix (8+ characters), or the folder. `stop` keeps the
|
|
167
|
+
folder disconnected after a reboot; `rm` removes the container, the key and the connection.
|
package/bin/commands/api.js
CHANGED
|
@@ -26,18 +26,28 @@ const dbUiFile = 'db-ui.ts';
|
|
|
26
26
|
* (u2 is a relative-path dependency without a `dg` subpath export). */
|
|
27
27
|
const emsDgModule = '@datagrok-libraries/ems/src/dg';
|
|
28
28
|
|
|
29
|
-
/**
|
|
30
|
-
*
|
|
29
|
+
/** The platform's `StringUtils.toSingular` (ddt utils.dart): regular forms only; a noun already
|
|
30
|
+
* singular in `-is`/`-us`/`-ss` passes through. */
|
|
31
|
+
function singularizeTableName(name) {
|
|
32
|
+
if (name.length <= 2 || !name.endsWith('s') || /(ss|is|us)$/.test(name)) return name;
|
|
33
|
+
if (name.endsWith('ies') && name.length > 3) return name.slice(0, -3) + 'y';
|
|
34
|
+
return /(xes|zzes|ches|shes|sses|tuses)$/.test(name) ? name.slice(0, -2) : name.slice(0, -1);
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
/** The platform's `StringUtils.toPlural` (ddt utils.dart) — `issue` → `issues`, `box` →
|
|
38
|
+
* `boxes`, `category` → `categories`, `analysis` → `analyses`. */
|
|
31
39
|
function pluralizeTableName(name) {
|
|
40
|
+
if (name.endsWith('is')) return name.slice(0, -2) + 'es';
|
|
32
41
|
if (/(s|x|z|ch|sh)$/.test(name)) return name + 'es';
|
|
33
|
-
if (/[^
|
|
42
|
+
if (/[^aeiou]y$/.test(name)) return name.slice(0, -1) + 'ies';
|
|
34
43
|
return name + 's';
|
|
35
44
|
}
|
|
36
45
|
|
|
37
46
|
/** The camelCase plural property name a table gets on the schema client and under the
|
|
38
|
-
* schema handle's `tables` (`issue_label` → `issueLabels`)
|
|
47
|
+
* schema handle's `tables` (`issue_label` → `issueLabels`, `categories` → `categories`): the
|
|
48
|
+
* plural of the singular, as the platform derives a table's plural name. */
|
|
39
49
|
function tableProp(tableName) {
|
|
40
|
-
return utils.snakeToCamelCase(pluralizeTableName(tableName), false);
|
|
50
|
+
return utils.snakeToCamelCase(pluralizeTableName(singularizeTableName(tableName)), false);
|
|
41
51
|
}
|
|
42
52
|
const domainSchemaPath = _path.default.join(_path.default.dirname(_path.default.dirname(__dirname)), 'domain-schema.schema.json');
|
|
43
53
|
/** The platform's own schema, whose tables a qualified ref may target (`Core.users`, ...). */
|
|
@@ -277,7 +287,9 @@ function generateDomainSchemaCode(manifest, manifestPath, emittedTypes, packageD
|
|
|
277
287
|
// different sets fall back to a `<alias><PascalTable>` name (deterministic).
|
|
278
288
|
const choicesAliases = {};
|
|
279
289
|
const choicesAlias = (tableName, columnName, values) => {
|
|
280
|
-
|
|
290
|
+
// JSON.stringify escapes every special character; inside single quotes only ' needs one more
|
|
291
|
+
const literals = values.map(v => `'${JSON.stringify(v).slice(1, -1).replace(/'/g, `\\'`)}'`);
|
|
292
|
+
const valueSet = literals.join(' | ');
|
|
281
293
|
let alias = utils.snakeToCamelCase(tableName) + utils.snakeToCamelCase(columnName);
|
|
282
294
|
if (choicesAliases[alias] !== undefined && choicesAliases[alias] !== valueSet) alias += utils.snakeToCamelCase(tableName);
|
|
283
295
|
if (choicesAliases[alias] !== undefined && choicesAliases[alias] !== valueSet) {
|
|
@@ -286,7 +298,7 @@ function generateDomainSchemaCode(manifest, manifestPath, emittedTypes, packageD
|
|
|
286
298
|
}
|
|
287
299
|
if (choicesAliases[alias] === undefined) {
|
|
288
300
|
choicesAliases[alias] = valueSet;
|
|
289
|
-
decls.push(wrapTokens(`export type ${alias} = `,
|
|
301
|
+
decls.push(wrapTokens(`export type ${alias} = `, literals, ' | ', ';'));
|
|
290
302
|
}
|
|
291
303
|
return alias;
|
|
292
304
|
};
|
|
@@ -364,6 +376,7 @@ function generateDomainSchemaCode(manifest, manifestPath, emittedTypes, packageD
|
|
|
364
376
|
insertType: column.type === 'datetime' ? 'Dayjs | string' : tsType,
|
|
365
377
|
required: column.required === true,
|
|
366
378
|
autoNumber: column.autoNumber != null,
|
|
379
|
+
hasDefault: column.default != null,
|
|
367
380
|
ref: ref
|
|
368
381
|
});
|
|
369
382
|
return true;
|
|
@@ -380,6 +393,7 @@ function generateDomainSchemaCode(manifest, manifestPath, emittedTypes, packageD
|
|
|
380
393
|
}
|
|
381
394
|
return columns;
|
|
382
395
|
}
|
|
396
|
+
const accessorTables = new Map();
|
|
383
397
|
for (const tableName of tableNames) {
|
|
384
398
|
const typeName = utils.snakeToCamelCase(tableName);
|
|
385
399
|
if (emittedTypes.has(typeName)) {
|
|
@@ -387,6 +401,12 @@ function generateDomainSchemaCode(manifest, manifestPath, emittedTypes, packageD
|
|
|
387
401
|
return null;
|
|
388
402
|
}
|
|
389
403
|
emittedTypes.add(typeName);
|
|
404
|
+
const accessor = tableProp(tableName);
|
|
405
|
+
if (accessorTables.has(accessor)) {
|
|
406
|
+
color.error(`${manifestPath}: tables '${accessorTables.get(accessor)}' and '${tableName}' ` + `both get the accessor '${accessor}' (rename one of them)`);
|
|
407
|
+
return null;
|
|
408
|
+
}
|
|
409
|
+
accessorTables.set(accessor, tableName);
|
|
390
410
|
const columns = collectColumns(tableName, manifest, false);
|
|
391
411
|
if (columns == null) return null;
|
|
392
412
|
tableColumns[tableName] = columns;
|
|
@@ -436,7 +456,7 @@ function generateDomainSchemaCode(manifest, manifestPath, emittedTypes, packageD
|
|
|
436
456
|
rowLines.push('}');
|
|
437
457
|
decls.push(rowLines.join(sep));
|
|
438
458
|
const insertLines = [`/** Insert payload for \`${manifest.name}.${tableName}\`. */`, `export interface ${typeName}Insert {`];
|
|
439
|
-
for (const c of columns) insertLines.push(` ${c.name}${c.required ? '' : '?'}: ${c.insertType};`);
|
|
459
|
+
for (const c of columns) insertLines.push(` ${c.name}${c.required && !c.hasDefault ? '' : '?'}: ${c.insertType};`);
|
|
440
460
|
for (const r of relations) insertLines.push(` /** Link set: \`${r.target}\` row ids. */`, ` ${r.name}?: string[];`);
|
|
441
461
|
if (table.idempotency === true) insertLines.push(' idempotencyKey?: string;');
|
|
442
462
|
insertLines.push('}');
|
|
@@ -476,6 +496,7 @@ function generateDomainSchemaCode(manifest, manifestPath, emittedTypes, packageD
|
|
|
476
496
|
}
|
|
477
497
|
decls.push(expandEntries.length === 0 ? `export type ${typeName}Expand = {};` : [`/** Expand keys of \`${manifest.name}.${tableName}\` → fields each adds to the row ` + `(consumed by query()/builder). */`, `export type ${typeName}Expand = {`, ...expandEntries, '};'].join(sep));
|
|
478
498
|
if (!external) txArms.push(` {op: 'insert'; table: '${tableName}'; ref?: string; values: DG.DomainTxValues<${typeName}Insert>; ` + `onDuplicate?: 'error'} |`, ` {op: 'update'; table: '${tableName}'; id: string; ` + `values: DG.DomainTxValues<${relations.length > 0 ? `${typeName}Update` : `Partial<${typeName}Row>`}>; ` + `expectedVersion?: number} |`, ` {op: 'delete'; table: '${tableName}'; id: string} |`);
|
|
499
|
+
if (!external && table.softDelete !== false) txArms.push(` {op: 'restore'; table: '${tableName}'; id: string} |`);
|
|
479
500
|
|
|
480
501
|
// No datetime config: the client resolves datetime columns from the domain
|
|
481
502
|
// registry itself (the Dayjs typing in <Table>Row stays true for every client).
|
package/bin/commands/check.js
CHANGED
|
@@ -13,6 +13,7 @@ exports.checkImportStatements = checkImportStatements;
|
|
|
13
13
|
exports.checkNpmIgnore = checkNpmIgnore;
|
|
14
14
|
exports.checkPackageFile = checkPackageFile;
|
|
15
15
|
exports.checkSourceMap = checkSourceMap;
|
|
16
|
+
exports.checkU2Usage = checkU2Usage;
|
|
16
17
|
exports.extractExternals = extractExternals;
|
|
17
18
|
var _fs = _interopRequireDefault(require("fs"));
|
|
18
19
|
var _path = _interopRequireDefault(require("path"));
|
|
@@ -20,6 +21,7 @@ var _ignoreWalk = _interopRequireDefault(require("ignore-walk"));
|
|
|
20
21
|
var utils = _interopRequireWildcard(require("../utils/utils"));
|
|
21
22
|
var color = _interopRequireWildcard(require("../utils/color-utils"));
|
|
22
23
|
var _const = require("../utils/const");
|
|
24
|
+
var _child_process = require("child_process");
|
|
23
25
|
function _interopRequireWildcard(e, t) { if ("function" == typeof WeakMap) var r = new WeakMap(), n = new WeakMap(); return (_interopRequireWildcard = function (e, t) { if (!t && e && e.__esModule) return e; var o, i, f = { __proto__: null, default: e }; if (null === e || "object" != typeof e && "function" != typeof e) return f; if (o = t ? n : r) { if (o.has(e)) return o.get(e); o.set(e, f); } for (const t in e) "default" !== t && {}.hasOwnProperty.call(e, t) && ((i = (o = Object.defineProperty) && Object.getOwnPropertyDescriptor(e, t)) && (i.get || i.set) ? o(f, t, i) : f[t] = e[t]); return f; })(e, t); }
|
|
24
26
|
const warns = ['Latest package version', 'Datagrok API version should contain', 'is served by the platform'];
|
|
25
27
|
const forbiddenNames = ['function', 'class', 'export'];
|
|
@@ -91,6 +93,8 @@ function runChecks(packagePath, soft = false, noExit = false) {
|
|
|
91
93
|
if (externals) errors.push(...checkImportStatements(packagePath, jsTsFiles, externals));
|
|
92
94
|
}
|
|
93
95
|
errors.push(...checkDatagrokApiImports(packagePath, jsTsFiles));
|
|
96
|
+
const u2Errors = checkU2Usage(packagePath, json);
|
|
97
|
+
errors.push(...u2Errors);
|
|
94
98
|
warnings.push(...checkHeavyImports(packagePath, jsTsFiles, _path.default.basename(packagePath)));
|
|
95
99
|
if (!soft) errors.push(...checkSourceMap(packagePath));
|
|
96
100
|
errors.push(...checkNpmIgnore(packagePath));
|
|
@@ -111,7 +115,8 @@ function runChecks(packagePath, soft = false, noExit = false) {
|
|
|
111
115
|
if (errors.length) {
|
|
112
116
|
console.log(`Checking package ${_path.default.basename(packagePath)}...`);
|
|
113
117
|
showError(errors);
|
|
114
|
-
|
|
118
|
+
// the u2 consumer ratchet holds pre-1.0 packages too
|
|
119
|
+
if (soft || u2Errors.length === 0 && (json.version.startsWith('0') || errors.every(w => warns.some(ww => w.includes(ww))))) return true;
|
|
115
120
|
if (noExit) return false;else process.exit(1);
|
|
116
121
|
}
|
|
117
122
|
color.log(`Checking package ${_path.default.basename(packagePath)}...\t\t\t\u2713 OK`);
|
|
@@ -213,6 +218,43 @@ function checkDatagrokApiImports(packagePath, files) {
|
|
|
213
218
|
}
|
|
214
219
|
return errors;
|
|
215
220
|
}
|
|
221
|
+
|
|
222
|
+
/** u2's consumer check for a package built on u2 or ems: the u2 lint rules and the shrink-only counts of
|
|
223
|
+
* `consumers-baseline.json`. Prints the ratchet line; growth and enforced rules are errors. */
|
|
224
|
+
function checkU2Usage(packagePath, json) {
|
|
225
|
+
const deps = {
|
|
226
|
+
...json.dependencies,
|
|
227
|
+
...json.devDependencies
|
|
228
|
+
};
|
|
229
|
+
if (!('@datagrok-libraries/u2' in deps) && !('@datagrok-libraries/ems' in deps)) return [];
|
|
230
|
+
let script;
|
|
231
|
+
try {
|
|
232
|
+
script = _path.default.join(_path.default.dirname(require.resolve('@datagrok-libraries/u2/package.json', {
|
|
233
|
+
paths: [packagePath]
|
|
234
|
+
})), 'scripts', 'check-consumer.mjs');
|
|
235
|
+
} catch {
|
|
236
|
+
return [];
|
|
237
|
+
}
|
|
238
|
+
if (!_fs.default.existsSync(script)) return [];
|
|
239
|
+
const run = (0, _child_process.spawnSync)(process.execPath, [script, packagePath, '--json'], {
|
|
240
|
+
encoding: 'utf-8',
|
|
241
|
+
maxBuffer: 64 * 1024 * 1024,
|
|
242
|
+
timeout: 300000
|
|
243
|
+
});
|
|
244
|
+
let report;
|
|
245
|
+
try {
|
|
246
|
+
report = JSON.parse(run.stdout);
|
|
247
|
+
} catch {
|
|
248
|
+
return [`u2 consumer check could not run: ${(run.stderr || run.stdout || String(run.error)).trim()}`];
|
|
249
|
+
}
|
|
250
|
+
const errors = [];
|
|
251
|
+
for (const tree of report.trees) {
|
|
252
|
+
for (const line of tree.summary) console.log(line);
|
|
253
|
+
for (const note of tree.notes) color.log(` ${note}`, 'warn');
|
|
254
|
+
errors.push(...tree.problems);
|
|
255
|
+
}
|
|
256
|
+
return errors;
|
|
257
|
+
}
|
|
216
258
|
function checkHeavyImports(packagePath, files, packageName = '') {
|
|
217
259
|
const warnings = [];
|
|
218
260
|
const isTestPackage = /tests?$/i.test(packageName);
|