monday-cli 0.5.0 → 0.7.0

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.
Files changed (49) hide show
  1. package/CHANGELOG.md +665 -0
  2. package/README.md +209 -35
  3. package/dist/api/column-types.d.ts +81 -19
  4. package/dist/api/column-types.d.ts.map +1 -1
  5. package/dist/api/column-types.js +44 -11
  6. package/dist/api/column-types.js.map +1 -1
  7. package/dist/api/column-values.d.ts +22 -10
  8. package/dist/api/column-values.d.ts.map +1 -1
  9. package/dist/api/column-values.js +50 -20
  10. package/dist/api/column-values.js.map +1 -1
  11. package/dist/api/file-column-set.d.ts +613 -0
  12. package/dist/api/file-column-set.d.ts.map +1 -0
  13. package/dist/api/file-column-set.js +568 -0
  14. package/dist/api/file-column-set.js.map +1 -0
  15. package/dist/api/raw-write.d.ts +38 -17
  16. package/dist/api/raw-write.d.ts.map +1 -1
  17. package/dist/api/raw-write.js +62 -25
  18. package/dist/api/raw-write.js.map +1 -1
  19. package/dist/api/resolver-error-fold.d.ts +25 -0
  20. package/dist/api/resolver-error-fold.d.ts.map +1 -1
  21. package/dist/api/resolver-error-fold.js +56 -0
  22. package/dist/api/resolver-error-fold.js.map +1 -1
  23. package/dist/commands/board/column-create.d.ts +13 -3
  24. package/dist/commands/board/column-create.d.ts.map +1 -1
  25. package/dist/commands/board/column-create.js +27 -8
  26. package/dist/commands/board/column-create.js.map +1 -1
  27. package/dist/commands/item/create.d.ts +24 -8
  28. package/dist/commands/item/create.d.ts.map +1 -1
  29. package/dist/commands/item/create.js +601 -44
  30. package/dist/commands/item/create.js.map +1 -1
  31. package/dist/commands/item/set.d.ts +33 -3
  32. package/dist/commands/item/set.d.ts.map +1 -1
  33. package/dist/commands/item/set.js +193 -15
  34. package/dist/commands/item/set.js.map +1 -1
  35. package/dist/commands/item/update.d.ts +203 -3
  36. package/dist/commands/item/update.d.ts.map +1 -1
  37. package/dist/commands/item/update.js +1015 -68
  38. package/dist/commands/item/update.js.map +1 -1
  39. package/dist/commands/item/upload.d.ts.map +1 -1
  40. package/dist/commands/item/upload.js +16 -69
  41. package/dist/commands/item/upload.js.map +1 -1
  42. package/dist/commands/update/upload.d.ts.map +1 -1
  43. package/dist/commands/update/upload.js +9 -59
  44. package/dist/commands/update/upload.js.map +1 -1
  45. package/dist/utils/file-source.d.ts +93 -0
  46. package/dist/utils/file-source.d.ts.map +1 -0
  47. package/dist/utils/file-source.js +140 -0
  48. package/dist/utils/file-source.js.map +1 -0
  49. package/package.json +1 -1
