imdone-core 1.47.2 → 1.48.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.
@@ -0,0 +1,50 @@
1
+ const { readFile, writeFile, exists } = require('../file-gateway')
2
+ const { CONFIG_DIR, CONFIG_FILE_YML } = require('../../constants')
3
+ const { loadYAML, dumpYAML } = require('../yaml')
4
+ const findUp = require('find-up')
5
+ const _path = require('path')
6
+ const Config = require('../../config')
7
+
8
+ module.exports = {
9
+ load,
10
+ save,
11
+ loadForFilePath,
12
+ findImdonePath,
13
+ }
14
+
15
+ async function load(projectPath) {
16
+ const configPath = _path.join(projectPath, CONFIG_FILE_YML)
17
+ const configLike = await getYamlConfig(configPath)
18
+ return configLike && new Config(configLike)
19
+ }
20
+
21
+ async function save(config, projectPath) {
22
+ const configPath = _path.join(projectPath, CONFIG_FILE_YML)
23
+ await writeFile(configPath, dumpYAML(config))
24
+ }
25
+
26
+ async function loadForFilePath(filePath) {
27
+ const projectPath = await findImdonePath(filePath)
28
+ return load(projectPath)
29
+ }
30
+
31
+ async function getYamlConfig(filePath) {
32
+ if (!(await exists(filePath))) return
33
+ const configData = await readFile(filePath, 'utf-8')
34
+ let configLike = {}
35
+ try {
36
+ configLike = loadYAML(configData.toString())
37
+ if (configLike.exclude) delete configLike.exclude
38
+ if (configLike.watcher) delete configLike.watcher
39
+
40
+ } catch (e) {
41
+ /* noop */
42
+ }
43
+ return configLike
44
+ }
45
+
46
+ async function findImdonePath(cwd) {
47
+ const configDir = await findUp(CONFIG_DIR, { cwd, type: 'directory' })
48
+ return _path.dirname(configDir)
49
+ }
50
+
@@ -0,0 +1,30 @@
1
+ const { readFile, writeFile, exists } = require('../file-gateway')
2
+ const { CONFIG_DIR } = require('../../constants')
3
+ const { loadYAML, dumpYAML } = require('../yaml')
4
+ const _path = require('path')
5
+
6
+ module.exports = {
7
+ load,
8
+ save
9
+ }
10
+
11
+ async function load(projectPath) {
12
+ const tagsPath = getTagsPath(projectPath)
13
+ if (!(await exists(tagsPath))) return
14
+ const tagsData = await readFile(tagsPath, 'utf-8')
15
+ try {
16
+ const { tags } = loadYAML(tagsData)
17
+ return tags
18
+ } catch (e) {
19
+ console.error(e)
20
+ return
21
+ }
22
+ }
23
+
24
+ async function save(tags, projectPath) {
25
+ await writeFile(getTagsPath(projectPath), dumpYAML({ tags }))
26
+ }
27
+
28
+ function getTagsPath(projectPath) {
29
+ return _path.join(projectPath, CONFIG_DIR, 'tags.yml')
30
+ }
package/lib/card.js CHANGED
@@ -78,36 +78,10 @@ module.exports = function newCard(task, _project, dontParse) {
78
78
  : { ...computed }
79
79
  }
80
80
 
81
- getCardActions() {
82
- // TODO Stop allowing links/actions from card config
83
- // <!-- order:-80 -->
84
- const links = project.config.cardActions
85
- const allLinks = this.frontMatter.links
86
- ? [...links, ...this.frontMatter.links]
87
- : [...links]
88
- return allLinks.filter(({ display }) => {
89
- if (!display) return true
90
- try {
91
- return display.call({ ...this.data, ...this.desc })
92
- } catch (e) {
93
- console.error(e)
94
- }
95
- return false
96
- })
97
- }
98
-
99
81
  initActions() {
100
- this.links = this.getCardActions().map(
101
- ({ pack, icon, title, href }, index) => {
102
- href = this.formatContent(href).content
103
- title = this.formatContent(title).content
104
- const action = JSON.stringify({ index })
105
- return { pack, icon, title, href, action } // Use index instead of action
106
- }
107
- )
108
-
82
+ this.links = []
109
83
  if (!pluginManager) return
110
- this.links = [...this.links, ...pluginManager.getCardActions(this)]
84
+ this.links = [...pluginManager.getCardActions(this)]
111
85
  }
112
86
 
