alfy 2.1.0 → 3.0.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.
package/index.d.ts CHANGED
@@ -22,7 +22,6 @@ export type OutputOptions = {
22
22
  readonly rerunInterval?: number;
23
23
  };
24
24
 
25
- // eslint-disable-next-line unicorn/prevent-abbreviations
26
25
  export type CacheConfGetOptions = {
27
26
  /**
28
27
  Get the item for the key provided without taking the `maxAge` of the item into account.
@@ -30,7 +29,6 @@ export type CacheConfGetOptions = {
30
29
  readonly ignoreMaxAge?: boolean;
31
30
  };
32
31
 
33
- // eslint-disable-next-line unicorn/prevent-abbreviations
34
32
  export type CacheConfSetOptions = {
35
33
  /**
36
34
  Number of milliseconds the cached value is valid.
@@ -39,7 +37,7 @@ export type CacheConfSetOptions = {
39
37
  };
40
38
 
41
39
  // TODO: Rename this in the next major version.
42
- // eslint-disable-next-line unicorn/prevent-abbreviations
40
+
43
41
  export type CacheConf<T extends Record<string, any> = Record<string, unknown>> = {
44
42
  isExpired: (key: keyof T) => boolean;
45
43
 
@@ -367,9 +365,9 @@ export type Alfy = {
367
365
  /**
368
366
  Log value to the Alfred workflow debugger.
369
367
 
370
- @param text
368
+ @param value
371
369
  */
372
- log: (text: string) => void;
370
+ log: (value: unknown) => void;
373
371
 
374
372
  /**
375
373
  Display an error or error message in Alfred.
package/index.js CHANGED
@@ -3,18 +3,20 @@ import process from 'node:process';
3
3
  import {createRequire} from 'node:module';
4
4
  import Conf from 'conf';
5
5
  import got from 'got';
6
- import {hookStderr} from 'hook-std';
7
6
  import loudRejection from 'loud-rejection';
8
7
  import cleanStack from 'clean-stack';
9
8
  import {getProperty} from 'dot-prop';
10
9
  import AlfredConfig from 'alfred-config';
11
- import updateNotification from './lib/update-notification.js'; // eslint-disable-line import/order
10
+ import updateNotification from './lib/update-notification.js'; // eslint-disable-line import-x/order
12
11
 
13
12
  const require = createRequire(import.meta.url);
14
13
  const CacheConf = require('cache-conf');
15
14
 
16
15
  const alfy = {};
17
16
 
17
+ // Track if output has been generated to avoid empty JSON
18
+ let hasOutput = false;
19
+
18
20
  updateNotification();
19
21
 
20
22
  const getIcon = name => `/System/Library/CoreServices/CoreTypes.bundle/Contents/Resources/${name}.icns`;
@@ -42,6 +44,7 @@ alfy.alfred = {
42
44
  alfy.input = process.argv[2];
43
45
 
44
46
  alfy.output = (items, {rerunInterval} = {}) => {
47
+ hasOutput = true;
45
48
  console.log(JSON.stringify({items, rerun: rerunInterval}, null, '\t'));
46
49
  };
47
50
 
@@ -73,6 +76,7 @@ alfy.log = text => {
73
76
 
74
77
  alfy.error = error => {
75
78
  const stack = cleanStack(error.stack || error);
79
+ const title = error.stack ? `${error.name}: ${error.message}` : String(error);
76
80
 
77
81
  const copy = `
78
82
  \`\`\`
@@ -86,7 +90,7 @@ ${process.platform} ${os.release()}
86
90
  `.trim();
87
91
 
88
92
  alfy.output([{
89
- title: error.stack ? `${error.name}: ${error.message}` : error,
93
+ title,
90
94
  subtitle: 'Press ⌘L to see the full error and ⌘C to copy it.',
91
95
  valid: false,
92
96
  text: {
@@ -97,6 +101,9 @@ ${process.platform} ${os.release()}
97
101
  path: alfy.icon.error,
98
102
  },
99
103
  }]);
104
+
105
+ // Also output to stderr for the debugger (as requested in issue #86)
106
+ console.error(stack);
100
107
  };
101
108
 
102
109
  alfy.config = new Conf({
@@ -133,7 +140,7 @@ alfy.fetch = async (url, options) => {
133
140
  delete options.transform;
134
141
  delete options.maxAge;
135
142
 
136
- const key = rawKey.replaceAll('.', '\\.');
143
+ const key = rawKey.replaceAll('.', String.raw`\.`);
137
144
  const cachedResponse = alfy.cache.get(key, {ignoreMaxAge: true});
138
145
 
139
146
  if (cachedResponse && !alfy.cache.isExpired(key)) {
@@ -181,6 +188,12 @@ alfy.icon = {
181
188
 
182
189
  loudRejection(alfy.error);
183
190
  process.on('uncaughtException', alfy.error);
184
- hookStderr(alfy.error);
191
+
192
+ // Ensure valid JSON output even if user forgets to call alfy.output() (fixes #82)
193
+ process.on('beforeExit', () => {
194
+ if (!hasOutput) {
195
+ alfy.output([]);
196
+ }
197
+ });
185
198
 
186
199
  export default alfy;
@@ -2,7 +2,7 @@ import {readPackageUp} from 'read-package-up';
2
2
  import alfredNotifier from 'alfred-notifier';
3
3
 
4
4
  export default async function updateNotification() {
5
- const {package: package_} = await readPackageUp();
5
+ const {package: package_} = (await readPackageUp()) ?? {};
6
6
  const alfy = package_?.alfy ?? {};
7
7
 
8
8
  if (alfy.updateNotification !== false) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "alfy",
3
- "version": "2.1.0",
3
+ "version": "3.0.0",
4
4
  "description": "Create Alfred workflows with ease",
5
5
  "license": "MIT",
6
6
  "repository": "sindresorhus/alfy",
@@ -17,7 +17,7 @@
17
17
  },
18
18
  "sideEffects": false,
19
19
  "engines": {
20
- "node": ">=18"
20
+ "node": ">=20"
21
21
  },
22
22
  "scripts": {
23
23
  "test": "xo && ava && tsd"
@@ -47,21 +47,21 @@
47
47
  "alfred-notifier": "^0.2.3",
48
48
  "cache-conf": "^0.6.0",
49
49
  "clean-stack": "^5.2.0",
50
- "conf": "^13.0.1",
51
- "dot-prop": "^9.0.0",
52
- "execa": "^9.3.0",
53
- "got": "^14.4.2",
54
- "hook-std": "^3.0.0",
50
+ "conf": "^14.0.0",
51
+ "dot-prop": "^10.0.0",
52
+ "execa": "^9.6.0",
53
+ "got": "^14.4.8",
54
+ "hook-std": "^4.0.0",
55
55
  "loud-rejection": "^2.2.0",
56
56
  "read-package-up": "^11.0.0"
57
57
  },
58
58
  "devDependencies": {
59
- "ava": "^6.1.3",
59
+ "ava": "^6.4.1",
60
60
  "delay": "^6.0.0",
61
- "nock": "^13.5.4",
61
+ "nock": "^14.0.10",
62
62
  "tempfile": "^5.0.0",
63
- "tsd": "^0.31.1",
64
- "xo": "^0.59.2"
63
+ "tsd": "^0.33.0",
64
+ "xo": "^1.2.2"
65
65
  },
66
66
  "tsd": {
67
67
  "compilerOptions": {
package/readme.md CHANGED
@@ -151,13 +151,16 @@ test('main', async t => {
151
151
 
152
152
  ## Debugging
153
153
 
154
- When developing your workflow it can be useful to be able to debug it when something is not working. This is when the [workflow debugger](https://www.alfredapp.com/help/workflows/advanced/debugger/) comes in handy. You can find it in your workflow view in Alfred. Press the insect icon to open it. It will show you the plain text output of `alfy.output()` and anything you log with `alfy.log()`:
154
+ When developing your workflow it can be useful to be able to debug it when something is not working. This is when the [workflow debugger](https://www.alfredapp.com/help/workflows/advanced/debugger/) comes in handy. You can find it in your workflow view in Alfred. Press the insect icon to open it. It will show you the plain text output of `alfy.output()` and anything you log with `alfy.log()` or `console.error()`:
155
155
 
156
156
  ```js
157
157
  import alfy from 'alfy';
158
158
 
159
159
  const unicorn = getUnicorn();
160
160
  alfy.log(unicorn);
161
+
162
+ // You can also use console.error() for debugging
163
+ console.error('Debug info:', {data: someData});
161
164
  ```
162
165
 
163
166
  ## Environment variables
@@ -237,7 +240,7 @@ Log `value` to the [Alfred workflow debugger](https://www.alfredapp.com/help/wor
237
240
 
238
241
  #### matches(input, list, item?)
239
242
 
240
- Returns an `string[]` of items in `list` that case-insensitively contains `input`.
243
+ Returns a `string[]` of items in `list` that case-insensitively contains `input`.
241
244
 
242
245
  ```js
243
246
  import alfy from 'alfy';