@assistkick/create 1.25.0 → 1.26.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 +1 -1
- package/templates/assistkick-product-system/packages/backend/src/services/init.ts +40 -2
- package/templates/assistkick-product-system/packages/shared/db/migrate.ts +22 -4
- package/templates/assistkick-product-system/packages/shared/drizzle.config.js +9 -4
- package/templates/assistkick-product-system/packages/shared/scripts/assign-project.ts +21 -4
package/package.json
CHANGED
|
@@ -5,6 +5,7 @@
|
|
|
5
5
|
|
|
6
6
|
import { join, dirname } from 'node:path';
|
|
7
7
|
import { fileURLToPath } from 'node:url';
|
|
8
|
+
import { appendFileSync, existsSync, mkdirSync, readFileSync, writeFileSync, statSync } from 'node:fs';
|
|
8
9
|
import { createClaudeService } from '@assistkick/shared/lib/claude-service.js';
|
|
9
10
|
import { GitWorkflow } from '@assistkick/shared/lib/git_workflow.js';
|
|
10
11
|
import { getDb } from '@assistkick/shared/lib/db.js';
|
|
@@ -41,16 +42,53 @@ const DEBUGGER_SKILL_PATH = join(SKILLS_DIR, 'product-debugger', 'SKILL.md');
|
|
|
41
42
|
const VIDEO_PACKAGE_DIR = join(SKILL_ROOT, 'video');
|
|
42
43
|
const BUNDLE_OUTPUT_DIR = process.env.REMOTION_BUNDLE_DIR || join(PROJECT_ROOT, 'data', 'remotion-bundle');
|
|
43
44
|
|
|
45
|
+
/* ── Persistent file logger ──────────────────────────────────────────────
|
|
46
|
+
* Writes every log line to data/server.log so logs survive tsx watch restarts.
|
|
47
|
+
* Truncates the file when it exceeds MAX_LOG_LINES to prevent unbounded growth.
|
|
48
|
+
*/
|
|
49
|
+
const LOG_DIR = join(SKILL_ROOT, 'data');
|
|
50
|
+
const LOG_FILE = join(LOG_DIR, 'server.log');
|
|
51
|
+
const MAX_LOG_LINES = 2000;
|
|
52
|
+
const TRUNCATE_TO = 1500; // keep last N lines after truncation
|
|
53
|
+
|
|
54
|
+
if (!existsSync(LOG_DIR)) mkdirSync(LOG_DIR, { recursive: true });
|
|
55
|
+
|
|
56
|
+
/** Append a line to the log file, truncating when it gets too large. */
|
|
57
|
+
const writeToLogFile = (line: string): void => {
|
|
58
|
+
try {
|
|
59
|
+
appendFileSync(LOG_FILE, line + '\n');
|
|
60
|
+
// Check file size periodically (cheap stat check — only truncate when > ~200KB)
|
|
61
|
+
const stats = statSync(LOG_FILE);
|
|
62
|
+
if (stats.size > 200_000) {
|
|
63
|
+
const content = readFileSync(LOG_FILE, 'utf-8');
|
|
64
|
+
const lines = content.split('\n');
|
|
65
|
+
if (lines.length > MAX_LOG_LINES) {
|
|
66
|
+
const trimmed = lines.slice(-TRUNCATE_TO).join('\n');
|
|
67
|
+
writeFileSync(LOG_FILE, trimmed + '\n');
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
} catch {
|
|
71
|
+
// Never let logging failures break the app
|
|
72
|
+
}
|
|
73
|
+
};
|
|
74
|
+
|
|
75
|
+
// Write startup marker so you can find restart boundaries in the log file
|
|
76
|
+
writeToLogFile(`\n${'='.repeat(80)}\n[${new Date().toISOString()}] SERVER STARTING (pid ${process.pid})\n${'='.repeat(80)}`);
|
|
77
|
+
|
|
44
78
|
export const log = (tag: string, ...args: any[]) => {
|
|
45
79
|
const ts = new Date().toISOString().slice(11, 23);
|
|
46
|
-
|
|
80
|
+
const line = `[${ts}] [${tag}] ${args.map(a => typeof a === 'string' ? a : JSON.stringify(a)).join(' ')}`;
|
|
81
|
+
console.log(line);
|
|
82
|
+
writeToLogFile(line);
|
|
47
83
|
};
|
|
48
84
|
|
|
49
85
|
/** Log an error with its stack trace for debugging. */
|
|
50
86
|
export const logError = (tag: string, msg: string, err: unknown) => {
|
|
51
87
|
const ts = new Date().toISOString().slice(11, 23);
|
|
52
88
|
const stack = err instanceof Error ? err.stack : String(err);
|
|
53
|
-
|
|
89
|
+
const line = `[${ts}] [${tag}] ERROR ${msg} ${stack}`;
|
|
90
|
+
console.error(line);
|
|
91
|
+
writeToLogFile(line);
|
|
54
92
|
};
|
|
55
93
|
|
|
56
94
|
export let claudeService: any;
|
|
@@ -14,12 +14,30 @@ import { migrate } from 'drizzle-orm/libsql/migrator';
|
|
|
14
14
|
import { drizzle } from 'drizzle-orm/libsql';
|
|
15
15
|
import { createClient } from '@libsql/client';
|
|
16
16
|
import { getTableColumns, getTableName } from 'drizzle-orm';
|
|
17
|
+
import { existsSync, mkdirSync } from 'node:fs';
|
|
18
|
+
import { join } from 'node:path';
|
|
17
19
|
import * as schema from './schema.js';
|
|
18
20
|
|
|
19
|
-
const
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
21
|
+
const tursoUrl = process.env.TURSO_DATABASE_URL;
|
|
22
|
+
const tursoAuthToken = process.env.TURSO_AUTH_TOKEN;
|
|
23
|
+
|
|
24
|
+
let connectionUrl: string;
|
|
25
|
+
let connectionAuthToken: string | undefined;
|
|
26
|
+
|
|
27
|
+
if (tursoUrl && tursoAuthToken) {
|
|
28
|
+
connectionUrl = tursoUrl;
|
|
29
|
+
connectionAuthToken = tursoAuthToken;
|
|
30
|
+
} else {
|
|
31
|
+
// Local SQLite fallback — same logic as lib/db.ts
|
|
32
|
+
const dataDir = join(import.meta.dirname, '..', '..', '..', 'data');
|
|
33
|
+
if (!existsSync(dataDir)) {
|
|
34
|
+
mkdirSync(dataDir, { recursive: true });
|
|
35
|
+
}
|
|
36
|
+
connectionUrl = `file:${join(dataDir, 'local.db')}`;
|
|
37
|
+
connectionAuthToken = undefined;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
const client = createClient({ url: connectionUrl, authToken: connectionAuthToken });
|
|
23
41
|
|
|
24
42
|
const db = drizzle(client);
|
|
25
43
|
|
|
@@ -1,14 +1,19 @@
|
|
|
1
1
|
import { defineConfig } from 'drizzle-kit';
|
|
2
2
|
import { config } from 'dotenv';
|
|
3
|
+
import { join } from 'node:path';
|
|
3
4
|
|
|
4
5
|
config({ path: '../../.env' });
|
|
5
6
|
|
|
7
|
+
const tursoUrl = process.env.TURSO_DATABASE_URL;
|
|
8
|
+
const tursoAuthToken = process.env.TURSO_AUTH_TOKEN;
|
|
9
|
+
|
|
10
|
+
const dbCredentials = (tursoUrl && tursoAuthToken)
|
|
11
|
+
? { url: tursoUrl, authToken: tursoAuthToken }
|
|
12
|
+
: { url: `file:${join(import.meta.dirname, '..', '..', 'data', 'local.db')}` };
|
|
13
|
+
|
|
6
14
|
export default defineConfig({
|
|
7
15
|
schema: './db/schema.ts',
|
|
8
16
|
out: './db/migrations',
|
|
9
17
|
dialect: 'turso',
|
|
10
|
-
dbCredentials
|
|
11
|
-
url: process.env.TURSO_DATABASE_URL,
|
|
12
|
-
authToken: process.env.TURSO_AUTH_TOKEN,
|
|
13
|
-
},
|
|
18
|
+
dbCredentials,
|
|
14
19
|
});
|
|
@@ -7,6 +7,8 @@ import { config } from 'dotenv';
|
|
|
7
7
|
config({ path: '../../.env' });
|
|
8
8
|
|
|
9
9
|
import { createClient } from '@libsql/client';
|
|
10
|
+
import { existsSync, mkdirSync } from 'node:fs';
|
|
11
|
+
import { join } from 'node:path';
|
|
10
12
|
|
|
11
13
|
const TABLES = [
|
|
12
14
|
'nodes',
|
|
@@ -25,10 +27,25 @@ if (!projectId) {
|
|
|
25
27
|
}
|
|
26
28
|
|
|
27
29
|
async function main() {
|
|
28
|
-
const
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
30
|
+
const tursoUrl = process.env.TURSO_DATABASE_URL;
|
|
31
|
+
const tursoAuthToken = process.env.TURSO_AUTH_TOKEN;
|
|
32
|
+
|
|
33
|
+
let connectionUrl: string;
|
|
34
|
+
let connectionAuthToken: string | undefined;
|
|
35
|
+
|
|
36
|
+
if (tursoUrl && tursoAuthToken) {
|
|
37
|
+
connectionUrl = tursoUrl;
|
|
38
|
+
connectionAuthToken = tursoAuthToken;
|
|
39
|
+
} else {
|
|
40
|
+
const dataDir = join(import.meta.dirname, '..', '..', '..', 'data');
|
|
41
|
+
if (!existsSync(dataDir)) {
|
|
42
|
+
mkdirSync(dataDir, { recursive: true });
|
|
43
|
+
}
|
|
44
|
+
connectionUrl = `file:${join(dataDir, 'local.db')}`;
|
|
45
|
+
connectionAuthToken = undefined;
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
const client = createClient({ url: connectionUrl, authToken: connectionAuthToken });
|
|
32
49
|
|
|
33
50
|
console.log(`Assigning unassigned rows to project: ${projectId}\n`);
|
|
34
51
|
|