gcf-board 0.2.18 → 0.2.19

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.
@@ -144,7 +144,7 @@ export function createApp(o) {
144
144
  const p = await projectOf(m[1]);
145
145
  // The board's own runs ride along: what it started and what waits in its queue; and the
146
146
  // count of plan writes, which tells the page an open plan's text changed.
147
- const own = { runs: runsOf(p.name), plans_rev: planRev(p.name) };
147
+ const own = { runs: runsOf(p.name), plans_rev: planRev(p.name), board_version: o.version };
148
148
  const board = await boardOf(p);
149
149
  // A running item's last log write tells a working session from a stuck one; a run's
150
150
  // lock is this board's run or a console's.
@@ -68,7 +68,13 @@ async function main() {
68
68
  const token = await boardToken();
69
69
  const url = `http://127.0.0.1:${port}/?t=${token}`;
70
70
  const open = () => !values['no-open'] && openInBrowser(url);
71
- const app = createApp({ entry: aiFactoryEntry(), token, port, web: webDir() });
71
+ const app = createApp({
72
+ entry: aiFactoryEntry(),
73
+ token,
74
+ port,
75
+ web: webDir(),
76
+ version: version(),
77
+ });
72
78
  app.on('error', async (e) => {
73
79
  if (e.code !== 'EADDRINUSE') {
74
80
  console.error(`gcf-board: cannot listen on port ${port}: ${e.message}`);
@@ -41,6 +41,19 @@ const many = (b, key) => {
41
41
  throw new HttpError(400, `${key} must be a list of text`);
42
42
  return v.filter(Boolean).map((x) => `--${key}=${x}`);
43
43
  };
44
+ // The core limits a tag to 40 characters too.
45
+ const TAG = /^[a-z0-9][a-z0-9:-]{0,39}$/;
46
+ /** A list as one comma-separated `--flag=` (a repeated option keeps only its last). */
47
+ const list = (b, key, re, what, flag = key) => {
48
+ const v = b[key];
49
+ if (v === undefined)
50
+ return [];
51
+ if (!Array.isArray(v) || v.some((x) => typeof x !== 'string' || !re.test(x)))
52
+ throw new HttpError(400, `${key} must be a list of ${what}`);
53
+ return v.length ? [`--${flag}=${v.join(',')}`] : [];
54
+ };
55
+ const idList = (b, key) => list(b, key, SLUG, 'ids');
56
+ const tagList = (b, key, flag = key) => list(b, key, TAG, 'tags', flag);
44
57
  /** `--remove` / `--no-remove` when the operator chose; the command's default otherwise. */
45
58
  const remove = (b) => b.remove === true ? ['--remove'] : b.remove === false ? ['--no-remove'] : [];
46
59
  const NEW_ITEM_OPTIONS = [
@@ -102,13 +115,24 @@ const MOVES = {
102
115
  'inbox',
103
116
  'add',
104
117
  ...opt(b, 'source'),
118
+ ...tagList(b, 'tags'),
105
119
  '--commit',
106
120
  `--text=${required(b, 'text')}`,
107
121
  ],
108
122
  'inbox-drop': (b) => ['inbox', 'drop', id(b), '--commit'],
123
+ 'inbox-tag': (b) => [
124
+ 'inbox',
125
+ 'tag',
126
+ id(b),
127
+ ...tagList(b, 'add'),
128
+ ...tagList(b, 'remove'),
129
+ '--commit',
130
+ ],
109
131
  'phase-next': (b) => ['phase', 'next', ...opt(b, 'reason')],
110
132
  // A column's new order after a drag: ranks 1, 2, 3… in one commit.
111
133
  prioritize: (b) => ['prioritize', ...runIds(b)],
134
+ // The ids an item waits for, added and removed; the core refuses an unknown id and a cycle.
135
+ depends: (b) => ['depends', id(b), ...idList(b, 'add'), ...idList(b, 'remove')],
112
136
  'question-answer': (b) => ['question', 'answer', id(b), `--text=${required(b, 'text')}`],
113
137
  // One setting of gcf/config.yml; the core checks the key and the value. An empty value takes
114
138
  // a number back to its default.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "gcf-board",
3
- "version": "0.2.18",
3
+ "version": "0.2.19",
4
4
  "description": "A local web board for GCF game projects: shows `gcf board --json` and runs the same ai-factory gcf commands an operator runs in a console",
5
5
  "type": "module",
6
6
  "license": "MIT",