@abraca/cli 1.6.0 → 1.8.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.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@abraca/cli",
3
- "version": "1.6.0",
3
+ "version": "1.8.0",
4
4
  "description": "CLI for Abracadabra — interact with CRDT document workspaces from the terminal",
5
5
  "license": "MIT",
6
6
  "type": "module",
@@ -32,13 +32,80 @@ registerCommand({
32
32
 
33
33
  const entry = toPlain(raw)
34
34
 
35
- // Collect meta updates from remaining params
36
- const metaKeys = new Set(['icon', 'color', 'priority', 'status', 'checked', 'rating',
37
- 'tags', 'dateStart', 'dateEnd', 'datetimeStart', 'datetimeEnd', 'allDay',
38
- 'url', 'email', 'phone', 'number', 'unit', 'subtitle', 'note',
39
- 'taskProgress', 'coverUploadId', 'geoType', 'geoLat', 'geoLng',
40
- 'deskX', 'deskY', 'deskMode', 'spShape', 'spColor', 'chartType',
41
- 'kanbanColumnWidth', 'galleryColumns', 'calendarView', 'tableMode',
35
+ // Known meta keys across all page types (universal + renderer-specific).
36
+ // Kept in sync with cou-sh/app/composables/useChildTree.ts DocPageMeta and
37
+ // the MCP PageMeta type.
38
+ const metaKeys = new Set([
39
+ // Universal display
40
+ 'color', 'icon', 'subtitle', 'note',
41
+ // Datetime
42
+ 'datetimeStart', 'datetimeEnd', 'allDay', 'dateStart', 'dateEnd',
43
+ 'timeStart', 'timeEnd', 'dateTaken',
44
+ // Task/status
45
+ 'checked', 'priority', 'status', 'taskProgress', 'rating', 'tags', 'members',
46
+ // Contact/value
47
+ 'url', 'email', 'phone', 'number', 'unit',
48
+ // Cover
49
+ 'coverUploadId', 'coverDocId', 'coverMimeType',
50
+ // Geo/Map (children)
51
+ 'geoType', 'geoLat', 'geoLng', 'geoDescription',
52
+ // Dashboard (children)
53
+ 'deskX', 'deskY', 'deskZ', 'deskMode',
54
+ // Mindmap layout (children)
55
+ 'mmX', 'mmY',
56
+ // Graph layout (children)
57
+ 'graphX', 'graphY', 'graphPinned',
58
+ // Spatial 3D children (plugin) — uses universal `color`, not spColor
59
+ 'spShape', 'spOpacity', 'spX', 'spY', 'spZ',
60
+ 'spRX', 'spRY', 'spRZ', 'spSX', 'spSY', 'spSZ',
61
+ 'spModelUploadId', 'spModelDocId',
62
+ // Slides children
63
+ 'slidesTransition',
64
+ // Coder children (plugin)
65
+ 'fileType', 'entry',
66
+ // Sheets cell formatting
67
+ 'bold', 'italic', 'textColor', 'bgColor', 'align', 'formula',
68
+ // Kanban renderer config (on page doc)
69
+ 'kanbanColumnWidth',
70
+ // Gallery renderer config
71
+ 'galleryColumns', 'galleryAspect', 'galleryCardStyle', 'galleryShowLabels', 'gallerySortBy',
72
+ // Calendar renderer config
73
+ 'calendarView', 'calendarWeekStart', 'calendarShowWeekNumbers',
74
+ // Table renderer config
75
+ 'tableMode', 'tableSortKey', 'tableSortDir',
76
+ // Timeline renderer config
77
+ 'timelineZoom', 'timelinePixelsPerDay', 'timelineCenterDate',
78
+ // Checklist renderer config
79
+ 'checklistFilter', 'checklistSort',
80
+ // Map renderer config
81
+ 'mapShowLabels',
82
+ // Graph renderer config
83
+ 'graphSpacing', 'graphShowLabels', 'graphEdgeThickness', 'showRefEdges',
84
+ // Mindmap renderer config
85
+ 'mmSpacing',
86
+ // Spatial renderer config
87
+ 'spatialGridVisible',
88
+ // Slides renderer config
89
+ 'slidesTheme',
90
+ // Chart renderer config
91
+ 'chartType', 'chartMetric', 'chartColorScheme', 'chartLimit',
92
+ 'chartShowLegend', 'chartShowValues',
93
+ // Sheets renderer config
94
+ 'sheetsDefaultColWidth', 'sheetsDefaultRowHeight', 'sheetsShowGridlines',
95
+ 'sheetsFreezeRows', 'sheetsFreezeCols',
96
+ // Media renderer config (plugin)
97
+ 'mediaRepeat', 'mediaShuffle',
98
+ ])
99
+
100
+ // Keys whose values should be parsed as numbers.
101
+ const numericKeys = new Set([
102
+ 'priority', 'rating', 'number', 'taskProgress', 'geoLat', 'geoLng',
103
+ 'deskX', 'deskY', 'deskZ', 'mmX', 'mmY', 'graphX', 'graphY',
104
+ 'spOpacity', 'spX', 'spY', 'spZ', 'spRX', 'spRY', 'spRZ',
105
+ 'spSX', 'spSY', 'spSZ',
106
+ 'galleryColumns', 'chartLimit', 'timelinePixelsPerDay',
107
+ 'sheetsDefaultColWidth', 'sheetsDefaultRowHeight',
108
+ 'sheetsFreezeRows', 'sheetsFreezeCols',
42
109
  ])
43
110
 
44
111
  const updates: Record<string, unknown> = {}
@@ -53,8 +120,7 @@ registerCommand({
53
120
  updates[key] = true
54
121
  } else if (value === 'false') {
55
122
  updates[key] = false
56
- } else if (['priority', 'rating', 'number', 'taskProgress', 'geoLat', 'geoLng',
57
- 'deskX', 'deskY', 'galleryColumns'].includes(key)) {
123
+ } else if (numericKeys.has(key)) {
58
124
  updates[key] = parseFloat(value)
59
125
  } else if (key === 'tags') {
60
126
  updates[key] = value.split(',').map(s => s.trim())
@@ -0,0 +1,90 @@
1
+ /**
2
+ * page-types / type-info commands: enumerate Abracadabra page types and their
3
+ * metadata schemas. Works without a server connection — the catalog is static.
4
+ */
5
+ import { registerCommand } from '../command.ts'
6
+ import type { CLIConnection } from '../connection.ts'
7
+ import type { ParsedArgs } from '../parser.ts'
8
+ import { printJson } from '../output.ts'
9
+ import { PAGE_TYPES, TYPE_ALIASES, resolvePageType } from '../converters/page-types.ts'
10
+ import type { PageTypeInfo, PageTypeMetaField } from '../converters/page-types.ts'
11
+
12
+ function describeField(f: PageTypeMetaField): string {
13
+ const bits: string[] = []
14
+ bits.push(f.type as string)
15
+ if (f.key) bits.push(`key=${f.key}`)
16
+ if (f.latKey) bits.push(`latKey=${f.latKey},lngKey=${f.lngKey}`)
17
+ if (f.startKey) bits.push(`startKey=${f.startKey},endKey=${f.endKey}${f.allDayKey ? `,allDayKey=${f.allDayKey}` : ''}`)
18
+ if (f.options) bits.push(`options=[${f.options.join(', ')}]`)
19
+ if (f.presets) bits.push(`presets=${f.presets.length}`)
20
+ if (typeof f.min === 'number' || typeof f.max === 'number') bits.push(`range=${f.min ?? '?'}..${f.max ?? '?'}`)
21
+ if (f.step) bits.push(`step=${f.step}`)
22
+ if (f.unit) bits.push(`unit=${f.unit}`)
23
+ if (f.default !== undefined) bits.push(`default=${f.default}`)
24
+ return bits.join(' ')
25
+ }
26
+
27
+ registerCommand({
28
+ name: 'page-types',
29
+ aliases: ['types', 'doctypes'],
30
+ description: 'List Abracadabra page types and their metadata schemas.',
31
+ usage: 'page-types [key=<type>] [--format=json]',
32
+ async run(_conn: CLIConnection | null, args: ParsedArgs): Promise<string> {
33
+ const key = args.params['key'] || args.params['type'] || args.positional[0]
34
+ const asJson = args.flags.has('json') || args.params['format'] === 'json'
35
+
36
+ if (key) {
37
+ const info = resolvePageType(key)
38
+ if (!info) {
39
+ return `Unknown page type "${key}". Run 'abracadabra page-types' to list all.`
40
+ }
41
+ if (asJson) return printJson(info)
42
+
43
+ const lines: string[] = [
44
+ `${info.label} (${info.key})${info.core ? '' : ` [plugin: ${info.plugin}]`}`,
45
+ info.description ? ` ${info.description}` : '',
46
+ ` icon: ${info.icon}`,
47
+ ` supportsChildren: ${info.supportsChildren}`,
48
+ ]
49
+ if (info.childLabel) lines.push(` childLabel: ${info.childLabel}`)
50
+ if (info.grandchildLabel) lines.push(` grandchildLabel: ${info.grandchildLabel}`)
51
+ if (info.defaultDepth !== undefined) lines.push(` defaultDepth: ${info.defaultDepth === -1 ? 'unlimited' : info.defaultDepth}`)
52
+
53
+ if (info.metaSchema?.length) {
54
+ lines.push('', ` metaSchema (applies to descendants):`)
55
+ for (const f of info.metaSchema) lines.push(` - ${describeField(f)}${f.label ? ` "${f.label}"` : ''}`)
56
+ }
57
+ if (info.defaultMetaFields?.length) {
58
+ lines.push('', ` defaultMetaFields (renderer config on this doc):`)
59
+ for (const f of info.defaultMetaFields) lines.push(` - ${describeField(f)}${f.label ? ` "${f.label}"` : ''}`)
60
+ }
61
+ return lines.filter(Boolean).join('\n')
62
+ }
63
+
64
+ // List all
65
+ const types = Object.values(PAGE_TYPES) as PageTypeInfo[]
66
+ if (asJson) return printJson({ types, aliases: TYPE_ALIASES })
67
+
68
+ const coreTypes = types.filter((t) => t.core)
69
+ const pluginTypes = types.filter((t) => !t.core)
70
+
71
+ const lines: string[] = ['Core page types:']
72
+ for (const t of coreTypes) {
73
+ const depth = t.defaultDepth === -1 ? '∞' : (t.grandchildLabel ? '2' : (t.supportsChildren ? '1' : '0'))
74
+ const nesting = [t.childLabel, t.grandchildLabel].filter(Boolean).join(' → ')
75
+ lines.push(` ${t.key.padEnd(12)}${(nesting || '—').padEnd(28)}depth=${depth}`)
76
+ }
77
+ lines.push('', 'Plugin page types (require plugin):')
78
+ for (const t of pluginTypes) {
79
+ const depth = t.defaultDepth === -1 ? '∞' : (t.grandchildLabel ? '2' : (t.supportsChildren ? '1' : '0'))
80
+ const nesting = [t.childLabel, t.grandchildLabel].filter(Boolean).join(' → ')
81
+ lines.push(` ${t.key.padEnd(12)}${(nesting || '—').padEnd(28)}depth=${depth} [plugin: ${t.plugin}]`)
82
+ }
83
+ lines.push('', 'Aliases:')
84
+ for (const [from, to] of Object.entries(TYPE_ALIASES)) {
85
+ lines.push(` ${from} → ${to}`)
86
+ }
87
+ lines.push('', `Run 'abracadabra page-types <key>' for field-level detail.`)
88
+ return lines.join('\n')
89
+ },
90
+ })
@@ -5,6 +5,10 @@
5
5
  * not on the MCP SDK, so importing via the source export condition is safe.
6
6
  */
7
7
  // @ts-ignore — resolve via monorepo source condition
8
- export { yjsToMarkdown } from '../../mcp/src/converters/yjsToMarkdown.ts'
8
+ export { yjsToMarkdown } from '../../../mcp/src/converters/yjsToMarkdown.ts'
9
9
  // @ts-ignore — resolve via monorepo source condition
10
- export { populateYDocFromMarkdown, parseFrontmatter } from '../../mcp/src/converters/markdownToYjs.ts'
10
+ export { populateYDocFromMarkdown, parseFrontmatter } from '../../../mcp/src/converters/markdownToYjs.ts'
11
+ // @ts-ignore — resolve via monorepo source condition
12
+ export { PAGE_TYPES, TYPE_ALIASES, resolvePageType } from '../../../mcp/src/converters/page-types.ts'
13
+ // @ts-ignore — resolve via monorepo source condition
14
+ export type { PageTypeInfo, PageTypeMetaField, MetaFieldType } from '../../../mcp/src/converters/page-types.ts'
@@ -0,0 +1,5 @@
1
+ // Re-export from @abraca/mcp converters (static data, no runtime deps).
2
+ // @ts-ignore — resolve via monorepo relative path
3
+ export { PAGE_TYPES, TYPE_ALIASES, resolvePageType } from '../../../mcp/src/converters/page-types.ts'
4
+ // @ts-ignore — resolve via monorepo relative path
5
+ export type { PageTypeInfo, PageTypeMetaField, MetaFieldType } from '../../../mcp/src/converters/page-types.ts'
package/src/index.ts CHANGED
@@ -27,9 +27,10 @@ import './commands/meta.ts'
27
27
  import './commands/awareness.ts'
28
28
  import './commands/files.ts'
29
29
  import './commands/permissions.ts'
30
+ import './commands/page-types.ts'
30
31
 
31
32
  // ── Commands that don't require a connection ─────────────────────────────────
32
- const NO_CONNECT_COMMANDS = new Set(['help', 'h', '?', 'version', 'v'])
33
+ const NO_CONNECT_COMMANDS = new Set(['help', 'h', '?', 'version', 'v', 'page-types', 'types', 'doctypes'])
33
34
 
34
35
  async function main() {
35
36
  const args = parseArgs(process.argv)