td-ai-tools 1.2.10 → 1.2.11

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "td-ai-tools",
3
- "version": "1.2.10",
3
+ "version": "1.2.11",
4
4
  "description": "Install agent skills and packs into your project",
5
5
  "type": "module",
6
6
  "scripts": {
@@ -0,0 +1,21 @@
1
+ import { execFile } from 'node:child_process';
2
+ import { fileURLToPath } from 'node:url';
3
+ import { dirname, resolve } from 'node:path';
4
+ import { promisify } from 'node:util';
5
+
6
+ import { describe, expect, it } from 'vitest';
7
+
8
+ const run = promisify(execFile);
9
+ const packageRoot = resolve(dirname(fileURLToPath(import.meta.url)), '..');
10
+
11
+ describe('the published build', () => {
12
+ // `npm install` runs `npm run build` for this plugin, so a type error here
13
+ // breaks setup for every consumer of the shopify-lint skill.
14
+ it('typechecks under the build config', async () => {
15
+ const result = await run('npx', ['tsc', '-p', 'tsconfig.build.json', '--noEmit'], {
16
+ cwd: packageRoot,
17
+ }).catch((error: { stdout?: string; stderr?: string }) => error);
18
+
19
+ expect([result.stdout, result.stderr].filter(Boolean).join('\n')).toBe('');
20
+ }, 120_000);
21
+ });
@@ -13,6 +13,7 @@ describe('require-jsdoc', () => {
13
13
  '/** A component. */\nconst Hero = class extends HTMLElement {};',
14
14
  '/** Add two values.\n * @param {number} a First value.\n * @param {number} b Second value.\n * @returns {number} Their sum.\n */\nfunction add(a, b) { return a + b; }',
15
15
  '/** Run setup.\n * @returns {void}\n */\nconst setup = () => {};',
16
+ '/** Run setup.\n * @param {number} times How many times.\n * @returns {void}\n */\nconst setup = function (times) {};',
16
17
  '/** A component. */\nclass Hero { constructor() {}\n/** Open it.\n * @param {boolean} animated Whether to animate.\n * @returns {void}\n */\nopen(animated) {} }',
17
18
  ],
18
19
  invalid: [
@@ -25,7 +26,12 @@ describe('require-jsdoc', () => {
25
26
  code: '/** Run it.\n * @param value Value.\n * @returns Result.\n */\nconst run = (value) => value;',
26
27
  errors: [{ messageId: 'params' }, { messageId: 'returns' }],
27
28
  },
29
+ {
30
+ code: 'const setup = function (times) {};',
31
+ errors: [{ messageId: 'missing', data: { kind: 'function' } }],
32
+ },
28
33
  { code: 'class Hero {}', errors: [{ messageId: 'missing', data: { kind: 'class' } }] },
34
+ { code: 'const Hero = class extends HTMLElement {};', errors: [{ messageId: 'missing', data: { kind: 'class' } }] },
29
35
  {
30
36
  code: '/** A component. */\nclass Hero { open() {} }',
31
37
  errors: [{ messageId: 'missing', data: { kind: 'function' } }],
@@ -1,5 +1,16 @@
1
1
  import type { Rule, SourceCode } from 'eslint';
2
- import type { Comment, Node } from 'estree';
2
+ import type {
3
+ ArrowFunctionExpression,
4
+ ClassExpression,
5
+ Comment,
6
+ FunctionExpression,
7
+ Node,
8
+ } from 'estree';
9
+
10
+ // Selector keys such as `'VariableDeclarator > FunctionExpression.init'` fall
11
+ // through `RuleListener`'s index signature, so their `node` needs an explicit
12
+ // type. The visited node is the initializer, hence it always has a parent.
13
+ type Visited<T> = T & Rule.NodeParentExtension;
3
14
 
4
15
  function jsdocFor(node: Rule.Node, sourceCode: SourceCode): Comment | undefined {
5
16
  const comment = sourceCode.getCommentsBefore(node as Node).at(-1);
@@ -20,6 +31,11 @@ function typedTags(comment: Comment, tag: 'param' | 'returns' | 'return'): numbe
20
31
  return [...comment.value.matchAll(expression)].length;
21
32
  }
22
33
 
34
+ /** Walks from a `const x = <function|class>` initializer to its declaration statement. */
35
+ function declarationOf(node: Rule.Node): Rule.Node {
36
+ return (node.parent as Rule.Node).parent as Rule.Node;
37
+ }
38
+
23
39
  /** Require documented, explicitly typed named JavaScript declarations. */
24
40
  export const requireJsdoc: Rule.RuleModule = {
25
41
  meta: {
@@ -46,11 +62,11 @@ export const requireJsdoc: Rule.RuleModule = {
46
62
  return comment;
47
63
  }
48
64
 
49
- function checkFunction(node: Rule.Node & { params?: unknown[] }, reportNode: Rule.Node = node) {
65
+ function checkFunction(fn: { params?: unknown[] }, reportNode: Rule.Node) {
50
66
  const comment = checkDocumented(reportNode, 'function');
51
67
  if (!comment) return;
52
68
 
53
- const expected = node.params?.length ?? 0;
69
+ const expected = fn.params?.length ?? 0;
54
70
  if (typedTags(comment, 'param') < expected) {
55
71
  context.report({ node: reportNode, messageId: 'params', data: { expected: String(expected) } });
56
72
  }
@@ -63,17 +79,17 @@ export const requireJsdoc: Rule.RuleModule = {
63
79
  ClassDeclaration(node) {
64
80
  checkDocumented(node, 'class');
65
81
  },
66
- 'VariableDeclarator > ClassExpression.init'(node) {
67
- checkDocumented(node.parent.parent as Rule.Node, 'class');
82
+ 'VariableDeclarator > ClassExpression.init'(node: Visited<ClassExpression>) {
83
+ checkDocumented(declarationOf(node), 'class');
68
84
  },
69
85
  FunctionDeclaration(node) {
70
- checkFunction(node);
86
+ checkFunction(node, node);
71
87
  },
72
- 'VariableDeclarator > ArrowFunctionExpression.init'(node) {
73
- checkFunction(node, node.parent.parent as Rule.Node);
88
+ 'VariableDeclarator > ArrowFunctionExpression.init'(node: Visited<ArrowFunctionExpression>) {
89
+ checkFunction(node, declarationOf(node));
74
90
  },
75
- 'VariableDeclarator > FunctionExpression.init'(node) {
76
- checkFunction(node, node.parent.parent as Rule.Node);
91
+ 'VariableDeclarator > FunctionExpression.init'(node: Visited<FunctionExpression>) {
92
+ checkFunction(node, declarationOf(node));
77
93
  },
78
94
  MethodDefinition(node) {
79
95
  if (node.kind !== 'constructor') {