imdone-core 2.1.4 → 2.1.6

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.
@@ -0,0 +1,70 @@
1
+ name: Release
2
+
3
+ on:
4
+ push:
5
+ branches:
6
+ - master
7
+
8
+ permissions:
9
+ contents: write
10
+
11
+ concurrency:
12
+ group: release-${{ github.ref }}
13
+ cancel-in-progress: false
14
+
15
+ jobs:
16
+ release:
17
+ runs-on: ubuntu-latest
18
+
19
+ steps:
20
+ - name: Checkout
21
+ uses: actions/checkout@v4
22
+ with:
23
+ fetch-depth: 0
24
+
25
+ - name: Use Node.js
26
+ uses: actions/setup-node@v4
27
+ with:
28
+ node-version: 22.x
29
+ cache: npm
30
+
31
+ - name: Install dependencies
32
+ run: npm ci
33
+
34
+ - name: Test
35
+ run: npm test
36
+
37
+ - name: Read package version
38
+ id: package
39
+ run: |
40
+ VERSION="$(node -p "require('./package.json').version")"
41
+ echo "version=$VERSION" >> "$GITHUB_OUTPUT"
42
+ echo "tag=v$VERSION" >> "$GITHUB_OUTPUT"
43
+
44
+ - name: Check for existing release
45
+ id: release
46
+ env:
47
+ GH_TOKEN: ${{ github.token }}
48
+ TAG: ${{ steps.package.outputs.tag }}
49
+ run: |
50
+ if gh release view "$TAG" >/dev/null 2>&1; then
51
+ echo "exists=true" >> "$GITHUB_OUTPUT"
52
+ else
53
+ echo "exists=false" >> "$GITHUB_OUTPUT"
54
+ fi
55
+
56
+ - name: Create GitHub release
57
+ if: steps.release.outputs.exists == 'false'
58
+ env:
59
+ GH_TOKEN: ${{ github.token }}
60
+ TAG: ${{ steps.package.outputs.tag }}
61
+ VERSION: ${{ steps.package.outputs.version }}
62
+ run: |
63
+ gh release create "$TAG" \
64
+ --target "$GITHUB_SHA" \
65
+ --title "$VERSION" \
66
+ --generate-notes
67
+
68
+ - name: Skip existing release
69
+ if: steps.release.outputs.exists == 'true'
70
+ run: echo "Release ${{ steps.package.outputs.tag }} already exists; skipping."
package/.imdone-cli.yml CHANGED
@@ -1,2 +1,3 @@
1
1
  backlogDir: backlog
2
- provider: jira
2
+ providers:
3
+ - github
package/CHANGELOG.md CHANGED
@@ -1,3 +1,15 @@
1
+ ## 2.1.5
2
+
3
+ - Create GitHub releases automatically from the npm package version when changes merge to `master`.
4
+ - Improve test coverage for environment detection, board actions, views, and view retrieval.
5
+ - Add enforced coverage thresholds to prevent coverage regressions.
6
+ - Update `monquery` to `0.2.2`.
7
+ - Update the imdone CLI project config to use the GitHub provider format.
8
+
9
+ ## 2.1.4
10
+
11
+ - Remove the deprecated `node-fetch` dependency from plugin downloads so installs no longer pull in `node-domexception`.
12
+
1
13
  ## 2.1.3
2
14
 
3
15
  - Update imdone-api dependency
package/lib/file.js CHANGED
@@ -535,16 +535,38 @@ export class File extends Emitter {
535
535
  }
536
536
  }
537
537
  extractTasks (config) {
538
+ // INSTRUMENTATION: Track timing for hang investigation
539
+ const startTime = Date.now()
540
+ log(`[INSTRUMENT] File.extractTasks START for ${this.path}`)
541
+
538
542
  this.tasks = []
539
543
  if (this.isMarkDownFile()) {
540
544
  const data = this.parseFrontMatter(config)
541
- if (data.imdone_ignore || data['kanban-plugin']) return this
545
+ if (data.imdone_ignore || data['kanban-plugin']) {
546
+ log(`[INSTRUMENT] File.extractTasks END (ignored) - ${Date.now() - startTime}ms`)
547
+ return this
548
+ }
542
549
  }
550
+
551
+ const frontMatterTime = Date.now()
552
+ log(`[INSTRUMENT] Front matter check took ${frontMatterTime - startTime}ms`)
553
+
543
554
  if (this.isCodeFile()) {
555
+ log(`[INSTRUMENT] About to extractTasksInCodeFile`)
544
556
  this.extractTasksInCodeFile(config)
557
+ log(`[INSTRUMENT] extractTasksInCodeFile took ${Date.now() - frontMatterTime}ms`)
545
558
  } else {
559
+ log(`[INSTRUMENT] About to extractTasksInNonCodeFile`)
546
560
  this.extractTasksInNonCodeFile(config)
561
+ log(`[INSTRUMENT] extractTasksInNonCodeFile took ${Date.now() - frontMatterTime}ms`)
562
+ }
563
+
564
+ const totalTime = Date.now() - startTime
565
+ if (totalTime > 1000) {
566
+ log(`[INSTRUMENT] ⚠️ SLOW File.extractTasks: ${this.path} took ${totalTime}ms`)
547
567
  }
568
+ log(`[INSTRUMENT] File.extractTasks END - total ${totalTime}ms`)
569
+
548
570
  return this
549
571
  }
