datagrok-tools 6.5.6 → 6.5.8
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/docker-compose.yaml +68 -24
- package/CHANGELOG.md +41 -6
- package/CLAUDE.md +35 -10
- package/Core.json +1027 -0
- package/GROK_S.md +563 -27
- package/bin/commands/api.js +121 -70
- package/bin/commands/help.js +3 -65
- package/bin/commands/server-domains.js +468 -0
- package/bin/commands/server-migrate.js +392 -0
- package/bin/commands/server.js +455 -92
- package/bin/grok.js +16 -5
- package/bin/utils/migrate/bundle.js +223 -0
- package/bin/utils/migrate/bundle.ts +222 -0
- package/bin/utils/migrate/parts.js +83 -0
- package/bin/utils/migrate/parts.ts +72 -0
- package/bin/utils/migrate/pool.js +17 -0
- package/bin/utils/migrate/pool.ts +13 -0
- package/bin/utils/migrate/pusher.js +980 -0
- package/bin/utils/migrate/pusher.ts +829 -0
- package/bin/utils/migrate/registry.js +349 -0
- package/bin/utils/migrate/registry.ts +255 -0
- package/bin/utils/migrate/rewriter.js +59 -0
- package/bin/utils/migrate/rewriter.ts +59 -0
- package/bin/utils/migrate/walker.js +571 -0
- package/bin/utils/migrate/walker.ts +509 -0
- package/bin/utils/node-dapi.js +787 -141
- package/bin/utils/playwright-runner.js +55 -39
- package/bin/utils/server-client.js +15 -2
- package/bin/utils/server-output.js +65 -4
- package/bin/utils/test-utils.js +1 -1
- package/domain-schema.schema.json +57 -6
- package/package.json +6 -1
- /package/{vitest.config.ts → vitest.config.mts} +0 -0
package/bin/commands/api.js
CHANGED
|
@@ -42,6 +42,11 @@ function tableProp(tableName) {
|
|
|
42
42
|
return utils.snakeToCamelCase(pluralizeTableName(tableName), false);
|
|
43
43
|
}
|
|
44
44
|
const domainSchemaPath = _path.default.join(_path.default.dirname(_path.default.dirname(__dirname)), 'domain-schema.schema.json');
|
|
45
|
+
/** The platform's own schema, whose tables a qualified ref may target (`Core.users`, ...). */
|
|
46
|
+
const CORE_SCHEMA = 'Core';
|
|
47
|
+
/** The sealed Core declaration (a copy of core/server/db/snapshots/Core.json, pinned equal by the
|
|
48
|
+
* server's seal test) — what a `ref: <CORE_SCHEMA>.<table>` resolves against at build time. */
|
|
49
|
+
const coreDeclarationPath = _path.default.join(_path.default.dirname(_path.default.dirname(__dirname)), `${CORE_SCHEMA}.json`);
|
|
45
50
|
const domainSystemColumns = [['id', 'string'], ['version', 'number'], ['created_on', 'Dayjs'], ['updated_on', 'Dayjs'], ['author_id', 'string']];
|
|
46
51
|
const domainTypeMap = {
|
|
47
52
|
string: 'string',
|
|
@@ -51,10 +56,22 @@ const domainTypeMap = {
|
|
|
51
56
|
datetime: 'Dayjs',
|
|
52
57
|
string_list: 'string[]',
|
|
53
58
|
ref: 'string',
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
file: 'string'
|
|
59
|
+
file: 'string',
|
|
60
|
+
json: '{[key: string]: any}'
|
|
57
61
|
};
|
|
62
|
+
|
|
63
|
+
/** `type: user` / `type: group` are aliases of a Core ref (the server's
|
|
64
|
+
* `DomainTableColumn.canonicalize`); codegen spells them the same way so both generate alike. */
|
|
65
|
+
const coreRefAliases = {
|
|
66
|
+
user: `${CORE_SCHEMA}.users`,
|
|
67
|
+
group: `${CORE_SCHEMA}.groups`
|
|
68
|
+
};
|
|
69
|
+
|
|
70
|
+
/** The sealed declaration lists a table's columns and a property schema's columns as
|
|
71
|
+
* `[{name, ...}]`; manifests key them by name. */
|
|
72
|
+
function columnsByName(columns) {
|
|
73
|
+
return Array.isArray(columns) ? Object.fromEntries(columns.map(c => [c.name, c])) : columns;
|
|
74
|
+
}
|
|
58
75
|
function normEol(s) {
|
|
59
76
|
return s.replace(/\r\n/g, '\n');
|
|
60
77
|
}
|
|
@@ -202,7 +219,7 @@ function generateDomainClients(packageDir = curDir, options) {
|
|
|
202
219
|
for (const err of validateManifest.errors ?? []) color.error(`${relPath}: ${err.instancePath || '/'} ${err.message}`);
|
|
203
220
|
return false;
|
|
204
221
|
}
|
|
205
|
-
const code = generateDomainSchemaCode(manifest, relPath, emittedTypes);
|
|
222
|
+
const code = generateDomainSchemaCode(manifest, relPath, emittedTypes, packageDir);
|
|
206
223
|
if (code == null) return false;
|
|
207
224
|
parts.push(code);
|
|
208
225
|
if (ui) uiParts.push(generateDomainUiCode(manifest, dbImports));
|
|
@@ -220,6 +237,26 @@ function generateDomainClients(packageDir = curDir, options) {
|
|
|
220
237
|
}
|
|
221
238
|
return true;
|
|
222
239
|
}
|
|
240
|
+
/** Subdirectory names of [dir], or none when it does not exist. */
|
|
241
|
+
function subdirs(dir) {
|
|
242
|
+
return _fs.default.existsSync(dir) ? _fs.default.readdirSync(dir, {
|
|
243
|
+
withFileTypes: true
|
|
244
|
+
}).filter(e => e.isDirectory()).map(e => e.name) : [];
|
|
245
|
+
}
|
|
246
|
+
|
|
247
|
+
/** The `databases/<schema>/schema.json` manifest named [schemaName] among the package's
|
|
248
|
+
* installed dependencies (scoped packages included), or null. */
|
|
249
|
+
function findDependencyManifest(packageDir, schemaName) {
|
|
250
|
+
const nm = _path.default.join(packageDir, 'node_modules');
|
|
251
|
+
const pkgDirs = subdirs(nm).flatMap(d => d.startsWith('@') ? subdirs(_path.default.join(nm, d)).map(s => _path.default.join(nm, d, s)) : [_path.default.join(nm, d)]);
|
|
252
|
+
for (const pkgDir of pkgDirs) for (const schemaDir of subdirs(_path.default.join(pkgDir, 'databases'))) {
|
|
253
|
+
const manifestPath = _path.default.join(pkgDir, 'databases', schemaDir, 'schema.json');
|
|
254
|
+
if (!_fs.default.existsSync(manifestPath)) continue;
|
|
255
|
+
const manifest = JSON.parse(_fs.default.readFileSync(manifestPath, 'utf8'));
|
|
256
|
+
if (manifest.name === schemaName) return manifest;
|
|
257
|
+
}
|
|
258
|
+
return null;
|
|
259
|
+
}
|
|
223
260
|
|
|
224
261
|
/** A resolved many-to-many relation of one table: the expand key and the target
|
|
225
262
|
* table whose row ids its write-side link set carries. */
|
|
@@ -227,10 +264,12 @@ function generateDomainClients(packageDir = curDir, options) {
|
|
|
227
264
|
/** Emits choices aliases, row/insert interfaces, column-name unions, expand maps, the
|
|
228
265
|
* `<Schema>TransactionOp` union, and the lazy `<schema>Db` clients for one manifest.
|
|
229
266
|
* Returns null on a semantic error (reported to the console). */
|
|
230
|
-
function generateDomainSchemaCode(manifest, manifestPath, emittedTypes) {
|
|
267
|
+
function generateDomainSchemaCode(manifest, manifestPath, emittedTypes, packageDir) {
|
|
231
268
|
const decls = [];
|
|
232
269
|
const systemColumnNames = new Set(domainSystemColumns.map(([name]) => name));
|
|
233
270
|
const tableNames = Object.keys(manifest.tables);
|
|
271
|
+
// Keyed by table name; a qualified ref target ('Core.queries', 'grit.issue') lands here
|
|
272
|
+
// under its qualified key so the expand map can list its columns — it gets no accessor.
|
|
234
273
|
const tableColumns = {};
|
|
235
274
|
// Choices aliases are deduplicated by name: identical value sets share the first alias,
|
|
236
275
|
// different sets fall back to a `<alias><PascalTable>` name (deterministic).
|
|
@@ -250,57 +289,112 @@ function generateDomainSchemaCode(manifest, manifestPath, emittedTypes) {
|
|
|
250
289
|
return alias;
|
|
251
290
|
};
|
|
252
291
|
|
|
253
|
-
//
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
if (
|
|
258
|
-
|
|
259
|
-
|
|
292
|
+
// A qualified ref target, resolved from files: `Core.<table>` from the CLI's sealed Core
|
|
293
|
+
// declaration, any other schema from a dependency's databases/*/schema.json.
|
|
294
|
+
const externalManifests = new Map();
|
|
295
|
+
function loadExternalTable(ref, where) {
|
|
296
|
+
if (tableColumns[ref] != null) return true;
|
|
297
|
+
const [schemaName, tableName] = ref.split('.');
|
|
298
|
+
const core = schemaName === CORE_SCHEMA;
|
|
299
|
+
if (!externalManifests.has(schemaName)) externalManifests.set(schemaName, core ? _fs.default.existsSync(coreDeclarationPath) ? JSON.parse(_fs.default.readFileSync(coreDeclarationPath, 'utf8')) : null : findDependencyManifest(packageDir, schemaName));
|
|
300
|
+
const owner = externalManifests.get(schemaName);
|
|
301
|
+
if (owner == null) {
|
|
302
|
+
color.error(`${where} references '${ref}', but ` + (core ? `the sealed ${CORE_SCHEMA} declaration is missing: ${coreDeclarationPath}` : `no installed dependency declares schema '${schemaName}' — install the package that declares ` + `schema '${schemaName}' as a dependency`));
|
|
303
|
+
return false;
|
|
260
304
|
}
|
|
261
|
-
|
|
305
|
+
if (owner.tables[tableName] == null) {
|
|
306
|
+
color.error(`${where} references '${ref}', but schema '${schemaName}' declares no table '${tableName}'`);
|
|
307
|
+
return false;
|
|
308
|
+
}
|
|
309
|
+
const columns = collectColumns(tableName, {
|
|
310
|
+
...owner,
|
|
311
|
+
name: schemaName
|
|
312
|
+
}, true);
|
|
313
|
+
if (columns == null) return false;
|
|
314
|
+
tableColumns[ref] = columns;
|
|
315
|
+
return true;
|
|
316
|
+
}
|
|
317
|
+
|
|
318
|
+
// Pass 1: resolve every table's full column list (relational + property-schema columns).
|
|
319
|
+
// [owner] is the manifest the table comes from; an external (qualified-ref target) table
|
|
320
|
+
// skips the system-column check — its declaration may legitimately name one (Core.packages
|
|
321
|
+
// has `version`) — and its own refs are never followed (no nested expand).
|
|
322
|
+
function collectColumns(tableName, owner, external) {
|
|
323
|
+
const table = owner.tables[tableName];
|
|
324
|
+
const key = external ? `${owner.name}.${tableName}` : tableName;
|
|
262
325
|
const columns = [];
|
|
263
|
-
const columnNames = new Set(systemColumnNames);
|
|
326
|
+
const columnNames = new Set(external ? [] : systemColumnNames);
|
|
264
327
|
const addColumn = (name, column) => {
|
|
328
|
+
if (coreRefAliases[column.type] != null) {
|
|
329
|
+
column = {
|
|
330
|
+
...column,
|
|
331
|
+
type: 'ref',
|
|
332
|
+
ref: coreRefAliases[column.type]
|
|
333
|
+
};
|
|
334
|
+
delete column.onDelete;
|
|
335
|
+
}
|
|
265
336
|
if (columnNames.has(name)) {
|
|
266
|
-
color.error(systemColumnNames.has(name) ? `${manifestPath}: table '${
|
|
337
|
+
color.error(systemColumnNames.has(name) && !external ? `${manifestPath}: table '${key}' column '${name}' collides with a generated system column` : `${manifestPath}: table '${key}' declares duplicate column '${name}'`);
|
|
267
338
|
return false;
|
|
268
339
|
}
|
|
269
340
|
columnNames.add(name);
|
|
270
341
|
let tsType = domainTypeMap[column.type];
|
|
271
342
|
if (Array.isArray(column.choices) && column.choices.length > 0) {
|
|
272
|
-
const alias = choicesAlias(
|
|
343
|
+
const alias = choicesAlias(key.replace('.', '_'), name, column.choices);
|
|
273
344
|
if (alias == null) return false;
|
|
274
345
|
tsType = alias;
|
|
275
346
|
}
|
|
347
|
+
let ref;
|
|
348
|
+
if (column.type === 'ref' && !external) {
|
|
349
|
+
if (column.ref == null) {
|
|
350
|
+
color.error(`${manifestPath}: table '${tableName}' column '${name}' is a ref column without a 'ref' target`);
|
|
351
|
+
return false;
|
|
352
|
+
}
|
|
353
|
+
if (column.ref.includes('.')) {
|
|
354
|
+
if (!loadExternalTable(column.ref, `${manifestPath}: table '${tableName}' column '${name}'`)) return false;
|
|
355
|
+
ref = column.ref;
|
|
356
|
+
} else if (manifest.tables[column.ref] != null) ref = column.ref;
|
|
357
|
+
}
|
|
276
358
|
columns.push({
|
|
277
359
|
name: name,
|
|
278
360
|
rawType: column.type,
|
|
279
361
|
tsType: tsType,
|
|
280
362
|
insertType: column.type === 'datetime' ? 'Dayjs | string' : tsType,
|
|
281
363
|
required: column.required === true,
|
|
282
|
-
|
|
364
|
+
autoNumber: column.autoNumber != null,
|
|
365
|
+
ref: ref
|
|
283
366
|
});
|
|
284
367
|
return true;
|
|
285
368
|
};
|
|
286
|
-
|
|
369
|
+
const declared = columnsByName(table.columns);
|
|
370
|
+
for (const columnName of Object.keys(declared)) if (!addColumn(columnName, declared[columnName])) return null;
|
|
287
371
|
for (const schemaName of table.schemas ?? []) {
|
|
288
|
-
const props =
|
|
372
|
+
const props = columnsByName(owner.propertySchemas?.[schemaName]);
|
|
289
373
|
if (props == null) {
|
|
290
|
-
color.error(`${manifestPath}: table '${
|
|
374
|
+
color.error(`${manifestPath}: table '${key}' references unknown property schema '${schemaName}'`);
|
|
291
375
|
return null;
|
|
292
376
|
}
|
|
293
377
|
for (const propName of Object.keys(props)) if (!addColumn(propName, props[propName])) return null;
|
|
294
378
|
}
|
|
379
|
+
return columns;
|
|
380
|
+
}
|
|
381
|
+
for (const tableName of tableNames) {
|
|
382
|
+
const typeName = utils.snakeToCamelCase(tableName);
|
|
383
|
+
if (emittedTypes.has(typeName)) {
|
|
384
|
+
color.error(`${manifestPath}: table '${tableName}' emits interface '${typeName}Row' ` + `already generated for another table (table names must be unique across the package's manifests)`);
|
|
385
|
+
return null;
|
|
386
|
+
}
|
|
387
|
+
emittedTypes.add(typeName);
|
|
388
|
+
const columns = collectColumns(tableName, manifest, false);
|
|
389
|
+
if (columns == null) return null;
|
|
295
390
|
tableColumns[tableName] = columns;
|
|
296
391
|
}
|
|
297
392
|
|
|
298
|
-
// Pass 1.5:
|
|
299
|
-
//
|
|
300
|
-
//
|
|
301
|
-
//
|
|
302
|
-
//
|
|
303
|
-
// that key is what keeps re-linking the same pair idempotent.
|
|
393
|
+
// Pass 1.5: declared many-to-many relations. Only what the generated code needs
|
|
394
|
+
// is checked here: the target table must be declared (its name lands in the
|
|
395
|
+
// generated doc comments) and the name must not collide with a column (relations
|
|
396
|
+
// and columns share one expand/filter namespace). Everything else about a
|
|
397
|
+
// relation (via, viaSelf/viaTarget, the junction business key) is the deploy's gate.
|
|
304
398
|
const tableRelations = {};
|
|
305
399
|
for (const tableName of tableNames) {
|
|
306
400
|
const relations = [];
|
|
@@ -315,53 +409,10 @@ function generateDomainSchemaCode(manifest, manifestPath, emittedTypes) {
|
|
|
315
409
|
color.error(`${where} collides with a column of '${tableName}' — relations and columns ` + `share one expand/filter namespace`);
|
|
316
410
|
return null;
|
|
317
411
|
}
|
|
318
|
-
if (manifest.tables[r.via] == null) {
|
|
319
|
-
color.error(`${where}: junction table '${r.via}' is not declared in this manifest`);
|
|
320
|
-
return null;
|
|
321
|
-
}
|
|
322
412
|
if (manifest.tables[r.target] == null) {
|
|
323
413
|
color.error(`${where}: target table '${r.target}' is not declared in this manifest`);
|
|
324
414
|
return null;
|
|
325
415
|
}
|
|
326
|
-
if (r.via === tableName || r.via === r.target) {
|
|
327
|
-
color.error(`${where}: junction table '${r.via}' must differ from the owner and the target table`);
|
|
328
|
-
return null;
|
|
329
|
-
}
|
|
330
|
-
if (r.target === tableName && (r.viaSelf == null || r.viaTarget == null)) {
|
|
331
|
-
color.error(`${where}: a self-referential relation must name both 'viaSelf' and 'viaTarget'`);
|
|
332
|
-
return null;
|
|
333
|
-
}
|
|
334
|
-
// One side of the junction: the declared column when explicit, otherwise
|
|
335
|
-
// the single ref column of `via` pointing at `to`.
|
|
336
|
-
const resolveSide = (key, explicit, to) => {
|
|
337
|
-
const candidates = tableColumns[r.via].filter(c => c.ref === to).map(c => c.name);
|
|
338
|
-
if (explicit != null) {
|
|
339
|
-
if (candidates.includes(explicit)) return explicit;
|
|
340
|
-
color.error(`${where}: '${explicit}' is not a ref column of junction table '${r.via}' ` + `targeting '${to}'`);
|
|
341
|
-
return null;
|
|
342
|
-
}
|
|
343
|
-
if (candidates.length === 0) {
|
|
344
|
-
color.error(`${where}: junction table '${r.via}' has no ref column targeting '${to}'`);
|
|
345
|
-
return null;
|
|
346
|
-
}
|
|
347
|
-
if (candidates.length > 1) {
|
|
348
|
-
color.error(`${where}: junction table '${r.via}' has more than one ref column targeting ` + `'${to}' (${candidates.join(', ')}) — declare '${key}' explicitly`);
|
|
349
|
-
return null;
|
|
350
|
-
}
|
|
351
|
-
return candidates[0];
|
|
352
|
-
};
|
|
353
|
-
const viaSelf = resolveSide('viaSelf', r.viaSelf, tableName);
|
|
354
|
-
const viaTarget = resolveSide('viaTarget', r.viaTarget, r.target);
|
|
355
|
-
if (viaSelf == null || viaTarget == null) return null;
|
|
356
|
-
if (viaSelf === viaTarget) {
|
|
357
|
-
color.error(`${where}: 'viaSelf' and 'viaTarget' must be different columns of '${r.via}'`);
|
|
358
|
-
return null;
|
|
359
|
-
}
|
|
360
|
-
const businessKey = manifest.tables[r.via].businessKey ?? [];
|
|
361
|
-
if (!businessKey.includes(viaSelf) || !businessKey.includes(viaTarget)) {
|
|
362
|
-
color.error(`${where}: junction table '${r.via}' must declare a 'businessKey' containing ` + `both '${viaSelf}' and '${viaTarget}', so linking the same pair twice stays idempotent`);
|
|
363
|
-
return null;
|
|
364
|
-
}
|
|
365
416
|
relations.push({
|
|
366
417
|
name: name,
|
|
367
418
|
target: r.target
|
|
@@ -379,7 +430,7 @@ function generateDomainSchemaCode(manifest, manifestPath, emittedTypes) {
|
|
|
379
430
|
const relations = tableRelations[tableName];
|
|
380
431
|
const rowLines = [`/** Row of \`${manifest.name}.${tableName}\`. */`, `export interface ${typeName}Row {`];
|
|
381
432
|
for (const [name, tsType] of domainSystemColumns) rowLines.push(` ${name}: ${tsType};`);
|
|
382
|
-
for (const c of columns) rowLines.push(` ${c.name}${c.required ? '' : '?'}: ${c.tsType};`);
|
|
433
|
+
for (const c of columns) rowLines.push(` ${c.name}${c.required || c.autoNumber ? '' : '?'}: ${c.tsType};`);
|
|
383
434
|
rowLines.push('}');
|
|
384
435
|
decls.push(rowLines.join(sep));
|
|
385
436
|
const insertLines = [`/** Insert payload for \`${manifest.name}.${tableName}\`. */`, `export interface ${typeName}Insert {`];
|
package/bin/commands/help.js
CHANGED
|
@@ -4,6 +4,7 @@ Object.defineProperty(exports, "__esModule", {
|
|
|
4
4
|
value: true
|
|
5
5
|
});
|
|
6
6
|
exports.help = void 0;
|
|
7
|
+
var _server = require("./server");
|
|
7
8
|
const HELP = `
|
|
8
9
|
Usage: grok <command>
|
|
9
10
|
|
|
@@ -391,69 +392,6 @@ Examples:
|
|
|
391
392
|
|
|
392
393
|
The instance name must match a server alias in ~/.grok/config.yaml.
|
|
393
394
|
`;
|
|
394
|
-
const HELP_SERVER = `
|
|
395
|
-
Usage: grok server <entity> <verb> [args] [options]
|
|
396
|
-
grok s <entity> <verb> [args] [options]
|
|
397
|
-
|
|
398
|
-
Manage a Datagrok server from the command line.
|
|
399
|
-
|
|
400
|
-
Entities:
|
|
401
|
-
users, groups, functions, connections, queries, scripts, packages, reports, files, tables
|
|
402
|
-
|
|
403
|
-
Verbs:
|
|
404
|
-
list List entities
|
|
405
|
-
get Get a single entity by ID or name
|
|
406
|
-
delete Delete an entity by ID
|
|
407
|
-
|
|
408
|
-
Special commands:
|
|
409
|
-
grok s functions run <Name:func(args)> Call a function
|
|
410
|
-
grok s functions list [--type <t>] [--language <l>] [--package <p>] [--filter <expr>]
|
|
411
|
-
Type: script|query|function|package; language applies to scripts
|
|
412
|
-
grok s files list [path] [-r] List files (recursive with -r)
|
|
413
|
-
grok s shares add <entity> <group>[,<group>...] [--access View|Edit]
|
|
414
|
-
Share an entity with groups
|
|
415
|
-
grok s shares list <entity-id> List who an entity (UUID) is shared with
|
|
416
|
-
grok s users save --json user.json Create or update a user from JSON
|
|
417
|
-
grok s users block <id-or-login> Block a user from the platform
|
|
418
|
-
grok s users unblock <id-or-login> Unblock a previously blocked user
|
|
419
|
-
grok s groups save --json group.json [--save-relations]
|
|
420
|
-
Create or update a group from JSON
|
|
421
|
-
grok s connections save --json conn.json [--save-credentials]
|
|
422
|
-
Create or update a connection from JSON
|
|
423
|
-
grok s connections test <id-or-name> Test connectivity of an existing connection
|
|
424
|
-
grok s connections test --json conn.json Test connectivity of a connection defined in JSON
|
|
425
|
-
grok s tables upload <name> <file.csv> Upload a CSV as a Datagrok table
|
|
426
|
-
grok s tables download <name-or-id> [-O <file>] Download a table as CSV (stdout by default)
|
|
427
|
-
grok s raw <METHOD> <path> Hit any API endpoint
|
|
428
|
-
grok s describe <entity-type> Show entity JSON schema
|
|
429
|
-
|
|
430
|
-
Options:
|
|
431
|
-
--host <alias|url> Server alias from config or full URL
|
|
432
|
-
--output <format> Output format: table (default), json, csv, quiet
|
|
433
|
-
--filter <text> Smart filter expression
|
|
434
|
-
--limit <n> Page size (default: 50)
|
|
435
|
-
--offset <n> Start offset (default: 0)
|
|
436
|
-
-r, --recursive Recursive (for files list)
|
|
437
|
-
--json <file> Read function parameters from JSON file
|
|
438
|
-
|
|
439
|
-
Examples:
|
|
440
|
-
grok s users list
|
|
441
|
-
grok s connections list --filter "PostgreSQL" --output json
|
|
442
|
-
grok s connections get <id>
|
|
443
|
-
grok s connections delete <id>
|
|
444
|
-
grok s connections save --json conn.json --save-credentials
|
|
445
|
-
grok s connections test "JohnDoe:MyConnection"
|
|
446
|
-
grok s connections test --json conn.json
|
|
447
|
-
grok s users save --json user.json
|
|
448
|
-
grok s groups save --json group.json --save-relations
|
|
449
|
-
grok s shares add "JohnDoe:MyConnection" Chemists,Admins --access Edit
|
|
450
|
-
grok s shares list <entity-uuid>
|
|
451
|
-
grok s functions run 'Chem:smilesToMw("ccc")'
|
|
452
|
-
grok s files list "System:AppData" -r
|
|
453
|
-
grok s raw GET /api/users/current
|
|
454
|
-
grok s describe connections
|
|
455
|
-
grok s users list --host dev
|
|
456
|
-
`;
|
|
457
395
|
const help = exports.help = {
|
|
458
396
|
add: HELP_ADD,
|
|
459
397
|
api: HELP_API,
|
|
@@ -471,7 +409,7 @@ const help = exports.help = {
|
|
|
471
409
|
test: HELP_TEST,
|
|
472
410
|
testall: HELP_TESTALL,
|
|
473
411
|
migrate: HELP_MIGRATE,
|
|
474
|
-
server: HELP_SERVER,
|
|
475
|
-
s: HELP_SERVER,
|
|
412
|
+
server: _server.HELP_SERVER,
|
|
413
|
+
s: _server.HELP_SERVER,
|
|
476
414
|
help: HELP
|
|
477
415
|
};
|