imdone-core 1.54.10 → 2.0.1
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/.dependency-cruiser.cjs +412 -0
- package/.github/workflows/ci.yml +2 -2
- package/.imdoneignore +2 -1
- package/README.md +2 -2
- package/_index.md +7 -0
- package/build.js +57 -0
- package/esm-migration.md +446 -0
- package/lib/FileProjectContext.js +13 -0
- package/lib/ProjectContext.js +19 -18
- package/lib/adapters/date-time.js +3 -8
- package/lib/adapters/environment.js +3 -0
- package/lib/adapters/file-gateway.js +133 -106
- package/lib/adapters/git-download.js +36 -16
- package/lib/adapters/index.js +9 -0
- package/lib/adapters/logger.js +136 -0
- package/lib/adapters/markdown.js +31 -19
- package/lib/adapters/parsers/DateLanguageParser.js +11 -9
- package/lib/adapters/parsers/content-transformer.js +35 -30
- package/lib/adapters/parsers/file/LocalFileParserFactory.js +8 -9
- package/lib/adapters/parsers/file/ReadStreamCodeParser.js +8 -8
- package/lib/adapters/parsers/file/ReadStreamMarkdownParser.js +4 -4
- package/lib/adapters/parsers/file/ReadStreamTaskParser.js +5 -3
- package/lib/adapters/parsers/file/index.js +4 -0
- package/lib/adapters/parsers/function-parser.js +1 -5
- package/lib/adapters/parsers/index.js +5 -0
- package/lib/adapters/parsers/task/CardContentParser.js +23 -32
- package/lib/adapters/parsers/task/CheckStyleTaskParser.js +2 -2
- package/lib/adapters/parsers/task/CodeStyleTaskParser.js +2 -2
- package/lib/adapters/parsers/task/HashStyleTaskParser.js +3 -3
- package/lib/adapters/parsers/task/MarkdownStyleTaskParser.js +2 -2
- package/lib/adapters/parsers/task/TaskParser.js +1 -1
- package/lib/adapters/parsers/task/index.js +6 -0
- package/lib/adapters/storage/config.js +15 -20
- package/lib/adapters/storage/index.js +2 -0
- package/lib/adapters/storage/tags.js +11 -12
- package/lib/adapters/yaml.js +8 -5
- package/lib/card.js +25 -26
- package/lib/checksum.js +22 -0
- package/lib/cli.js +114 -0
- package/lib/config.js +106 -71
- package/lib/constants.js +21 -50
- package/lib/context/ApplicationContext.js +7 -4
- package/lib/context/index.js +1 -0
- package/lib/default-settings.js +3 -3
- package/lib/domain/entities/View.js +4 -11
- package/lib/domain/entities/index.js +1 -0
- package/lib/domain/index.js +2 -0
- package/lib/domain/usecases/GetViewsUsecase.js +6 -12
- package/lib/domain/usecases/SaveViewUsecase.js +8 -14
- package/lib/domain/usecases/index.js +2 -0
- package/lib/file.js +1158 -1162
- package/lib/get-tasks-to-modify.js +117 -0
- package/lib/index.js +23 -0
- package/lib/languages.js +4 -5
- package/lib/list.js +46 -95
- package/lib/migrate-config.js +5 -5
- package/lib/mixins/index.js +2 -0
- package/lib/mixins/repo-fs-store.js +224 -289
- package/lib/mixins/repo-watched-fs-store.js +158 -147
- package/lib/plugins/archive-plugin.js +10 -8
- package/lib/plugins/default-board-actions-plugin.js +2 -2
- package/lib/plugins/default-board-properties-plugin.js +7 -7
- package/lib/plugins/default-plugins.js +7 -0
- package/lib/plugins/epic-plugin.js +6 -5
- package/lib/plugins/extension-plugin.js +24 -17
- package/lib/plugins/index.js +9 -0
- package/lib/plugins/persist-tags-plugin.js +4 -3
- package/lib/plugins/plugin-manager.js +89 -52
- package/lib/plugins/plugin-registry.js +12 -16
- package/lib/project-factory.js +21 -24
- package/lib/project.js +97 -144
- package/lib/repository.js +1323 -1555
- package/lib/task.js +562 -580
- package/lib/tools.js +39 -113
- package/lib/usecases/actions.js +32 -0
- package/lib/usecases/get-project-tags.js +3 -12
- package/lib/usecases/get-tasks-in-file.js +4 -7
- package/lib/usecases/index.js +4 -0
- package/package.json +44 -66
- package/scripts/delete-markdown-indexes.js +87 -0
- package/scripts/generate-index.js +35 -0
- package/{index-markdown.js → scripts/index-markdown.js} +7 -7
- package/tsconfig.json +15 -0
- package/types/FileProjectContext.d.ts +4 -0
- package/types/ProjectContext.d.ts +9 -0
- package/types/adapters/date-time.d.ts +2 -0
- package/types/adapters/environment.d.ts +1 -0
- package/types/adapters/file-gateway.d.ts +51 -0
- package/types/adapters/git-download.d.ts +1 -0
- package/types/adapters/index.d.ts +9 -0
- package/types/adapters/logger.d.ts +24 -0
- package/types/adapters/markdown.d.ts +13 -0
- package/types/adapters/parsers/DateLanguageParser.d.ts +1 -0
- package/types/adapters/parsers/content-transformer.d.ts +10 -0
- package/types/adapters/parsers/file/LocalFileParserFactory.d.ts +5 -0
- package/types/adapters/parsers/file/ReadStreamCodeParser.d.ts +13 -0
- package/types/adapters/parsers/file/ReadStreamMarkdownParser.d.ts +7 -0
- package/types/adapters/parsers/file/ReadStreamTaskParser.d.ts +19 -0
- package/types/adapters/parsers/file/index.d.ts +4 -0
- package/types/adapters/parsers/function-parser.d.ts +1 -0
- package/types/adapters/parsers/index.d.ts +5 -0
- package/types/adapters/parsers/task/CardContentParser.d.ts +45 -0
- package/types/adapters/parsers/task/CheckStyleTaskParser.d.ts +12 -0
- package/types/adapters/parsers/task/CodeStyleTaskParser.d.ts +14 -0
- package/types/adapters/parsers/task/HashStyleTaskParser.d.ts +13 -0
- package/types/adapters/parsers/task/MarkdownStyleTaskParser.d.ts +14 -0
- package/types/adapters/parsers/task/TaskParser.d.ts +7 -0
- package/types/adapters/parsers/task/index.d.ts +6 -0
- package/types/adapters/storage/config.d.ts +6 -0
- package/types/adapters/storage/index.d.ts +2 -0
- package/types/adapters/storage/tags.d.ts +3 -0
- package/types/adapters/yaml.d.ts +2 -0
- package/types/card.d.ts +166 -0
- package/types/checksum.d.ts +8 -0
- package/types/config.d.ts +61 -0
- package/types/constants.d.ts +46 -0
- package/types/context/ApplicationContext.d.ts +24 -0
- package/types/context/index.d.ts +1 -0
- package/types/default-settings.d.ts +2 -0
- package/types/domain/entities/FileProjectContext.d.ts +5 -0
- package/types/domain/entities/View.d.ts +17 -0
- package/types/domain/entities/index.d.ts +1 -0
- package/types/domain/index.d.ts +2 -0
- package/types/domain/usecases/GetViewsUsecase.d.ts +4 -0
- package/types/domain/usecases/SaveViewUsecase.d.ts +8 -0
- package/types/domain/usecases/index.d.ts +2 -0
- package/types/file.d.ts +344 -0
- package/types/get-tasks-to-modify.d.ts +3 -0
- package/types/index.d.ts +23 -0
- package/types/languages.d.ts +649 -0
- package/types/list.d.ts +30 -0
- package/types/migrate-config.d.ts +1 -0
- package/types/mixins/index.d.ts +2 -0
- package/types/mixins/repo-fs-store.d.ts +2 -0
- package/types/mixins/repo-watched-fs-store.d.ts +2 -0
- package/types/plugins/archive-plugin.d.ts +8 -0
- package/types/plugins/default-board-actions-plugin.d.ts +9 -0
- package/types/plugins/default-board-properties-plugin.d.ts +16 -0
- package/types/plugins/default-plugins.d.ts +6 -0
- package/types/plugins/epic-plugin.d.ts +19 -0
- package/types/plugins/extension-plugin.d.ts +15 -0
- package/types/plugins/index.d.ts +9 -0
- package/types/plugins/persist-tags-plugin.d.ts +4 -0
- package/types/plugins/plugin-manager.d.ts +68 -0
- package/types/plugins/plugin-registry.d.ts +1 -0
- package/types/project-factory.d.ts +14 -0
- package/types/project.d.ts +158 -0
- package/types/repository.d.ts +996 -0
- package/types/task.d.ts +202 -0
- package/types/tools.d.ts +29 -0
- package/types/usecases/actions.d.ts +7 -0
- package/types/usecases/get-imdone-url.d.ts +1 -0
- package/types/usecases/get-project-tags.d.ts +1 -0
- package/types/usecases/get-tasks-in-file.d.ts +4 -0
- package/types/usecases/index.d.ts +4 -0
- package/vitest.config.js +13 -0
- package/cli.js +0 -74
- package/index.js +0 -1
- package/lib/adapters/readers/FileSystemProjectReader.js +0 -45
- package/lib/context/StreamingApplicationContext.js +0 -31
- package/lib/controlers/SaveViewController.js +0 -10
- package/lib/domain/entities/FileProjectContext.js +0 -10
- package/lib/domain/usecases/OpenProjectUsecase.js +0 -13
|
@@ -1,194 +1,205 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
module.exports = mixin
|
|
1
|
+
import { fileSystemStoreMixin } from './repo-fs-store.js'
|
|
2
|
+
import debug from 'debug'
|
|
3
|
+
const log = debug('imdone-mixins:repo-watched-fs-store')
|
|
4
|
+
import { File } from '../file.js'
|
|
5
|
+
import { constants } from '../constants.js'
|
|
6
|
+
import chokidar from 'chokidar'
|
|
7
|
+
import realFs from 'fs'
|
|
8
|
+
import { logger } from '../adapters/logger.js'
|
|
10
9
|
|
|
11
10
|
// BACKLOG Only emit file.update if the file checksum has changed
|
|
12
11
|
// <!--
|
|
13
12
|
// order:-650
|
|
14
13
|
// -->
|
|
15
|
-
function
|
|
16
|
-
repo =
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
14
|
+
export function watchedFileSystemStoreMixin(repo, fs = realFs) {
|
|
15
|
+
repo = fileSystemStoreMixin(repo, fs)
|
|
16
|
+
const _refresh = repo.refresh
|
|
17
|
+
const _destroy = repo.destroy
|
|
18
|
+
const _init = repo.init
|
|
19
|
+
let initializing = false
|
|
20
|
+
let refreshing = false
|
|
21
|
+
|
|
22
|
+
function ready() {
|
|
23
|
+
return !initializing && !refreshing
|
|
24
|
+
}
|
|
21
25
|
|
|
22
|
-
|
|
26
|
+
async function waitForReady() {
|
|
27
|
+
while (!ready()) {
|
|
28
|
+
logger.log('Waiting for repo to be ready:', repo.path)
|
|
29
|
+
await new Promise(resolve => setTimeout(resolve, 500))
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
// READY Refactor init to async/await
|
|
34
|
+
// #esm-migration #important
|
|
35
|
+
// <!--
|
|
36
|
+
// order:-310
|
|
37
|
+
// -->
|
|
38
|
+
repo.init = async function () {
|
|
23
39
|
if (initializing) {
|
|
24
|
-
|
|
25
|
-
console.error(err.message)
|
|
26
|
-
return cb ? cb(err) : null
|
|
40
|
+
throw new Error("Can't initialize repo while it's initializing.")
|
|
27
41
|
}
|
|
28
42
|
log('Initializing repo:', repo.path)
|
|
29
43
|
initializing = true
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
})
|
|
44
|
+
try {
|
|
45
|
+
const files = await _init.call(repo)
|
|
46
|
+
await repo.initWatcher()
|
|
47
|
+
repo.emit('watching', { ok: true, lists: repo.getLists() })
|
|
48
|
+
initializing = false
|
|
49
|
+
return files
|
|
50
|
+
} catch (err) {
|
|
51
|
+
initializing = false
|
|
52
|
+
throw new Error(`Error initializing repo: ${repo.path}`, { cause: err })
|
|
53
|
+
}
|
|
41
54
|
}
|
|
42
55
|
|
|
43
|
-
repo.destroy = function () {
|
|
44
|
-
if (repo.watcher) repo.watcher.close()
|
|
45
|
-
_destroy.apply(repo)
|
|
56
|
+
repo.destroy = async function () {
|
|
57
|
+
if (repo.watcher) await repo.watcher.close()
|
|
58
|
+
await _destroy.apply(repo)
|
|
46
59
|
}
|
|
47
60
|
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
61
|
+
// READY Refactor refresh to async/await
|
|
62
|
+
// #esm-migration #important
|
|
63
|
+
// <!--
|
|
64
|
+
// order:-330
|
|
65
|
+
// -->
|
|
66
|
+
repo.refresh = async function () {
|
|
67
|
+
await waitForReady()
|
|
68
|
+
log('Refreshing repo:', repo.path)
|
|
69
|
+
refreshing = true
|
|
70
|
+
try {
|
|
71
|
+
const files = await _refresh.call(repo)
|
|
72
|
+
await repo.initWatcher()
|
|
73
|
+
refreshing = false
|
|
74
|
+
return files
|
|
75
|
+
} catch (err) {
|
|
76
|
+
refreshing = false
|
|
77
|
+
throw new Error(`Error refreshing repo: ${repo.path}`, { cause: err })
|
|
51
78
|
}
|
|
52
|
-
|
|
53
|
-
initializing = true
|
|
54
|
-
if (repo.watcher) repo.watcher.close()
|
|
55
|
-
_refresh.call(repo, function (err, files) {
|
|
56
|
-
if (err) {
|
|
57
|
-
initializing = false
|
|
58
|
-
return cb ? cb(err) : null
|
|
59
|
-
}
|
|
60
|
-
repo.initWatcher(() => {
|
|
61
|
-
initializing = false
|
|
62
|
-
return cb ? cb(err, files) : null
|
|
63
|
-
})
|
|
64
|
-
})
|
|
79
|
+
|
|
65
80
|
}
|
|
66
81
|
|
|
67
|
-
|
|
82
|
+
function _isImdoneConfig(path) {
|
|
68
83
|
return path === constants.CONFIG_FILE_YML
|
|
69
84
|
}
|
|
70
85
|
|
|
71
|
-
|
|
86
|
+
function _isImdoneIgnore(path) {
|
|
72
87
|
return path === constants.IGNORE_FILE
|
|
73
88
|
}
|
|
74
89
|
|
|
75
|
-
|
|
76
|
-
|
|
90
|
+
async function onConfigChange(file) {
|
|
91
|
+
logger.info('Loading config. Observed a change to:', file)
|
|
77
92
|
const label = `Refresh repo: ${repo.path}`
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
console.timeEnd(label)
|
|
93
|
+
logger.time(label)
|
|
94
|
+
try {
|
|
95
|
+
await repo.refresh()
|
|
82
96
|
repo.emitConfigUpdate(file, repo.config)
|
|
83
|
-
}
|
|
97
|
+
} finally {
|
|
98
|
+
logger.timeEnd(label)
|
|
99
|
+
}
|
|
84
100
|
}
|
|
85
101
|
|
|
86
102
|
const onIgnoreChange = onConfigChange
|
|
87
103
|
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
repo.watcher
|
|
110
|
-
.on('error', (err) => {
|
|
111
|
-
console.error('Error in watcher')
|
|
112
|
-
console.error(err)
|
|
113
|
-
cb(err)
|
|
114
|
-
})
|
|
115
|
-
.on('ready', () => {
|
|
116
|
-
console.log('watcher ready for:', repo.path)
|
|
117
|
-
initializing = false
|
|
118
|
-
cb()
|
|
119
|
-
})
|
|
120
|
-
.on('add', function (path, root, stat) {
|
|
121
|
-
console.log('Watcher received add event for file: ' + path)
|
|
122
|
-
if (stat.isDirectory()) return
|
|
123
|
-
var file = repo.getFile(path)
|
|
124
|
-
if (file === undefined) {
|
|
125
|
-
log('Creating file: ' + path)
|
|
126
|
-
file = new File({
|
|
127
|
-
repoId: repo.getId(),
|
|
128
|
-
filePath: path,
|
|
129
|
-
languages: repo.languages,
|
|
130
|
-
project: repo.project,
|
|
131
|
-
})
|
|
104
|
+
// READY Refactor initWatcher to async/await
|
|
105
|
+
// #esm-migration #important
|
|
106
|
+
// <!--
|
|
107
|
+
// order:-320
|
|
108
|
+
// defer:2025-03-18
|
|
109
|
+
// -->
|
|
110
|
+
repo.initWatcher = async () => {
|
|
111
|
+
return new Promise(async (resolve, reject) => {
|
|
112
|
+
logger.log('initializing watcher for:', repo.path)
|
|
113
|
+
repo.watcher = chokidar.watch(repo.path, {
|
|
114
|
+
persistent: true,
|
|
115
|
+
usePolling: false,
|
|
116
|
+
alwaysStat: true,
|
|
117
|
+
awaitWriteFinish: true,
|
|
118
|
+
atomic: true,
|
|
119
|
+
ignoreInitial: true,
|
|
120
|
+
ignored: (file) => {
|
|
121
|
+
const ignored = !repo.shouldInclude(file)
|
|
122
|
+
if (ignored) logger.log('Ignoring file:', file)
|
|
123
|
+
return ignored
|
|
132
124
|
}
|
|
125
|
+
}).on('error', (err) => {
|
|
126
|
+
logger.error('Error in watcher')
|
|
127
|
+
logger.error(err)
|
|
128
|
+
repo.emit('watch.error', err)
|
|
129
|
+
reject(err)
|
|
130
|
+
})
|
|
131
|
+
.on('ready', () => {
|
|
132
|
+
logger.log('watcher ready for:', repo.path)
|
|
133
|
+
initializing = false
|
|
134
|
+
resolve()
|
|
135
|
+
})
|
|
136
|
+
.on('add', async function (path, stat) {
|
|
137
|
+
logger.log('Watcher received add event for file: ' + path)
|
|
138
|
+
if (stat.isDirectory()) return
|
|
139
|
+
let file = repo.getFile(path)
|
|
140
|
+
if (file === undefined) {
|
|
141
|
+
log('Creating file: ' + path)
|
|
142
|
+
file = new File({
|
|
143
|
+
repoId: repo.getId(),
|
|
144
|
+
filePath: path,
|
|
145
|
+
languages: repo.languages,
|
|
146
|
+
project: repo.project,
|
|
147
|
+
})
|
|
148
|
+
}
|
|
133
149
|
|
|
134
|
-
|
|
150
|
+
stat = await repo.fileOK()
|
|
135
151
|
log('fileOK returned: ' + JSON.stringify(stat))
|
|
136
|
-
if (err || !stat) return
|
|
137
152
|
if (stat.mtime <= file.getModifiedTime()) {
|
|
138
153
|
return log('File update already applied. Change ignored for file: ' + path)
|
|
139
154
|
}
|
|
140
155
|
log('Reading file: ' + path)
|
|
141
|
-
repo.readFile(file
|
|
142
|
-
|
|
143
|
-
|
|
156
|
+
file = await repo.readFile(file)
|
|
157
|
+
repo.emi('watch.add', file)
|
|
158
|
+
repo.emitFileUpdate(file)
|
|
144
159
|
})
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
// console.log("File update already applied. Change ignored.")
|
|
161
|
-
return
|
|
162
|
-
}
|
|
163
|
-
if (_isImdoneConfig(path)) return onConfigChange(path)
|
|
164
|
-
if (_isImdoneIgnore(path)) return onIgnoreChange(path)
|
|
165
|
-
|
|
166
|
-
repo.fileOK((file && file.path) || path, function (err, ok) {
|
|
167
|
-
if (err) {
|
|
168
|
-
console.error('Error processing ignore on path: ', path, err)
|
|
160
|
+
.on('change', async function (path, stat) {
|
|
161
|
+
logger.log(
|
|
162
|
+
`Watcher received change event for file: ${path} repoPath: ${repo.path}`,
|
|
163
|
+
stat.mtime
|
|
164
|
+
)
|
|
165
|
+
if (!path || stat.isDirectory()) return
|
|
166
|
+
var file = repo.getFile(path) || path
|
|
167
|
+
const isFile = File.isFile(file)
|
|
168
|
+
// BACKLOG ## Handle the case where the file is not in the repo
|
|
169
|
+
// #urgent #1.12.0
|
|
170
|
+
// <!--
|
|
171
|
+
// order:-660
|
|
172
|
+
// -->
|
|
173
|
+
if (isFile && stat.mtime <= file.getModifiedTime()) {
|
|
174
|
+
// logger.log("File update already applied. Change ignored.")
|
|
169
175
|
return
|
|
170
176
|
}
|
|
177
|
+
if (_isImdoneConfig(path)) return onConfigChange(path)
|
|
178
|
+
if (_isImdoneIgnore(path)) return onIgnoreChange(path)
|
|
179
|
+
|
|
180
|
+
const ok = await repo.fileOK((file && file.path) || path)
|
|
171
181
|
if (!ok) return
|
|
172
182
|
log('Reading file: ' + path)
|
|
173
183
|
if (!isFile) file = repo.getFile(path)
|
|
174
|
-
repo.readFile(file
|
|
175
|
-
|
|
176
|
-
|
|
184
|
+
file = await repo.readFile(file)
|
|
185
|
+
repo.emit('watch.change', file)
|
|
186
|
+
repo.emitFileUpdate(file)
|
|
177
187
|
})
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
188
|
+
.on('delete', async function (path) {
|
|
189
|
+
log('Watcher received unlink event for file: ' + path)
|
|
190
|
+
repo.removeFilePath(path)
|
|
191
|
+
var file = new File({
|
|
192
|
+
repoId: repo.getId(),
|
|
193
|
+
filePath: path,
|
|
194
|
+
languages: repo.languages,
|
|
195
|
+
project: repo.project,
|
|
196
|
+
})
|
|
197
|
+
log('Removing file: ' + path)
|
|
198
|
+
repo.removeFile(file)
|
|
199
|
+
repo.emit('watch.delete', file)
|
|
200
|
+
repo.emitFileUpdate(file, true)
|
|
187
201
|
})
|
|
188
|
-
|
|
189
|
-
repo.removeFile(file)
|
|
190
|
-
repo.emitFileUpdate(file, true)
|
|
191
|
-
})
|
|
202
|
+
});
|
|
192
203
|
}
|
|
193
204
|
|
|
194
205
|
return repo
|
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
1
|
+
import Plugin from 'imdone-api'
|
|
2
|
+
import path from 'path'
|
|
3
|
+
import { getRawTask } from '../adapters/parsers/task/CardContentParser.js'
|
|
4
4
|
|
|
5
|
-
|
|
5
|
+
export default class ArchivePlugin extends Plugin {
|
|
6
6
|
constructor(project) {
|
|
7
7
|
super(project)
|
|
8
8
|
}
|
|
@@ -29,7 +29,9 @@ module.exports = class ArchivePlugin extends Plugin {
|
|
|
29
29
|
if (messageUser) this.project.snackBar({message: `Archiving ${cards.length} card(s)...`})
|
|
30
30
|
}
|
|
31
31
|
|
|
32
|
-
|
|
32
|
+
for (const card of cards) {
|
|
33
|
+
await this.archiveTask(card)
|
|
34
|
+
}
|
|
33
35
|
|
|
34
36
|
if (messageUser) this.project.snackBar({message: ` Done archiving ${cards.length} card(s). Deleting original(s)...`})
|
|
35
37
|
await this.project.deleteTasks(cards)
|
|
@@ -39,7 +41,7 @@ module.exports = class ArchivePlugin extends Plugin {
|
|
|
39
41
|
|
|
40
42
|
}
|
|
41
43
|
|
|
42
|
-
archiveTask (task, config = this.config) {
|
|
44
|
+
async archiveTask (task, config = this.config) {
|
|
43
45
|
const archiveFolder = config.archiveFolder
|
|
44
46
|
const fileDir = path.dirname(task.relPath)
|
|
45
47
|
|
|
@@ -63,8 +65,8 @@ module.exports = class ArchivePlugin extends Plugin {
|
|
|
63
65
|
const taskStart = getRawTask({tokenPrefix, beforeText, list, text: ''})
|
|
64
66
|
const taskContent = `${taskStart} ${content}\n\n\n`
|
|
65
67
|
|
|
66
|
-
this.fileGateway.preparePathForWriting(newPath)
|
|
67
|
-
this.fileGateway.appendFileSync(newPath, taskContent)
|
|
68
|
+
await this.fileGateway.preparePathForWriting(newPath)
|
|
69
|
+
await this.fileGateway.appendFileSync(newPath, taskContent)
|
|
68
70
|
}
|
|
69
71
|
|
|
70
72
|
}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
1
|
+
import Plugin from 'imdone-api'
|
|
2
|
+
import { getIsoDateWithOffset } from '../adapters/date-time.js'
|
|
3
|
+
import path from 'path'
|
|
4
4
|
|
|
5
5
|
const simpleTemplate = '\n<!--\ncreated:${timestamp}\n-->\n'
|
|
6
6
|
|
|
@@ -13,7 +13,7 @@ function flattenObject(object) {
|
|
|
13
13
|
}, {});
|
|
14
14
|
}
|
|
15
15
|
|
|
16
|
-
|
|
16
|
+
export default class DefaultBoardPropertiesPlugin extends Plugin {
|
|
17
17
|
constructor(project) {
|
|
18
18
|
super(project)
|
|
19
19
|
this.templates = {}
|
|
@@ -66,11 +66,11 @@ module.exports = class DefaultBoardPropertiesPlugin extends Plugin {
|
|
|
66
66
|
|
|
67
67
|
|
|
68
68
|
async getTemplates() {
|
|
69
|
-
const { preparePathForWriting, readdir, readFile, stat } = this.project.fileGateway;
|
|
69
|
+
const { preparePathForWriting, readdir, readFile, stat, exists } = this.project.fileGateway;
|
|
70
70
|
const templateDir = path.join(this.project.configDir, 'templates');
|
|
71
71
|
const githubDir = path.join(this.project.path, '.github');
|
|
72
72
|
|
|
73
|
-
preparePathForWriting(templateDir);
|
|
73
|
+
await preparePathForWriting(templateDir, true);
|
|
74
74
|
|
|
75
75
|
const readMarkdownFiles = async (dir, prefix = '') => {
|
|
76
76
|
const files = await readdir(dir);
|
|
@@ -92,7 +92,7 @@ module.exports = class DefaultBoardPropertiesPlugin extends Plugin {
|
|
|
92
92
|
};
|
|
93
93
|
|
|
94
94
|
const templatesFromTemplateDir = await readMarkdownFiles(templateDir);
|
|
95
|
-
const templatesFromGithubDir = await
|
|
95
|
+
const templatesFromGithubDir = await exists(githubDir)
|
|
96
96
|
? await readMarkdownFiles(githubDir, 'github_')
|
|
97
97
|
: {};
|
|
98
98
|
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
export * as ArchivePlugin from './archive-plugin.js'
|
|
2
|
+
export * as DefaultBoardActionsPlugin from './default-board-actions-plugin.js'
|
|
3
|
+
export * as DefaultBoardPropertiesPlugin from './default-board-properties-plugin.js'
|
|
4
|
+
export * as EpicPlugin from './epic-plugin.js'
|
|
5
|
+
export * as PersistTagsPlugin from './persist-tags-plugin.js'
|
|
6
|
+
export * as ExtensionPlugin from './extension-plugin.js'
|
|
7
|
+
|
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
|
|
1
|
+
import Plugin from 'imdone-api'
|
|
2
|
+
import { logger } from '../adapters/logger.js'
|
|
2
3
|
|
|
3
4
|
function getIsEpicMeta(task) {
|
|
4
5
|
return task.allMeta && task.allMeta['is-epic'] && task.allMeta['is-epic'][0]
|
|
@@ -8,7 +9,7 @@ function getEpicMeta(task) {
|
|
|
8
9
|
return task.allMeta && task.allMeta['epic'] && task.allMeta['epic'][0]
|
|
9
10
|
}
|
|
10
11
|
|
|
11
|
-
|
|
12
|
+
export default class EpicPlugin extends Plugin {
|
|
12
13
|
constructor(project) {
|
|
13
14
|
super(project)
|
|
14
15
|
this.epics = {}
|
|
@@ -20,13 +21,13 @@ module.exports = class EpicPlugin extends Plugin {
|
|
|
20
21
|
|
|
21
22
|
onBoardUpdate(lists) {
|
|
22
23
|
// this html is getting initialized before onBoardUpdate
|
|
23
|
-
|
|
24
|
+
logger.log(
|
|
24
25
|
`${this.project.name} epics found:`,
|
|
25
26
|
Object.keys(this.epics).length
|
|
26
27
|
)
|
|
27
|
-
|
|
28
|
+
logger.time(`${this.project.name} Epic updates`)
|
|
28
29
|
this.updateCardMD(lists)
|
|
29
|
-
|
|
30
|
+
logger.timeEnd(`${this.project.name} Epic updates`)
|
|
30
31
|
}
|
|
31
32
|
|
|
32
33
|
onTaskUpdate(task) {
|
|
@@ -1,31 +1,39 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
1
|
+
import Plugin from 'imdone-api'
|
|
2
|
+
import _path from 'path'
|
|
3
|
+
import { exists } from '../adapters/file-gateway.js'
|
|
4
|
+
import { createRequire } from 'node:module';
|
|
5
|
+
import { logger } from '../adapters/logger.js';
|
|
4
6
|
|
|
5
|
-
|
|
7
|
+
const require = createRequire(import.meta.url);
|
|
8
|
+
const url = new URL(import.meta.url)
|
|
9
|
+
const __dirname = _path.dirname(url.pathname)
|
|
10
|
+
|
|
11
|
+
export default class ExtensionPlugin extends Plugin {
|
|
6
12
|
constructor(project) {
|
|
7
13
|
super(project)
|
|
8
|
-
|
|
14
|
+
logger.log('loading extensions')
|
|
9
15
|
this.configDir = _path.join(project.path, '.imdone')
|
|
16
|
+
}
|
|
10
17
|
|
|
11
|
-
|
|
18
|
+
async init() {
|
|
19
|
+
this.cardActionsFunction = await this.loadExtensionModule(
|
|
12
20
|
() => [],
|
|
13
21
|
'actions',
|
|
14
22
|
'card'
|
|
15
23
|
)
|
|
16
|
-
this.boardActionsFunction = this.loadExtensionModule(
|
|
24
|
+
this.boardActionsFunction = await this.loadExtensionModule(
|
|
17
25
|
() => [],
|
|
18
26
|
'actions',
|
|
19
27
|
'board'
|
|
20
28
|
)
|
|
21
|
-
this.cardPropertiesFunction = this.loadExtensionModule(
|
|
29
|
+
this.cardPropertiesFunction = await this.loadExtensionModule(
|
|
22
30
|
() => {
|
|
23
31
|
return {}
|
|
24
32
|
},
|
|
25
33
|
'properties',
|
|
26
34
|
'card'
|
|
27
35
|
)
|
|
28
|
-
this.boardPropertiesFunction = this.loadExtensionModule(
|
|
36
|
+
this.boardPropertiesFunction = await this.loadExtensionModule(
|
|
29
37
|
() => {
|
|
30
38
|
return {}
|
|
31
39
|
},
|
|
@@ -33,7 +41,6 @@ module.exports = class ExtensionPlugin extends Plugin {
|
|
|
33
41
|
'board'
|
|
34
42
|
)
|
|
35
43
|
}
|
|
36
|
-
|
|
37
44
|
getCardProperties(task) {
|
|
38
45
|
return this.cardPropertiesFunction(task)
|
|
39
46
|
}
|
|
@@ -57,26 +64,26 @@ module.exports = class ExtensionPlugin extends Plugin {
|
|
|
57
64
|
}
|
|
58
65
|
|
|
59
66
|
getConfigPath(relativePath) {
|
|
60
|
-
return _path.join(this.configDir, ...relativePath)
|
|
67
|
+
return _path.resolve(_path.join(this.configDir, ...relativePath) + '.js')
|
|
61
68
|
}
|
|
62
69
|
|
|
63
|
-
loadExtensionModule(_default, ...path) {
|
|
70
|
+
async loadExtensionModule(_default, ...path) {
|
|
64
71
|
let extension = _default
|
|
65
72
|
const extensionPath = this.getConfigPath(path)
|
|
66
73
|
try {
|
|
67
|
-
|
|
68
|
-
delete require.cache[
|
|
74
|
+
await exists(extensionPath)
|
|
75
|
+
delete require.cache[extensionPath]
|
|
69
76
|
extension = require(extensionPath)
|
|
70
77
|
} catch (e) {
|
|
71
78
|
if (e.code === 'ENOENT') {
|
|
72
|
-
|
|
79
|
+
logger.log('No extension found at:', extensionPath)
|
|
73
80
|
} else {
|
|
74
|
-
|
|
81
|
+
logger.warn('Error loading extension:', e.message)
|
|
75
82
|
}
|
|
76
83
|
}
|
|
77
84
|
|
|
78
85
|
if (typeof extension !== 'function') {
|
|
79
|
-
|
|
86
|
+
logger.warn(
|
|
80
87
|
`${extensionPath} does not export a function. Using default empty function. ${_default.toString()}`
|
|
81
88
|
)
|
|
82
89
|
extension = _default
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
export * from './archive-plugin.js';
|
|
2
|
+
export * from './default-board-actions-plugin.js';
|
|
3
|
+
export * from './default-board-properties-plugin.js';
|
|
4
|
+
export * from './default-plugins.js';
|
|
5
|
+
export * from './epic-plugin.js';
|
|
6
|
+
export * from './extension-plugin.js';
|
|
7
|
+
export * from './persist-tags-plugin.js';
|
|
8
|
+
export * from './plugin-manager.js';
|
|
9
|
+
export * from './plugin-registry.js';
|
|
@@ -1,7 +1,8 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
1
|
+
import Plugin from 'imdone-api'
|
|
2
|
+
import { save } from '../adapters/storage/tags.js'
|
|
3
3
|
|
|
4
|
-
|
|
4
|
+
export default class PersistTagsPlugin extends Plugin {
|
|
5
|
+
|
|
5
6
|
constructor(project) {
|
|
6
7
|
super(project)
|
|
7
8
|
}
|