550
572
 
@@ -560,20 +582,62 @@ export class File extends Emitter {
560
582
  // order:40
561
583
  // -->
562
584
  extractTasksInCodeFile (config) {
585
+ // INSTRUMENTATION: Track regex iterations
586
+ const startTime = Date.now()
563
587
  var self = this
564
588
  var commentRegex = this.getCodeCommentRegex()
589
+ log(`[INSTRUMENT] getCodeCommentRegex took ${Date.now() - startTime}ms`)
590
+
565
591
  var result
592
+ var iterationCount = 0
593
+ const contentLength = self.getContent()?.length || 0
594
+ log(`[INSTRUMENT] Starting regex loop, content length: ${contentLength}`)
595
+
566
596
  while ((result = commentRegex.exec(self.getContent())) !== null) {
597
+ iterationCount++
598
+ if (iterationCount % 100 === 0) {
599
+ log(`[INSTRUMENT] Regex iteration ${iterationCount}, elapsed: ${Date.now() - startTime}ms`)
600
+ }
601
+
567
602
  var comment = result[0]
568
603
  var commentStart = result.index
569
604
  self.extractCodeStyleTasks(config, commentStart, comment)
605
+
606
+ // Safety check for infinite loop
607
+ if (iterationCount > 10000) {
608
+ log(`[INSTRUMENT] ⚠️ WARNING: Exceeded 10000 regex iterations, breaking loop`)
609
+ break
610
+ }
570
611
  }
612
+
613
+ const totalTime = Date.now() - startTime
614
+ log(`[INSTRUMENT] extractTasksInCodeFile END - ${iterationCount} iterations, ${totalTime}ms`)
571
615
  }
572
616
 
573
617
  extractTasksInNonCodeFile (config) {
574
- this.extractHashStyleTasks(config, 0, this.getContent())
575
- this.extractLinkStyleTasks(config, 0, this.getContent())
576
- this.extractCheckboxTasks(config, 0, this.getContent())
618
+ // INSTRUMENTATION: Track each extraction method
619
+ const startTime = Date.now()
620
+ const content = this.getContent()
621
+ const contentLength = content?.length || 0
622
+ log(`[INSTRUMENT] extractTasksInNonCodeFile START, content length: ${contentLength}`)
623
+
624
+ log(`[INSTRUMENT] About to extractHashStyleTasks`)
625
+ this.extractHashStyleTasks(config, 0, content)
626
+ const hashTime = Date.now()
627
+ log(`[INSTRUMENT] extractHashStyleTasks took ${hashTime - startTime}ms`)
628
+
629
+ log(`[INSTRUMENT] About to extractLinkStyleTasks`)
630
+ this.extractLinkStyleTasks(config, 0, content)
631
+ const linkTime = Date.now()
632
+ log(`[INSTRUMENT] extractLinkStyleTasks took ${linkTime - hashTime}ms`)
633
+
634
+ log(`[INSTRUMENT] About to extractCheckboxTasks`)
635
+ this.extractCheckboxTasks(config, 0, content)
636
+ const checkboxTime = Date.now()
637
+ log(`[INSTRUMENT] extractCheckboxTasks took ${checkboxTime - linkTime}ms`)
638
+
639
+ const totalTime = Date.now() - startTime
640
+ log(`[INSTRUMENT] extractTasksInNonCodeFile END - total ${totalTime}ms`)
577
641
  }
578
642
 
579
643
  deleteBlankLine (lineNo) {
package/lib/repository.js CHANGED
@@ -755,20 +755,54 @@ export class Repository extends Emitter {
755
755
  // order:-100
756
756
  // -->
757
757
  async extractTasks (file) {
758
+ // INSTRUMENTATION: Track timing for hang investigation
759
+ const extractStartTime = Date.now()
760
+ logger.debug(`[INSTRUMENT] extractTasks START for ${file.path}`)
761
+
758
762
  if (file.content === null) {
759
763
  await this.readFileContent(file)
760
764
  }
765
+
766
+ const readTime = Date.now()
767
+ logger.debug(`[INSTRUMENT] readFileContent took ${readTime - extractStartTime}ms`)
768
+
761
769
  file.on('task.found', this.taskFoundListener)
762
770
  file.on('task.modified', this.taskModifiedListener)
763
771
  const fileContent = file.content
772
+
773
+ logger.debug(`[INSTRUMENT] About to call extractAndTransformTasks, content length: ${fileContent?.length || 0}`)
764
774
  file.extractAndTransformTasks(this.getConfig())
775
+
776
+ const transformTime = Date.now()
777
+ logger.debug(`[INSTRUMENT] extractAndTransformTasks took ${transformTime - readTime}ms`)
778
+
765
779
  if (!file.isModified() || fileContent === file.content) {
766
780
  this.resetFile(file)
781
+ const totalTime = Date.now() - extractStartTime
782
+ logger.debug(`[INSTRUMENT] extractTasks END (no changes) - total ${totalTime}ms`)
767
783
  return file
768
784
  }
785
+
786
+ logger.debug(`[INSTRUMENT] About to call file.extractTasks`)
769
787
  file.extractTasks(this.getConfig())
770
- if (file.modified) await this.writeFile(file)
788
+
789
+ const extractTime = Date.now()
790
+ logger.debug(`[INSTRUMENT] file.extractTasks took ${extractTime - transformTime}ms`)
791
+
792
+ if (file.modified) {
793
+ logger.debug(`[INSTRUMENT] About to writeFile`)
794
+ await this.writeFile(file)
795
+ logger.debug(`[INSTRUMENT] writeFile took ${Date.now() - extractTime}ms`)
796
+ }
797
+
771
798
  this.resetFile(file)
799
+
800
+ const totalTime = Date.now() - extractStartTime
801
+ if (totalTime > 1000) {
802
+ logger.warn(`[INSTRUMENT] ⚠️ SLOW extractTasks: ${file.path} took ${totalTime}ms`)
803
+ }
804
+ logger.debug(`[INSTRUMENT] extractTasks END - total ${totalTime}ms`)
805
+
772
806
  return file
773
807
  }
774
808
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "imdone-core",
3
- "version": "2.1.4",
3
+ "version": "2.1.6",
4
4
  "description": "imdone-core",
5
5
  "repository": {
6
6
  "type": "git",
@@ -84,7 +84,7 @@
84
84
  "markdown-it-emoji": "^2.0.0",
85
85
  "markdown-it-mark": "^3.0.1",
86
86
  "moment": "^2.29.1",
87
- "monquery": "github:imdone/node-monquery#0.2.1",
87
+ "monquery": "github:imdone/node-monquery#0.2.2",
88
88
  "multilang-extract-comments": "^0.4.0",
89
89
  "open": "^9.1.0",
90
90
  "ora": "^8.2.0",
package/vitest.config.js CHANGED
@@ -2,14 +2,25 @@ import { defineConfig } from 'vitest/config';
2
2
 
3
3
  export default defineConfig({
4
4
  test: {
5
- include: ['lib/**/*.spec.js'], // Only look for test files inside src/
5
+ include: ['lib/**/*.spec.js'],
6
6
  coverage: {
7
- provider: "v8", // or "istanbul" if using @vitest/coverage-istanbul
8
- reporter: ["text"], // Ensure text output is included
7
+ provider: "v8",
8
+ reporter: ["text"],
9
9
  clean: false,
10
10
  reportOnFailure: true,
11
- include: ['lib'], // Only include files from src/
12
- exclude: ['_lib', 'lib/**/index.*']
11
+ include: ['lib/**/*.js'],
12
+ exclude: [
13
+ '_lib',
14
+ 'lib/**/index.*',
15
+ 'lib/**/__tests__/**',
16
+ 'lib/**/*.spec.js',
17
+ ],
18
+ thresholds: {
19
+ statements: 87,
20
+ branches: 83,
21
+ functions: 80,
22
+ lines: 87,
23
+ },
13
24
  },
14
25
  },
15
26
  });