zinkee 0.1.33 → 0.1.34
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 +4 -1
- package/dist/index.js +112 -32
- 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 +85 -12
- package/src/utils/examples.ts +42 -22
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"
|
package/dist/index.js
CHANGED
|
@@ -2832,35 +2832,55 @@ 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 must match the target's current targetDisplayField.",
|
|
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
|
+
]
|
|
2864
2884
|
}`
|
|
2865
2885
|
}
|
|
2866
2886
|
]),
|
|
@@ -10735,10 +10755,10 @@ var RecordsApi = class {
|
|
|
10735
10755
|
`/api/v2/schemas/${selectorValue8(schema)}/records/${selectorValue8(record)}`
|
|
10736
10756
|
);
|
|
10737
10757
|
}
|
|
10738
|
-
|
|
10758
|
+
createRecords(schema, records) {
|
|
10739
10759
|
return this.client.requestJson(
|
|
10740
10760
|
`/api/v2/schemas/${selectorValue8(schema)}/records`,
|
|
10741
|
-
jsonOptions6(
|
|
10761
|
+
jsonOptions6({ records }, "POST")
|
|
10742
10762
|
);
|
|
10743
10763
|
}
|
|
10744
10764
|
updateRecord(schema, record, input) {
|
|
@@ -11140,7 +11160,60 @@ function buildRecordQueryInput(options, allowRaw) {
|
|
|
11140
11160
|
}
|
|
11141
11161
|
return input;
|
|
11142
11162
|
}
|
|
11143
|
-
function
|
|
11163
|
+
function readRecordsFromFile(path) {
|
|
11164
|
+
let contents;
|
|
11165
|
+
try {
|
|
11166
|
+
contents = readFileSync8(path, "utf8");
|
|
11167
|
+
} catch (error) {
|
|
11168
|
+
const message = error instanceof Error ? error.message : "Unable to read file.";
|
|
11169
|
+
throw new CliError(
|
|
11170
|
+
"invalid_cli_usage",
|
|
11171
|
+
`Failed to read records from ${path}: ${message}`
|
|
11172
|
+
);
|
|
11173
|
+
}
|
|
11174
|
+
let parsed;
|
|
11175
|
+
try {
|
|
11176
|
+
parsed = JSON.parse(contents);
|
|
11177
|
+
} catch (error) {
|
|
11178
|
+
const message = error instanceof Error ? error.message : "Invalid JSON.";
|
|
11179
|
+
throw new CliError(
|
|
11180
|
+
"invalid_cli_usage",
|
|
11181
|
+
`Failed to parse JSON from --records-file ${path}: ${message}`
|
|
11182
|
+
);
|
|
11183
|
+
}
|
|
11184
|
+
if (!Array.isArray(parsed)) {
|
|
11185
|
+
throw new CliError(
|
|
11186
|
+
"invalid_cli_usage",
|
|
11187
|
+
`Expected --records-file ${path} to contain a JSON array of record objects.`
|
|
11188
|
+
);
|
|
11189
|
+
}
|
|
11190
|
+
if (parsed.length === 0) {
|
|
11191
|
+
throw new CliError(
|
|
11192
|
+
"invalid_cli_usage",
|
|
11193
|
+
`--records-file ${path} must contain at least one record.`
|
|
11194
|
+
);
|
|
11195
|
+
}
|
|
11196
|
+
return parsed.map((record, index) => {
|
|
11197
|
+
if (!isJsonObject6(record)) {
|
|
11198
|
+
throw new CliError(
|
|
11199
|
+
"invalid_cli_usage",
|
|
11200
|
+
`Record at index ${index} in --records-file ${path} must be a JSON object.`
|
|
11201
|
+
);
|
|
11202
|
+
}
|
|
11203
|
+
return record;
|
|
11204
|
+
});
|
|
11205
|
+
}
|
|
11206
|
+
function buildCreateRecords(options) {
|
|
11207
|
+
const hasSingleRecordFlags = (options.set?.length ?? 0) > 0 || (options.setJson?.length ?? 0) > 0 || options.raw !== void 0 || options.rawFile !== void 0;
|
|
11208
|
+
if (options.recordsFile !== void 0) {
|
|
11209
|
+
if (hasSingleRecordFlags) {
|
|
11210
|
+
throw new CliError(
|
|
11211
|
+
"invalid_cli_usage",
|
|
11212
|
+
'Provide either "--records-file" or the single-record flags (--set/--set-json/--raw/--raw-file), not both.'
|
|
11213
|
+
);
|
|
11214
|
+
}
|
|
11215
|
+
return readRecordsFromFile(options.recordsFile);
|
|
11216
|
+
}
|
|
11144
11217
|
const values = {
|
|
11145
11218
|
...readRawObject3(options.raw, options.rawFile),
|
|
11146
11219
|
...buildAssignmentObject(options.set, options.setJson)
|
|
@@ -11148,10 +11221,10 @@ function buildRecordCreateInput(options) {
|
|
|
11148
11221
|
if (isEmptyObject5(values)) {
|
|
11149
11222
|
throw new CliError(
|
|
11150
11223
|
"invalid_cli_usage",
|
|
11151
|
-
'Provide record fields via "--set", "--set-json", "--raw", or "--
|
|
11224
|
+
'Provide record fields via "--set", "--set-json", "--raw", "--raw-file", or load multiple records with "--records-file".'
|
|
11152
11225
|
);
|
|
11153
11226
|
}
|
|
11154
|
-
return
|
|
11227
|
+
return [values];
|
|
11155
11228
|
}
|
|
11156
11229
|
function buildRecordUpdateInput(options) {
|
|
11157
11230
|
const raw = readRawObject3(options.raw, options.rawFile);
|
|
@@ -11274,19 +11347,26 @@ function registerRecordsCommands(program, options = {}) {
|
|
|
11274
11347
|
}
|
|
11275
11348
|
emitTable4(stdout, data);
|
|
11276
11349
|
});
|
|
11277
|
-
records.command("create").description("Create
|
|
11350
|
+
records.command("create").description("Create one or more records").argument("<schema>", "schema uuid or slug", parseUuidOrSlugSelector8).option("--set <field=value>", "set a string field", collectKeyValueAssignments, []).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(
|
|
11351
|
+
"--records-file <path>",
|
|
11352
|
+
"path to a JSON array of record objects (mutually exclusive with --set/--set-json/--raw/--raw-file)"
|
|
11353
|
+
).action(async function action(schema, commandOptions) {
|
|
11278
11354
|
const { api, schemasApi, json, readOnly } = createRecordsApi(this, filePath);
|
|
11279
11355
|
ensureWritable7("records create", readOnly, "write");
|
|
11356
|
+
const records2 = buildCreateRecords(commandOptions);
|
|
11280
11357
|
const resolvedSchema = await resolveSchemaSelector(schemasApi, schema);
|
|
11281
|
-
const data = await api.
|
|
11282
|
-
resolvedSchema,
|
|
11283
|
-
buildRecordCreateInput(commandOptions)
|
|
11284
|
-
);
|
|
11358
|
+
const data = await api.createRecords(resolvedSchema, records2);
|
|
11285
11359
|
if (json) {
|
|
11286
11360
|
emitJson10(stdout, "records create", data, filePath);
|
|
11287
11361
|
return;
|
|
11288
11362
|
}
|
|
11289
|
-
writeLine10(stdout, `Created record "${
|
|
11363
|
+
writeLine10(stdout, `Created ${data.created.length} record(s) in schema "${schema.value}".`);
|
|
11364
|
+
if (data.errors.length > 0) {
|
|
11365
|
+
writeLine10(stdout, `${data.errors.length} record(s) rejected:`);
|
|
11366
|
+
for (const error of data.errors) {
|
|
11367
|
+
writeLine10(stdout, ` - index ${error.index}: ${error.message}`);
|
|
11368
|
+
}
|
|
11369
|
+
}
|
|
11290
11370
|
});
|
|
11291
11371
|
records.command("update").description("Update a record").argument("<schema>", "schema uuid or slug", parseUuidOrSlugSelector8).argument("<record>", "record uuid or slug", parseUuidOrSlugSelector8).option("--set <field=value>", "set a string field", collectKeyValueAssignments, []).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
11372
|
const { api, schemasApi, json, readOnly } = createRecordsApi(this, filePath);
|