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 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: "Minimal create using just two plain string fields.",
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
- "values": {
2839
- "contact-name": "Ada Lovelace",
2840
- "contact-email": "ada@example.com"
2841
- }
2838
+ "records": [
2839
+ {
2840
+ "contact-name": "Ada Lovelace",
2841
+ "contact-email": "ada@example.com"
2842
+ }
2843
+ ]
2842
2844
  }`,
2843
2845
  response: `{
2844
- "recordId": "550e8400-e29b-41d4-a716-446655440000",
2845
- "values": {
2846
- "contact-name": "Ada Lovelace",
2847
- "contact-email": "ada@example.com"
2848
- }
2846
+ "created": [
2847
+ "550e8400-e29b-41d4-a716-446655440000"
2848
+ ],
2849
+ "errors": []
2849
2850
  }`
2850
2851
  },
2851
2852
  {
2852
- description: "Create a record mixing text, option, number, date, reference and member fields. ReferenceField values must match the target's current targetDisplayField (read it from the target record before writing).",
2853
- command: `zinkee --json records create contacts --set contact-name="Grace Hopper" --set contact-email=grace@example.com --set status=2 --set amount=1999.99 --set due-date=2026-06-01T09:00:00Z --set customer-ref="CUST-12" --set owner=6c8a3e0d-4e5f-4a1b-9c2d-3e4f5a6b7c8d`,
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
- "values": {
2856
- "contact-name": "Grace Hopper",
2857
- "contact-email": "grace@example.com",
2858
- "status": 2,
2859
- "amount": 1999.99,
2860
- "due-date": "2026-06-01T09:00:00Z",
2861
- "customer-ref": "CUST-12",
2862
- "owner": "6c8a3e0d-4e5f-4a1b-9c2d-3e4f5a6b7c8d"
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
- createRecord(schema, input) {
10758
+ createRecords(schema, records) {
10739
10759
  return this.client.requestJson(
10740
10760
  `/api/v2/schemas/${selectorValue8(schema)}/records`,
10741
- jsonOptions6(input, "POST")
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 buildRecordCreateInput(options) {
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 "--raw-file".'
11224
+ 'Provide record fields via "--set", "--set-json", "--raw", "--raw-file", or load multiple records with "--records-file".'
11152
11225
  );
11153
11226
  }
11154
- return { values };
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 a record").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").action(async function action(schema, commandOptions) {
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.createRecord(
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 "${getRecordIdentifier(data)}".`);
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);