@@ -0,0 +1,140 @@
1
+ /**
2
+ * Local-file pre-check + Blob-construction shared helpers for the
3
+ * multipart-upload surfaces. Lifted at v0.6-M38 IMPL kickoff per
4
+ * R-v0.6-NEW-1 (3-consumer trigger fires at IMPL: v0.4-M31's `monday
5
+ * item upload` action body + v0.4-M31's `monday update upload` action
6
+ * body + v0.6-M38's `executeFileColumnSet` runtime body). Mirrors
7
+ * R-NEW-29's M25 lift-ahead-of-feat cadence (extract the shared
8
+ * pattern BEFORE the feat commit that crystallizes the 3rd consumer
9
+ * so the feat diff stays focused on the behavioural change).
10
+ *
11
+ * **Two helpers, distinct fire points** — the M31 / M38 callers run
12
+ * the pre-check BEFORE `resolveClient` so a missing/unreadable-file
13
+ * error surfaces as `usage_error` (exit 1) rather than getting
14
+ * tangled up with `config_error` (exit 3) on a token miss; the Blob
15
+ * construction fires AFTER column-type validation so a non-`file`
16
+ * column rejection or an `item update` mutex rejection doesn't pay
17
+ * for the full read:
18
+ *
19
+ * 1. {@link precheckLocalFile} — `fs.stat()` + `fs.access(R_OK)` +
20
+ * non-empty check. Surfaces `usage_error` with `details.reason:
21
+ * 'file_not_readable'` (ENOENT / EACCES / path is a directory)
22
+ * or `'file_empty'` (zero bytes).
23
+ * 2. {@link buildBlobFromPath} — `fs/promises.readFile()` + Web
24
+ * `Blob` construction with the sniffed `Content-Type` from
25
+ * `sniffContentType(...)`. No additional error surfaces — read
26
+ * failures past the pre-check are TOCTOU-class (file removed
27
+ * between pre-check and read) and surface via the caller's
28
+ * catch-all.
29
+ *
30
+ * **Behaviour-preserving lift.** Byte-equivalent to the M31 inline
31
+ * copies the lift consolidates — same `usage_error` message prose,
32
+ * same `details.reason` discriminator + `errno_code` slot + hint
33
+ * text, same path resolution (`resolve(process.cwd(), rawPath)`)
34
+ * and basename (`basename(filePath)`). Integration tests for the
35
+ * 2 M31 consumers cover the pre-check error branches; this module
36
+ * adds direct unit tests for the helper + the buildBlobFromPath
37
+ * sibling.
38
+ */
39
+ import { stat as fsStat, access as fsAccess, readFile } from 'node:fs/promises';
40
+ import { constants as fsConstants } from 'node:fs';
41
+ import { resolve as resolvePath, basename } from 'node:path';
42
+ import { UsageError, asError, errorCode } from './errors.js';
43
+ import { sniffContentType } from './mime.js';
44
+ /**
45
+ * Resolves `rawPath` relative to `process.cwd()` and confirms the
46
+ * file is (a) a regular file (not a directory / socket / device),
47
+ * (b) readable by the current user, and (c) non-empty. Throws
48
+ * {@link UsageError} on any check failure with a `details.reason`
49
+ * discriminator:
50
+ *
51
+ * - `'file_not_readable'` — `ENOENT` / `EACCES` / path resolves
52
+ * to a directory or special file. `details.errno_code` echoes
53
+ * the underlying errno when one was attached to the Node fs
54
+ * error.
55
+ * - `'file_empty'` — file exists and is readable but has zero
56
+ * bytes. Monday rejects empty uploads server-side; the CLI
57
+ * surfaces the rejection with a clearer hint via the local
58
+ * pre-check.
59
+ *
60
+ * The Web `Blob` construction for the actual upload payload happens
61
+ * later via {@link buildBlobFromPath} — callers run the pre-check
62
+ * BEFORE the wire dispatch so a bad path doesn't burn a network
63
+ * round-trip, and run the Blob construction AFTER any column-type
64
+ * / mutex validation so a non-`file` column rejection doesn't pay
65
+ * for the full read.
66
+ */
67
+ export const precheckLocalFile = async (rawPath) => {
68
+ const filePath = resolvePath(process.cwd(), rawPath);
69
+ const filename = basename(filePath);
70
+ let fileSizeBytes;
71
+ try {
72
+ const stats = await fsStat(filePath);
73
+ if (!stats.isFile()) {
74
+ throw new UsageError(`<file> ${JSON.stringify(rawPath)} is not a regular file ` +
75
+ `(resolved to ${JSON.stringify(filePath)}).`, {
76
+ details: {
77
+ reason: 'file_not_readable',
78
+ file_path: filePath,
79
+ hint: 'pass a path to a regular readable file; directories ' +
80
+ 'and special files (sockets, devices) are rejected.',
81
+ },
82
+ });
83
+ }
84
+ await fsAccess(filePath, fsConstants.R_OK);
85
+ fileSizeBytes = stats.size;
86
+ }
87
+ catch (err) {
88
+ if (err instanceof UsageError) {
89
+ throw err;
90
+ }
91
+ const code = errorCode(err);
92
+ throw new UsageError(`<file> ${JSON.stringify(rawPath)} cannot be read ` +
93
+ `(resolved to ${JSON.stringify(filePath)}): ` +
94
+ `${asError(err).message}.`, {
95
+ cause: err,
96
+ details: {
97
+ reason: 'file_not_readable',
98
+ file_path: filePath,
99
+ ...(code === undefined ? {} : { errno_code: code }),
100
+ hint: 'check that the path exists, is readable by the current ' +
101
+ "user, and isn't a directory.",
102
+ },
103
+ });
104
+ }
105
+ if (fileSizeBytes === 0) {
106
+ throw new UsageError(`<file> ${JSON.stringify(rawPath)} is empty (0 bytes); ` +
107
+ `Monday rejects empty uploads server-side.`, {
108
+ details: {
109
+ reason: 'file_empty',
110
+ file_path: filePath,
111
+ filename,
112
+ file_size_bytes: 0,
113
+ hint: 'Monday returns FILE_SIZE_LIMIT_EXCEEDED on empty ' +
114
+ 'uploads. Provide a non-empty file or remove the upload ' +
115
+ 'call.',
116
+ },
117
+ });
118
+ }
119
+ return { filePath, filename, fileSizeBytes };
120
+ };
121
+ /**
122
+ * Reads the file at `precheck.filePath` into memory and wraps it as
123
+ * a Web `Blob` with a `Content-Type` sniffed from the filename
124
+ * extension via {@link sniffContentType}. The Blob is the payload
125
+ * the multipart transport sends to Monday's wire `File!` scalar.
126
+ *
127
+ * Run AFTER {@link precheckLocalFile} so the path is known good and
128
+ * the size is known non-zero. Run AFTER column-type validation / M38
129
+ * mutex checks so a non-`file` column rejection or a mutex violation
130
+ * doesn't pay for the full read. The read uses `fs/promises.readFile`
131
+ * which buffers the entire payload into memory — Monday's per-file
132
+ * cap is plan-tier-dependent (typically 500 MB at standard tiers);
133
+ * callers don't pre-check size against a hardcoded ceiling because
134
+ * the cap isn't exposed via the GraphQL schema.
135
+ */
136
+ export const buildBlobFromPath = async (precheck) => {
137
+ const bytes = await readFile(precheck.filePath);
138
+ return new Blob([bytes], { type: sniffContentType(precheck.filename) });
139
+ };
140
+ //# sourceMappingURL=file-source.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"file-source.js","sourceRoot":"","sources":["../../src/utils/file-source.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "monday-cli",
3
- "version": "0.5.0",
3
+ "version": "0.7.0",
4
4
  "description": "Agent-first CLI for Monday.com — read boards, file backlog items, transition statuses, and post comments from the terminal. Built for AI coding agents (Claude Code, Codex) with humans as a welcome second audience.",
5
5
  "type": "module",
6
6
  "engines": {