kozou 0.0.2 → 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.
- package/LICENSE +202 -21
- package/README.md +96 -17
- package/dist/cli.d.ts +3 -0
- package/dist/cli.d.ts.map +1 -0
- package/dist/cli.js +52 -0
- package/dist/cli.js.map +1 -0
- package/dist/commands/dev.d.ts +5 -0
- package/dist/commands/dev.d.ts.map +1 -0
- package/dist/commands/dev.js +21 -0
- package/dist/commands/dev.js.map +1 -0
- package/dist/commands/inspect.d.ts +10 -0
- package/dist/commands/inspect.d.ts.map +1 -0
- package/dist/commands/inspect.js +47 -0
- package/dist/commands/inspect.js.map +1 -0
- package/dist/commands/mcp.d.ts +8 -0
- package/dist/commands/mcp.d.ts.map +1 -0
- package/dist/commands/mcp.js +29 -0
- package/dist/commands/mcp.js.map +1 -0
- package/dist/config.d.ts +178 -0
- package/dist/config.d.ts.map +1 -0
- package/dist/config.js +154 -0
- package/dist/config.js.map +1 -0
- package/dist/create-kozou.d.ts +3 -0
- package/dist/create-kozou.d.ts.map +1 -0
- package/dist/create-kozou.js +27 -0
- package/dist/create-kozou.js.map +1 -0
- package/dist/index.d.ts +12 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +11 -0
- package/dist/index.js.map +1 -0
- package/dist/scaffold.d.ts +11 -0
- package/dist/scaffold.d.ts.map +1 -0
- package/dist/scaffold.js +54 -0
- package/dist/scaffold.js.map +1 -0
- package/dist/templates/docker-compose.yml +63 -0
- package/dist/templates/env.example +11 -0
- package/dist/templates/kozou.config.yaml +29 -0
- package/dist/templates/migrations/0001_init.sql +25 -0
- package/dist/templates/ui-hints.yaml +26 -0
- package/package.json +44 -21
package/dist/config.d.ts
ADDED
|
@@ -0,0 +1,178 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
declare const configSchema: z.ZodObject<{
|
|
3
|
+
database: z.ZodObject<{
|
|
4
|
+
url: z.ZodString;
|
|
5
|
+
schemas: z.ZodDefault<z.ZodArray<z.ZodString, "many">>;
|
|
6
|
+
}, "strip", z.ZodTypeAny, {
|
|
7
|
+
url: string;
|
|
8
|
+
schemas: string[];
|
|
9
|
+
}, {
|
|
10
|
+
url: string;
|
|
11
|
+
schemas?: string[] | undefined;
|
|
12
|
+
}>;
|
|
13
|
+
server: z.ZodDefault<z.ZodObject<{
|
|
14
|
+
ui: z.ZodDefault<z.ZodObject<{
|
|
15
|
+
port: z.ZodDefault<z.ZodNumber>;
|
|
16
|
+
host: z.ZodDefault<z.ZodString>;
|
|
17
|
+
}, "strip", z.ZodTypeAny, {
|
|
18
|
+
port: number;
|
|
19
|
+
host: string;
|
|
20
|
+
}, {
|
|
21
|
+
port?: number | undefined;
|
|
22
|
+
host?: string | undefined;
|
|
23
|
+
}>>;
|
|
24
|
+
mcp: z.ZodDefault<z.ZodObject<{
|
|
25
|
+
http: z.ZodDefault<z.ZodObject<{
|
|
26
|
+
port: z.ZodDefault<z.ZodNumber>;
|
|
27
|
+
host: z.ZodDefault<z.ZodString>;
|
|
28
|
+
}, "strip", z.ZodTypeAny, {
|
|
29
|
+
port: number;
|
|
30
|
+
host: string;
|
|
31
|
+
}, {
|
|
32
|
+
port?: number | undefined;
|
|
33
|
+
host?: string | undefined;
|
|
34
|
+
}>>;
|
|
35
|
+
stdio: z.ZodDefault<z.ZodBoolean>;
|
|
36
|
+
}, "strip", z.ZodTypeAny, {
|
|
37
|
+
http: {
|
|
38
|
+
port: number;
|
|
39
|
+
host: string;
|
|
40
|
+
};
|
|
41
|
+
stdio: boolean;
|
|
42
|
+
}, {
|
|
43
|
+
http?: {
|
|
44
|
+
port?: number | undefined;
|
|
45
|
+
host?: string | undefined;
|
|
46
|
+
} | undefined;
|
|
47
|
+
stdio?: boolean | undefined;
|
|
48
|
+
}>>;
|
|
49
|
+
}, "strip", z.ZodTypeAny, {
|
|
50
|
+
ui: {
|
|
51
|
+
port: number;
|
|
52
|
+
host: string;
|
|
53
|
+
};
|
|
54
|
+
mcp: {
|
|
55
|
+
http: {
|
|
56
|
+
port: number;
|
|
57
|
+
host: string;
|
|
58
|
+
};
|
|
59
|
+
stdio: boolean;
|
|
60
|
+
};
|
|
61
|
+
}, {
|
|
62
|
+
ui?: {
|
|
63
|
+
port?: number | undefined;
|
|
64
|
+
host?: string | undefined;
|
|
65
|
+
} | undefined;
|
|
66
|
+
mcp?: {
|
|
67
|
+
http?: {
|
|
68
|
+
port?: number | undefined;
|
|
69
|
+
host?: string | undefined;
|
|
70
|
+
} | undefined;
|
|
71
|
+
stdio?: boolean | undefined;
|
|
72
|
+
} | undefined;
|
|
73
|
+
}>>;
|
|
74
|
+
adapter: z.ZodDefault<z.ZodObject<{
|
|
75
|
+
type: z.ZodDefault<z.ZodLiteral<"postgrest">>;
|
|
76
|
+
url: z.ZodDefault<z.ZodString>;
|
|
77
|
+
}, "strip", z.ZodTypeAny, {
|
|
78
|
+
type: "postgrest";
|
|
79
|
+
url: string;
|
|
80
|
+
}, {
|
|
81
|
+
type?: "postgrest" | undefined;
|
|
82
|
+
url?: string | undefined;
|
|
83
|
+
}>>;
|
|
84
|
+
uiHints: z.ZodDefault<z.ZodObject<{
|
|
85
|
+
path: z.ZodDefault<z.ZodNullable<z.ZodString>>;
|
|
86
|
+
}, "strip", z.ZodTypeAny, {
|
|
87
|
+
path: string | null;
|
|
88
|
+
}, {
|
|
89
|
+
path?: string | null | undefined;
|
|
90
|
+
}>>;
|
|
91
|
+
cache: z.ZodDefault<z.ZodObject<{
|
|
92
|
+
ttlMs: z.ZodDefault<z.ZodNumber>;
|
|
93
|
+
}, "strip", z.ZodTypeAny, {
|
|
94
|
+
ttlMs: number;
|
|
95
|
+
}, {
|
|
96
|
+
ttlMs?: number | undefined;
|
|
97
|
+
}>>;
|
|
98
|
+
}, "strip", z.ZodTypeAny, {
|
|
99
|
+
database: {
|
|
100
|
+
url: string;
|
|
101
|
+
schemas: string[];
|
|
102
|
+
};
|
|
103
|
+
server: {
|
|
104
|
+
ui: {
|
|
105
|
+
port: number;
|
|
106
|
+
host: string;
|
|
107
|
+
};
|
|
108
|
+
mcp: {
|
|
109
|
+
http: {
|
|
110
|
+
port: number;
|
|
111
|
+
host: string;
|
|
112
|
+
};
|
|
113
|
+
stdio: boolean;
|
|
114
|
+
};
|
|
115
|
+
};
|
|
116
|
+
adapter: {
|
|
117
|
+
type: "postgrest";
|
|
118
|
+
url: string;
|
|
119
|
+
};
|
|
120
|
+
uiHints: {
|
|
121
|
+
path: string | null;
|
|
122
|
+
};
|
|
123
|
+
cache: {
|
|
124
|
+
ttlMs: number;
|
|
125
|
+
};
|
|
126
|
+
}, {
|
|
127
|
+
database: {
|
|
128
|
+
url: string;
|
|
129
|
+
schemas?: string[] | undefined;
|
|
130
|
+
};
|
|
131
|
+
server?: {
|
|
132
|
+
ui?: {
|
|
133
|
+
port?: number | undefined;
|
|
134
|
+
host?: string | undefined;
|
|
135
|
+
} | undefined;
|
|
136
|
+
mcp?: {
|
|
137
|
+
http?: {
|
|
138
|
+
port?: number | undefined;
|
|
139
|
+
host?: string | undefined;
|
|
140
|
+
} | undefined;
|
|
141
|
+
stdio?: boolean | undefined;
|
|
142
|
+
} | undefined;
|
|
143
|
+
} | undefined;
|
|
144
|
+
adapter?: {
|
|
145
|
+
type?: "postgrest" | undefined;
|
|
146
|
+
url?: string | undefined;
|
|
147
|
+
} | undefined;
|
|
148
|
+
uiHints?: {
|
|
149
|
+
path?: string | null | undefined;
|
|
150
|
+
} | undefined;
|
|
151
|
+
cache?: {
|
|
152
|
+
ttlMs?: number | undefined;
|
|
153
|
+
} | undefined;
|
|
154
|
+
}>;
|
|
155
|
+
export type KozouConfig = z.infer<typeof configSchema>;
|
|
156
|
+
export type KozouConfigIssue = {
|
|
157
|
+
path: string;
|
|
158
|
+
message: string;
|
|
159
|
+
};
|
|
160
|
+
export declare class KozouConfigError extends Error {
|
|
161
|
+
readonly issues: KozouConfigIssue[];
|
|
162
|
+
readonly filePath: string | null;
|
|
163
|
+
constructor(message: string, filePath: string | null, issues: KozouConfigIssue[]);
|
|
164
|
+
}
|
|
165
|
+
export type LoadConfigOptions = {
|
|
166
|
+
/** Path to kozou.config.yaml. Default: ./kozou.config.yaml relative to cwd. */
|
|
167
|
+
path?: string;
|
|
168
|
+
/** Environment variables for ${VAR} expansion. Default: process.env. */
|
|
169
|
+
env?: NodeJS.ProcessEnv;
|
|
170
|
+
/**
|
|
171
|
+
* If true, do not read any file from disk; only honor explicit options and
|
|
172
|
+
* environment variables. Useful for unit tests.
|
|
173
|
+
*/
|
|
174
|
+
skipFile?: boolean;
|
|
175
|
+
};
|
|
176
|
+
export declare function loadConfig(opts?: LoadConfigOptions): Promise<KozouConfig>;
|
|
177
|
+
export {};
|
|
178
|
+
//# sourceMappingURL=config.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAWA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAwDxB,QAAA,MAAM,YAAY;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAMhB,CAAC;AAEH,MAAM,MAAM,WAAW,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,YAAY,CAAC,CAAC;AAIvD,MAAM,MAAM,gBAAgB,GAAG;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,MAAM,CAAA;CAAE,CAAC;AAEjE,qBAAa,gBAAiB,SAAQ,KAAK;IACzC,QAAQ,CAAC,MAAM,EAAE,gBAAgB,EAAE,CAAC;IACpC,QAAQ,CAAC,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;gBACrB,OAAO,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,IAAI,EAAE,MAAM,EAAE,gBAAgB,EAAE;CAMjF;AAMD,MAAM,MAAM,iBAAiB,GAAG;IAC9B,+EAA+E;IAC/E,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,wEAAwE;IACxE,GAAG,CAAC,EAAE,MAAM,CAAC,UAAU,CAAC;IACxB;;;OAGG;IACH,QAAQ,CAAC,EAAE,OAAO,CAAC;CACpB,CAAC;AA6CF,wBAAsB,UAAU,CAAC,IAAI,GAAE,iBAAsB,GAAG,OAAO,CAAC,WAAW,CAAC,CA2CnF"}
|
package/dist/config.js
ADDED
|
@@ -0,0 +1,154 @@
|
|
|
1
|
+
// kozou.config.yaml loader.
|
|
2
|
+
//
|
|
3
|
+
// Reads the YAML config file, expands ${VAR} / ${VAR:-default} placeholders
|
|
4
|
+
// against the process environment, fills in defaults, and validates the
|
|
5
|
+
// result with zod. Every field has a default so kozou can run with only the
|
|
6
|
+
// DATABASE_URL environment variable set, per the Kozou v0.1 design spec §9.2.
|
|
7
|
+
import { readFile } from 'node:fs/promises';
|
|
8
|
+
import { existsSync } from 'node:fs';
|
|
9
|
+
import { resolve, isAbsolute } from 'node:path';
|
|
10
|
+
import { parse as parseYAML } from 'yaml';
|
|
11
|
+
import { z } from 'zod';
|
|
12
|
+
// ---- Schema ---------------------------------------------------------------
|
|
13
|
+
const uiServerSchema = z
|
|
14
|
+
.object({
|
|
15
|
+
port: z.number().int().min(0).max(65_535).default(3333),
|
|
16
|
+
host: z.string().min(1).default('0.0.0.0'),
|
|
17
|
+
})
|
|
18
|
+
.default({});
|
|
19
|
+
const mcpHttpServerSchema = z
|
|
20
|
+
.object({
|
|
21
|
+
port: z.number().int().min(0).max(65_535).default(3334),
|
|
22
|
+
host: z.string().min(1).default('0.0.0.0'),
|
|
23
|
+
})
|
|
24
|
+
.default({});
|
|
25
|
+
const mcpServerSchema = z
|
|
26
|
+
.object({
|
|
27
|
+
http: mcpHttpServerSchema,
|
|
28
|
+
stdio: z.boolean().default(false),
|
|
29
|
+
})
|
|
30
|
+
.default({});
|
|
31
|
+
const serverSchema = z
|
|
32
|
+
.object({
|
|
33
|
+
ui: uiServerSchema,
|
|
34
|
+
mcp: mcpServerSchema,
|
|
35
|
+
})
|
|
36
|
+
.default({});
|
|
37
|
+
const adapterSchema = z
|
|
38
|
+
.object({
|
|
39
|
+
type: z.literal('postgrest').default('postgrest'),
|
|
40
|
+
url: z.string().min(1).default('http://postgrest:3000'),
|
|
41
|
+
})
|
|
42
|
+
.default({});
|
|
43
|
+
const uiHintsSchema = z
|
|
44
|
+
.object({
|
|
45
|
+
path: z.string().nullable().default(null),
|
|
46
|
+
})
|
|
47
|
+
.default({});
|
|
48
|
+
const cacheSchema = z
|
|
49
|
+
.object({
|
|
50
|
+
ttlMs: z.number().int().min(0).default(60_000),
|
|
51
|
+
})
|
|
52
|
+
.default({});
|
|
53
|
+
const databaseSchema = z.object({
|
|
54
|
+
url: z.string().min(1, 'database.url is required (set DATABASE_URL or kozou.config.yaml)'),
|
|
55
|
+
schemas: z.array(z.string().min(1)).default(['public']),
|
|
56
|
+
});
|
|
57
|
+
const configSchema = z.object({
|
|
58
|
+
database: databaseSchema,
|
|
59
|
+
server: serverSchema,
|
|
60
|
+
adapter: adapterSchema,
|
|
61
|
+
uiHints: uiHintsSchema,
|
|
62
|
+
cache: cacheSchema,
|
|
63
|
+
});
|
|
64
|
+
export class KozouConfigError extends Error {
|
|
65
|
+
issues;
|
|
66
|
+
filePath;
|
|
67
|
+
constructor(message, filePath, issues) {
|
|
68
|
+
super(message);
|
|
69
|
+
this.name = 'KozouConfigError';
|
|
70
|
+
this.filePath = filePath;
|
|
71
|
+
this.issues = issues;
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
// ---- Loader --------------------------------------------------------------
|
|
75
|
+
const DEFAULT_CONFIG_PATH = 'kozou.config.yaml';
|
|
76
|
+
const ENV_VAR_RE = /\$\{([A-Za-z_][A-Za-z0-9_]*)(?::-([^}]*))?\}/g;
|
|
77
|
+
function expandEnvVars(value, env) {
|
|
78
|
+
if (typeof value === 'string') {
|
|
79
|
+
return value.replace(ENV_VAR_RE, (_match, name, fallback) => {
|
|
80
|
+
const v = env[name];
|
|
81
|
+
if (v !== undefined)
|
|
82
|
+
return v;
|
|
83
|
+
if (fallback !== undefined)
|
|
84
|
+
return fallback;
|
|
85
|
+
return '';
|
|
86
|
+
});
|
|
87
|
+
}
|
|
88
|
+
if (Array.isArray(value)) {
|
|
89
|
+
return value.map((v) => expandEnvVars(v, env));
|
|
90
|
+
}
|
|
91
|
+
if (value !== null && typeof value === 'object') {
|
|
92
|
+
const out = {};
|
|
93
|
+
for (const [k, v] of Object.entries(value)) {
|
|
94
|
+
out[k] = expandEnvVars(v, env);
|
|
95
|
+
}
|
|
96
|
+
return out;
|
|
97
|
+
}
|
|
98
|
+
return value;
|
|
99
|
+
}
|
|
100
|
+
function injectDatabaseUrlFromEnv(raw, env) {
|
|
101
|
+
if (raw === null || typeof raw !== 'object')
|
|
102
|
+
return raw;
|
|
103
|
+
const obj = raw;
|
|
104
|
+
const envUrl = env.DATABASE_URL;
|
|
105
|
+
if (envUrl === undefined || envUrl === '')
|
|
106
|
+
return obj;
|
|
107
|
+
const existing = obj.database;
|
|
108
|
+
if (existing === undefined) {
|
|
109
|
+
return { ...obj, database: { url: envUrl } };
|
|
110
|
+
}
|
|
111
|
+
if (existing !== null && typeof existing === 'object') {
|
|
112
|
+
const db = existing;
|
|
113
|
+
if (db.url === undefined || db.url === '') {
|
|
114
|
+
return { ...obj, database: { ...db, url: envUrl } };
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
return obj;
|
|
118
|
+
}
|
|
119
|
+
export async function loadConfig(opts = {}) {
|
|
120
|
+
const env = opts.env ?? process.env;
|
|
121
|
+
const requestedPath = opts.path ?? DEFAULT_CONFIG_PATH;
|
|
122
|
+
const absPath = isAbsolute(requestedPath)
|
|
123
|
+
? requestedPath
|
|
124
|
+
: resolve(process.cwd(), requestedPath);
|
|
125
|
+
let raw = {};
|
|
126
|
+
let fileLoaded = null;
|
|
127
|
+
if (!opts.skipFile && existsSync(absPath)) {
|
|
128
|
+
const content = await readFile(absPath, 'utf8');
|
|
129
|
+
try {
|
|
130
|
+
raw = parseYAML(content) ?? {};
|
|
131
|
+
}
|
|
132
|
+
catch (err) {
|
|
133
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
134
|
+
throw new KozouConfigError(`Failed to parse kozou config: ${message}`, absPath, [{ path: '<yaml>', message }]);
|
|
135
|
+
}
|
|
136
|
+
fileLoaded = absPath;
|
|
137
|
+
}
|
|
138
|
+
// Fall back to DATABASE_URL env if database.url is not set in the file.
|
|
139
|
+
const withDbDefault = injectDatabaseUrlFromEnv(raw, env);
|
|
140
|
+
const expanded = expandEnvVars(withDbDefault, env);
|
|
141
|
+
try {
|
|
142
|
+
return configSchema.parse(expanded);
|
|
143
|
+
}
|
|
144
|
+
catch (err) {
|
|
145
|
+
if (err instanceof z.ZodError) {
|
|
146
|
+
throw new KozouConfigError(`Invalid kozou config: ${err.issues.length} issue(s)`, fileLoaded, err.issues.map((i) => ({
|
|
147
|
+
path: i.path.join('.') || '<root>',
|
|
148
|
+
message: i.message,
|
|
149
|
+
})));
|
|
150
|
+
}
|
|
151
|
+
throw err;
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
//# sourceMappingURL=config.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"config.js","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"create-kozou.d.ts","sourceRoot":"","sources":["../src/create-kozou.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
// `create-kozou` bin entry. Thin wrapper around createKozouScaffold().
|
|
3
|
+
import { createKozouScaffold, KozouScaffoldError } from './scaffold.js';
|
|
4
|
+
async function main() {
|
|
5
|
+
const target = process.argv[2];
|
|
6
|
+
if (!target || target === '--help' || target === '-h') {
|
|
7
|
+
process.stderr.write('Usage: create-kozou <directory>\n');
|
|
8
|
+
process.exit(target ? 0 : 1);
|
|
9
|
+
}
|
|
10
|
+
try {
|
|
11
|
+
await createKozouScaffold({ target });
|
|
12
|
+
}
|
|
13
|
+
catch (err) {
|
|
14
|
+
if (err instanceof KozouScaffoldError) {
|
|
15
|
+
process.stderr.write(`${err.message}\n`);
|
|
16
|
+
process.exit(1);
|
|
17
|
+
}
|
|
18
|
+
throw err;
|
|
19
|
+
}
|
|
20
|
+
process.stderr.write(`Scaffolded ${target}/\n`);
|
|
21
|
+
process.stderr.write(`Next: cd ${target} && cp .env.example .env && docker compose up\n`);
|
|
22
|
+
}
|
|
23
|
+
main().catch((err) => {
|
|
24
|
+
process.stderr.write(`create-kozou: fatal: ${err instanceof Error ? err.message : String(err)}\n`);
|
|
25
|
+
process.exit(1);
|
|
26
|
+
});
|
|
27
|
+
//# sourceMappingURL=create-kozou.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"create-kozou.js","sourceRoot":"","sources":["../src/create-kozou.ts"],"names":[],"mappings":";AACA,uEAAuE;AAEvE,OAAO,EAAE,mBAAmB,EAAE,kBAAkB,EAAE,MAAM,eAAe,CAAC;AAExE,KAAK,UAAU,IAAI;IACjB,MAAM,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAC/B,IAAI,CAAC,MAAM,IAAI,MAAM,KAAK,QAAQ,IAAI,MAAM,KAAK,IAAI,EAAE,CAAC;QACtD,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,mCAAmC,CAAC,CAAC;QAC1D,OAAO,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;IAC/B,CAAC;IAED,IAAI,CAAC;QACH,MAAM,mBAAmB,CAAC,EAAE,MAAM,EAAE,CAAC,CAAC;IACxC,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,IAAI,GAAG,YAAY,kBAAkB,EAAE,CAAC;YACtC,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,GAAG,GAAG,CAAC,OAAO,IAAI,CAAC,CAAC;YACzC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QAClB,CAAC;QACD,MAAM,GAAG,CAAC;IACZ,CAAC;IAED,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,cAAc,MAAM,KAAK,CAAC,CAAC;IAChD,OAAO,CAAC,MAAM,CAAC,KAAK,CAClB,YAAY,MAAM,iDAAiD,CACpE,CAAC;AACJ,CAAC;AAED,IAAI,EAAE,CAAC,KAAK,CAAC,CAAC,GAAG,EAAE,EAAE;IACnB,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,wBAAwB,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;IACnG,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;AAClB,CAAC,CAAC,CAAC"}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
export declare const PACKAGE_VERSION = "0.1.0";
|
|
2
|
+
export { loadConfig, KozouConfigError } from './config.js';
|
|
3
|
+
export type { KozouConfig, KozouConfigIssue, LoadConfigOptions } from './config.js';
|
|
4
|
+
export { inspectCommand } from './commands/inspect.js';
|
|
5
|
+
export type { InspectOptions } from './commands/inspect.js';
|
|
6
|
+
export { mcpCommand } from './commands/mcp.js';
|
|
7
|
+
export type { McpOptions } from './commands/mcp.js';
|
|
8
|
+
export { devCommand } from './commands/dev.js';
|
|
9
|
+
export type { DevOptions } from './commands/dev.js';
|
|
10
|
+
export { createKozouScaffold, KozouScaffoldError } from './scaffold.js';
|
|
11
|
+
export type { CreateScaffoldOptions } from './scaffold.js';
|
|
12
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAKA,eAAO,MAAM,eAAe,UAAU,CAAC;AAEvC,OAAO,EAAE,UAAU,EAAE,gBAAgB,EAAE,MAAM,aAAa,CAAC;AAC3D,YAAY,EAAE,WAAW,EAAE,gBAAgB,EAAE,iBAAiB,EAAE,MAAM,aAAa,CAAC;AAEpF,OAAO,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;AACvD,YAAY,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;AAE5D,OAAO,EAAE,UAAU,EAAE,MAAM,mBAAmB,CAAC;AAC/C,YAAY,EAAE,UAAU,EAAE,MAAM,mBAAmB,CAAC;AAEpD,OAAO,EAAE,UAAU,EAAE,MAAM,mBAAmB,CAAC;AAC/C,YAAY,EAAE,UAAU,EAAE,MAAM,mBAAmB,CAAC;AAEpD,OAAO,EAAE,mBAAmB,EAAE,kBAAkB,EAAE,MAAM,eAAe,CAAC;AACxE,YAAY,EAAE,qBAAqB,EAAE,MAAM,eAAe,CAAC"}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
// kozou (CLI package): public API surface for adopters embedding the
|
|
2
|
+
// commands programmatically. The bin entry points live in cli.ts and
|
|
3
|
+
// create-kozou.ts; this module re-exports the underlying primitives so
|
|
4
|
+
// integrators can build their own glue if they need to.
|
|
5
|
+
export const PACKAGE_VERSION = '0.1.0';
|
|
6
|
+
export { loadConfig, KozouConfigError } from './config.js';
|
|
7
|
+
export { inspectCommand } from './commands/inspect.js';
|
|
8
|
+
export { mcpCommand } from './commands/mcp.js';
|
|
9
|
+
export { devCommand } from './commands/dev.js';
|
|
10
|
+
export { createKozouScaffold, KozouScaffoldError } from './scaffold.js';
|
|
11
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,qEAAqE;AACrE,qEAAqE;AACrE,uEAAuE;AACvE,wDAAwD;AAExD,MAAM,CAAC,MAAM,eAAe,GAAG,OAAO,CAAC;AAEvC,OAAO,EAAE,UAAU,EAAE,gBAAgB,EAAE,MAAM,aAAa,CAAC;AAG3D,OAAO,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;AAGvD,OAAO,EAAE,UAAU,EAAE,MAAM,mBAAmB,CAAC;AAG/C,OAAO,EAAE,UAAU,EAAE,MAAM,mBAAmB,CAAC;AAG/C,OAAO,EAAE,mBAAmB,EAAE,kBAAkB,EAAE,MAAM,eAAe,CAAC"}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
export type CreateScaffoldOptions = {
|
|
2
|
+
/** Target directory. Must not already exist. */
|
|
3
|
+
target: string;
|
|
4
|
+
/** Override the templates directory (used by unit tests). */
|
|
5
|
+
templatesDir?: string;
|
|
6
|
+
};
|
|
7
|
+
export declare class KozouScaffoldError extends Error {
|
|
8
|
+
constructor(message: string);
|
|
9
|
+
}
|
|
10
|
+
export declare function createKozouScaffold(opts: CreateScaffoldOptions): Promise<void>;
|
|
11
|
+
//# sourceMappingURL=scaffold.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"scaffold.d.ts","sourceRoot":"","sources":["../src/scaffold.ts"],"names":[],"mappings":"AAeA,MAAM,MAAM,qBAAqB,GAAG;IAClC,gDAAgD;IAChD,MAAM,EAAE,MAAM,CAAC;IACf,6DAA6D;IAC7D,YAAY,CAAC,EAAE,MAAM,CAAC;CACvB,CAAC;AAEF,qBAAa,kBAAmB,SAAQ,KAAK;gBAC/B,OAAO,EAAE,MAAM;CAI5B;AAyBD,wBAAsB,mBAAmB,CAAC,IAAI,EAAE,qBAAqB,GAAG,OAAO,CAAC,IAAI,CAAC,CAWpF"}
|
package/dist/scaffold.js
ADDED
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
// `create-kozou` scaffolding logic.
|
|
2
|
+
//
|
|
3
|
+
// Copies the contents of packages/kozou/src/templates/ into the target
|
|
4
|
+
// directory the user picks. Renames env.example to .env.example along
|
|
5
|
+
// the way so the scaffolded project ships a real dotfile (the template
|
|
6
|
+
// stays a normal file because npm's tarball handling for dotfiles
|
|
7
|
+
// inside published packages can be surprising).
|
|
8
|
+
import { mkdir, readdir, readFile, writeFile } from 'node:fs/promises';
|
|
9
|
+
import { existsSync } from 'node:fs';
|
|
10
|
+
import { join } from 'node:path';
|
|
11
|
+
import { fileURLToPath } from 'node:url';
|
|
12
|
+
const DEFAULT_TEMPLATE_DIR = fileURLToPath(new URL('./templates', import.meta.url));
|
|
13
|
+
export class KozouScaffoldError extends Error {
|
|
14
|
+
constructor(message) {
|
|
15
|
+
super(message);
|
|
16
|
+
this.name = 'KozouScaffoldError';
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
async function copyRecursive(src, dest) {
|
|
20
|
+
const entries = await readdir(src, { withFileTypes: true });
|
|
21
|
+
for (const entry of entries) {
|
|
22
|
+
const sourcePath = join(src, entry.name);
|
|
23
|
+
let targetName = entry.name;
|
|
24
|
+
// env.example -> .env.example so the scaffolded project has a real
|
|
25
|
+
// dotfile but the template itself stays out of dotfile-tooling
|
|
26
|
+
// edge cases when published to npm.
|
|
27
|
+
if (entry.isFile() && entry.name === 'env.example') {
|
|
28
|
+
targetName = '.env.example';
|
|
29
|
+
}
|
|
30
|
+
const destPath = join(dest, targetName);
|
|
31
|
+
if (entry.isDirectory()) {
|
|
32
|
+
await mkdir(destPath, { recursive: true });
|
|
33
|
+
await copyRecursive(sourcePath, destPath);
|
|
34
|
+
}
|
|
35
|
+
else if (entry.isFile()) {
|
|
36
|
+
const content = await readFile(sourcePath, 'utf8');
|
|
37
|
+
await writeFile(destPath, content, 'utf8');
|
|
38
|
+
}
|
|
39
|
+
// Symlinks and other entry kinds are skipped intentionally.
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
export async function createKozouScaffold(opts) {
|
|
43
|
+
const target = (opts.target ?? '').trim();
|
|
44
|
+
if (target === '') {
|
|
45
|
+
throw new KozouScaffoldError('create-kozou: target directory is required');
|
|
46
|
+
}
|
|
47
|
+
if (existsSync(target)) {
|
|
48
|
+
throw new KozouScaffoldError(`create-kozou: "${target}" already exists`);
|
|
49
|
+
}
|
|
50
|
+
const templatesDir = opts.templatesDir ?? DEFAULT_TEMPLATE_DIR;
|
|
51
|
+
await mkdir(target, { recursive: true });
|
|
52
|
+
await copyRecursive(templatesDir, target);
|
|
53
|
+
}
|
|
54
|
+
//# sourceMappingURL=scaffold.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"scaffold.js","sourceRoot":"","sources":["../src/scaffold.ts"],"names":[],"mappings":"AAAA,oCAAoC;AACpC,EAAE;AACF,uEAAuE;AACvE,sEAAsE;AACtE,uEAAuE;AACvE,kEAAkE;AAClE,gDAAgD;AAEhD,OAAO,EAAE,KAAK,EAAE,OAAO,EAAE,QAAQ,EAAE,SAAS,EAAE,MAAM,kBAAkB,CAAC;AACvE,OAAO,EAAE,UAAU,EAAE,MAAM,SAAS,CAAC;AACrC,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AACjC,OAAO,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;AAEzC,MAAM,oBAAoB,GAAG,aAAa,CAAC,IAAI,GAAG,CAAC,aAAa,EAAE,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC;AASpF,MAAM,OAAO,kBAAmB,SAAQ,KAAK;IAC3C,YAAY,OAAe;QACzB,KAAK,CAAC,OAAO,CAAC,CAAC;QACf,IAAI,CAAC,IAAI,GAAG,oBAAoB,CAAC;IACnC,CAAC;CACF;AAED,KAAK,UAAU,aAAa,CAAC,GAAW,EAAE,IAAY;IACpD,MAAM,OAAO,GAAG,MAAM,OAAO,CAAC,GAAG,EAAE,EAAE,aAAa,EAAE,IAAI,EAAE,CAAC,CAAC;IAC5D,KAAK,MAAM,KAAK,IAAI,OAAO,EAAE,CAAC;QAC5B,MAAM,UAAU,GAAG,IAAI,CAAC,GAAG,EAAE,KAAK,CAAC,IAAI,CAAC,CAAC;QACzC,IAAI,UAAU,GAAG,KAAK,CAAC,IAAI,CAAC;QAC5B,mEAAmE;QACnE,+DAA+D;QAC/D,oCAAoC;QACpC,IAAI,KAAK,CAAC,MAAM,EAAE,IAAI,KAAK,CAAC,IAAI,KAAK,aAAa,EAAE,CAAC;YACnD,UAAU,GAAG,cAAc,CAAC;QAC9B,CAAC;QACD,MAAM,QAAQ,GAAG,IAAI,CAAC,IAAI,EAAE,UAAU,CAAC,CAAC;QACxC,IAAI,KAAK,CAAC,WAAW,EAAE,EAAE,CAAC;YACxB,MAAM,KAAK,CAAC,QAAQ,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;YAC3C,MAAM,aAAa,CAAC,UAAU,EAAE,QAAQ,CAAC,CAAC;QAC5C,CAAC;aAAM,IAAI,KAAK,CAAC,MAAM,EAAE,EAAE,CAAC;YAC1B,MAAM,OAAO,GAAG,MAAM,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC,CAAC;YACnD,MAAM,SAAS,CAAC,QAAQ,EAAE,OAAO,EAAE,MAAM,CAAC,CAAC;QAC7C,CAAC;QACD,4DAA4D;IAC9D,CAAC;AACH,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,mBAAmB,CAAC,IAA2B;IACnE,MAAM,MAAM,GAAG,CAAC,IAAI,CAAC,MAAM,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE,CAAC;IAC1C,IAAI,MAAM,KAAK,EAAE,EAAE,CAAC;QAClB,MAAM,IAAI,kBAAkB,CAAC,4CAA4C,CAAC,CAAC;IAC7E,CAAC;IACD,IAAI,UAAU,CAAC,MAAM,CAAC,EAAE,CAAC;QACvB,MAAM,IAAI,kBAAkB,CAAC,kBAAkB,MAAM,kBAAkB,CAAC,CAAC;IAC3E,CAAC;IACD,MAAM,YAAY,GAAG,IAAI,CAAC,YAAY,IAAI,oBAAoB,CAAC;IAC/D,MAAM,KAAK,CAAC,MAAM,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;IACzC,MAAM,aAAa,CAAC,YAAY,EAAE,MAAM,CAAC,CAAC;AAC5C,CAAC"}
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
# Docker Compose stack for a kozou project.
|
|
2
|
+
#
|
|
3
|
+
# Brings up (v0.1.0):
|
|
4
|
+
# - postgres PostgreSQL 16 (the source of truth)
|
|
5
|
+
# - postgrest REST adapter consumed by the Kozou DataAdapter
|
|
6
|
+
# (MIT-licensed external dependency, not bundled)
|
|
7
|
+
#
|
|
8
|
+
# The `kozou` service block is commented out for v0.1.0: the
|
|
9
|
+
# published `ghcr.io/kozou-dev/kozou:v0.1.0` image's entrypoint is
|
|
10
|
+
# the `kozou` CLI, which does not bind a port. Host integration
|
|
11
|
+
# (`kozou dev` spawning the bundled Admin UI + MCP HTTP server)
|
|
12
|
+
# lands in v0.1.1; uncomment the block then.
|
|
13
|
+
#
|
|
14
|
+
# Customize the credentials in .env before running `docker compose up`.
|
|
15
|
+
|
|
16
|
+
services:
|
|
17
|
+
postgres:
|
|
18
|
+
image: postgres:16
|
|
19
|
+
environment:
|
|
20
|
+
POSTGRES_USER: ${POSTGRES_USER:-kozou}
|
|
21
|
+
POSTGRES_PASSWORD: ${POSTGRES_PASSWORD:-kozou}
|
|
22
|
+
POSTGRES_DB: ${POSTGRES_DB:-kozou}
|
|
23
|
+
ports:
|
|
24
|
+
- "${POSTGRES_PORT:-5432}:5432"
|
|
25
|
+
volumes:
|
|
26
|
+
- ./migrations:/docker-entrypoint-initdb.d:ro
|
|
27
|
+
healthcheck:
|
|
28
|
+
test: ["CMD-SHELL", "pg_isready -U ${POSTGRES_USER:-kozou}"]
|
|
29
|
+
interval: 5s
|
|
30
|
+
timeout: 5s
|
|
31
|
+
retries: 10
|
|
32
|
+
|
|
33
|
+
postgrest:
|
|
34
|
+
image: postgrest/postgrest:latest
|
|
35
|
+
environment:
|
|
36
|
+
PGRST_DB_URI: postgres://${POSTGRES_USER:-kozou}:${POSTGRES_PASSWORD:-kozou}@postgres:5432/${POSTGRES_DB:-kozou}
|
|
37
|
+
PGRST_DB_SCHEMA: public
|
|
38
|
+
PGRST_DB_ANON_ROLE: ${POSTGRES_USER:-kozou}
|
|
39
|
+
ports:
|
|
40
|
+
- "3000:3000"
|
|
41
|
+
depends_on:
|
|
42
|
+
postgres:
|
|
43
|
+
condition: service_healthy
|
|
44
|
+
|
|
45
|
+
# kozou:
|
|
46
|
+
# # v0.1.1: reactivate once `kozou dev` spawns the bundled
|
|
47
|
+
# # @kozou/svelte-ui Admin UI + MCP HTTP server. v0.1.0 only
|
|
48
|
+
# # ships the CLI entrypoint, which exits immediately when
|
|
49
|
+
# # run without arguments and therefore would bring no port
|
|
50
|
+
# # online.
|
|
51
|
+
# image: ghcr.io/kozou-dev/kozou:v0.1.0
|
|
52
|
+
# command: ["dev"]
|
|
53
|
+
# environment:
|
|
54
|
+
# DATABASE_URL: postgres://${POSTGRES_USER:-kozou}:${POSTGRES_PASSWORD:-kozou}@postgres:5432/${POSTGRES_DB:-kozou}
|
|
55
|
+
# KOZOU_ADAPTER_URL: http://postgrest:3000
|
|
56
|
+
# depends_on:
|
|
57
|
+
# postgres:
|
|
58
|
+
# condition: service_healthy
|
|
59
|
+
# postgrest:
|
|
60
|
+
# condition: service_started
|
|
61
|
+
# ports:
|
|
62
|
+
# - "3333:3333" # Admin UI
|
|
63
|
+
# - "3334:3334" # MCP HTTP
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
# Copy this file to .env and fill in the real values before running
|
|
2
|
+
# `docker compose up`.
|
|
3
|
+
|
|
4
|
+
POSTGRES_USER=kozou
|
|
5
|
+
POSTGRES_PASSWORD=change-me
|
|
6
|
+
POSTGRES_DB=kozou
|
|
7
|
+
POSTGRES_PORT=5432
|
|
8
|
+
|
|
9
|
+
# Used by kozou + postgrest at runtime; defaults match the compose stack.
|
|
10
|
+
DATABASE_URL=postgres://kozou:change-me@postgres:5432/kozou
|
|
11
|
+
KOZOU_ADAPTER_URL=http://postgrest:3000
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
# kozou.config.yaml
|
|
2
|
+
#
|
|
3
|
+
# Every field has a sensible default; only set what you need to override.
|
|
4
|
+
# All ${VAR} and ${VAR:-fallback} placeholders are expanded against the
|
|
5
|
+
# process environment at startup.
|
|
6
|
+
|
|
7
|
+
database:
|
|
8
|
+
url: ${DATABASE_URL}
|
|
9
|
+
schemas: [public]
|
|
10
|
+
|
|
11
|
+
server:
|
|
12
|
+
ui:
|
|
13
|
+
port: 3333
|
|
14
|
+
host: 0.0.0.0
|
|
15
|
+
mcp:
|
|
16
|
+
http:
|
|
17
|
+
port: 3334
|
|
18
|
+
host: 0.0.0.0
|
|
19
|
+
stdio: false
|
|
20
|
+
|
|
21
|
+
adapter:
|
|
22
|
+
type: postgrest
|
|
23
|
+
url: ${KOZOU_ADAPTER_URL:-http://postgrest:3000}
|
|
24
|
+
|
|
25
|
+
uiHints:
|
|
26
|
+
path: ./ui-hints.yaml
|
|
27
|
+
|
|
28
|
+
cache:
|
|
29
|
+
ttlMs: 60000
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
-- 0001_init.sql
|
|
2
|
+
--
|
|
3
|
+
-- Add your CREATE TABLE / CREATE VIEW / COMMENT ON statements here.
|
|
4
|
+
-- kozou reads from this database at runtime; the COMMENT ON text is what
|
|
5
|
+
-- shapes the Admin UI and the MCP context handed to AI agents.
|
|
6
|
+
--
|
|
7
|
+
-- See https://kozou.org for documentation on the COMMENT conventions
|
|
8
|
+
-- (@ai / @widget / @policy / @example tags), VIEW-as-domain-concept,
|
|
9
|
+
-- and the recommended layout for migrations.
|
|
10
|
+
|
|
11
|
+
-- Example (delete and replace with your own schema):
|
|
12
|
+
--
|
|
13
|
+
-- CREATE TABLE users (
|
|
14
|
+
-- id uuid PRIMARY KEY DEFAULT gen_random_uuid(),
|
|
15
|
+
-- email text NOT NULL UNIQUE,
|
|
16
|
+
-- full_name text,
|
|
17
|
+
-- created_at timestamptz NOT NULL DEFAULT now(),
|
|
18
|
+
-- deleted_at timestamptz
|
|
19
|
+
-- );
|
|
20
|
+
--
|
|
21
|
+
-- COMMENT ON TABLE users IS
|
|
22
|
+
-- 'Application users.
|
|
23
|
+
-- @ai: rows with deleted_at IS NOT NULL must be excluded from queries.';
|
|
24
|
+
--
|
|
25
|
+
-- COMMENT ON COLUMN users.email IS 'Login email (unique).';
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
# ui-hints.yaml (optional)
|
|
2
|
+
#
|
|
3
|
+
# COMMENT ON and CREATE VIEW already give kozou enough information to
|
|
4
|
+
# render a usable Admin UI out of the box. Use this file only to fine-tune
|
|
5
|
+
# presentation: override a table label, force a specific widget for a
|
|
6
|
+
# column, or surface relation search fields.
|
|
7
|
+
#
|
|
8
|
+
# See Kozou v0.1 design spec §4.3 for the full schema.
|
|
9
|
+
|
|
10
|
+
tables: {}
|
|
11
|
+
|
|
12
|
+
# Example overrides (uncomment and adapt):
|
|
13
|
+
#
|
|
14
|
+
# tables:
|
|
15
|
+
# users:
|
|
16
|
+
# label: People
|
|
17
|
+
# displayField: full_name
|
|
18
|
+
# columns:
|
|
19
|
+
# bio:
|
|
20
|
+
# widget: textarea
|
|
21
|
+
# avatar_url:
|
|
22
|
+
# widget: image-url
|
|
23
|
+
#
|
|
24
|
+
# views:
|
|
25
|
+
# vw_active_users:
|
|
26
|
+
# label: Active users
|