@myapihq/cli 2.11.2 → 2.12.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.
@@ -6,5 +6,6 @@ export declare const SCHEMA: FlagSchema;
6
6
  export declare function list(flags: Flags): Promise<void>;
7
7
  export declare function create(bodyArg: string | undefined, flags: Flags): Promise<void>;
8
8
  export declare function resolve(id: string, flags: Flags): Promise<void>;
9
+ export declare function del(id: string | undefined, flags: Flags): Promise<void>;
9
10
  export declare function widget(sub: string | undefined, arg: string | undefined, flags: Flags): Promise<void>;
10
11
  export declare function run(subcommand: string | undefined, args: string[], flags: Flags): Promise<void>;
@@ -13,6 +13,7 @@ export const EXPOSES = [
13
13
  'GET /feedback/orgs/{org_id}/items',
14
14
  'POST /feedback/orgs/{org_id}/items',
15
15
  'POST /feedback/orgs/{org_id}/items/{id}/resolve',
16
+ 'DELETE /feedback/orgs/{org_id}/items/{id}',
16
17
  'POST /feedback/orgs/{org_id}/widgets',
17
18
  'DELETE /feedback/orgs/{org_id}/widgets/{id}',
18
19
  ];
@@ -92,6 +93,18 @@ export async function resolve(id, flags) {
92
93
  success(`Resolved ${id}`);
93
94
  info('(An unknown id answers the same way, so this is not confirmation the item existed.)');
94
95
  }
96
+ export async function del(id, flags) {
97
+ const usage = 'myapi feedback delete <id> [--yes] [--org <id>]';
98
+ const config = requireConfig();
99
+ const orgId = requireOrg(flags, config, usage);
100
+ requireArg(id, 'id', usage);
101
+ // Erases rather than closes. `resolve` is the reversible one; this is not,
102
+ // so it takes the same confirmation every destructive verb here takes.
103
+ await confirmDestructive(flags, `permanently delete feedback ${id} (resolve keeps it; this erases it)`, usage);
104
+ await sdkFeedback.deleteFeedback(config.api_key, orgId, id);
105
+ success(`Deleted ${id}`);
106
+ info('(Idempotent — an unknown id answers the same way, so this is not confirmation the item existed.)');
107
+ }
95
108
  export async function widget(sub, arg, flags) {
96
109
  const config = requireConfig();
97
110
  const orgId = requireOrg(flags, config, 'myapi feedback widget create <name> | revoke <id>');
@@ -128,6 +141,11 @@ export async function widget(sub, arg, flags) {
128
141
  error('Usage: myapi feedback widget create <name> [--origins <list>]\n myapi feedback widget revoke <id>');
129
142
  }
130
143
  const SUBCOMMAND_USAGE = {
144
+ 'delete': `myapi feedback delete <id> [--yes] [--org <id>]
145
+
146
+ Erases an item. \`resolve\` closes one and keeps it; this removes it — for spam,
147
+ or a report where somebody typed personal details into the box. Idempotent, and
148
+ an unknown id answers the same way.`,
131
149
  'list': `myapi feedback list [--kind bug|issue|suggestion] [--status open|resolved]
132
150
  [--limit N] [--offset N] [--org <id>] [--json]
133
151
 
@@ -151,6 +169,7 @@ page submit without a credential; you list, filter and resolve the results.
151
169
 
152
170
  Subcommands:
153
171
  create "<text>" Record one piece of feedback (--kind bug|issue|suggestion)
172
+ delete <id> Erase an item (resolve keeps it; this does not)
154
173
  list List feedback, newest first (--kind, --status, --limit, --offset)
155
174
  resolve <id> Close a piece of feedback
156
175
  widget create <name> Mint a PUBLIC widget key for a site (--origins to restrict)
@@ -167,6 +186,7 @@ All commands accept --org <id> (or set default: myapi config set-org <id>).`);
167
186
  switch (subcommand) {
168
187
  case 'create': return create(args[0], flags);
169
188
  case 'list': return list(flags);
189
+ case 'delete': return del(args[0], flags);
170
190
  case 'resolve': return resolve(args[0], flags);
171
191
  case 'widget': return widget(args[0], args[1], flags);
172
192
  default: error(`Unknown subcommand: ${subcommand}. Run "myapi feedback --help" for a list of valid subcommands.`);
@@ -1,10 +1,10 @@
1
1
  ---
2
2
  name: my-feedback-api
3
- version: 1.1.0
3
+ version: 1.2.0
4
4
  description: >
5
5
  Collect feedback from the people using what you built. A public widget key lets a page submit without a credential; you list, filter and resolve the results. Kind is chosen by the person reporting, not inferred from their wording.
6
6
  triggers: [feedback, bug report, user feedback, feature request, widget, support, complaints, praise]
7
- checksum: sha256-544fcdb87744431fe7c3adbda341bf858c6d4177695b811a3d29aa4a311c927b
7
+ checksum: sha256-199fba185e85ccc91a6858bce4a60e20167a6591dee28cbc475606c72cb8d787
8
8
  ---
9
9
 
10
10
  # MyFeedbackAPI
@@ -33,30 +33,44 @@ myapi feedback widget create site --origins app.example.com,example.com
33
33
  Revoke with `myapi feedback widget revoke <id>`. Submissions stop immediately;
34
34
  feedback already collected is kept.
35
35
 
36
- ### How a page submits with it
36
+ ### Embedding it: one script tag
37
37
 
38
- `POST https://api.myapihq.com/feedback/in/<widget_key>` no auth, no SDK, no
39
- CLI. This is the browser-side half, and it is the whole point of the widget key.
38
+ The platform hosts the widget, compiled per key with that widget's routes and
39
+ theme baked in. This is the intended way in you do not build a UI:
40
+
41
+ ```html
42
+ <script src="https://api.myapihq.com/feedback/in/<widget_key>/widget.js" async></script>
43
+ ```
44
+
45
+ It renders a button, shows itself only on the routes the widget is configured
46
+ for, and lets the person point at an element or drag a region. It sends `kind`,
47
+ `body`, `page_url`, `route`, `viewport`, plus **either** `target_selector` (they
48
+ clicked something) **or** `target_region` `{x,y,w,h}` (they dragged a box).
49
+
50
+ A wrong key does not break the page: the response is `application/javascript`
51
+ carrying a JS comment that names the fix, so a typo cannot throw a syntax error
52
+ in your app.
53
+
54
+ **No screenshots.** The submit body takes no image and there is no multipart
55
+ form — `target_selector` / `target_region` are the platform's answer to "where
56
+ were they pointing". Do not build a capture step expecting somewhere to put it.
57
+
58
+ ### Submitting by hand (only if you cannot use the script)
59
+
60
+ `POST https://api.myapihq.com/feedback/in/<widget_key>` — no auth, no SDK.
61
+ Same fields the widget sends:
40
62
 
41
63
  ```js
42
64
  await fetch(`https://api.myapihq.com/feedback/in/${WIDGET_KEY}`, {
43
65
  method: 'POST',
44
66
  headers: { 'Content-Type': 'application/json' },
45
- body: JSON.stringify({
46
- kind: 'bug', // required — bug | issue | suggestion
47
- body: text, // required — ≤8000 chars, refused not truncated
48
- page_url: location.href, // optional context, all of it
49
- route: router.currentRoute,
50
- target_selector: '#checkout button',
51
- target_region: { x, y, w, h }, // viewport pixels, e.g. a dragged box
52
- viewport: { w: innerWidth, h: innerHeight },
53
- }),
67
+ body: JSON.stringify({ kind: 'bug', body: text, page_url: location.href }),
54
68
  });
