alfy 1.1.0 → 2.1.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/cleanup.js CHANGED
@@ -6,14 +6,12 @@ import {execa} from 'execa';
6
6
 
7
7
  const __dirname = path.dirname(fileURLToPath(import.meta.url));
8
8
 
9
- (async () => {
10
- try {
11
- await execa('alfred-unlink', {
12
- preferLocal: true,
13
- localDir: __dirname,
14
- });
15
- } catch (error) {
16
- console.error(error);
17
- process.exit(1);
18
- }
19
- })();
9
+ try {
10
+ await execa('alfred-unlink', {
11
+ preferLocal: true,
12
+ localDir: __dirname,
13
+ });
14
+ } catch (error) {
15
+ console.error(error);
16
+ process.exit(1);
17
+ }
package/index.d.ts CHANGED
@@ -1,7 +1,7 @@
1
- import Conf from 'conf';
2
- import {Options} from 'got';
1
+ import type Conf from 'conf';
2
+ import {type Options} from 'got';
3
3
 
4
- export interface FetchOptions extends Partial<Options> {
4
+ export type FetchOptions = {
5
5
  /**
6
6
  Number of milliseconds this request should be cached.
7
7
  */
@@ -11,33 +11,37 @@ export interface FetchOptions extends Partial<Options> {
11
11
  Transform the response before it gets cached.
12
12
  */
13
13
  readonly transform?: (body: unknown) => unknown;
14
- }
14
+ } & Partial<Options>;
15
15
 
16
- export interface OutputOptions {
16
+ export type OutputOptions = {
17
17
  /**
18
18
  A script can be set to re-run automatically after some interval.
19
19
 
20
20
  The script will only be re-run if the script filter is still active and the user hasn't changed the state of the filter by typing and triggering a re-run. For example, it could be used to update the progress of a particular task:
21
21
  */
22
22
  readonly rerunInterval?: number;
23
- }
23
+ };
24
24
 
25
- export interface CacheConfGetOptions {
25
+ // eslint-disable-next-line unicorn/prevent-abbreviations
26
+ export type CacheConfGetOptions = {
26
27
  /**
27
28
  Get the item for the key provided without taking the `maxAge` of the item into account.
28
29
  */
29
30
  readonly ignoreMaxAge?: boolean;
30
- }
31
+ };
31
32
 
32
- export interface CacheConfSetOptions {
33
+ // eslint-disable-next-line unicorn/prevent-abbreviations
34
+ export type CacheConfSetOptions = {
33
35
  /**
34
36
  Number of milliseconds the cached value is valid.
35
37
  */
36
38
  readonly maxAge?: number;
37
- }
39
+ };
38
40
 
39
- export interface CacheConf<T> extends Conf<T> {
40
- isExpired: (key: T) => boolean;
41
+ // TODO: Rename this in the next major version.
42
+ // eslint-disable-next-line unicorn/prevent-abbreviations
43
+ export type CacheConf<T extends Record<string, any> = Record<string, unknown>> = {
44
+ isExpired: (key: keyof T) => boolean;
41
45
 
42
46
  get<Key extends keyof T>(key: Key, options?: CacheConfGetOptions): T[Key];
43
47
  get<Key extends keyof T>(key: Key, defaultValue: Required<T>[Key], options?: CacheConfGetOptions): Required<T>[Key];
@@ -48,7 +52,7 @@ export interface CacheConf<T> extends Conf<T> {
48
52
  set(key: string, value: unknown, options: CacheConfSetOptions): void;
49
53
  set(object: Partial<T>, options: CacheConfSetOptions): void;
50
54
  set<Key extends keyof T>(key: Partial<T> | Key | string, value?: T[Key] | unknown, options?: CacheConfSetOptions): void;
51
- }
55
+ } & Conf<T>;
52
56
 
53
57
  /**
54
58
  The icon displayed in the result row. Workflows are run from their workflow folder, so you can reference icons stored in your workflow relatively.
@@ -59,17 +63,17 @@ By using `{type: 'fileicon}`, Alfred will get the icon for the specified path.
59
63
 
60
64
  Finally, by using `{type: 'filetype'}`, you can get the icon of a specific file. For example, `{path: 'public.png'}`.
61
65
  */
62
- export interface IconElement {
66
+ export type IconElement = {
63
67
  readonly path?: string;
64
68
  readonly type?: 'fileicon' | 'filetype';
65
- }
69
+ };
66
70
 
67
71
  /**
68
72
  The text element defines the text the user will get when copying the selected result row with `⌘C` or displaying large type with `⌘L`.
69
73
 
70
74
  If these are not defined, you will inherit Alfred's standard behaviour where the argument is copied to the Clipboard or used for Large Type.
71
75
  */
72
- export interface TextElement {
76
+ export type TextElement = {
73
77
  /**
74
78
  User will get when copying the selected result row with `⌘C`.
75
79
  */
@@ -79,28 +83,28 @@ export interface TextElement {
79
83
  User will get displaying large type with `⌘L`.
80
84
  */
81
85
  readonly largetype?: string;
82
- }
86
+ };
83
87
 
84
88
  /**
85
89
  Defines what to change when the modifier key is pressed.
86
90
 
87
91
  When you release the modifier key, it returns to the original item.
88
92
  */
89
- export interface ModifierKeyItem {
93
+ export type ModifierKeyItem = {
90
94
  readonly valid?: boolean;
91
95
  readonly title?: string;
92
96
  readonly subtitle?: string;
93
97
  readonly arg?: string;
94
98
  readonly icon?: string;
95
99
  readonly variables?: Record<string, string>;
96
- }
100
+ };
97
101
 
98
102
  /**
99
103
  This element defines the Universal Action items used when actioning the result, and overrides arg being used for actioning.
100
104
 
101
105
  The action key can take a string or array for simple types, and the content type will automatically be derived by Alfred to file, URL or text.
102
106
  */
103
- export interface ActionElement {
107
+ export type ActionElement = {
104
108
  /**
105
109
  Forward text to Alfred.
106
110
  */
@@ -120,14 +124,14 @@ export interface ActionElement {
120
124
  Forward some value and let the value type be infered from Alfred.
121
125
  */
122
126
  readonly auto?: string | string[];
123
- }
127
+ };
124
128
 
125
129
  type PossibleModifiers = 'fn' | 'ctrl' | 'opt' | 'cmd' | 'shift';
126
130
 
127
131
  /**
128
132
  Each item describes a result row displayed in Alfred.
129
133
  */
130
- export interface ScriptFilterItem {
134
+ export type ScriptFilterItem = {
131
135
  /**
132
136
  This is a unique identifier for the item which allows help Alfred to learn about this item for subsequent sorting and ordering of the user's actioned results.
133
137
 
@@ -289,7 +293,7 @@ export interface ScriptFilterItem {
289
293
  Variables can be passed out of the script filter within a variables object.
290
294
  */
291
295
  readonly variables?: Record<string, string>;
292
- }
296
+ };
293
297
 
294
298
  /**
295
299
  Create Alfred workflows with ease
@@ -311,7 +315,7 @@ const items = alfy
311
315
  alfy.output(items);
312
316
  ```
313
317
  */
314
- export interface Alfy {
318
+ export type Alfy = {
315
319
  /**
316
320
  Return output to Alfred.
317
321
 
@@ -433,7 +437,7 @@ export interface Alfy {
433
437
  //=> '🦄'
434
438
  ```
435
439
  */
436
- config: Conf<Record<string, unknown>>;
440
+ config: Conf;
437
441
 
438
442
  /**
439
443
  Persist cache data.
@@ -450,7 +454,7 @@ export interface Alfy {
450
454
  //=> '🦄'
451
455
  ```
452
456
  */
453
- cache: CacheConf<unknown>;
457
+ cache: CacheConf;
454
458
 
455
459
  /**
456
460
  Get various default system icons.
@@ -542,7 +546,7 @@ export interface Alfy {
542
546
  ```
543
547
  */
544
548
  userConfig: Map<string, string>;
545
- }
549
+ };
546
550
 
547
551
  declare const alfy: Alfy;
548
552
 
package/index.js CHANGED
@@ -8,7 +8,7 @@ import loudRejection from 'loud-rejection';
8
8
  import cleanStack from 'clean-stack';
9
9
  import {getProperty} from 'dot-prop';
10
10
  import AlfredConfig from 'alfred-config';
11
- import updateNotification from './lib/update-notification.js';
11
+ import updateNotification from './lib/update-notification.js'; // eslint-disable-line import/order
12
12
 
13
13
  const require = createRequire(import.meta.url);
14
14
  const CacheConf = require('cache-conf');
@@ -100,6 +100,7 @@ ${process.platform} ${os.release()}
100
100
  };
101
101
 
102
102
  alfy.config = new Conf({
103
+ projectName: 'alfy',
103
104
  cwd: alfy.alfred.data,
104
105
  });
105
106
 
@@ -117,11 +118,6 @@ alfy.fetch = async (url, options) => {
117
118
  ...options,
118
119
  };
119
120
 
120
- // TODO: Remove this in 2024.
121
- if (options.query) {
122
- throw new Error('The `query` option was renamed to `searchParams`.');
123
- }
124
-
125
121
  if (typeof url !== 'string') {
126
122
  throw new TypeError(`Expected \`url\` to be a \`string\`, got \`${typeof url}\``);
127
123
  }
@@ -137,7 +133,7 @@ alfy.fetch = async (url, options) => {
137
133
  delete options.transform;
138
134
  delete options.maxAge;
139
135
 
140
- const key = rawKey.replace(/\./g, '\\.');
136
+ const key = rawKey.replaceAll('.', '\\.');
141
137
  const cachedResponse = alfy.cache.get(key, {ignoreMaxAge: true});
142
138
 
143
139
  if (cachedResponse && !alfy.cache.isExpired(key)) {
package/init.js CHANGED
@@ -6,21 +6,18 @@ import {execa} from 'execa';
6
6
 
7
7
  const __dirname = path.dirname(fileURLToPath(import.meta.url));
8
8
 
9
- (async () => {
10
- try {
11
- await execa('alfred-link', {
12
- preferLocal: true,
13
- localDir: __dirname,
14
- });
15
-
16
- await execa('alfred-config', {
17
- preferLocal: true,
18
- localDir: __dirname,
19
- stdio: 'inherit',
20
- });
21
- } catch (error) {
22
- console.error(error);
23
- process.exit(1);
24
- }
25
- })();
9
+ try {
10
+ await execa('alfred-link', {
11
+ preferLocal: true,
12
+ localDir: __dirname,
13
+ });
26
14
 
15
+ await execa('alfred-config', {
16
+ preferLocal: true,
17
+ localDir: __dirname,
18
+ stdio: 'inherit',
19
+ });
20
+ } catch (error) {
21
+ console.error(error);
22
+ process.exit(1);
23
+ }
@@ -1,9 +1,9 @@
1
- import {readPackageUp} from 'read-pkg-up';
1
+ 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: pkg} = await readPackageUp();
6
- const alfy = (pkg || {}).alfy || {};
5
+ const {package: package_} = await readPackageUp();
6
+ const alfy = package_?.alfy ?? {};
7
7
 
8
8
  if (alfy.updateNotification !== false) {
9
9
  alfredNotifier();
package/package.json CHANGED
@@ -1,18 +1,23 @@
1
1
  {
2
2
  "name": "alfy",
3
- "version": "1.1.0",
3
+ "version": "2.1.0",
4
4
  "description": "Create Alfred workflows with ease",
5
5
  "license": "MIT",
6
6
  "repository": "sindresorhus/alfy",
7
+ "funding": "https://github.com/sponsors/sindresorhus",
7
8
  "type": "module",
8
- "exports": "./index.js",
9
9
  "bin": {
10
10
  "run-node": "./run-node.sh",
11
11
  "alfy-init": "./init.js",
12
12
  "alfy-cleanup": "./cleanup.js"
13
13
  },
14
+ "exports": {
15
+ "types": "./index.d.ts",
16
+ "default": "./index.js"
17
+ },
18
+ "sideEffects": false,
14
19
  "engines": {
15
- "node": ">=14.13.1"
20
+ "node": ">=18"
16
21
  },
17
22
  "scripts": {
18
23
  "test": "xo && ava && tsd"
@@ -41,22 +46,26 @@
41
46
  "alfred-link": "^0.3.1",
42
47
  "alfred-notifier": "^0.2.3",
43
48
  "cache-conf": "^0.6.0",
44
- "clean-stack": "^4.1.0",
45
- "conf": "^10.1.1",
46
- "dot-prop": "^7.2.0",
47
- "execa": "^6.1.0",
48
- "got": "^12.0.3",
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",
49
54
  "hook-std": "^3.0.0",
50
55
  "loud-rejection": "^2.2.0",
51
- "read-pkg-up": "^9.1.0"
56
+ "read-package-up": "^11.0.0"
52
57
  },
53
58
  "devDependencies": {
54
- "ava": "^4.1.0",
55
- "delay": "^5.0.0",
56
- "nock": "^13.2.4",
57
- "tempfile": "^4.0.0",
58
- "tsd": "^0.19.1",
59
- "typescript": "^4.6.3",
60
- "xo": "^0.48.0"
59
+ "ava": "^6.1.3",
60
+ "delay": "^6.0.0",
61
+ "nock": "^13.5.4",
62
+ "tempfile": "^5.0.0",
63
+ "tsd": "^0.31.1",
64
+ "xo": "^0.59.2"
65
+ },
66
+ "tsd": {
67
+ "compilerOptions": {
68
+ "module": "node16"
69
+ }
61
70
  }
62
71
  }
package/readme.md CHANGED
@@ -17,7 +17,7 @@
17
17
 
18
18
  ## Prerequisites
19
19
 
20
- You need [Node.js 14+](https://nodejs.org) and [Alfred 4](https://www.alfredapp.com) with the paid [Powerpack](https://www.alfredapp.com/powerpack/) upgrade.
20
+ You need [Node.js 18+](https://nodejs.org) and [Alfred 4 or later](https://www.alfredapp.com) with the paid [Powerpack](https://www.alfredapp.com/powerpack/) upgrade.
21
21
 
22
22
  ## Install
23
23
 
@@ -103,7 +103,7 @@ By adding `alfy-init` as `postinstall` and `alfy-cleanup` as `preuninstall` scri
103
103
  "author": {
104
104
  "name": "Sindre Sorhus",
105
105
  "email": "sindresorhus@gmail.com",
106
- "url": "sindresorhus.com"
106
+ "url": "https://sindresorhus.com"
107
107
  },
108
108
  "scripts": {
109
109
  "postinstall": "alfy-init",
@@ -323,6 +323,29 @@ alfy.matches('Foo', list, (item, input) => item === input);
323
323
 
324
324
  Same as `matches()`, but with `alfy.input` as `input`.
325
325
 
326
+ If you want to match against multiple items, you must define your own matching function ([as shown here](#item)). Let’s extend the [example from the beginning](#example) to search for a keyword that appears either within the `title` or `body` property or both.
327
+
328
+ ```js
329
+ import alfy from 'alfy';
330
+
331
+ const data = await alfy.fetch('https://jsonplaceholder.typicode.com/posts');
332
+
333
+ const items = alfy
334
+ .inputMatches(
335
+ data,
336
+ (item, input) =>
337
+ item.title?.toLowerCase().includes(input) ||
338
+ item.body?.toLowerCase().includes(input)
339
+ )
340
+ .map((element) => ({
341
+ title: element.title,
342
+ subtitle: element.body,
343
+ arg: element.id,
344
+ }));
345
+
346
+ alfy.output(items);
347
+ ```
348
+
326
349
  #### error(error)
327
350
 
328
351
  Display an error or error message in Alfred.