sogo-db-core 0.1.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 @@
1
+ {"version":3,"sources":["../src/types.ts","../src/formula.ts","../src/relations.ts","../src/rollup.ts","../src/utils.ts","../src/sort-filter.ts","../src/io.ts","../src/migration.ts","../src/templates.ts","../src/csv.ts"],"sourcesContent":["/**\n * ---\n * @anchor: .patterns/core-module\n * @spec: specs/core-library.md#type-definitions\n * @task: TASK-002\n * @validated: null\n * ---\n */\n\nexport type DatabaseScope = 'global' | 'workspace';\n\nexport type FieldType =\n\t| 'text'\n\t| 'number'\n\t| 'select'\n\t| 'multiselect'\n\t| 'relation'\n\t| 'rollup'\n\t| 'formula'\n\t| 'date'\n\t| 'checkbox'\n\t| 'url'\n\t| 'email'\n\t| 'phone'\n\t| 'status'\n\t| 'createdAt'\n\t| 'lastEditedAt';\n\nexport const STATUS_GROUPS: Record<string, { label: string; color: string }> = {\n\t'Not started': { label: 'Not started', color: '#5e5e5e' },\n\t'In progress': { label: 'In progress', color: '#2e75d0' },\n\t'Done': { label: 'Done', color: '#2d9e6b' },\n};\n\nexport const STATUS_OPTIONS = ['Not started', 'In progress', 'Done'] as const;\n\nexport type RollupAggregation = 'count' | 'count_not_empty' | 'sum' | 'avg' | 'min' | 'max';\n\nexport interface RelationConfig {\n\ttargetDatabaseId?: string;\n\ttargetRelationFieldId?: string;\n}\n\nexport interface RollupConfig {\n\trelationFieldId: string;\n\ttargetFieldId?: string;\n\taggregation: RollupAggregation;\n}\n\nexport interface FormulaConfig {\n\texpression: string;\n}\n\nexport interface Field {\n\tid: string;\n\tname: string;\n\ttype: FieldType;\n\toptions?: string[];\n\toptionColors?: Record<string, string>;\n\trelation?: RelationConfig;\n\trollup?: RollupConfig;\n\tformula?: FormulaConfig;\n}\n\nexport type ViewType = 'table' | 'kanban' | 'list' | 'gallery' | 'calendar';\n\nexport interface DBView {\n\tid: string;\n\tname: string;\n\ttype: ViewType;\n\tgroupBy?: string;\n\tcardCoverField?: string;\n\tcardFields?: string[];\n\tsort: Array<{ fieldId: string; direction: 'asc' | 'desc' }>;\n\tfilter: Array<{ fieldId: string; op: string; value: string }>;\n\thiddenFields: string[];\n\tfieldOrder?: string[];\n\tcolumnWidths?: Record<string, number>;\n}\n\nexport interface DBRecord {\n\tid: string;\n\t_body?: string;\n\t[fieldId: string]: string | number | boolean | string[] | null | undefined;\n}\n\nexport interface Database {\n\tid: string;\n\tname: string;\n\tscope?: DatabaseScope;\n\tschema: Field[];\n\tviews: DBView[];\n\trecords: DBRecord[];\n\theaderFieldIds?: string[];\n}\n\nexport type DatabaseResolver = (databaseId: string) => Database | undefined;\n\nexport const DEFAULT_OPTION_COLORS = [\n\t'#6b7280', '#8b6b4a', '#f59e0b', '#10b981', '#3b82f6', '#a855f7', '#ef4444',\n];\n","/**\n * ---\n * @anchor: .patterns/core-module\n * @spec: specs/core-library.md#formula-engine\n * @task: TASK-004\n * @validated: null\n * ---\n */\n\nimport type { DBRecord, Field } from './types.js';\n\nexport function computeFormulaValue(record: DBRecord, field: Field): string | number | null {\n\tlet expression = field.formula?.expression?.trim();\n\tif (!expression) return null;\n\tif (expression.startsWith('=')) expression = expression.slice(1).trim();\n\n\tconst functionMatch = /^([a-zA-Z_][a-zA-Z0-9_]*)\\((.*)\\)$/.exec(expression);\n\tif (functionMatch) {\n\t\tconst fnName = functionMatch[1].toUpperCase();\n\t\tconst args = splitFormulaArgs(functionMatch[2]).map(arg => evaluateFormulaToken(arg, record));\n\t\treturn applyFormulaFunction(fnName, args, record);\n\t}\n\n\tconst arithmetic = tryEvaluateArithmetic(expression, record);\n\tif (arithmetic !== null && arithmetic !== undefined) return arithmetic;\n\n\tconst replaced = expression.replace(/\\{([^}]+)\\}/g, (_full, fieldId) => {\n\t\tconst value = record[String(fieldId).trim()];\n\t\tif (value === null || value === undefined) return '';\n\t\tif (Array.isArray(value)) return value.join(', ');\n\t\treturn String(value);\n\t});\n\tconst asNumber = Number(replaced);\n\treturn Number.isFinite(asNumber) && replaced !== '' ? asNumber : replaced;\n}\n\nfunction splitFormulaArgs(args: string): string[] {\n\tconst out: string[] = [];\n\tlet current = '';\n\tlet depth = 0;\n\tlet quote: '\"' | '\\'' | null = null;\n\tfor (let i = 0; i < args.length; i++) {\n\t\tconst ch = args[i];\n\t\tif ((ch === '\"' || ch === '\\'') && (!quote || quote === ch)) {\n\t\t\tquote = quote ? null : (ch as '\"' | '\\'');\n\t\t\tcurrent += ch;\n\t\t\tcontinue;\n\t\t}\n\t\tif (!quote) {\n\t\t\tif (ch === '(') { depth++; current += ch; continue; }\n\t\t\tif (ch === ')') { depth = Math.max(0, depth - 1); current += ch; continue; }\n\t\t\tif (ch === ',' && depth === 0) {\n\t\t\t\tout.push(current.trim());\n\t\t\t\tcurrent = '';\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t}\n\t\tcurrent += ch;\n\t}\n\tif (current.trim()) out.push(current.trim());\n\treturn out;\n}\n\nexport function evaluateFormulaToken(token: string, record: DBRecord): string | number | boolean | null {\n\tconst t = token.trim();\n\tif (!t.length) return null;\n\tif ((t.startsWith('\"') && t.endsWith('\"')) || (t.startsWith('\\'') && t.endsWith('\\''))) {\n\t\treturn t.slice(1, -1);\n\t}\n\tconst num = Number(t);\n\tif (Number.isFinite(num) && !/[a-zA-Z{}]/.test(t)) return num;\n\tconst fieldRef = /^\\{([^}]+)\\}$/.exec(t);\n\tif (fieldRef) {\n\t\tconst value = record[fieldRef[1].trim()];\n\t\tif (Array.isArray(value)) return value.join(', ');\n\t\tif (value === null || value === undefined) return null;\n\t\treturn value as string | number | boolean;\n\t}\n\tconst bool = t.toLowerCase();\n\tif (bool === 'true') return true;\n\tif (bool === 'false') return false;\n\treturn t;\n}\n\nfunction applyFormulaFunction(\n\tname: string,\n\targs: Array<string | number | boolean | null>,\n\trecord: DBRecord,\n): string | number | null {\n\tswitch (name) {\n\t\tcase 'SUM':\n\t\t\treturn numericArgs(args).reduce((sum, v) => sum + v, 0);\n\t\tcase 'AVG': {\n\t\t\tconst nums = numericArgs(args);\n\t\t\treturn nums.length ? nums.reduce((sum, v) => sum + v, 0) / nums.length : 0;\n\t\t}\n\t\tcase 'MIN': {\n\t\t\tconst nums = numericArgs(args);\n\t\t\treturn nums.length ? Math.min(...nums) : 0;\n\t\t}\n\t\tcase 'MAX': {\n\t\t\tconst nums = numericArgs(args);\n\t\t\treturn nums.length ? Math.max(...nums) : 0;\n\t\t}\n\t\tcase 'ABS': return Math.abs(Number(args[0] ?? 0));\n\t\tcase 'ROUND': return Math.round(Number(args[0] ?? 0));\n\t\tcase 'LEN': return String(args[0] ?? '').length;\n\t\tcase 'UPPER': return String(args[0] ?? '').toUpperCase();\n\t\tcase 'LOWER': return String(args[0] ?? '').toLowerCase();\n\t\tcase 'CONCAT': return args.map(v => v === null || v === undefined ? '' : String(v)).join('');\n\t\tcase 'NOW': return new Date().toISOString();\n\t\tcase 'TODAY': return new Date().toISOString().slice(0, 10);\n\t\tcase 'IF': {\n\t\t\tconst condition = evaluateFormulaCondition(args[0], record);\n\t\t\treturn condition\n\t\t\t\t? (args[1] === null || args[1] === undefined ? '' : (args[1] as string | number))\n\t\t\t\t: (args[2] === null || args[2] === undefined ? '' : (args[2] as string | number));\n\t\t}\n\t\tdefault:\n\t\t\treturn args[0] === null || args[0] === undefined ? null : String(args[0]);\n\t}\n}\n\nfunction evaluateFormulaCondition(raw: string | number | boolean | null, record: DBRecord): boolean {\n\tif (typeof raw === 'boolean') return raw;\n\tif (typeof raw === 'number') return raw !== 0;\n\tif (raw === null || raw === undefined) return false;\n\tconst condition = String(raw).trim();\n\tconst match = /(.+?)(>=|<=|!=|=|>|<)(.+)/.exec(condition);\n\tif (!match) return Boolean(condition);\n\tconst left = evaluateFormulaToken(match[1].trim(), record);\n\tconst right = evaluateFormulaToken(match[3].trim(), record);\n\tconst op = match[2];\n\tif (typeof left === 'number' || typeof right === 'number') {\n\t\tconst ln = Number(left ?? 0);\n\t\tconst rn = Number(right ?? 0);\n\t\tswitch (op) {\n\t\t\tcase '>': return ln > rn;\n\t\t\tcase '<': return ln < rn;\n\t\t\tcase '>=': return ln >= rn;\n\t\t\tcase '<=': return ln <= rn;\n\t\t\tcase '=': return ln === rn;\n\t\t\tcase '!=': return ln !== rn;\n\t\t\tdefault: return false;\n\t\t}\n\t}\n\tconst ls = String(left ?? '');\n\tconst rs = String(right ?? '');\n\tswitch (op) {\n\t\tcase '=': return ls === rs;\n\t\tcase '!=': return ls !== rs;\n\t\tcase '>': return ls > rs;\n\t\tcase '<': return ls < rs;\n\t\tcase '>=': return ls >= rs;\n\t\tcase '<=': return ls <= rs;\n\t\tdefault: return false;\n\t}\n}\n\nfunction numericArgs(args: Array<string | number | boolean | null>): number[] {\n\treturn args.map(v => Number(v)).filter(v => Number.isFinite(v));\n}\n\nfunction tryEvaluateArithmetic(expression: string, record: DBRecord): number | null {\n\tconst replaced = expression.replace(/\\{([^}]+)\\}/g, (_full, fieldId) => {\n\t\tconst value = Number(record[String(fieldId).trim()]);\n\t\treturn Number.isFinite(value) ? String(value) : '0';\n\t});\n\tif (!/^[0-9+\\-*/().\\s%]+$/.test(replaced)) return null;\n\ttry {\n\t\tconst value = Function(`\"use strict\"; return (${replaced});`)();\n\t\treturn Number.isFinite(value) ? Number(value) : null;\n\t} catch {\n\t\treturn null;\n\t}\n}\n","/**\n * ---\n * @anchor: .patterns/core-module\n * @spec: specs/core-library.md#relation-utilities\n * @task: TASK-005\n * @validated: null\n * ---\n */\n\nimport type { Database, DatabaseResolver, Field } from './types.js';\n\nexport function getRelationTargetDatabase(\n\tdb: Database,\n\trelationField: Field,\n\tresolveDatabase?: DatabaseResolver,\n): Database {\n\tconst targetDatabaseId = relationField.relation?.targetDatabaseId;\n\tif (targetDatabaseId && resolveDatabase) {\n\t\treturn resolveDatabase(targetDatabaseId) ?? db;\n\t}\n\treturn db;\n}\n\nexport function inferImplicitRelationTargets(db: Database, databases: Iterable<Database>): boolean {\n\tconst peers = [...databases].filter(candidate => candidate.id !== db.id);\n\tlet changed = false;\n\n\tfor (const field of db.schema) {\n\t\tif (field.type !== 'relation') continue;\n\t\tfield.relation ??= {};\n\t\tif (field.relation.targetDatabaseId) continue;\n\n\t\tconst inferred = inferTargetDatabase(field.name, db.name, peers);\n\t\tif (!inferred) continue;\n\n\t\tfield.relation.targetDatabaseId = inferred.id;\n\t\tchanged = true;\n\n\t\tif (!field.relation.targetRelationFieldId) {\n\t\t\tconst backlink = inferBacklinkField(inferred, db.name);\n\t\t\tif (backlink) field.relation.targetRelationFieldId = backlink.id;\n\t\t}\n\t}\n\n\treturn changed;\n}\n\nfunction inferTargetDatabase(\n\trelationFieldName: string,\n\tsourceDbName: string,\n\tpeers: Database[],\n): Database | undefined {\n\tconst relationToken = normalizeToken(relationFieldName);\n\tconst sourceToken = normalizeToken(sourceDbName);\n\tconst candidates = [\n\t\t...peers.filter(p => normalizeToken(p.name) === relationToken),\n\t\t...peers.filter(p => normalizeToken(p.name).includes(relationToken)),\n\t\t...peers.filter(p => relationToken.includes(normalizeToken(p.name))),\n\t];\n\tif (candidates.length) return candidates[0];\n\n\tif (relationToken.includes('project')) {\n\t\treturn peers.find(p => normalizeToken(p.name).includes('project'));\n\t}\n\tif (sourceToken.includes('task') && relationToken.includes('project')) {\n\t\treturn peers.find(p => normalizeToken(p.name).includes('project'));\n\t}\n\tif (sourceToken.includes('project') && relationToken.includes('task')) {\n\t\treturn peers.find(p => normalizeToken(p.name).includes('task'));\n\t}\n\treturn undefined;\n}\n\nfunction inferBacklinkField(targetDb: Database, sourceDbName: string): Field | undefined {\n\tconst sourceToken = normalizeToken(sourceDbName);\n\treturn targetDb.schema.find(\n\t\tfield => field.type === 'relation' && normalizeToken(field.name).includes(sourceToken),\n\t);\n}\n\nfunction normalizeToken(value: string): string {\n\treturn value.toLowerCase().replace(/[^a-z0-9]/g, '').replace(/s$/, '');\n}\n","/**\n * ---\n * @anchor: .patterns/core-module\n * @spec: specs/core-library.md#rollup-engine\n * @task: TASK-004\n * @validated: null\n * ---\n */\n\nimport type { Database, DatabaseResolver, DBRecord, Field } from './types.js';\nimport { getRelationTargetDatabase } from './relations.js';\n\nexport function computeRollupValue(\n\trecord: DBRecord,\n\tfield: Field,\n\tdb: Database,\n\tresolveDatabase?: DatabaseResolver,\n): number | null {\n\tconst rollup = field.rollup;\n\tif (!rollup) return null;\n\n\tconst relationField = db.schema.find(f => f.id === rollup.relationFieldId && f.type === 'relation');\n\tif (!relationField) return null;\n\n\tconst targetDb = getRelationTargetDatabase(db, relationField, resolveDatabase);\n\tconst rawLinked = record[relationField.id];\n\tconst linkedIds = Array.isArray(rawLinked) ? rawLinked.map(id => String(id)) : [];\n\n\tif (!linkedIds.length) {\n\t\treturn rollup.aggregation === 'count' ? 0 : null;\n\t}\n\n\tconst linkedRecords = targetDb.records.filter(r => linkedIds.includes(r.id));\n\tif (!linkedRecords.length) {\n\t\treturn rollup.aggregation === 'count' ? 0 : null;\n\t}\n\n\tif (rollup.aggregation === 'count') return linkedRecords.length;\n\n\tif (rollup.aggregation === 'count_not_empty') {\n\t\tconst target = rollup.targetFieldId;\n\t\tif (!target) return 0;\n\t\treturn linkedRecords.filter(r => {\n\t\t\tconst value = r[target];\n\t\t\treturn value !== null && value !== undefined && value !== '' && !(Array.isArray(value) && value.length === 0);\n\t\t}).length;\n\t}\n\n\tconst targetFieldId = rollup.targetFieldId;\n\tif (!targetFieldId) return null;\n\n\tconst nums = linkedRecords\n\t\t.map(r => Number(r[targetFieldId]))\n\t\t.filter(v => Number.isFinite(v));\n\tif (!nums.length) return null;\n\n\tswitch (rollup.aggregation) {\n\t\tcase 'sum': return nums.reduce((sum, v) => sum + v, 0);\n\t\tcase 'avg': return nums.reduce((sum, v) => sum + v, 0) / nums.length;\n\t\tcase 'min': return Math.min(...nums);\n\t\tcase 'max': return Math.max(...nums);\n\t\tdefault: return null;\n\t}\n}\n","/**\n * ---\n * @anchor: .patterns/core-module\n * @spec: specs/core-library.md#utility-functions\n * @task: TASK-003\n * @validated: null\n * ---\n */\n\nimport type { Database, DatabaseResolver, DBRecord, DBView, Field } from './types.js';\nimport { DEFAULT_OPTION_COLORS, STATUS_GROUPS } from './types.js';\nimport { computeFormulaValue } from './formula.js';\nimport { computeRollupValue } from './rollup.js';\n\nexport function getFieldValue(\n\trecord: DBRecord,\n\tfield: Field,\n\tdb: Database,\n\tresolveDatabase?: DatabaseResolver,\n): string | number | boolean | string[] | null | undefined {\n\tif (field.type === 'rollup') {\n\t\treturn computeRollupValue(record, field, db, resolveDatabase);\n\t}\n\tif (field.type === 'formula') {\n\t\treturn computeFormulaValue(record, field);\n\t}\n\treturn record[field.id];\n}\n\nexport function getFieldDisplayValue(\n\trecord: DBRecord,\n\tfieldId: string,\n\tschema?: Field[],\n\tdb?: Database,\n\tresolveDatabase?: DatabaseResolver,\n): string {\n\tconst field = schema?.find(f => f.id === fieldId);\n\tconst val = field && db ? getFieldValue(record, field, db, resolveDatabase) : record[fieldId];\n\tif (val === null || val === undefined) return '';\n\tif (Array.isArray(val)) return val.join(', ');\n\tif (typeof val === 'boolean') return val ? '\\u2713' : '\\u2014';\n\treturn String(val);\n}\n\nexport function getRecordTitle(record: DBRecord, schema: Field[]): string {\n\tconst titleField = schema.find(f => f.type === 'text');\n\tif (!titleField) return 'Untitled';\n\tconst val = record[titleField.id];\n\treturn val !== null && val !== undefined && val !== '' ? String(val) : 'Untitled';\n}\n\nexport function getVisibleFields(schema: Field[], view: DBView): Field[] {\n\tconst order = view.fieldOrder ?? schema.map(f => f.id);\n\tconst hidden = new Set(view.hiddenFields ?? []);\n\treturn order\n\t\t.map(id => schema.find(f => f.id === id))\n\t\t.filter((f): f is Field => f !== undefined && !hidden.has(f.id));\n}\n\nexport function getStatusColor(value: string): string {\n\treturn STATUS_GROUPS[value]?.color ?? '#5e5e5e';\n}\n\nexport function getFieldOptionColor(field: Field, option: string): string {\n\tconst explicit = field.optionColors?.[option];\n\tif (explicit) return explicit;\n\tconst options = field.options ?? [];\n\tconst index = options.indexOf(option);\n\tif (index >= 0) return DEFAULT_OPTION_COLORS[index % DEFAULT_OPTION_COLORS.length];\n\treturn DEFAULT_OPTION_COLORS[0];\n}\n\nexport function getReadableTextColor(background: string): string {\n\tconst hex = background.replace('#', '').trim();\n\tif (!/^[0-9a-fA-F]{6}$/.test(hex)) return '#ffffff';\n\tconst r = parseInt(hex.slice(0, 2), 16);\n\tconst g = parseInt(hex.slice(2, 4), 16);\n\tconst b = parseInt(hex.slice(4, 6), 16);\n\tconst luminance = (0.2126 * r + 0.7152 * g + 0.0722 * b) / 255;\n\treturn luminance > 0.62 ? '#1f2937' : '#ffffff';\n}\n","/**\n * ---\n * @anchor: .patterns/core-module\n * @spec: specs/core-library.md#sort--filter-engine\n * @task: TASK-004\n * @validated: null\n * ---\n */\n\nimport type { Database, DatabaseResolver, DBRecord, DBView, Field } from './types.js';\nimport { getFieldValue } from './utils.js';\n\nexport function applySorts(\n\trecords: DBRecord[],\n\tsorts: DBView['sort'],\n\tschema?: Field[],\n\tdb?: Database,\n\tresolveDatabase?: DatabaseResolver,\n): DBRecord[] {\n\tif (!sorts.length) return records;\n\treturn [...records].sort((a, b) => {\n\t\tfor (const s of sorts) {\n\t\t\tconst field = schema?.find(f => f.id === s.fieldId);\n\t\t\tconst av = field && db ? getFieldValue(a, field, db, resolveDatabase) : (a[s.fieldId] ?? '');\n\t\t\tconst bv = field && db ? getFieldValue(b, field, db, resolveDatabase) : (b[s.fieldId] ?? '');\n\t\t\tconst cmp = compareValues(av, bv);\n\t\t\tif (cmp !== 0) return s.direction === 'asc' ? cmp : -cmp;\n\t\t}\n\t\treturn 0;\n\t});\n}\n\nexport function applyFilters(\n\trecords: DBRecord[],\n\tfilters: DBView['filter'],\n\tschema?: Field[],\n\tdb?: Database,\n\tresolveDatabase?: DatabaseResolver,\n): DBRecord[] {\n\tif (!filters.length) return records;\n\treturn records.filter(record =>\n\t\tfilters.every(f => {\n\t\t\tconst field = schema?.find(candidate => candidate.id === f.fieldId);\n\t\t\tconst val = field && db ? getFieldValue(record, field, db, resolveDatabase) : record[f.fieldId];\n\t\t\tconst strVal = valueAsFilterString(val);\n\t\t\tconst filterVal = f.value.toLowerCase();\n\t\t\tswitch (f.op) {\n\t\t\t\tcase 'contains': return strVal.includes(filterVal);\n\t\t\t\tcase 'not_contains': return !strVal.includes(filterVal);\n\t\t\t\tcase 'equals': return strVal === filterVal;\n\t\t\t\tcase 'not_equals': return strVal !== filterVal;\n\t\t\t\tcase 'is_empty': return val === null || val === undefined || val === '' || (Array.isArray(val) && val.length === 0);\n\t\t\t\tcase 'is_not_empty': return val !== null && val !== undefined && val !== '' && !(Array.isArray(val) && val.length === 0);\n\t\t\t\tcase 'gt': return Number(val) > Number(f.value);\n\t\t\t\tcase 'gte': return Number(val) >= Number(f.value);\n\t\t\t\tcase 'lt': return Number(val) < Number(f.value);\n\t\t\t\tcase 'lte': return Number(val) <= Number(f.value);\n\t\t\t\tdefault: return true;\n\t\t\t}\n\t\t}),\n\t);\n}\n\nfunction compareValues(a: unknown, b: unknown): number {\n\tif ((a === null || a === undefined) && (b === null || b === undefined)) return 0;\n\tif (a === null || a === undefined) return -1;\n\tif (b === null || b === undefined) return 1;\n\tif (typeof a === 'number' && typeof b === 'number') return a - b;\n\tif (typeof a === 'boolean' && typeof b === 'boolean') return Number(a) - Number(b);\n\treturn valueAsFilterString(a).localeCompare(valueAsFilterString(b), undefined, { numeric: true, sensitivity: 'base' });\n}\n\nfunction valueAsFilterString(value: unknown): string {\n\tif (value === null || value === undefined) return '';\n\tif (Array.isArray(value)) return value.map(item => String(item)).join(', ').toLowerCase();\n\tif (typeof value === 'boolean') return value ? 'true' : 'false';\n\treturn String(value).toLowerCase();\n}\n","/**\n * ---\n * @anchor: .patterns/core-module\n * @spec: specs/core-library.md#file-io-utilities\n * @task: TASK-005\n * @validated: null\n * ---\n */\n\nimport { readFile, writeFile, readdir, stat } from 'node:fs/promises';\nimport { join } from 'node:path';\nimport { homedir } from 'node:os';\nimport type { Database } from './types.js';\n\nexport function getGlobalDatabasePath(): string {\n\treturn join(homedir(), '.sogo', 'globalDatabases');\n}\n\nexport async function readDatabaseFile(filePath: string): Promise<Database> {\n\tconst content = await readFile(filePath, 'utf-8');\n\tconst db = JSON.parse(content) as Database;\n\tdb.schema ??= [];\n\tdb.views ??= [];\n\tdb.records ??= [];\n\tfor (const view of db.views) {\n\t\tview.sort ??= [];\n\t\tview.filter ??= [];\n\t\tview.hiddenFields ??= [];\n\t}\n\treturn db;\n}\n\nexport async function writeDatabaseFile(db: Database, filePath: string): Promise<void> {\n\tawait writeFile(filePath, JSON.stringify(db, null, '\\t'), 'utf-8');\n}\n\nexport async function scanDirectory(\n\tdirPath: string,\n\tdepth: number = 3,\n): Promise<Array<{ db: Database; path: string }>> {\n\tconst results: Array<{ db: Database; path: string }> = [];\n\tawait scanDirectoryRecursive(dirPath, results, depth);\n\treturn results;\n}\n\nasync function scanDirectoryRecursive(\n\tdirPath: string,\n\tresults: Array<{ db: Database; path: string }>,\n\tdepth: number,\n): Promise<void> {\n\tif (depth <= 0) return;\n\ttry {\n\t\tconst entries = await readdir(dirPath, { withFileTypes: true });\n\t\tfor (const entry of entries) {\n\t\t\tconst fullPath = join(dirPath, entry.name);\n\t\t\tif (!entry.isDirectory() && entry.name.endsWith('.db.json')) {\n\t\t\t\ttry {\n\t\t\t\t\tconst db = await readDatabaseFile(fullPath);\n\t\t\t\t\tresults.push({ db, path: fullPath });\n\t\t\t\t} catch { /* skip malformed */ }\n\t\t\t} else if (entry.isDirectory() && depth > 1 && !entry.name.startsWith('.') && entry.name !== 'node_modules') {\n\t\t\t\tawait scanDirectoryRecursive(fullPath, results, depth - 1);\n\t\t\t}\n\t\t}\n\t} catch { /* skip inaccessible */ }\n}\n\nexport async function scanAll(\n\tworkspacePath: string,\n\tglobalPath?: string,\n\tscanDepth: number = 3,\n): Promise<Array<{ db: Database; path: string; scope: 'global' | 'workspace' }>> {\n\tconst seenIds = new Set<string>();\n\tconst results: Array<{ db: Database; path: string; scope: 'global' | 'workspace' }> = [];\n\n\tconst resolvedGlobalPath = globalPath ?? getGlobalDatabasePath();\n\tconst globalResults = await scanDirectory(resolvedGlobalPath, 2);\n\tfor (const entry of globalResults) {\n\t\tif (!seenIds.has(entry.db.id)) {\n\t\t\tseenIds.add(entry.db.id);\n\t\t\tresults.push({ ...entry, scope: 'global' });\n\t\t}\n\t}\n\n\tconst workspaceResults = await scanDirectory(workspacePath, scanDepth);\n\tfor (const entry of workspaceResults) {\n\t\tif (!seenIds.has(entry.db.id)) {\n\t\t\tseenIds.add(entry.db.id);\n\t\t\tresults.push({ ...entry, scope: 'workspace' });\n\t\t}\n\t}\n\n\treturn results;\n}\n","/**\n * ---\n * @anchor: .patterns/core-module\n * @spec: specs/core-library.md#schema-migration\n * @task: TASK-006\n * @validated: null\n * ---\n */\n\nimport type { Database, Field } from './types.js';\n\nexport function migrateSchema(db: Database, newSchema: Field[]): void {\n\tconst oldSchema = db.schema ?? [];\n\tconst newFieldById = new Map(newSchema.map(f => [f.id, f]));\n\tconst newFieldIds = new Set(newSchema.map(f => f.id));\n\n\tfor (const record of db.records) {\n\t\tfor (const oldField of oldSchema) {\n\t\t\tif (!newFieldIds.has(oldField.id)) {\n\t\t\t\tdelete record[oldField.id];\n\t\t\t}\n\t\t}\n\n\t\tfor (const newField of newSchema) {\n\t\t\tconst oldField = oldSchema.find(f => f.id === newField.id);\n\t\t\tconst previousValue = record[newField.id];\n\t\t\tif (oldField && oldField.type === newField.type && previousValue !== undefined) continue;\n\t\t\trecord[newField.id] = coerceValueForField(newField, previousValue);\n\t\t}\n\t}\n\n\tconst fallbackGroupBy = newSchema.find(f => f.type === 'status' || f.type === 'select')?.id;\n\tfor (const view of db.views) {\n\t\tview.sort = (view.sort ?? []).filter(s => newFieldById.has(s.fieldId));\n\t\tview.filter = (view.filter ?? []).filter(f => newFieldById.has(f.fieldId));\n\t\tview.hiddenFields = (view.hiddenFields ?? []).filter(id => newFieldById.has(id));\n\t\tif (view.fieldOrder) {\n\t\t\tconst order = view.fieldOrder.filter(id => newFieldById.has(id));\n\t\t\tfor (const field of newSchema) {\n\t\t\t\tif (!order.includes(field.id)) order.push(field.id);\n\t\t\t}\n\t\t\tview.fieldOrder = order;\n\t\t}\n\t\tif (view.columnWidths) {\n\t\t\tconst kept: Record<string, number> = {};\n\t\t\tfor (const [fieldId, width] of Object.entries(view.columnWidths)) {\n\t\t\t\tif (newFieldById.has(fieldId)) kept[fieldId] = width;\n\t\t\t}\n\t\t\tview.columnWidths = kept;\n\t\t}\n\t\tif ((view.type === 'kanban' || view.type === 'gallery') && (!view.groupBy || !newFieldById.has(view.groupBy))) {\n\t\t\tview.groupBy = fallbackGroupBy;\n\t\t}\n\t}\n\n\tdb.schema = newSchema.map(f => ({ ...f, options: f.options ? [...f.options] : undefined }));\n}\n\nexport function coerceValueForField(\n\tfield: Field,\n\tvalue: unknown,\n): string | number | boolean | string[] | null {\n\tif (value === undefined || value === null || value === '') {\n\t\tif (field.type === 'multiselect' || field.type === 'relation') return [];\n\t\tif (field.type === 'rollup' || field.type === 'formula') return null;\n\t\tif (field.type === 'createdAt' || field.type === 'lastEditedAt') return new Date().toISOString();\n\t\treturn null;\n\t}\n\n\tswitch (field.type) {\n\t\tcase 'number': {\n\t\t\tconst num = typeof value === 'number' ? value : Number(value);\n\t\t\treturn Number.isFinite(num) ? num : null;\n\t\t}\n\t\tcase 'checkbox':\n\t\t\tif (typeof value === 'boolean') return value;\n\t\t\tif (typeof value === 'number') return value !== 0;\n\t\t\tif (typeof value === 'string') {\n\t\t\t\tconst normalized = value.trim().toLowerCase();\n\t\t\t\treturn normalized === 'true' || normalized === '1' || normalized === 'yes' || normalized === 'on';\n\t\t\t}\n\t\t\treturn false;\n\t\tcase 'multiselect':\n\t\t\tif (Array.isArray(value)) return value.map(item => String(item)).filter(Boolean);\n\t\t\tif (typeof value === 'string') return value.split(/[;,]/).map(item => item.trim()).filter(Boolean);\n\t\t\treturn [];\n\t\tcase 'relation':\n\t\t\tif (Array.isArray(value)) return value.map(item => String(item)).filter(Boolean);\n\t\t\tif (typeof value === 'string') return value.split(/[;,]/).map(item => item.trim()).filter(Boolean);\n\t\t\treturn [];\n\t\tcase 'rollup':\n\t\tcase 'formula':\n\t\t\treturn null;\n\t\tcase 'select':\n\t\tcase 'status': {\n\t\t\tconst normalized = Array.isArray(value) ? (value[0] ?? null) : value;\n\t\t\tconst candidate = (normalized === null || normalized === undefined) ? null : String(normalized);\n\t\t\tif (!candidate) return null;\n\t\t\tif (field.options?.length && !field.options.includes(candidate)) return null;\n\t\t\treturn candidate;\n\t\t}\n\t\tcase 'createdAt':\n\t\tcase 'lastEditedAt':\n\t\tcase 'text':\n\t\tcase 'date':\n\t\tcase 'url':\n\t\tcase 'email':\n\t\tcase 'phone':\n\t\t\treturn String(value);\n\t}\n}\n","/**\n * ---\n * @anchor: .patterns/core-module\n * @spec: specs/core-library.md#database-templates\n * @task: TASK-006\n * @validated: null\n * ---\n */\n\nimport type { Database } from './types.js';\nimport { STATUS_OPTIONS } from './types.js';\n\nexport function createDefaultDatabaseTemplate(name: string): Database {\n\tconst titleId = crypto.randomUUID();\n\tconst statusId = crypto.randomUUID();\n\treturn {\n\t\tid: crypto.randomUUID(),\n\t\tname,\n\t\tschema: [\n\t\t\t{ id: titleId, name: 'Title', type: 'text' },\n\t\t\t{ id: statusId, name: 'Status', type: 'status', options: [...STATUS_OPTIONS] },\n\t\t],\n\t\tviews: [\n\t\t\t{\n\t\t\t\tid: crypto.randomUUID(),\n\t\t\t\tname: 'All Items',\n\t\t\t\ttype: 'table',\n\t\t\t\tsort: [],\n\t\t\t\tfilter: [],\n\t\t\t\thiddenFields: [],\n\t\t\t},\n\t\t\t{\n\t\t\t\tid: crypto.randomUUID(),\n\t\t\t\tname: 'Kanban',\n\t\t\t\ttype: 'kanban',\n\t\t\t\tgroupBy: statusId,\n\t\t\t\tsort: [],\n\t\t\t\tfilter: [],\n\t\t\t\thiddenFields: [],\n\t\t\t},\n\t\t],\n\t\trecords: [],\n\t};\n}\n\nexport function createTaskDatabaseTemplate(name: string): Database {\n\tconst titleId = crypto.randomUUID();\n\tconst statusId = crypto.randomUUID();\n\tconst priorityId = crypto.randomUUID();\n\tconst dueDateId = crypto.randomUUID();\n\tconst effortId = crypto.randomUUID();\n\tconst blockedId = crypto.randomUUID();\n\tconst projectsId = crypto.randomUUID();\n\treturn {\n\t\tid: crypto.randomUUID(),\n\t\tname,\n\t\tschema: [\n\t\t\t{ id: titleId, name: 'Title', type: 'text' },\n\t\t\t{ id: statusId, name: 'Status', type: 'status', options: [...STATUS_OPTIONS] },\n\t\t\t{ id: priorityId, name: 'Priority', type: 'select', options: ['Low', 'Medium', 'High'] },\n\t\t\t{ id: dueDateId, name: 'Due Date', type: 'date' },\n\t\t\t{ id: effortId, name: 'Effort', type: 'number' },\n\t\t\t{ id: blockedId, name: 'Blocked', type: 'checkbox' },\n\t\t\t{ id: projectsId, name: 'Project', type: 'relation', relation: {} },\n\t\t],\n\t\tviews: [\n\t\t\t{\n\t\t\t\tid: crypto.randomUUID(),\n\t\t\t\tname: 'All Tasks',\n\t\t\t\ttype: 'table',\n\t\t\t\tsort: [{ fieldId: dueDateId, direction: 'asc' }],\n\t\t\t\tfilter: [],\n\t\t\t\thiddenFields: [],\n\t\t\t},\n\t\t\t{\n\t\t\t\tid: crypto.randomUUID(),\n\t\t\t\tname: 'By Status',\n\t\t\t\ttype: 'kanban',\n\t\t\t\tgroupBy: statusId,\n\t\t\t\tsort: [],\n\t\t\t\tfilter: [],\n\t\t\t\thiddenFields: [],\n\t\t\t},\n\t\t\t{\n\t\t\t\tid: crypto.randomUUID(),\n\t\t\t\tname: 'Calendar',\n\t\t\t\ttype: 'calendar',\n\t\t\t\tgroupBy: dueDateId,\n\t\t\t\tsort: [],\n\t\t\t\tfilter: [],\n\t\t\t\thiddenFields: [],\n\t\t\t},\n\t\t],\n\t\trecords: [],\n\t};\n}\n\nexport function isTasksDatabaseName(name: string): boolean {\n\treturn /\\btask(s)?\\b/i.test(name.trim());\n}\n\nexport function createDatabase(name: string): Database {\n\treturn isTasksDatabaseName(name)\n\t\t? createTaskDatabaseTemplate(name)\n\t\t: createDefaultDatabaseTemplate(name);\n}\n","/**\n * ---\n * @anchor: .patterns/core-module\n * @spec: specs/core-library.md#csv-importexport\n * @task: TASK-006\n * @validated: null\n * ---\n */\n\nimport type { Database, DBRecord, Field } from './types.js';\n\nexport function exportCsv(db: Database): string {\n\tconst { schema } = db;\n\tconst headers = ['id', ...schema.map(f => f.name)];\n\tconst rows: string[] = [headers.map(csvEscape).join(',')];\n\tfor (const record of db.records) {\n\t\tconst cells = [\n\t\t\tcsvEscape(record.id),\n\t\t\t...schema.map(f => {\n\t\t\t\tconst val = record[f.id];\n\t\t\t\tif (val === null || val === undefined) return '';\n\t\t\t\tif (Array.isArray(val)) return csvEscape(val.join(';'));\n\t\t\t\treturn csvEscape(String(val));\n\t\t\t}),\n\t\t];\n\t\trows.push(cells.join(','));\n\t}\n\treturn rows.join('\\r\\n');\n}\n\nexport function importCsvRecords(\n\tdb: Database,\n\tcsvText: string,\n\tfieldMap: Record<string, string>,\n): DBRecord[] {\n\tconst lines = csvText.split(/\\r?\\n/).filter(l => l.trim());\n\tif (lines.length < 2) return [];\n\tconst headers = parseCsvRow(lines[0]);\n\tconst records: DBRecord[] = [];\n\tfor (let i = 1; i < lines.length; i++) {\n\t\tconst cells = parseCsvRow(lines[i]);\n\t\tconst record: DBRecord = { id: crypto.randomUUID() };\n\t\tfor (let j = 0; j < headers.length; j++) {\n\t\t\tconst csvHeader = headers[j];\n\t\t\tconst fieldId = fieldMap[csvHeader];\n\t\t\tif (!fieldId) continue;\n\t\t\tconst field = db.schema.find(f => f.id === fieldId);\n\t\t\tif (!field) continue;\n\t\t\tconst raw = cells[j] ?? '';\n\t\t\trecord[fieldId] = coerceCsvValue(field, raw);\n\t\t}\n\t\trecords.push(record);\n\t}\n\treturn records;\n}\n\nfunction coerceCsvValue(field: Field, raw: string): string | number | boolean | string[] | null {\n\tif (field.type === 'number') {\n\t\treturn raw === '' ? null : Number(raw);\n\t}\n\tif (field.type === 'checkbox') {\n\t\treturn raw.toLowerCase() === 'true' || raw === '1';\n\t}\n\tif (field.type === 'multiselect') {\n\t\treturn raw ? raw.split(';').map(s => s.trim()) : [];\n\t}\n\treturn raw || null;\n}\n\nfunction csvEscape(val: string): string {\n\tif (val.includes(',') || val.includes('\"') || val.includes('\\n')) {\n\t\treturn `\"${val.replace(/\"/g, '\"\"')}\"`;\n\t}\n\treturn val;\n}\n\nfunction parseCsvRow(line: string): string[] {\n\tconst cells: string[] = [];\n\tlet cur = '';\n\tlet inQuotes = false;\n\tfor (let i = 0; i < line.length; i++) {\n\t\tconst ch = line[i];\n\t\tif (ch === '\"') {\n\t\t\tif (inQuotes && line[i + 1] === '\"') { cur += '\"'; i++; }\n\t\t\telse { inQuotes = !inQuotes; }\n\t\t} else if (ch === ',' && !inQuotes) {\n\t\t\tcells.push(cur); cur = '';\n\t\t} else {\n\t\t\tcur += ch;\n\t\t}\n\t}\n\tcells.push(cur);\n\treturn cells;\n}\n"],"mappings":"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","names":[]}
package/package.json ADDED
@@ -0,0 +1,49 @@
1
+ {
2
+ "name": "sogo-db-core",
3
+ "version": "0.1.0",
4
+ "description": "Core types and utilities for Sogo DB — Notion-style databases as .db.json files",
5
+ "type": "module",
6
+ "license": "MIT",
7
+ "author": "DataRM",
8
+ "repository": {
9
+ "type": "git",
10
+ "url": "https://github.com/shucho/sogo-db.git",
11
+ "directory": "packages/core"
12
+ },
13
+ "homepage": "https://github.com/shucho/sogo-db#readme",
14
+ "keywords": [
15
+ "database",
16
+ "notion",
17
+ "json",
18
+ "schema",
19
+ "records",
20
+ "csv",
21
+ "migration"
22
+ ],
23
+ "main": "dist/index.cjs",
24
+ "module": "dist/index.js",
25
+ "types": "dist/index.d.ts",
26
+ "exports": {
27
+ ".": {
28
+ "types": "./dist/index.d.ts",
29
+ "import": "./dist/index.js",
30
+ "require": "./dist/index.cjs"
31
+ }
32
+ },
33
+ "files": [
34
+ "dist"
35
+ ],
36
+ "devDependencies": {
37
+ "@types/node": "^22.19.13",
38
+ "tsup": "^8.0.0",
39
+ "typescript": "^5.7.0",
40
+ "vitest": "^3.0.0"
41
+ },
42
+ "scripts": {
43
+ "build": "tsup",
44
+ "dev": "tsup --watch",
45
+ "test": "vitest run",
46
+ "typecheck": "tsc --noEmit",
47
+ "lint": "tsc --noEmit"
48
+ }
49
+ }