@iwo-szapar/data-mcp 0.4.0 → 0.6.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/dist/adapter/factory.d.ts +2 -2
- package/dist/adapter/factory.js +7 -3
- package/dist/adapter/owner-scope.d.ts +31 -0
- package/dist/adapter/owner-scope.js +155 -0
- package/dist/adapter/types.d.ts +2 -1
- package/dist/config.d.ts +20 -4
- package/dist/config.js +14 -1
- package/dist/server.js +2 -2
- package/dist/tools/memory/contact-create.js +3 -1
- package/dist/tools/memory/goal-create.js +3 -1
- package/dist/tools/memory/knowledge-decide.js +3 -1
- package/dist/tools/memory/knowledge-learn.js +3 -1
- package/dist/tools/memory/knowledge-list.js +5 -1
- package/dist/tools/memory/knowledge-recall.js +22 -7
- package/dist/tools/memory/knowledge-store.js +11 -5
- package/dist/tools/memory/link-create.js +15 -9
- package/dist/tools/memory/link-delete.js +1 -1
- package/dist/tools/memory/link-related.js +1 -1
- package/dist/tools/memory/link-suggest.js +1 -1
- package/dist/tools/memory/session-log.js +3 -1
- package/dist/tools/memory/task-create.js +3 -1
- package/dist/tools/register.js +3 -1
- package/dist/tools/setup/setup-bootstrap.js +71 -0
- package/dist/tools/setup/setup-migrate.js +20 -16
- package/dist/tools/setup/setup-status.js +11 -6
- package/migrations/pocketbase/001_core_schema.js +24 -28
- package/migrations/pocketbase/002_goals_tasks.js +15 -18
- package/migrations/pocketbase/003_contacts.js +9 -12
- package/migrations/pocketbase/004_entity_aliases.js +9 -12
- package/migrations/pocketbase/005_prospects.js +11 -14
- package/migrations/pocketbase/006_business.js +29 -33
- package/migrations/pocketbase/007_newsletter_affiliates.js +16 -19
- package/migrations/pocketbase/008_knowledge_links.js +34 -37
- package/migrations/supabase/009_align_to_production.sql +14 -11
- package/package.json +1 -1
- package/README.md +0 -286
|
@@ -24,6 +24,7 @@ export function registerSessionLog(server, adapter) {
|
|
|
24
24
|
})).optional().describe('Patterns learned during the session'),
|
|
25
25
|
knowledge_created: z.number().int().min(0).optional().describe('Number of knowledge items created'),
|
|
26
26
|
knowledge_updated: z.number().int().min(0).optional().describe('Number of knowledge items updated'),
|
|
27
|
+
owner_scope: z.enum(['private', 'shared']).optional().describe('Store privately for this user or in shared team memory'),
|
|
27
28
|
metadata: z.record(z.unknown()).optional().describe('Additional metadata'),
|
|
28
29
|
}, withGracefulDegradation('sessions', adapter, async (params) => {
|
|
29
30
|
try {
|
|
@@ -40,6 +41,7 @@ export function registerSessionLog(server, adapter) {
|
|
|
40
41
|
patterns_learned: params.patterns_learned ?? [],
|
|
41
42
|
knowledge_created: params.knowledge_created ?? 0,
|
|
42
43
|
knowledge_updated: params.knowledge_updated ?? 0,
|
|
44
|
+
...(adapter.ownerScopeEnabled ? { owner_scope: params.owner_scope } : {}),
|
|
43
45
|
metadata: params.metadata ?? null,
|
|
44
46
|
});
|
|
45
47
|
return makeToolResponse({
|
|
@@ -53,4 +55,4 @@ export function registerSessionLog(server, adapter) {
|
|
|
53
55
|
}
|
|
54
56
|
}));
|
|
55
57
|
}
|
|
56
|
-
//# sourceMappingURL=session-log.js.map
|
|
58
|
+
//# sourceMappingURL=session-log.js.map
|
|
@@ -13,6 +13,7 @@ export function registerTaskCreate(server, adapter) {
|
|
|
13
13
|
due_date: z.string().max(50).optional().describe('Due date (ISO format)'),
|
|
14
14
|
tags: z.array(z.string().max(100)).max(20).optional().describe('Tags for categorization'),
|
|
15
15
|
goal_id: z.string().min(1).optional().describe('Related goal ID'),
|
|
16
|
+
owner_scope: z.enum(['private', 'shared']).optional().describe('Store privately for this user or in shared team memory'),
|
|
16
17
|
}, withGracefulDegradation('tasks', adapter, async (params) => {
|
|
17
18
|
try {
|
|
18
19
|
const record = await adapter.create('tasks', {
|
|
@@ -23,6 +24,7 @@ export function registerTaskCreate(server, adapter) {
|
|
|
23
24
|
due_date: params.due_date ?? null,
|
|
24
25
|
tags: params.tags ?? [],
|
|
25
26
|
goal_id: params.goal_id ?? null,
|
|
27
|
+
...(adapter.ownerScopeEnabled ? { owner_scope: params.owner_scope } : {}),
|
|
26
28
|
});
|
|
27
29
|
return makeToolResponse({
|
|
28
30
|
created: true,
|
|
@@ -35,4 +37,4 @@ export function registerTaskCreate(server, adapter) {
|
|
|
35
37
|
}
|
|
36
38
|
}));
|
|
37
39
|
}
|
|
38
|
-
//# sourceMappingURL=task-create.js.map
|
|
40
|
+
//# sourceMappingURL=task-create.js.map
|
package/dist/tools/register.js
CHANGED
|
@@ -28,9 +28,10 @@ import { registerLinkCreate } from './memory/link-create.js';
|
|
|
28
28
|
import { registerLinkDelete } from './memory/link-delete.js';
|
|
29
29
|
import { registerLinkRelated } from './memory/link-related.js';
|
|
30
30
|
import { registerLinkSuggest } from './memory/link-suggest.js';
|
|
31
|
-
// Setup tools (
|
|
31
|
+
// Setup tools (4)
|
|
32
32
|
import { registerSetupStatus } from './setup/setup-status.js';
|
|
33
33
|
import { registerSetupMigrate } from './setup/setup-migrate.js';
|
|
34
|
+
import { registerSetupBootstrap } from './setup/setup-bootstrap.js';
|
|
34
35
|
import { registerSetupSeed } from './setup/setup-seed.js';
|
|
35
36
|
// Business tools (11)
|
|
36
37
|
import { registerProspectCreate } from './business/prospect-create.js';
|
|
@@ -75,6 +76,7 @@ export function registerAllTools(server, adapter) {
|
|
|
75
76
|
// Setup tools
|
|
76
77
|
registerSetupStatus(server, adapter);
|
|
77
78
|
registerSetupMigrate(server, adapter);
|
|
79
|
+
registerSetupBootstrap(server, adapter);
|
|
78
80
|
registerSetupSeed(server, adapter);
|
|
79
81
|
// Business tools
|
|
80
82
|
registerProspectCreate(server, adapter);
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Tool: setup_bootstrap
|
|
3
|
+
*
|
|
4
|
+
* RC-2 fix (incident 2026-05-11): Generates a single SQL block containing
|
|
5
|
+
* every bundled Supabase migration concatenated in numeric order, followed
|
|
6
|
+
* by NOTIFY pgrst, 'reload schema'. Customer pastes the block into the
|
|
7
|
+
* Supabase SQL Editor and runs it once. Stops short of running the SQL
|
|
8
|
+
* itself because Supabase service-role over PostgREST does not expose
|
|
9
|
+
* arbitrary SQL execution — that needs either a custom exec_sql function
|
|
10
|
+
* (Approach B, opt-in by customer) or the Management API with a personal
|
|
11
|
+
* access token (Approach C, adds auth surface). This is Approach A: lowest
|
|
12
|
+
* friction, no new auth, works on Cloud + self-hosted.
|
|
13
|
+
*
|
|
14
|
+
* After the customer runs the block, setup_migrate will report all
|
|
15
|
+
* collections present.
|
|
16
|
+
*/
|
|
17
|
+
import { readFileSync, readdirSync } from 'node:fs';
|
|
18
|
+
import { dirname, join } from 'node:path';
|
|
19
|
+
import { fileURLToPath } from 'node:url';
|
|
20
|
+
import { makeToolResponse, makeErrorResponse } from '../shared.js';
|
|
21
|
+
const MIGRATIONS_DIR = join(dirname(fileURLToPath(import.meta.url)), '..', '..', '..', 'migrations', 'supabase');
|
|
22
|
+
export function registerSetupBootstrap(server, adapter) {
|
|
23
|
+
server.tool('setup_bootstrap', 'Generate a paste-ready SQL block (all bundled Supabase migrations + PostgREST reload). Open the returned sql_editor_url, paste sql, run. Idempotent. Supabase backend only — PocketBase customers use setup_migrate.', {}, async () => {
|
|
24
|
+
if (adapter.backend !== 'supabase') {
|
|
25
|
+
return makeErrorResponse('setup_bootstrap is Supabase-only. PocketBase customers use setup_migrate.');
|
|
26
|
+
}
|
|
27
|
+
try {
|
|
28
|
+
const files = readdirSync(MIGRATIONS_DIR).filter((f) => f.endsWith('.sql')).sort();
|
|
29
|
+
if (files.length === 0) {
|
|
30
|
+
return makeErrorResponse(`No bundled migration files found at ${MIGRATIONS_DIR}. Package install may be corrupted.`);
|
|
31
|
+
}
|
|
32
|
+
const blocks = files.map((f) => `-- ===== ${f} =====\n${readFileSync(join(MIGRATIONS_DIR, f), 'utf-8').trimEnd()}\n`);
|
|
33
|
+
const sql = [
|
|
34
|
+
...blocks,
|
|
35
|
+
'-- ===== Reload PostgREST schema cache =====',
|
|
36
|
+
"-- Without this, PostgREST keeps serving stale cache and knowledge_* calls fail.",
|
|
37
|
+
"NOTIFY pgrst, 'reload schema';",
|
|
38
|
+
'',
|
|
39
|
+
].join('\n');
|
|
40
|
+
// Supabase URL format: https://<ref>.supabase.co. The SQL Editor URL is
|
|
41
|
+
// https://supabase.com/dashboard/project/<ref>/sql/new. We try to extract
|
|
42
|
+
// the ref; if the URL doesn't match the expected format (self-hosted,
|
|
43
|
+
// etc.), we fall back to the generic dashboard.
|
|
44
|
+
const supabaseUrl = adapter.supabaseUrl || '';
|
|
45
|
+
const refMatch = supabaseUrl.match(/https?:\/\/([a-z0-9]+)\.supabase\.co/);
|
|
46
|
+
const sqlEditorUrl = refMatch
|
|
47
|
+
? `https://supabase.com/dashboard/project/${refMatch[1]}/sql/new`
|
|
48
|
+
: 'https://supabase.com/dashboard/project/_/sql/new';
|
|
49
|
+
return makeToolResponse({
|
|
50
|
+
backend: 'supabase',
|
|
51
|
+
migrations_path: MIGRATIONS_DIR,
|
|
52
|
+
files_count: files.length,
|
|
53
|
+
files,
|
|
54
|
+
sql,
|
|
55
|
+
sql_editor_url: sqlEditorUrl,
|
|
56
|
+
instructions: [
|
|
57
|
+
`1. Open ${sqlEditorUrl}`,
|
|
58
|
+
'2. Paste the contents of the `sql` field above into the editor.',
|
|
59
|
+
'3. Run.',
|
|
60
|
+
'4. Verify with setup_migrate (it should report 0 missing collections).',
|
|
61
|
+
],
|
|
62
|
+
});
|
|
63
|
+
}
|
|
64
|
+
catch (err) {
|
|
65
|
+
const msg = err instanceof Error ? err.message : 'unknown';
|
|
66
|
+
console.error('[setup_bootstrap] Error:', err);
|
|
67
|
+
return makeErrorResponse(`Failed to assemble bootstrap SQL from ${MIGRATIONS_DIR}: ${msg}`);
|
|
68
|
+
}
|
|
69
|
+
});
|
|
70
|
+
}
|
|
71
|
+
//# sourceMappingURL=setup-bootstrap.js.map
|
|
@@ -3,8 +3,16 @@
|
|
|
3
3
|
*
|
|
4
4
|
* Apply migrations — additive only, skips existing collections.
|
|
5
5
|
* Creates all expected collections in the database.
|
|
6
|
+
*
|
|
7
|
+
* RC-3 fix (incident 2026-05-11): Replaced hardcoded project-relative
|
|
8
|
+
* "migrations/supabase/" string with runtime-resolved absolute path to
|
|
9
|
+
* the bundled SQL files inside this package.
|
|
6
10
|
*/
|
|
11
|
+
import { dirname, join } from 'node:path';
|
|
12
|
+
import { fileURLToPath } from 'node:url';
|
|
7
13
|
import { makeToolResponse, makeErrorResponse } from '../shared.js';
|
|
14
|
+
const PACKAGE_MIGRATIONS_SUPABASE = join(dirname(fileURLToPath(import.meta.url)), '..', '..', '..', 'migrations', 'supabase');
|
|
15
|
+
const PACKAGE_MIGRATIONS_POCKETBASE = join(dirname(fileURLToPath(import.meta.url)), '..', '..', '..', 'migrations', 'pocketbase');
|
|
8
16
|
/** Collection schemas for PocketBase creation */
|
|
9
17
|
const COLLECTION_SCHEMAS = [
|
|
10
18
|
{ name: 'knowledge', description: 'Knowledge items (facts, patterns, insights, lessons, references)' },
|
|
@@ -23,10 +31,11 @@ const COLLECTION_SCHEMAS = [
|
|
|
23
31
|
{ name: 'affiliates', description: 'Affiliate partners and commissions' },
|
|
24
32
|
];
|
|
25
33
|
export function registerSetupMigrate(server, adapter) {
|
|
26
|
-
server.tool('setup_migrate', 'Create missing database collections/tables. Additive only — existing collections are skipped. For PocketBase, creates collections via API. For Supabase, reports SQL migrations
|
|
34
|
+
server.tool('setup_migrate', 'Create missing database collections/tables. Additive only — existing collections are skipped. For PocketBase, creates collections via API. For Supabase, reports SQL migrations and recommends running setup_bootstrap for paste-ready SQL.', {}, async () => {
|
|
27
35
|
try {
|
|
28
36
|
const skipped = [];
|
|
29
37
|
const needsMigration = [];
|
|
38
|
+
const migrationsPath = adapter.backend === 'supabase' ? PACKAGE_MIGRATIONS_SUPABASE : PACKAGE_MIGRATIONS_POCKETBASE;
|
|
30
39
|
for (const schema of COLLECTION_SCHEMAS) {
|
|
31
40
|
try {
|
|
32
41
|
const exists = await adapter.collectionExists(schema.name);
|
|
@@ -34,18 +43,12 @@ export function registerSetupMigrate(server, adapter) {
|
|
|
34
43
|
skipped.push(schema.name);
|
|
35
44
|
continue;
|
|
36
45
|
}
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
}
|
|
43
|
-
else {
|
|
44
|
-
needsMigration.push({
|
|
45
|
-
name: schema.name,
|
|
46
|
-
instruction: 'Run PocketBase migrations from migrations/pocketbase/ directory.',
|
|
47
|
-
});
|
|
48
|
-
}
|
|
46
|
+
needsMigration.push({
|
|
47
|
+
name: schema.name,
|
|
48
|
+
instruction: adapter.backend === 'supabase'
|
|
49
|
+
? `Apply SQL from ${migrationsPath}/. Easiest path: call setup_bootstrap for a paste-ready SQL block.`
|
|
50
|
+
: `Apply migration from ${migrationsPath}/.`,
|
|
51
|
+
});
|
|
49
52
|
}
|
|
50
53
|
catch (err) {
|
|
51
54
|
const msg = err instanceof Error ? err.message : 'Unknown error';
|
|
@@ -55,6 +58,7 @@ export function registerSetupMigrate(server, adapter) {
|
|
|
55
58
|
}
|
|
56
59
|
return makeToolResponse({
|
|
57
60
|
backend: adapter.backend,
|
|
61
|
+
migrations_path: migrationsPath,
|
|
58
62
|
existing: skipped.length,
|
|
59
63
|
needs_migration: needsMigration.length,
|
|
60
64
|
details: {
|
|
@@ -62,8 +66,8 @@ export function registerSetupMigrate(server, adapter) {
|
|
|
62
66
|
needs_migration: needsMigration.length > 0 ? needsMigration : undefined,
|
|
63
67
|
},
|
|
64
68
|
message: adapter.backend === 'pocketbase'
|
|
65
|
-
? `Schema check complete. ${skipped.length} existing, ${needsMigration.length} need migration files.
|
|
66
|
-
: `Schema check complete. ${skipped.length} existing, ${needsMigration.length} need SQL
|
|
69
|
+
? `Schema check complete. ${skipped.length} existing, ${needsMigration.length} need migration files. Apply from ${migrationsPath}/.`
|
|
70
|
+
: `Schema check complete. ${skipped.length} existing, ${needsMigration.length} need SQL. Run setup_bootstrap for a paste-ready block, or apply from ${migrationsPath}/ manually.`,
|
|
67
71
|
});
|
|
68
72
|
}
|
|
69
73
|
catch (error) {
|
|
@@ -72,4 +76,4 @@ export function registerSetupMigrate(server, adapter) {
|
|
|
72
76
|
}
|
|
73
77
|
});
|
|
74
78
|
}
|
|
75
|
-
//# sourceMappingURL=setup-migrate.js.map
|
|
79
|
+
//# sourceMappingURL=setup-migrate.js.map
|
|
@@ -2,6 +2,13 @@
|
|
|
2
2
|
* Tool: setup_status
|
|
3
3
|
*
|
|
4
4
|
* Check backend connection, list existing/missing collections, report status.
|
|
5
|
+
*
|
|
6
|
+
* RC-1 fix (incident 2026-05-11): Previously called adapter.listCollections()
|
|
7
|
+
* which uses rpc('get_public_tables') — a custom Postgres function absent from
|
|
8
|
+
* fresh Supabase projects. Fallback to information_schema also failed because
|
|
9
|
+
* PostgREST only exposes the public schema. Now uses the same code path as
|
|
10
|
+
* setup_migrate (adapter.collectionExists per expected collection) so the
|
|
11
|
+
* diagnostic agrees with the data tools.
|
|
5
12
|
*/
|
|
6
13
|
import { makeToolResponse, makeErrorResponse } from '../shared.js';
|
|
7
14
|
const EXPECTED_COLLECTIONS = [
|
|
@@ -23,20 +30,18 @@ const EXPECTED_COLLECTIONS = [
|
|
|
23
30
|
export function registerSetupStatus(server, adapter) {
|
|
24
31
|
server.tool('setup_status', 'Check database connection status, list existing and missing collections, and report schema readiness.', {}, { readOnlyHint: true }, async () => {
|
|
25
32
|
try {
|
|
26
|
-
// Test connection by listing collections
|
|
27
|
-
const existing = await adapter.listCollections();
|
|
28
|
-
const existingSet = new Set(existing);
|
|
29
33
|
const present = [];
|
|
30
34
|
const missing = [];
|
|
31
35
|
for (const collection of EXPECTED_COLLECTIONS) {
|
|
32
|
-
|
|
36
|
+
const exists = await adapter.collectionExists(collection);
|
|
37
|
+
if (exists) {
|
|
33
38
|
present.push(collection);
|
|
34
39
|
}
|
|
35
40
|
else {
|
|
36
41
|
missing.push(collection);
|
|
37
42
|
}
|
|
38
43
|
}
|
|
39
|
-
|
|
44
|
+
const existingSet = new Set(present);
|
|
40
45
|
let schemaVersion = null;
|
|
41
46
|
if (existingSet.has('settings')) {
|
|
42
47
|
try {
|
|
@@ -75,4 +80,4 @@ export function registerSetupStatus(server, adapter) {
|
|
|
75
80
|
}
|
|
76
81
|
});
|
|
77
82
|
}
|
|
78
|
-
//# sourceMappingURL=setup-status.js.map
|
|
83
|
+
//# sourceMappingURL=setup-status.js.map
|
|
@@ -2,26 +2,24 @@
|
|
|
2
2
|
* PocketBase Migration 001: Core schema
|
|
3
3
|
*
|
|
4
4
|
* Creates knowledge, decisions, sessions collections.
|
|
5
|
-
* PocketBase v0.23+ field format.
|
|
6
5
|
*/
|
|
7
6
|
|
|
8
7
|
/// <reference path="../pb_data/types.d.ts" />
|
|
9
8
|
|
|
10
9
|
migrate((app) => {
|
|
10
|
+
// knowledge collection
|
|
11
11
|
const knowledge = new Collection({
|
|
12
12
|
name: 'knowledge',
|
|
13
13
|
type: 'base',
|
|
14
|
-
|
|
15
|
-
{ name: 'type', type: 'select', required: true,
|
|
16
|
-
{ name: 'title', type: 'text', required: true,
|
|
17
|
-
{ name: 'content', type: 'editor', required: true, maxSize: 50000 },
|
|
18
|
-
{ name: 'summary', type: 'text',
|
|
14
|
+
schema: [
|
|
15
|
+
{ name: 'type', type: 'select', required: true, options: { values: ['fact', 'knowledge', 'pattern', 'insight', 'lesson', 'reference'] } },
|
|
16
|
+
{ name: 'title', type: 'text', required: true, options: { maxSize: 500 } },
|
|
17
|
+
{ name: 'content', type: 'editor', required: true, options: { maxSize: 50000 } },
|
|
18
|
+
{ name: 'summary', type: 'text', options: { maxSize: 2000 } },
|
|
19
19
|
{ name: 'tags', type: 'json' },
|
|
20
|
-
{ name: 'source', type: 'text',
|
|
21
|
-
{ name: 'confidence', type: 'number', min: 0, max: 1 },
|
|
20
|
+
{ name: 'source', type: 'text', options: { maxSize: 500 } },
|
|
21
|
+
{ name: 'confidence', type: 'number', options: { min: 0, max: 1 } },
|
|
22
22
|
{ name: 'last_validated_at', type: 'date' },
|
|
23
|
-
{ name: 'created', type: 'autodate', onCreate: true },
|
|
24
|
-
{ name: 'updated', type: 'autodate', onCreate: true, onUpdate: true },
|
|
25
23
|
],
|
|
26
24
|
indexes: [
|
|
27
25
|
'CREATE INDEX idx_knowledge_type ON knowledge (type)',
|
|
@@ -30,47 +28,45 @@ migrate((app) => {
|
|
|
30
28
|
});
|
|
31
29
|
app.save(knowledge);
|
|
32
30
|
|
|
31
|
+
// decisions collection
|
|
33
32
|
const decisions = new Collection({
|
|
34
33
|
name: 'decisions',
|
|
35
34
|
type: 'base',
|
|
36
|
-
|
|
37
|
-
{ name: 'title', type: 'text', required: true,
|
|
38
|
-
{ name: 'context', type: 'editor', maxSize: 5000 },
|
|
35
|
+
schema: [
|
|
36
|
+
{ name: 'title', type: 'text', required: true, options: { maxSize: 500 } },
|
|
37
|
+
{ name: 'context', type: 'editor', options: { maxSize: 5000 } },
|
|
39
38
|
{ name: 'options_considered', type: 'json', required: true },
|
|
40
|
-
{ name: 'chosen_option', type: 'text', required: true,
|
|
41
|
-
{ name: 'rationale', type: 'editor', maxSize: 5000 },
|
|
42
|
-
{ name: 'outcome', type: 'editor', maxSize: 5000 },
|
|
39
|
+
{ name: 'chosen_option', type: 'text', required: true, options: { maxSize: 500 } },
|
|
40
|
+
{ name: 'rationale', type: 'editor', options: { maxSize: 5000 } },
|
|
41
|
+
{ name: 'outcome', type: 'editor', options: { maxSize: 5000 } },
|
|
43
42
|
{ name: 'tags', type: 'json' },
|
|
44
|
-
{ name: 'created', type: 'autodate', onCreate: true },
|
|
45
|
-
{ name: 'updated', type: 'autodate', onCreate: true, onUpdate: true },
|
|
46
43
|
],
|
|
47
44
|
});
|
|
48
45
|
app.save(decisions);
|
|
49
46
|
|
|
47
|
+
// sessions collection
|
|
50
48
|
const sessions = new Collection({
|
|
51
49
|
name: 'sessions',
|
|
52
50
|
type: 'base',
|
|
53
|
-
|
|
54
|
-
{ name: 'title', type: 'text', required: true,
|
|
55
|
-
{ name: 'summary', type: 'editor', required: true, maxSize: 10000 },
|
|
51
|
+
schema: [
|
|
52
|
+
{ name: 'title', type: 'text', required: true, options: { maxSize: 500 } },
|
|
53
|
+
{ name: 'summary', type: 'editor', required: true, options: { maxSize: 10000 } },
|
|
56
54
|
{ name: 'session_date', type: 'date' },
|
|
57
55
|
{ name: 'skills_used', type: 'json' },
|
|
58
56
|
{ name: 'files_changed', type: 'json' },
|
|
59
57
|
{ name: 'decisions_made', type: 'json' },
|
|
60
58
|
{ name: 'duration_minutes', type: 'number' },
|
|
61
|
-
{ name: 'task_id', type: 'text',
|
|
62
|
-
{ name: 'branch', type: 'text',
|
|
59
|
+
{ name: 'task_id', type: 'text', options: { maxSize: 100 } },
|
|
60
|
+
{ name: 'branch', type: 'text', options: { maxSize: 200 } },
|
|
63
61
|
{ name: 'patterns_learned', type: 'json' },
|
|
64
62
|
{ name: 'knowledge_created', type: 'number' },
|
|
65
63
|
{ name: 'knowledge_updated', type: 'number' },
|
|
66
64
|
{ name: 'metadata', type: 'json' },
|
|
67
|
-
{ name: 'created', type: 'autodate', onCreate: true },
|
|
68
|
-
{ name: 'updated', type: 'autodate', onCreate: true, onUpdate: true },
|
|
69
65
|
],
|
|
70
66
|
});
|
|
71
67
|
app.save(sessions);
|
|
72
68
|
}, (app) => {
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
69
|
+
app.delete(app.findCollectionByNameOrId('sessions'));
|
|
70
|
+
app.delete(app.findCollectionByNameOrId('decisions'));
|
|
71
|
+
app.delete(app.findCollectionByNameOrId('knowledge'));
|
|
76
72
|
});
|
|
@@ -1,23 +1,21 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* PocketBase Migration 002: Goals and tasks
|
|
3
|
-
* PocketBase v0.23+ field format.
|
|
4
3
|
*/
|
|
5
4
|
|
|
6
5
|
/// <reference path="../pb_data/types.d.ts" />
|
|
7
6
|
|
|
8
7
|
migrate((app) => {
|
|
8
|
+
// goals collection
|
|
9
9
|
const goals = new Collection({
|
|
10
10
|
name: 'goals',
|
|
11
11
|
type: 'base',
|
|
12
|
-
|
|
13
|
-
{ name: 'title', type: 'text', required: true,
|
|
14
|
-
{ name: 'description', type: 'editor', maxSize: 5000 },
|
|
15
|
-
{ name: 'timeframe', type: 'select', required: true,
|
|
16
|
-
{ name: 'status', type: 'select', required: true,
|
|
12
|
+
schema: [
|
|
13
|
+
{ name: 'title', type: 'text', required: true, options: { maxSize: 500 } },
|
|
14
|
+
{ name: 'description', type: 'editor', options: { maxSize: 5000 } },
|
|
15
|
+
{ name: 'timeframe', type: 'select', required: true, options: { values: ['daily', 'weekly', 'monthly', 'quarterly', 'yearly'] } },
|
|
16
|
+
{ name: 'status', type: 'select', required: true, options: { values: ['active', 'completed', 'paused', 'abandoned'] } },
|
|
17
17
|
{ name: 'key_results', type: 'json' },
|
|
18
18
|
{ name: 'tags', type: 'json' },
|
|
19
|
-
{ name: 'created', type: 'autodate', onCreate: true },
|
|
20
|
-
{ name: 'updated', type: 'autodate', onCreate: true, onUpdate: true },
|
|
21
19
|
],
|
|
22
20
|
indexes: [
|
|
23
21
|
'CREATE INDEX idx_goals_status ON goals (status)',
|
|
@@ -26,19 +24,18 @@ migrate((app) => {
|
|
|
26
24
|
});
|
|
27
25
|
app.save(goals);
|
|
28
26
|
|
|
27
|
+
// tasks collection
|
|
29
28
|
const tasks = new Collection({
|
|
30
29
|
name: 'tasks',
|
|
31
30
|
type: 'base',
|
|
32
|
-
|
|
33
|
-
{ name: 'title', type: 'text', required: true,
|
|
34
|
-
{ name: 'description', type: 'editor', maxSize: 5000 },
|
|
35
|
-
{ name: 'status', type: 'select', required: true,
|
|
36
|
-
{ name: 'priority', type: 'select', required: true,
|
|
31
|
+
schema: [
|
|
32
|
+
{ name: 'title', type: 'text', required: true, options: { maxSize: 500 } },
|
|
33
|
+
{ name: 'description', type: 'editor', options: { maxSize: 5000 } },
|
|
34
|
+
{ name: 'status', type: 'select', required: true, options: { values: ['todo', 'in_progress', 'done', 'cancelled'] } },
|
|
35
|
+
{ name: 'priority', type: 'select', required: true, options: { values: ['low', 'medium', 'high', 'urgent'] } },
|
|
37
36
|
{ name: 'due_date', type: 'date' },
|
|
38
37
|
{ name: 'tags', type: 'json' },
|
|
39
|
-
{ name: 'goal_id', type: 'text',
|
|
40
|
-
{ name: 'created', type: 'autodate', onCreate: true },
|
|
41
|
-
{ name: 'updated', type: 'autodate', onCreate: true, onUpdate: true },
|
|
38
|
+
{ name: 'goal_id', type: 'text', options: { maxSize: 100 } },
|
|
42
39
|
],
|
|
43
40
|
indexes: [
|
|
44
41
|
'CREATE INDEX idx_tasks_status ON tasks (status)',
|
|
@@ -47,6 +44,6 @@ migrate((app) => {
|
|
|
47
44
|
});
|
|
48
45
|
app.save(tasks);
|
|
49
46
|
}, (app) => {
|
|
50
|
-
|
|
51
|
-
|
|
47
|
+
app.delete(app.findCollectionByNameOrId('tasks'));
|
|
48
|
+
app.delete(app.findCollectionByNameOrId('goals'));
|
|
52
49
|
});
|
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* PocketBase Migration 003: Contacts
|
|
3
|
-
* PocketBase v0.23+ field format.
|
|
4
3
|
*/
|
|
5
4
|
|
|
6
5
|
/// <reference path="../pb_data/types.d.ts" />
|
|
@@ -9,18 +8,16 @@ migrate((app) => {
|
|
|
9
8
|
const contacts = new Collection({
|
|
10
9
|
name: 'contacts',
|
|
11
10
|
type: 'base',
|
|
12
|
-
|
|
13
|
-
{ name: 'name', type: 'text', required: true,
|
|
14
|
-
{ name: 'company', type: 'text',
|
|
15
|
-
{ name: 'role', type: 'text',
|
|
16
|
-
{ name: 'email', type: 'email' },
|
|
17
|
-
{ name: 'phone', type: 'text',
|
|
18
|
-
{ name: 'relationship', type: 'select',
|
|
19
|
-
{ name: 'notes', type: 'editor', maxSize: 5000 },
|
|
11
|
+
schema: [
|
|
12
|
+
{ name: 'name', type: 'text', required: true, options: { maxSize: 200 } },
|
|
13
|
+
{ name: 'company', type: 'text', options: { maxSize: 200 } },
|
|
14
|
+
{ name: 'role', type: 'text', options: { maxSize: 200 } },
|
|
15
|
+
{ name: 'email', type: 'email', options: { maxSize: 200 } },
|
|
16
|
+
{ name: 'phone', type: 'text', options: { maxSize: 50 } },
|
|
17
|
+
{ name: 'relationship', type: 'select', options: { values: ['colleague', 'client', 'prospect', 'partner', 'other'] } },
|
|
18
|
+
{ name: 'notes', type: 'editor', options: { maxSize: 5000 } },
|
|
20
19
|
{ name: 'tags', type: 'json' },
|
|
21
20
|
{ name: 'last_contact_date', type: 'date' },
|
|
22
|
-
{ name: 'created', type: 'autodate', onCreate: true },
|
|
23
|
-
{ name: 'updated', type: 'autodate', onCreate: true, onUpdate: true },
|
|
24
21
|
],
|
|
25
22
|
indexes: [
|
|
26
23
|
'CREATE INDEX idx_contacts_name ON contacts (name)',
|
|
@@ -28,5 +25,5 @@ migrate((app) => {
|
|
|
28
25
|
});
|
|
29
26
|
app.save(contacts);
|
|
30
27
|
}, (app) => {
|
|
31
|
-
|
|
28
|
+
app.delete(app.findCollectionByNameOrId('contacts'));
|
|
32
29
|
});
|
|
@@ -1,19 +1,17 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* PocketBase Migration 004: Entity aliases + settings
|
|
3
|
-
* PocketBase v0.23+ field format.
|
|
4
3
|
*/
|
|
5
4
|
|
|
6
5
|
/// <reference path="../pb_data/types.d.ts" />
|
|
7
6
|
|
|
8
7
|
migrate((app) => {
|
|
8
|
+
// entity_aliases collection
|
|
9
9
|
const aliases = new Collection({
|
|
10
10
|
name: 'entity_aliases',
|
|
11
11
|
type: 'base',
|
|
12
|
-
|
|
13
|
-
{ name: 'canonical', type: 'text', required: true,
|
|
14
|
-
{ name: 'alias', type: 'text', required: true,
|
|
15
|
-
{ name: 'created', type: 'autodate', onCreate: true },
|
|
16
|
-
{ name: 'updated', type: 'autodate', onCreate: true, onUpdate: true },
|
|
12
|
+
schema: [
|
|
13
|
+
{ name: 'canonical', type: 'text', required: true, options: { maxSize: 100 } },
|
|
14
|
+
{ name: 'alias', type: 'text', required: true, options: { maxSize: 200 } },
|
|
17
15
|
],
|
|
18
16
|
indexes: [
|
|
19
17
|
'CREATE UNIQUE INDEX idx_entity_aliases_unique ON entity_aliases (canonical, alias)',
|
|
@@ -23,14 +21,13 @@ migrate((app) => {
|
|
|
23
21
|
});
|
|
24
22
|
app.save(aliases);
|
|
25
23
|
|
|
24
|
+
// settings collection
|
|
26
25
|
const settings = new Collection({
|
|
27
26
|
name: 'settings',
|
|
28
27
|
type: 'base',
|
|
29
|
-
|
|
30
|
-
{ name: 'key', type: 'text', required: true,
|
|
28
|
+
schema: [
|
|
29
|
+
{ name: 'key', type: 'text', required: true, options: { maxSize: 100 } },
|
|
31
30
|
{ name: 'value', type: 'editor' },
|
|
32
|
-
{ name: 'created', type: 'autodate', onCreate: true },
|
|
33
|
-
{ name: 'updated', type: 'autodate', onCreate: true, onUpdate: true },
|
|
34
31
|
],
|
|
35
32
|
indexes: [
|
|
36
33
|
'CREATE UNIQUE INDEX idx_settings_key ON settings (key)',
|
|
@@ -38,6 +35,6 @@ migrate((app) => {
|
|
|
38
35
|
});
|
|
39
36
|
app.save(settings);
|
|
40
37
|
}, (app) => {
|
|
41
|
-
|
|
42
|
-
|
|
38
|
+
app.delete(app.findCollectionByNameOrId('settings'));
|
|
39
|
+
app.delete(app.findCollectionByNameOrId('entity_aliases'));
|
|
43
40
|
});
|
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* PocketBase Migration 005: Prospects (CRM)
|
|
3
|
-
* PocketBase v0.23+ field format.
|
|
4
3
|
*/
|
|
5
4
|
|
|
6
5
|
/// <reference path="../pb_data/types.d.ts" />
|
|
@@ -9,22 +8,20 @@ migrate((app) => {
|
|
|
9
8
|
const prospects = new Collection({
|
|
10
9
|
name: 'prospects',
|
|
11
10
|
type: 'base',
|
|
12
|
-
|
|
13
|
-
{ name: 'name', type: 'text', required: true,
|
|
14
|
-
{ name: 'email', type: 'email' },
|
|
15
|
-
{ name: 'company', type: 'text',
|
|
16
|
-
{ name: 'role', type: 'text',
|
|
17
|
-
{ name: 'stage', type: 'select', required: true,
|
|
18
|
-
{ name: 'source', type: 'text',
|
|
11
|
+
schema: [
|
|
12
|
+
{ name: 'name', type: 'text', required: true, options: { maxSize: 200 } },
|
|
13
|
+
{ name: 'email', type: 'email', options: { maxSize: 200 } },
|
|
14
|
+
{ name: 'company', type: 'text', options: { maxSize: 200 } },
|
|
15
|
+
{ name: 'role', type: 'text', options: { maxSize: 200 } },
|
|
16
|
+
{ name: 'stage', type: 'select', required: true, options: { values: ['new', 'contacted', 'responded', 'interested', 'ready_to_buy', 'proposal_sent', 'negotiating', 'closed_won', 'closed_lost', 'nurturing'] } },
|
|
17
|
+
{ name: 'source', type: 'text', options: { maxSize: 200 } },
|
|
19
18
|
{ name: 'estimated_value', type: 'number' },
|
|
20
|
-
{ name: 'next_action_type', type: 'text',
|
|
19
|
+
{ name: 'next_action_type', type: 'text', options: { maxSize: 100 } },
|
|
21
20
|
{ name: 'next_followup_date', type: 'date' },
|
|
22
21
|
{ name: 'last_contact_date', type: 'date' },
|
|
23
|
-
{ name: 'notes', type: 'editor', maxSize: 10000 },
|
|
22
|
+
{ name: 'notes', type: 'editor', options: { maxSize: 10000 } },
|
|
24
23
|
{ name: 'tags', type: 'json' },
|
|
25
|
-
{ name: 'linkedin_url', type: 'url' },
|
|
26
|
-
{ name: 'created', type: 'autodate', onCreate: true },
|
|
27
|
-
{ name: 'updated', type: 'autodate', onCreate: true, onUpdate: true },
|
|
24
|
+
{ name: 'linkedin_url', type: 'url', options: { maxSize: 500 } },
|
|
28
25
|
],
|
|
29
26
|
indexes: [
|
|
30
27
|
'CREATE INDEX idx_prospects_stage ON prospects (stage)',
|
|
@@ -32,5 +29,5 @@ migrate((app) => {
|
|
|
32
29
|
});
|
|
33
30
|
app.save(prospects);
|
|
34
31
|
}, (app) => {
|
|
35
|
-
|
|
32
|
+
app.delete(app.findCollectionByNameOrId('prospects'));
|
|
36
33
|
});
|