113
87
  get projectPath() {
package/lib/config.js CHANGED
@@ -123,17 +123,6 @@ class Config {
123
123
  return this.settings.views
124
124
  }
125
125
 
126
- get cardActions() {
127
- return [..._get(this, 'settings.cards.links', [])]
128
- }
129
-
130
- get boardActions() {
131
- const settingsActions = _get(this, 'settings.actions', []).map((action) => {
132
- return { name: action.name, action: action['function'] }
133
- })
134
- return [...settingsActions]
135
- }
136
-
137
126
  get appendNewCardsTo() {
138
127
  return _get(this, 'settings.appendNewCardsTo', false)
139
128
  }
@@ -223,27 +212,4 @@ Config.newDefaultConfig = (config = {}) => new Config(
223
212
  }
224
213
  )
225
214
 
226
- Config.findImdonePath = async (cwd) => {
227
- const configDir = await findUp(CONFIG_DIR, { cwd, type: 'directory' })
228
- return _path.dirname(configDir)
229
- }
230
-
231
- Config.getYamlConfig = async (filePath) => {
232
- if (!(await exists(filePath))) return
233
- const configData = await readFile(filePath, 'utf-8')
234
- let configLike = {}
235
- try {
236
- configLike = loadYAML(configData.toString())
237
- } catch (e) {
238
- /* noop */
239
- }
240
- return configLike
241
- }
242
-
243
- Config.load = async (imdonePath) => {
244
- const configPath = _path.join(imdonePath, CONFIG_FILE_YML)
245
- const configLike = await Config.getYamlConfig(configPath)
246
- return new Config(configLike)
247
- }
248
-
249
215
  module.exports = Config
package/lib/constants.js CHANGED
@@ -57,6 +57,8 @@ module.exports = {
57
57
  NOT_A_FILE: 'file must be of type File',
58
58
  CALLBACK_REQUIRED: 'Last paramter must be a callback function',
59
59
  NO_CONTENT: 'File has no content',
60
+ LIST_NOT_FOUND: 'List not found',
61
+ TASK_NOT_FOUND: 'Task not found',
60
62
  },