55
69
  ```
56
70
 
57
- Errors are `WIDGET_NOT_FOUND` (revoked reads the same as invented, so keys
71
+ Errors: `WIDGET_NOT_FOUND` (a revoked key reads like an invented one, so keys
58
72
  cannot be probed), `ORIGIN_NOT_ALLOWED`, `RATE_LIMITED`, `INVALID_KIND`,
59
- `BODY_REQUIRED`, `BODY_TOO_LONG`. The key can only write — it reads nothing.
73
+ `BODY_REQUIRED`, `BODY_TOO_LONG`. The key only ever writes.
60
74
 
61
75
  ### Kind is a claim, not a guess
62
76
 
@@ -87,7 +101,8 @@ that is deliberate, so ids cannot be probed across orgs.
87
101
  |---|---|
88
102
  | `myapi feedback create "<text>" --kind <k>` | Record one item (`--page-url`, `--route` for context) |
89
103
  | `myapi feedback list [--kind bug\|issue\|suggestion] [--status open\|resolved] [--limit N] [--offset N]` | List feedback, newest first |
90
- | `myapi feedback resolve <id>` | Close an item |
104
+ | `myapi feedback resolve <id>` | Close an item, keeping it |
105
+ | `myapi feedback delete <id>` | Erase an item — for spam, or personal details typed into the box |
91
106
  | `myapi feedback widget create <name> [--origins a.com,b.com]` | Mint a PUBLIC widget key for a site |
92
107
  | `myapi feedback widget revoke <id>` | Revoke a key; collected feedback is kept |
93
108
  <!-- generated:end -->
@@ -117,6 +132,9 @@ myapi feedback resolve <id>
117
132
  - The widget key is public by design — restrict it with `--origins` rather than hiding it.
118
133
  - `resolve` is idempotent and deliberately indistinguishable from an unknown id.
119
134
  - Feedback survives widget revocation.
135
+ - **`resolve` keeps, `delete` erases.** A public inbox collects spam and the
136
+ occasional report with personal details in it; `delete` is how those leave.
137
+ Both are idempotent and answer the same for an unknown id.
120
138
 
121
139
  ## HTTP (from deployed code)
122
140
 
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@myapihq/cli",
3
3
  "license": "Apache-2.0",
4
- "version": "2.11.2",
4
+ "version": "2.12.0",
5
5
  "description": "MyAPI command-line interface",
6
6
  "repository": {
7
7
  "type": "git",
@@ -46,7 +46,7 @@
46
46
  "lint:skills:strict": "node scripts/copy-skills.js && node scripts/lint-skills.js --strict"
47
47
  },
48
48
  "dependencies": {
49
- "@myapihq/sdk": "^2.11.2"
49
+ "@myapihq/sdk": "^2.12.0"
50
50
  },
51
51
  "devDependencies": {
52
52
  "@types/node": "^25.6.0",