zinkee 0.1.33 → 0.1.35
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 +9 -1
- package/dist/index.js +162 -33
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
- package/src/api/records.ts +17 -7
- package/src/commands/records.test.ts +101 -9
- package/src/commands/records.ts +97 -14
- package/src/utils/examples.test.ts +4 -2
- package/src/utils/examples.ts +84 -21
package/README.md
CHANGED
|
@@ -279,13 +279,16 @@ Notes:
|
|
|
279
279
|
### CRUD operations
|
|
280
280
|
|
|
281
281
|
```bash
|
|
282
|
-
# Create
|
|
282
|
+
# Create a single record (--set/--set-json/--raw/--raw-file build one record)
|
|
283
283
|
zinkee records create projects \
|
|
284
284
|
--set name="Website Redesign" \
|
|
285
285
|
--set budget=25000 \
|
|
286
286
|
--set start-date="2026-01-15T00:00:00.000Z" \
|
|
287
287
|
--set status=1
|
|
288
288
|
|
|
289
|
+
# Create many records from a JSON array file (one object per record; mutually exclusive with the single-record flags)
|
|
290
|
+
zinkee --json records create projects --records-file ./projects.json
|
|
291
|
+
|
|
289
292
|
# List and query
|
|
290
293
|
zinkee --json records list projects --limit 50
|
|
291
294
|
zinkee --json records query projects --limit 10 --sort "_id:desc"
|
|
@@ -299,6 +302,11 @@ zinkee --json records get projects <record-uuid>
|
|
|
299
302
|
# Update
|
|
300
303
|
zinkee records update projects <record-uuid> --set status=2
|
|
301
304
|
|
|
305
|
+
# Reference fields: pass the target record id (bare UUID or "recordId::label" — the label is
|
|
306
|
+
# ignored) or an exact display value. The server stores the canonical "recordId::displayValue"
|
|
307
|
+
# and rejects unknown references (reason "data_field_reference_not_found").
|
|
308
|
+
zinkee records create deals --set deal-name="Acme renewal" --set customer-ref=<target-record-uuid>
|
|
309
|
+
|
|
302
310
|
# Delete one or more records (--record is repeatable)
|
|
303
311
|
zinkee records delete projects --record <record-uuid> --record <record-uuid>
|
|
304
312
|
|
package/dist/index.js
CHANGED
|
@@ -2832,35 +2832,78 @@ var specificExamples = {
|
|
|
2832
2832
|
]),
|
|
2833
2833
|
"records create": buildCommandExamples([
|
|
2834
2834
|
{
|
|
2835
|
-
description: "
|
|
2835
|
+
description: "Create a single record with --set/--set-json (the single-record flags build one record, sent as a one-element 'records' array).",
|
|
2836
2836
|
command: `zinkee --json records create contacts --set contact-name="Ada Lovelace" --set contact-email=ada@example.com`,
|
|
2837
2837
|
raw: `{
|
|
2838
|
-
"
|
|
2839
|
-
|
|
2840
|
-
|
|
2841
|
-
|
|
2838
|
+
"records": [
|
|
2839
|
+
{
|
|
2840
|
+
"contact-name": "Ada Lovelace",
|
|
2841
|
+
"contact-email": "ada@example.com"
|
|
2842
|
+
}
|
|
2843
|
+
]
|
|
2842
2844
|
}`,
|
|
2843
2845
|
response: `{
|
|
2844
|
-
"
|
|
2845
|
-
|
|
2846
|
-
|
|
2847
|
-
|
|
2848
|
-
}
|
|
2846
|
+
"created": [
|
|
2847
|
+
"550e8400-e29b-41d4-a716-446655440000"
|
|
2848
|
+
],
|
|
2849
|
+
"errors": []
|
|
2849
2850
|
}`
|
|
2850
2851
|
},
|
|
2851
2852
|
{
|
|
2852
|
-
description: "Create a
|
|
2853
|
-
command: `zinkee --json records create contacts --
|
|
2853
|
+
description: "Create many records from a JSON array file (one object per record, slug -> value). Best-effort: valid records are created and invalid ones are reported per index in 'errors'. ReferenceField values accept the target record id (a bare UUID, or the compound 'recordId::anything' whose label is ignored) or an exact display value; the server stores the canonical 'recordId::displayValue'.",
|
|
2854
|
+
command: `zinkee --json records create contacts --records-file ./records.json`,
|
|
2854
2855
|
raw: `{
|
|
2855
|
-
"
|
|
2856
|
-
|
|
2857
|
-
|
|
2858
|
-
|
|
2859
|
-
|
|
2860
|
-
|
|
2861
|
-
|
|
2862
|
-
|
|
2863
|
-
|
|
2856
|
+
"records": [
|
|
2857
|
+
{
|
|
2858
|
+
"contact-name": "Ada Lovelace",
|
|
2859
|
+
"contact-email": "ada@example.com"
|
|
2860
|
+
},
|
|
2861
|
+
{
|
|
2862
|
+
"contact-name": "Grace Hopper",
|
|
2863
|
+
"contact-email": "grace@example.com",
|
|
2864
|
+
"status": 2,
|
|
2865
|
+
"amount": 1999.99,
|
|
2866
|
+
"due-date": "2026-06-01T09:00:00Z",
|
|
2867
|
+
"customer-ref": "8ad602a1-f6e3-43f6-9ab2-f1c5afc99621",
|
|
2868
|
+
"owner": "6c8a3e0d-4e5f-4a1b-9c2d-3e4f5a6b7c8d"
|
|
2869
|
+
}
|
|
2870
|
+
]
|
|
2871
|
+
}`,
|
|
2872
|
+
response: `{
|
|
2873
|
+
"created": [
|
|
2874
|
+
"550e8400-e29b-41d4-a716-446655440000"
|
|
2875
|
+
],
|
|
2876
|
+
"errors": [
|
|
2877
|
+
{
|
|
2878
|
+
"index": 1,
|
|
2879
|
+
"reason": "record_field_not_found",
|
|
2880
|
+
"message": "Field 'contact-emial' was not found in schema '2eb8bdcf-6d9c-4fbb-9018-7fa8180f4c5e'.",
|
|
2881
|
+
"action": "Use a valid field slug from the schema and retry."
|
|
2882
|
+
}
|
|
2883
|
+
]
|
|
2884
|
+
}`
|
|
2885
|
+
},
|
|
2886
|
+
{
|
|
2887
|
+
description: "Set a ReferenceField by the target record id (a bare UUID, or the compound 'recordId::anything' whose label is ignored) or by an exact display value. The server resolves and stores the canonical 'recordId::displayValue'. Unknown references are rejected per index with reason 'data_field_reference_not_found'.",
|
|
2888
|
+
command: `zinkee --json records create deals --set deal-name="Acme renewal" --set customer-ref=00000000-0000-0000-0000-000000000000`,
|
|
2889
|
+
raw: `{
|
|
2890
|
+
"records": [
|
|
2891
|
+
{
|
|
2892
|
+
"deal-name": "Acme renewal",
|
|
2893
|
+
"customer-ref": "00000000-0000-0000-0000-000000000000"
|
|
2894
|
+
}
|
|
2895
|
+
]
|
|
2896
|
+
}`,
|
|
2897
|
+
response: `{
|
|
2898
|
+
"created": [],
|
|
2899
|
+
"errors": [
|
|
2900
|
+
{
|
|
2901
|
+
"index": 0,
|
|
2902
|
+
"reason": "data_field_reference_not_found",
|
|
2903
|
+
"message": "Referenced record was not found in the target schema.",
|
|
2904
|
+
"action": "Use an existing record id or an existing display value for this reference field."
|
|
2905
|
+
}
|
|
2906
|
+
]
|
|
2864
2907
|
}`
|
|
2865
2908
|
}
|
|
2866
2909
|
]),
|
|
@@ -2902,6 +2945,22 @@ var specificExamples = {
|
|
|
2902
2945
|
command: "zinkee --json records update contacts 550e8400-e29b-41d4-a716-446655440000 --unset contact-email --unset due-date",
|
|
2903
2946
|
raw: `{
|
|
2904
2947
|
"unset": ["contact-email", "due-date"]
|
|
2948
|
+
}`
|
|
2949
|
+
},
|
|
2950
|
+
{
|
|
2951
|
+
description: "Set a ReferenceField on an existing record. Pass the target record id (a bare UUID, or the compound 'recordId::anything' whose label is ignored) or an exact display value; the response shows the canonical 'recordId::displayValue' the server stored. If the reference doesn't exist the whole update is rejected with reason 'data_field_reference_not_found'.",
|
|
2952
|
+
command: "zinkee --json records update deals 550e8400-e29b-41d4-a716-446655440000 --set customer-ref=8ad602a1-f6e3-43f6-9ab2-f1c5afc99621",
|
|
2953
|
+
raw: `{
|
|
2954
|
+
"set": {
|
|
2955
|
+
"customer-ref": "8ad602a1-f6e3-43f6-9ab2-f1c5afc99621"
|
|
2956
|
+
}
|
|
2957
|
+
}`,
|
|
2958
|
+
response: `{
|
|
2959
|
+
"recordId": "550e8400-e29b-41d4-a716-446655440000",
|
|
2960
|
+
"values": {
|
|
2961
|
+
"deal-name": "Acme renewal",
|
|
2962
|
+
"customer-ref": "8ad602a1-f6e3-43f6-9ab2-f1c5afc99621::Acme Corp"
|
|
2963
|
+
}
|
|
2905
2964
|
}`
|
|
2906
2965
|
}
|
|
2907
2966
|
]),
|
|
@@ -10735,10 +10794,10 @@ var RecordsApi = class {
|
|
|
10735
10794
|
`/api/v2/schemas/${selectorValue8(schema)}/records/${selectorValue8(record)}`
|
|
10736
10795
|
);
|
|
10737
10796
|
}
|
|
10738
|
-
|
|
10797
|
+
createRecords(schema, records) {
|
|
10739
10798
|
return this.client.requestJson(
|
|
10740
10799
|
`/api/v2/schemas/${selectorValue8(schema)}/records`,
|
|
10741
|
-
jsonOptions6(
|
|
10800
|
+
jsonOptions6({ records }, "POST")
|
|
10742
10801
|
);
|
|
10743
10802
|
}
|
|
10744
10803
|
updateRecord(schema, record, input) {
|
|
@@ -11140,7 +11199,60 @@ function buildRecordQueryInput(options, allowRaw) {
|
|
|
11140
11199
|
}
|
|
11141
11200
|
return input;
|
|
11142
11201
|
}
|
|
11143
|
-
function
|
|
11202
|
+
function readRecordsFromFile(path) {
|
|
11203
|
+
let contents;
|
|
11204
|
+
try {
|
|
11205
|
+
contents = readFileSync8(path, "utf8");
|
|
11206
|
+
} catch (error) {
|
|
11207
|
+
const message = error instanceof Error ? error.message : "Unable to read file.";
|
|
11208
|
+
throw new CliError(
|
|
11209
|
+
"invalid_cli_usage",
|
|
11210
|
+
`Failed to read records from ${path}: ${message}`
|
|
11211
|
+
);
|
|
11212
|
+
}
|
|
11213
|
+
let parsed;
|
|
11214
|
+
try {
|
|
11215
|
+
parsed = JSON.parse(contents);
|
|
11216
|
+
} catch (error) {
|
|
11217
|
+
const message = error instanceof Error ? error.message : "Invalid JSON.";
|
|
11218
|
+
throw new CliError(
|
|
11219
|
+
"invalid_cli_usage",
|
|
11220
|
+
`Failed to parse JSON from --records-file ${path}: ${message}`
|
|
11221
|
+
);
|
|
11222
|
+
}
|
|
11223
|
+
if (!Array.isArray(parsed)) {
|
|
11224
|
+
throw new CliError(
|
|
11225
|
+
"invalid_cli_usage",
|
|
11226
|
+
`Expected --records-file ${path} to contain a JSON array of record objects.`
|
|
11227
|
+
);
|
|
11228
|
+
}
|
|
11229
|
+
if (parsed.length === 0) {
|
|
11230
|
+
throw new CliError(
|
|
11231
|
+
"invalid_cli_usage",
|
|
11232
|
+
`--records-file ${path} must contain at least one record.`
|
|
11233
|
+
);
|
|
11234
|
+
}
|
|
11235
|
+
return parsed.map((record, index) => {
|
|
11236
|
+
if (!isJsonObject6(record)) {
|
|
11237
|
+
throw new CliError(
|
|
11238
|
+
"invalid_cli_usage",
|
|
11239
|
+
`Record at index ${index} in --records-file ${path} must be a JSON object.`
|
|
11240
|
+
);
|
|
11241
|
+
}
|
|
11242
|
+
return record;
|
|
11243
|
+
});
|
|
11244
|
+
}
|
|
11245
|
+
function buildCreateRecords(options) {
|
|
11246
|
+
const hasSingleRecordFlags = (options.set?.length ?? 0) > 0 || (options.setJson?.length ?? 0) > 0 || options.raw !== void 0 || options.rawFile !== void 0;
|
|
11247
|
+
if (options.recordsFile !== void 0) {
|
|
11248
|
+
if (hasSingleRecordFlags) {
|
|
11249
|
+
throw new CliError(
|
|
11250
|
+
"invalid_cli_usage",
|
|
11251
|
+
'Provide either "--records-file" or the single-record flags (--set/--set-json/--raw/--raw-file), not both.'
|
|
11252
|
+
);
|
|
11253
|
+
}
|
|
11254
|
+
return readRecordsFromFile(options.recordsFile);
|
|
11255
|
+
}
|
|
11144
11256
|
const values = {
|
|
11145
11257
|
...readRawObject3(options.raw, options.rawFile),
|
|
11146
11258
|
...buildAssignmentObject(options.set, options.setJson)
|
|
@@ -11148,10 +11260,10 @@ function buildRecordCreateInput(options) {
|
|
|
11148
11260
|
if (isEmptyObject5(values)) {
|
|
11149
11261
|
throw new CliError(
|
|
11150
11262
|
"invalid_cli_usage",
|
|
11151
|
-
'Provide record fields via "--set", "--set-json", "--raw", or "--
|
|
11263
|
+
'Provide record fields via "--set", "--set-json", "--raw", "--raw-file", or load multiple records with "--records-file".'
|
|
11152
11264
|
);
|
|
11153
11265
|
}
|
|
11154
|
-
return
|
|
11266
|
+
return [values];
|
|
11155
11267
|
}
|
|
11156
11268
|
function buildRecordUpdateInput(options) {
|
|
11157
11269
|
const raw = readRawObject3(options.raw, options.rawFile);
|
|
@@ -11274,21 +11386,38 @@ function registerRecordsCommands(program, options = {}) {
|
|
|
11274
11386
|
}
|
|
11275
11387
|
emitTable4(stdout, data);
|
|
11276
11388
|
});
|
|
11277
|
-
records.command("create").description("Create
|
|
11389
|
+
records.command("create").description("Create one or more records").argument("<schema>", "schema uuid or slug", parseUuidOrSlugSelector8).option(
|
|
11390
|
+
"--set <field=value>",
|
|
11391
|
+
"set a string field (reference fields: a record id, 'recordId::label', or an exact display value)",
|
|
11392
|
+
collectKeyValueAssignments,
|
|
11393
|
+
[]
|
|
11394
|
+
).option("--set-json <field=json>", "set a structured field", collectJsonAssignments, []).option("--raw <json>", "raw JSON object payload").option("--raw-file <path>", "path to a raw JSON object payload").option(
|
|
11395
|
+
"--records-file <path>",
|
|
11396
|
+
"path to a JSON array of record objects (mutually exclusive with --set/--set-json/--raw/--raw-file)"
|
|
11397
|
+
).action(async function action(schema, commandOptions) {
|
|
11278
11398
|
const { api, schemasApi, json, readOnly } = createRecordsApi(this, filePath);
|
|
11279
11399
|
ensureWritable7("records create", readOnly, "write");
|
|
11400
|
+
const records2 = buildCreateRecords(commandOptions);
|
|
11280
11401
|
const resolvedSchema = await resolveSchemaSelector(schemasApi, schema);
|
|
11281
|
-
const data = await api.
|
|
11282
|
-
resolvedSchema,
|
|
11283
|
-
buildRecordCreateInput(commandOptions)
|
|
11284
|
-
);
|
|
11402
|
+
const data = await api.createRecords(resolvedSchema, records2);
|
|
11285
11403
|
if (json) {
|
|
11286
11404
|
emitJson10(stdout, "records create", data, filePath);
|
|
11287
11405
|
return;
|
|
11288
11406
|
}
|
|
11289
|
-
writeLine10(stdout, `Created record "${
|
|
11407
|
+
writeLine10(stdout, `Created ${data.created.length} record(s) in schema "${schema.value}".`);
|
|
11408
|
+
if (data.errors.length > 0) {
|
|
11409
|
+
writeLine10(stdout, `${data.errors.length} record(s) rejected:`);
|
|
11410
|
+
for (const error of data.errors) {
|
|
11411
|
+
writeLine10(stdout, ` - index ${error.index}: ${error.message}`);
|
|
11412
|
+
}
|
|
11413
|
+
}
|
|
11290
11414
|
});
|
|
11291
|
-
records.command("update").description("Update a record").argument("<schema>", "schema uuid or slug", parseUuidOrSlugSelector8).argument("<record>", "record uuid or slug", parseUuidOrSlugSelector8).option(
|
|
11415
|
+
records.command("update").description("Update a record").argument("<schema>", "schema uuid or slug", parseUuidOrSlugSelector8).argument("<record>", "record uuid or slug", parseUuidOrSlugSelector8).option(
|
|
11416
|
+
"--set <field=value>",
|
|
11417
|
+
"set a string field (reference fields: a record id, 'recordId::label', or an exact display value)",
|
|
11418
|
+
collectKeyValueAssignments,
|
|
11419
|
+
[]
|
|
11420
|
+
).option("--set-json <field=json>", "set a structured field", collectJsonAssignments, []).option("--unset <field>", "unset a field", collectStringValues, []).option("--raw <json>", "raw JSON object of fields to set").option("--raw-file <path>", "path to a JSON object of fields to set").action(async function action(schema, record, commandOptions) {
|
|
11292
11421
|
const { api, schemasApi, json, readOnly } = createRecordsApi(this, filePath);
|
|
11293
11422
|
ensureWritable7("records update", readOnly, "write");
|
|
11294
11423
|
const resolvedSchema = await resolveSchemaSelector(schemasApi, schema);
|