61
63
  DEFAULT_CONFIG: {
62
64
  keepEmptyPriority: false,
package/lib/file.js CHANGED
@@ -290,7 +290,7 @@ File.prototype.transformTask = function ({config, modify, task}) {
290
290
  }
291
291
 
292
292
  File.prototype.transformTasks = function (config, modify) {
293
- if (this.isCodeFile()) return
293
+ // if (this.isCodeFile()) return
294
294
  fastSort(this.getTasks())
295
295
  .desc(u => u.line)
296
296
  .forEach(task => this.transformTask({config, modify, task}))
@@ -270,9 +270,6 @@ function mixin(repo, fs = require('fs')) {
270
270
  let configLike = {}
271
271
  try {
272
272
  configLike = loadYAML(configData.toString())
273
- Repository.trimFunctionsInSettings(configLike)
274
- if (configLike.exclude) delete configLike.exclude
275
- if (configLike.watcher) delete configLike.watcher
276
273
  } catch (e) {
277
274
  /* noop */
278
275
  }
@@ -0,0 +1,13 @@
1
+ const Plugin = require('imdone-api')
2
+ const { save } = require('../adapters/storage/tags.js')
3
+
4
+ module.exports = class PersistTagsPlugin extends Plugin {
5
+ constructor(project) {
6
+ super(project)
7
+ }
8
+
9
+ async onBoardUpdate() {
10
+ await save(this.project.allTags, this.project.path)
11
+ }
12
+
13
+ }
@@ -14,7 +14,8 @@ module.exports = class PluginManager extends Emitter {
14
14
  this.defaultPlugins = [
15
15
  './archive-plugin',
16
16
  './epic-plugin',
17
- './extension-plugin'
17
+ './extension-plugin',
18
+ './persist-tags-plugin',
18
19
  ]
19
20
  this.pluginsMap = {}
20
21
  this.pluginPath = _path.join(project.path, '.imdone', 'plugins')
@@ -234,13 +235,13 @@ module.exports = class PluginManager extends Emitter {
234
235
  )
235
236
  }
236
237
 
237
- onBoardUpdate(lists) {
238
+ async onBoardUpdate(lists) {
238
239
  if (!lists || lists.length == 0) return
239
- this.eachPlugin(({ pluginInstance }) => {
240
+ this.eachPluginAsync(async ({ pluginInstance }) => {
240
241
  // const timeLabel = `${this.getPluginName(pluginInstance)} onBoardUpdate time`
241
242
  // console.time(timeLabel)
242
243
  try {
243
- pluginInstance.onBoardUpdate(lists)
244
+ await pluginInstance.onBoardUpdate(lists)
244
245
  } catch (e) {
245
246
  this.pluginError('onBoardUpdate', pluginInstance, e)
246
247
  }
package/lib/project.js CHANGED
@@ -142,9 +142,9 @@ module.exports = class WorkerProject extends Project {
142
142
  files: this.files,
143
143
  totals,
144
144
  tags: this.getTags(),
145
- allMeta: this.repo.allMeta,
146
- allContexts: [...this.repo.allContexts],
147
- allTags: [...this.repo.allTags],
145
+ allMeta: this.allMeta,
146
+ allContexts: this.allContexts,
147
+ allTags: this.allTags,
148
148
  filter: this.filter,
149
149
  defaultFilter: this.defaultFilter,
150
150
  actions: this.boardActions,
@@ -164,6 +164,18 @@ module.exports = class WorkerProject extends Project {
164
164
  if (this.pluginManager) this.pluginManager.destroyPlugins()
165
165
  }
166
166
 
167
+ get allTags() {
168
+ return [...this.repo.allTags]
169
+ }
170
+
171
+ get allContexts() {
172
+ return [...this.repo.allContexts]
173
+ }
174
+
175
+ get allMeta() {
176
+ return this.repo.allMeta
177
+ }
178
+
167
179
  get lists() {
168
180
  return this.getLists({
169
181
  tasks: this.filteredCards,
@@ -219,8 +231,8 @@ module.exports = class WorkerProject extends Project {
219
231
  ...new Set(queryProps),
220
232
  ...[...this.repo.metaKeys].map(key => `allMeta.${key}`),
221
233
  ...[...this.repo.metaKeys].map(key => `meta.${key}`),
222
- ...this.repo.allTags,
223
- ...this.repo.allContexts,
234
+ ...this.allTags,
235
+ ...this.allContexts,
224
236
  ]
225
237
  }
226
238
 
@@ -295,12 +307,7 @@ module.exports = class WorkerProject extends Project {
295
307
  }
296
308
 
297
309
  get boardActions() {
298
- // TODO Stop allowing board actions from config
299
- // <!-- order:-90 -->
300
310
  return [
301
- ...this.config.boardActions.map((item, index) => {
302
- return { ...item, index }
303
- }),
304
311
  ...this.pluginManager.getBoardActions(),
305
312
  ]
306
313
  }
@@ -474,15 +481,7 @@ module.exports = class WorkerProject extends Project {
474
481
  return new Promise((resolve, reject) => {
475
482
  this.repo.addTaskToFile(filePath, list, content, (err, file, task) => {
476
483
  if (err) return reject(err)
477
-
478
- const newList = task.list
479
- const list = this.lists.find(l => l.name === newList)
480
- const newPos = this.config.isAddNewCardsToTop() ? 0 : list.tasks.length - 1
481
-
482
- this.repo.moveTask({ task, newList, newPos }, (err) => {
483
- if (err) return reject(err)
484
- resolve({ file, task })
485
- })
484
+ resolve({ file, task })
486
485
  })
487
486
  })
488
487
  }
package/lib/repository.js CHANGED
@@ -943,8 +943,10 @@ Repository.prototype.writeAndExtract = function (file, emit, cb) {
943
943
  this.writeFile(file, emit, (err, file) => {
944
944
  if (err) return cb(new Error('Unable to write file:' + file.path))
945
945
  this.extractTasks(file, (err, file) => {
946
- if (err)
946
+ if (err) {
947
947
  return cb(new Error('Unable to extract tasks for file:' + file.path))
948
+ }
949
+
948
950
  this.addFile(file, (err) => {
949
951
  if (err) {
950
952
  err.message = `Unable to add file after extracting tasks: #{file.path}\n${err.message}`
@@ -1098,20 +1100,18 @@ Repository.prototype.appendTask = function({file, content, list}, cb) {
1098
1100
  let sep = fileContent.indexOf(crlf) > -1 ? crlf : String(eol.lf)
1099
1101
  if (fileContent.endsWith(sep) || fileIsEmpty) sep = ''
1100
1102
  const order = appContext().projectContext.getOrder(list)
1101
- const orderString = isNumber(order) ? order : ''
1102
- const description =
1103
- lines.length > 1 ? Task.padDescription(lines.slice(1), taskPrefix) : []
1104
-
1105
- const rawTask = getRawTask({tokenPrefix: config.tokenPrefix, orderMeta: config.orderMeta, list, order, text, type: taskSyntax})
1106
- const taskContent = config.orderMeta
1107
- ? this.getTaskContent({
1108
- description,
1109
- order,
1110
- text,
1111
- taskPrefix,
1112
- taskSyntax,
1113
- })
1114
- : description.join(eol.lf)
1103
+ const description = lines.length > 1 ? Task.padDescription(lines.slice(1), taskPrefix) : []
1104
+ const { orderMeta, tokenPrefix } = config
1105
+ const rawTask = getRawTask({tokenPrefix, orderMeta, list, order, text, type: taskSyntax})
1106
+ const taskContent = config.orderMeta
1107
+ ? this.getTaskContent({
1108
+ description,
1109
+ order,
1110
+ text,
1111
+ taskPrefix,
1112
+ taskSyntax,
1113
+ })
1114
+ : description.join(eol.lf)
1115
1115
 
1116
1116
  let appendContent = File.trimBlankLines(
1117
1117
  `${taskPrefix}${rawTask}${eol.lf}${taskContent}`
@@ -1675,55 +1675,4 @@ Repository.prototype.query = function (queryString) {
1675
1675
  return Repository.getTasksByList(this, result, true)
1676
1676
  }
1677
1677
 
1678
- function trimFunction(propValue) {
1679
- let func = null
1680
- if (propValue && _isFunction(propValue)) {
1681
- const functionMatch = propValue.toString().match(functionRegex())
1682
- const lines = eol.split(functionMatch[3])
1683
- const funcBody = lines.filter((line) => line.trim().length > 0).join(eol.lf)
1684
- try {
1685
- func = new Function(funcBody)
1686
- } catch (e) {
1687
- console.error(`Unable to parse function:`, propValue.toString())
1688
- console.error(e)
1689
- }
1690
- }
1691
- return func
1692
- }
1693
-
1694
- Repository.trimFunctionsInSettings = function (config) {
1695
- const computed = _get(config, 'settings.cards.computed')
1696
- if (_isObject(computed)) {
1697
- Object.keys(computed).forEach((key) => {
1698
- const value = computed[key]
1699
- const func = trimFunction(value)
1700
- if (func) config.settings.cards.computed[key] = func
1701
- })
1702
- }
1703
-
1704
- let links = _get(config, 'settings.cards.links')
1705
- if (Array.isArray(links)) {
1706
- links = links.map((link) => {
1707
- ;['action', 'display'].forEach((prop) => {
1708
- const propValue = link[prop]
1709
- const func = trimFunction(propValue)
1710
- if (func) link[prop] = func
1711
- })
1712
- return link
1713
- })
1714
- config.settings.cards.links = links
1715
- }
1716
-
1717
- let actions = _get(config, 'settings.actions')
1718
- if (Array.isArray(actions)) {
1719
- actions = actions.map((action) => {
1720
- const propValue = action.function
1721
- const func = trimFunction(propValue)
1722
- if (func) action.function = func
1723
- return action
1724
- })
1725
- config.settings.actions = actions
1726
- }
1727
- }
1728
-
1729
1678
  module.exports = Repository
@@ -0,0 +1,17 @@
1
+ const {
2
+ load,
3
+ save
4
+ } = require('../adapters/storage/tags.js')
5
+
6
+ const {
7
+ findImdonePath
8
+ } = require('../adapters/storage/config.js')
9
+
10
+ module.exports = {
11
+ getTags
12
+ }
13
+
14
+ async function getTags(filePath) {
15
+ const projectPath = await findImdonePath(filePath)
16
+ return load(projectPath)
17
+ }
@@ -1,11 +1,13 @@
1
- const Config = require('../config')
1
+ const { loadForFilePath } = require('../adapters/storage/config')
2
2
  const { getFileParser } = require('../adapters/parsers/file/LocalFileParserFactory')
3
3
  const { Readable } = require('stream');
4
4
 
5
+ module.exports = {
6
+ getTasks
7
+ }
5
8
 
6
- export async function getTasks({filePath, content}) {
7
- const projectPath = await Config.findImdonePath(filePath)
8
- const config = await Config.load(projectPath)
9
+ async function getTasks({filePath, content}) {
10
+ const config = await loadForFilePath(filePath)
9
11
 
10
12
  const readStream = new Readable({
11
13
  read() {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "imdone-core",
3
- "version": "1.47.2",
3
+ "version": "1.48.0",
4
4
  "description": "imdone-core",
5
5
  "main": "index.js",
6
6
  "scripts": {
@@ -1,10 +0,0 @@
1
- module.exports = class FileSystemConfigReader {
2
- constructor(location) {
3
- this.location = location
4
- }
5
-
6
- // BACKLOG:-880 ## Implement the read method
7
- // [${source.path}](${source.path}) #adapter #urgent
8
- // <!-- epic:"Release 2.0" -->
9
- async read() {}
10
- }