@agentic-kit/pi 0.17.1 → 0.18.1
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/README.md +5 -7
- package/confirm-gate.d.ts +1 -2
- package/esm/confirm-gate.d.ts +1 -2
- package/esm/host.d.ts +5 -110
- package/esm/host.js +5 -18
- package/esm/index.d.ts +17 -9
- package/esm/index.js +20 -38
- package/esm/pi-tool.d.ts +16 -0
- package/esm/pi-tool.js +32 -0
- package/host.d.ts +5 -110
- package/host.js +10 -22
- package/index.d.ts +17 -9
- package/index.js +47 -62
- package/package.json +6 -10
- package/pi-tool.d.ts +16 -0
- package/pi-tool.js +36 -0
- package/app-workspace.d.ts +0 -16
- package/app-workspace.js +0 -145
- package/context.d.ts +0 -62
- package/context.js +0 -282
- package/db-probe.d.ts +0 -30
- package/db-probe.js +0 -50
- package/esm/app-workspace.d.ts +0 -16
- package/esm/app-workspace.js +0 -134
- package/esm/context.d.ts +0 -62
- package/esm/context.js +0 -270
- package/esm/db-probe.d.ts +0 -30
- package/esm/db-probe.js +0 -47
- package/esm/policy/add-policies-to-table.d.ts +0 -26
- package/esm/policy/add-policies-to-table.js +0 -66
- package/esm/policy/provision-helpers.d.ts +0 -38
- package/esm/policy/provision-helpers.js +0 -50
- package/esm/provision-database/credential.d.ts +0 -14
- package/esm/provision-database/credential.js +0 -19
- package/esm/provision-database/env-file.d.ts +0 -37
- package/esm/provision-database/env-file.js +0 -85
- package/esm/provision-database/manifest.d.ts +0 -10
- package/esm/provision-database/manifest.js +0 -48
- package/esm/provision-database/pg-fixups.d.ts +0 -16
- package/esm/provision-database/pg-fixups.js +0 -132
- package/esm/provision-database/preset-match.d.ts +0 -13
- package/esm/provision-database/preset-match.js +0 -66
- package/esm/provision-database/presets.d.ts +0 -4
- package/esm/provision-database/presets.js +0 -13
- package/esm/provision-database/request-database.d.ts +0 -61
- package/esm/provision-database/request-database.js +0 -130
- package/esm/provision-database/resolve.d.ts +0 -27
- package/esm/provision-database/resolve.js +0 -49
- package/esm/records/meta.d.ts +0 -41
- package/esm/records/meta.js +0 -167
- package/esm/run-codegen/barrels.d.ts +0 -3
- package/esm/run-codegen/barrels.js +0 -48
- package/esm/run-codegen/endpoints.d.ts +0 -8
- package/esm/run-codegen/endpoints.js +0 -46
- package/esm/schema-resolve.d.ts +0 -23
- package/esm/schema-resolve.js +0 -69
- package/esm/tool-schema.d.ts +0 -3
- package/esm/tool-schema.js +0 -10
- package/esm/tools/add-policies.d.ts +0 -8
- package/esm/tools/add-policies.js +0 -96
- package/esm/tools/add-records.d.ts +0 -14
- package/esm/tools/add-records.js +0 -124
- package/esm/tools/add-relation-schema.d.ts +0 -30
- package/esm/tools/add-relation-schema.js +0 -58
- package/esm/tools/add-relation.d.ts +0 -10
- package/esm/tools/add-relation.js +0 -91
- package/esm/tools/create-api-key.d.ts +0 -18
- package/esm/tools/create-api-key.js +0 -216
- package/esm/tools/describe-schema.d.ts +0 -18
- package/esm/tools/describe-schema.js +0 -132
- package/esm/tools/manage-entity-types.d.ts +0 -41
- package/esm/tools/manage-entity-types.js +0 -203
- package/esm/tools/mutations.d.ts +0 -14
- package/esm/tools/mutations.js +0 -235
- package/esm/tools/provision-blueprint.d.ts +0 -22
- package/esm/tools/provision-blueprint.js +0 -111
- package/esm/tools/provision-database.d.ts +0 -14
- package/esm/tools/provision-database.js +0 -262
- package/esm/tools/run-codegen.d.ts +0 -11
- package/esm/tools/run-codegen.js +0 -139
- package/esm/tools/templates.d.ts +0 -49
- package/esm/tools/templates.js +0 -337
- package/policy/add-policies-to-table.d.ts +0 -26
- package/policy/add-policies-to-table.js +0 -71
- package/policy/provision-helpers.d.ts +0 -38
- package/policy/provision-helpers.js +0 -58
- package/provision-database/credential.d.ts +0 -14
- package/provision-database/credential.js +0 -22
- package/provision-database/env-file.d.ts +0 -37
- package/provision-database/env-file.js +0 -91
- package/provision-database/manifest.d.ts +0 -10
- package/provision-database/manifest.js +0 -56
- package/provision-database/pg-fixups.d.ts +0 -16
- package/provision-database/pg-fixups.js +0 -170
- package/provision-database/preset-match.d.ts +0 -13
- package/provision-database/preset-match.js +0 -70
- package/provision-database/presets.d.ts +0 -4
- package/provision-database/presets.js +0 -17
- package/provision-database/request-database.d.ts +0 -61
- package/provision-database/request-database.js +0 -134
- package/provision-database/resolve.d.ts +0 -27
- package/provision-database/resolve.js +0 -53
- package/records/meta.d.ts +0 -41
- package/records/meta.js +0 -172
- package/run-codegen/barrels.d.ts +0 -3
- package/run-codegen/barrels.js +0 -54
- package/run-codegen/endpoints.d.ts +0 -8
- package/run-codegen/endpoints.js +0 -51
- package/schema-resolve.d.ts +0 -23
- package/schema-resolve.js +0 -75
- package/tool-schema.d.ts +0 -3
- package/tool-schema.js +0 -13
- package/tools/add-policies.d.ts +0 -8
- package/tools/add-policies.js +0 -99
- package/tools/add-records.d.ts +0 -14
- package/tools/add-records.js +0 -127
- package/tools/add-relation-schema.d.ts +0 -30
- package/tools/add-relation-schema.js +0 -62
- package/tools/add-relation.d.ts +0 -10
- package/tools/add-relation.js +0 -94
- package/tools/create-api-key.d.ts +0 -18
- package/tools/create-api-key.js +0 -222
- package/tools/describe-schema.d.ts +0 -18
- package/tools/describe-schema.js +0 -135
- package/tools/manage-entity-types.d.ts +0 -41
- package/tools/manage-entity-types.js +0 -208
- package/tools/mutations.d.ts +0 -14
- package/tools/mutations.js +0 -238
- package/tools/provision-blueprint.d.ts +0 -22
- package/tools/provision-blueprint.js +0 -114
- package/tools/provision-database.d.ts +0 -14
- package/tools/provision-database.js +0 -268
- package/tools/run-codegen.d.ts +0 -11
- package/tools/run-codegen.js +0 -143
- package/tools/templates.d.ts +0 -49
- package/tools/templates.js +0 -341
package/esm/records/meta.d.ts
DELETED
|
@@ -1,41 +0,0 @@
|
|
|
1
|
-
import type { Table, TableInflection } from '@constructive-io/graphql-query/types/schema';
|
|
2
|
-
export declare const META_QUERY = "\n query DbToolsMeta {\n _meta {\n tables {\n name\n query { all one create update delete }\n inflection {\n allRows\n conditionType\n connection\n createInputType\n createPayloadType\n deletePayloadType\n edge\n filterType\n orderByType\n patchType\n tableType\n updatePayloadType\n }\n fields {\n name\n isNotNull\n hasDefault\n type {\n gqlType\n isArray\n pgType\n subtype\n isNotNull\n hasDefault\n }\n }\n }\n }\n }\n";
|
|
3
|
-
type RawType = {
|
|
4
|
-
gqlType: string;
|
|
5
|
-
isArray: boolean;
|
|
6
|
-
modifier?: string | number | null;
|
|
7
|
-
pgAlias?: string | null;
|
|
8
|
-
pgType?: string | null;
|
|
9
|
-
subtype?: string | null;
|
|
10
|
-
typmod?: number | null;
|
|
11
|
-
isNotNull?: boolean | null;
|
|
12
|
-
hasDefault?: boolean | null;
|
|
13
|
-
};
|
|
14
|
-
type RawField = {
|
|
15
|
-
name: string;
|
|
16
|
-
isNotNull?: boolean | null;
|
|
17
|
-
hasDefault?: boolean | null;
|
|
18
|
-
type: RawType;
|
|
19
|
-
};
|
|
20
|
-
type RawInflection = Partial<Record<keyof TableInflection, string | null>>;
|
|
21
|
-
type RawQuery = {
|
|
22
|
-
all: string | null;
|
|
23
|
-
one?: string | null;
|
|
24
|
-
create?: string | null;
|
|
25
|
-
update?: string | null;
|
|
26
|
-
delete?: string | null;
|
|
27
|
-
};
|
|
28
|
-
export type RawMetaTable = {
|
|
29
|
-
name: string;
|
|
30
|
-
query?: RawQuery | null;
|
|
31
|
-
inflection?: RawInflection | null;
|
|
32
|
-
fields?: (RawField | null)[] | null;
|
|
33
|
-
};
|
|
34
|
-
export type MetaResponse = {
|
|
35
|
-
_meta?: {
|
|
36
|
-
tables?: (RawMetaTable | null)[] | null;
|
|
37
|
-
} | null;
|
|
38
|
-
};
|
|
39
|
-
export declare function cleanTable(meta: RawMetaTable): Table;
|
|
40
|
-
export declare function findMetaTable(tables: RawMetaTable[], requested: string): RawMetaTable | undefined;
|
|
41
|
-
export {};
|
package/esm/records/meta.js
DELETED
|
@@ -1,167 +0,0 @@
|
|
|
1
|
-
// Vendored from constructive-client's `@constructive-io/data` (not published to
|
|
2
|
-
// the registry). We query the per-DB data endpoint's `_meta` introspection and
|
|
3
|
-
// reshape each table into the `Table` shape `buildPostGraphileCreate` expects.
|
|
4
|
-
// Relations are intentionally left empty: the create-mutation builder only reads
|
|
5
|
-
// them to skip relational fields in the return selection, and every `_meta` field
|
|
6
|
-
// is a real scalar column, so selecting them all is valid.
|
|
7
|
-
//
|
|
8
|
-
// Only fields the live backend's `_meta` actually exposes are selected here —
|
|
9
|
-
// over-selecting (e.g. MetaType.modifier or MetaInflection.createField) fails
|
|
10
|
-
// GraphQL validation. The reshapers below tolerate the omitted fields.
|
|
11
|
-
export const META_QUERY = `
|
|
12
|
-
query DbToolsMeta {
|
|
13
|
-
_meta {
|
|
14
|
-
tables {
|
|
15
|
-
name
|
|
16
|
-
query { all one create update delete }
|
|
17
|
-
inflection {
|
|
18
|
-
allRows
|
|
19
|
-
conditionType
|
|
20
|
-
connection
|
|
21
|
-
createInputType
|
|
22
|
-
createPayloadType
|
|
23
|
-
deletePayloadType
|
|
24
|
-
edge
|
|
25
|
-
filterType
|
|
26
|
-
orderByType
|
|
27
|
-
patchType
|
|
28
|
-
tableType
|
|
29
|
-
updatePayloadType
|
|
30
|
-
}
|
|
31
|
-
fields {
|
|
32
|
-
name
|
|
33
|
-
isNotNull
|
|
34
|
-
hasDefault
|
|
35
|
-
type {
|
|
36
|
-
gqlType
|
|
37
|
-
isArray
|
|
38
|
-
pgType
|
|
39
|
-
subtype
|
|
40
|
-
isNotNull
|
|
41
|
-
hasDefault
|
|
42
|
-
}
|
|
43
|
-
}
|
|
44
|
-
}
|
|
45
|
-
}
|
|
46
|
-
}
|
|
47
|
-
`;
|
|
48
|
-
function convertInflection(inflection) {
|
|
49
|
-
if (!inflection)
|
|
50
|
-
return undefined;
|
|
51
|
-
const s = (key) => inflection[key] ?? '';
|
|
52
|
-
const n = (key) => inflection[key] ?? null;
|
|
53
|
-
return {
|
|
54
|
-
allRows: s('allRows'),
|
|
55
|
-
allRowsSimple: s('allRowsSimple'),
|
|
56
|
-
conditionType: s('conditionType'),
|
|
57
|
-
connection: s('connection'),
|
|
58
|
-
createField: s('createField'),
|
|
59
|
-
createInputType: s('createInputType'),
|
|
60
|
-
createPayloadType: s('createPayloadType'),
|
|
61
|
-
deleteByPrimaryKey: n('deleteByPrimaryKey'),
|
|
62
|
-
deletePayloadType: s('deletePayloadType'),
|
|
63
|
-
edge: s('edge'),
|
|
64
|
-
edgeField: s('edgeField'),
|
|
65
|
-
enumType: s('enumType'),
|
|
66
|
-
filterType: n('filterType'),
|
|
67
|
-
inputType: s('inputType'),
|
|
68
|
-
orderByType: s('orderByType'),
|
|
69
|
-
patchField: s('patchField'),
|
|
70
|
-
patchType: n('patchType'),
|
|
71
|
-
tableFieldName: s('tableFieldName'),
|
|
72
|
-
tableType: s('tableType'),
|
|
73
|
-
typeName: s('typeName'),
|
|
74
|
-
updateByPrimaryKey: n('updateByPrimaryKey'),
|
|
75
|
-
updatePayloadType: n('updatePayloadType'),
|
|
76
|
-
};
|
|
77
|
-
}
|
|
78
|
-
function convertQuery(query) {
|
|
79
|
-
if (!query)
|
|
80
|
-
return undefined;
|
|
81
|
-
return {
|
|
82
|
-
all: query.all ?? '',
|
|
83
|
-
one: query.one ?? null,
|
|
84
|
-
create: query.create ?? '',
|
|
85
|
-
update: query.update ?? null,
|
|
86
|
-
delete: query.delete ?? null,
|
|
87
|
-
};
|
|
88
|
-
}
|
|
89
|
-
export function cleanTable(meta) {
|
|
90
|
-
return {
|
|
91
|
-
name: meta.name,
|
|
92
|
-
inflection: convertInflection(meta.inflection),
|
|
93
|
-
query: convertQuery(meta.query),
|
|
94
|
-
fields: (meta.fields ?? [])
|
|
95
|
-
.filter((f) => Boolean(f))
|
|
96
|
-
.map((field) => ({
|
|
97
|
-
name: field.name,
|
|
98
|
-
type: {
|
|
99
|
-
gqlType: field.type.gqlType,
|
|
100
|
-
isArray: field.type.isArray,
|
|
101
|
-
modifier: field.type.modifier,
|
|
102
|
-
pgAlias: field.type.pgAlias,
|
|
103
|
-
pgType: field.type.pgType,
|
|
104
|
-
subtype: field.type.subtype,
|
|
105
|
-
typmod: field.type.typmod,
|
|
106
|
-
},
|
|
107
|
-
isNotNull: field.isNotNull ?? field.type.isNotNull ?? null,
|
|
108
|
-
hasDefault: field.hasDefault ?? field.type.hasDefault ?? null,
|
|
109
|
-
})),
|
|
110
|
-
relations: { belongsTo: [], hasOne: [], hasMany: [], manyToMany: [] },
|
|
111
|
-
};
|
|
112
|
-
}
|
|
113
|
-
function normalizeTableLookupKey(value) {
|
|
114
|
-
return (value ?? '')
|
|
115
|
-
.trim()
|
|
116
|
-
.toLowerCase()
|
|
117
|
-
.replace(/[^a-z0-9]/g, '');
|
|
118
|
-
}
|
|
119
|
-
function getTableLookupVariants(value) {
|
|
120
|
-
const normalized = normalizeTableLookupKey(value);
|
|
121
|
-
if (!normalized)
|
|
122
|
-
return [];
|
|
123
|
-
const variants = new Set([normalized]);
|
|
124
|
-
if (normalized.endsWith('y')) {
|
|
125
|
-
variants.add(`${normalized}s`);
|
|
126
|
-
variants.add(`${normalized.slice(0, -1)}ies`);
|
|
127
|
-
}
|
|
128
|
-
if (normalized.endsWith('ies')) {
|
|
129
|
-
variants.add(`${normalized.slice(0, -3)}y`);
|
|
130
|
-
}
|
|
131
|
-
if (/(s|x|z|ch|sh)$/.test(normalized))
|
|
132
|
-
variants.add(`${normalized}es`);
|
|
133
|
-
if (normalized.endsWith('es'))
|
|
134
|
-
variants.add(normalized.slice(0, -2));
|
|
135
|
-
if (!normalized.endsWith('s'))
|
|
136
|
-
variants.add(`${normalized}s`);
|
|
137
|
-
if (normalized.endsWith('s'))
|
|
138
|
-
variants.add(normalized.slice(0, -1));
|
|
139
|
-
return [...variants].filter(Boolean);
|
|
140
|
-
}
|
|
141
|
-
// Resolve a user-supplied table name (snake_case singular or plural) against the
|
|
142
|
-
// PascalCase-singular `_meta` table names, tolerating pluralization differences.
|
|
143
|
-
export function findMetaTable(tables, requested) {
|
|
144
|
-
const index = new Map();
|
|
145
|
-
for (const table of tables) {
|
|
146
|
-
const keys = [
|
|
147
|
-
table.name,
|
|
148
|
-
table.query?.all,
|
|
149
|
-
table.query?.one,
|
|
150
|
-
table.inflection?.tableType,
|
|
151
|
-
table.inflection?.tableFieldName,
|
|
152
|
-
table.inflection?.allRows,
|
|
153
|
-
];
|
|
154
|
-
for (const key of keys) {
|
|
155
|
-
for (const variant of getTableLookupVariants(key)) {
|
|
156
|
-
if (!index.has(variant))
|
|
157
|
-
index.set(variant, table);
|
|
158
|
-
}
|
|
159
|
-
}
|
|
160
|
-
}
|
|
161
|
-
for (const variant of getTableLookupVariants(requested)) {
|
|
162
|
-
const match = index.get(variant);
|
|
163
|
-
if (match)
|
|
164
|
-
return match;
|
|
165
|
-
}
|
|
166
|
-
return undefined;
|
|
167
|
-
}
|
|
@@ -1,48 +0,0 @@
|
|
|
1
|
-
// Turbopack barrel normalization (TURBOPACK-BARREL-001).
|
|
2
|
-
//
|
|
3
|
-
// Codegen emits directory barrel re-exports like `export * from './hooks'` where
|
|
4
|
-
// `./hooks` is a directory with an index.ts. Next.js 16's Turbopack cannot
|
|
5
|
-
// resolve directory specifiers — it needs an explicit `./hooks/index`. This pass
|
|
6
|
-
// rewrites `./X` -> `./X/index` only when X resolves to a sibling DIRECTORY,
|
|
7
|
-
// leaving file specifiers (and ones already ending in /index) untouched.
|
|
8
|
-
//
|
|
9
|
-
// Pure-ish: operates on a real directory tree (so it's exercised with a temp
|
|
10
|
-
// fixture in tests) and is idempotent — safe to re-run.
|
|
11
|
-
import fs from 'node:fs';
|
|
12
|
-
import path from 'node:path';
|
|
13
|
-
const SPEC_RE = /((?:export|import)[^\n]*?from\s*["'])(\.\.?\/[^"']+?)(["'])/g;
|
|
14
|
-
const FILE_EXT_RE = /\.(tsx?|jsx?|json|css)$/;
|
|
15
|
-
/** Rewrite directory barrel specifiers under `root` in place. Returns the count
|
|
16
|
-
* of files changed. No-op (returns 0) when `root` does not exist. */
|
|
17
|
-
export function normalizeSdkBarrels(root) {
|
|
18
|
-
if (!fs.existsSync(root))
|
|
19
|
-
return 0;
|
|
20
|
-
let changed = 0;
|
|
21
|
-
const walk = (dir) => {
|
|
22
|
-
for (const entry of fs.readdirSync(dir, { withFileTypes: true })) {
|
|
23
|
-
const p = path.join(dir, entry.name);
|
|
24
|
-
if (entry.isDirectory()) {
|
|
25
|
-
walk(p);
|
|
26
|
-
continue;
|
|
27
|
-
}
|
|
28
|
-
if (!/\.tsx?$/.test(entry.name))
|
|
29
|
-
continue;
|
|
30
|
-
const orig = fs.readFileSync(p, 'utf8');
|
|
31
|
-
const next = orig.replace(SPEC_RE, (match, pre, spec, post) => {
|
|
32
|
-
if (FILE_EXT_RE.test(spec))
|
|
33
|
-
return match; // already a file
|
|
34
|
-
const abs = path.resolve(path.dirname(p), spec);
|
|
35
|
-
if (fs.existsSync(abs) && fs.statSync(abs).isDirectory()) {
|
|
36
|
-
return pre + spec.replace(/\/$/, '') + '/index' + post;
|
|
37
|
-
}
|
|
38
|
-
return match;
|
|
39
|
-
});
|
|
40
|
-
if (next !== orig) {
|
|
41
|
-
fs.writeFileSync(p, next);
|
|
42
|
-
changed++;
|
|
43
|
-
}
|
|
44
|
-
}
|
|
45
|
-
};
|
|
46
|
-
walk(root);
|
|
47
|
-
return changed;
|
|
48
|
-
}
|
|
@@ -1,8 +0,0 @@
|
|
|
1
|
-
export type PlaneEndpoints = {
|
|
2
|
-
admin: string;
|
|
3
|
-
auth: string;
|
|
4
|
-
app: string;
|
|
5
|
-
};
|
|
6
|
-
export declare function derivePlaneEndpoints(apiEndpoint: string, databaseName: string): PlaneEndpoints | undefined;
|
|
7
|
-
export declare function codegenEndpointEnv(planes: PlaneEndpoints): Record<string, string>;
|
|
8
|
-
export declare function envLocalContent(databaseName: string, planes: PlaneEndpoints | undefined): string;
|
|
@@ -1,46 +0,0 @@
|
|
|
1
|
-
// Codegen and the Next.js dev server default every per-DB vhost to
|
|
2
|
-
// *-<db>.localhost:3000, which only exists on a local backend. Derive the real
|
|
3
|
-
// vhosts from the api endpoint the binding belongs to by swapping its first
|
|
4
|
-
// host label (api.launchql.dev -> admin-<db>.launchql.dev) — the same scheme
|
|
5
|
-
// context.ts uses for the data plane. The app DATA plane is `api-<db>`, not
|
|
6
|
-
// `app-<db>` (SUBDOMAIN-001).
|
|
7
|
-
export function derivePlaneEndpoints(apiEndpoint, databaseName) {
|
|
8
|
-
const derive = (label) => {
|
|
9
|
-
try {
|
|
10
|
-
const url = new URL(apiEndpoint);
|
|
11
|
-
const labels = url.hostname.split('.');
|
|
12
|
-
labels[0] = `${label}-${databaseName}`;
|
|
13
|
-
url.hostname = labels.join('.');
|
|
14
|
-
return url.toString();
|
|
15
|
-
}
|
|
16
|
-
catch {
|
|
17
|
-
return undefined;
|
|
18
|
-
}
|
|
19
|
-
};
|
|
20
|
-
const admin = derive('admin');
|
|
21
|
-
const auth = derive('auth');
|
|
22
|
-
const app = derive('api');
|
|
23
|
-
return admin && auth && app ? { admin, auth, app } : undefined;
|
|
24
|
-
}
|
|
25
|
-
// The template's graphql-codegen.config.ts honors CODEGEN_*_ENDPOINT for the
|
|
26
|
-
// URL and CODEGEN_*_HOST for the Host header; set both so scheme and routing
|
|
27
|
-
// stay in sync on any backend.
|
|
28
|
-
export function codegenEndpointEnv(planes) {
|
|
29
|
-
return {
|
|
30
|
-
CODEGEN_ADMIN_ENDPOINT: planes.admin,
|
|
31
|
-
CODEGEN_ADMIN_HOST: new URL(planes.admin).host,
|
|
32
|
-
CODEGEN_AUTH_ENDPOINT: planes.auth,
|
|
33
|
-
CODEGEN_AUTH_HOST: new URL(planes.auth).host,
|
|
34
|
-
CODEGEN_APP_ENDPOINT: planes.app,
|
|
35
|
-
CODEGEN_APP_HOST: new URL(planes.app).host,
|
|
36
|
-
};
|
|
37
|
-
}
|
|
38
|
-
// .env.local for the dev server: the template's runtime config falls back to
|
|
39
|
-
// localhost vhosts unless NEXT_PUBLIC_*_ENDPOINT overrides are present.
|
|
40
|
-
export function envLocalContent(databaseName, planes) {
|
|
41
|
-
const lines = [`NEXT_PUBLIC_DB_NAME=${databaseName}`];
|
|
42
|
-
if (planes) {
|
|
43
|
-
lines.push(`NEXT_PUBLIC_ADMIN_ENDPOINT=${planes.admin}`, `NEXT_PUBLIC_AUTH_ENDPOINT=${planes.auth}`, `NEXT_PUBLIC_APP_ENDPOINT=${planes.app}`);
|
|
44
|
-
}
|
|
45
|
-
return `${lines.join('\n')}\n`;
|
|
46
|
-
}
|
package/esm/schema-resolve.d.ts
DELETED
|
@@ -1,23 +0,0 @@
|
|
|
1
|
-
import type { ProjectContext } from './context';
|
|
2
|
-
export type ResolvedField = {
|
|
3
|
-
id: string;
|
|
4
|
-
name: string;
|
|
5
|
-
tableId: string;
|
|
6
|
-
};
|
|
7
|
-
export type ResolvedUniqueConstraint = {
|
|
8
|
-
id: string;
|
|
9
|
-
fieldIds: string[];
|
|
10
|
-
};
|
|
11
|
-
export type ResolvedTable = {
|
|
12
|
-
id: string;
|
|
13
|
-
name: string;
|
|
14
|
-
fields: ResolvedField[];
|
|
15
|
-
uniqueConstraints: ResolvedUniqueConstraint[];
|
|
16
|
-
};
|
|
17
|
-
export type ResolvedSchema = {
|
|
18
|
-
tables: ResolvedTable[];
|
|
19
|
-
};
|
|
20
|
-
export declare function resolveSchema(context: ProjectContext): Promise<ResolvedSchema>;
|
|
21
|
-
export declare function resolveTable(schema: ResolvedSchema, tableName: string): ResolvedTable;
|
|
22
|
-
export declare function resolveField(table: ResolvedTable, fieldName: string): ResolvedField;
|
|
23
|
-
export declare function findUniqueConstraintId(table: ResolvedTable, fieldId: string): string | undefined;
|
package/esm/schema-resolve.js
DELETED
|
@@ -1,69 +0,0 @@
|
|
|
1
|
-
export async function resolveSchema(context) {
|
|
2
|
-
const { api, databaseId } = context;
|
|
3
|
-
const tablesResult = await api.table
|
|
4
|
-
.findMany({
|
|
5
|
-
select: { id: true, name: true },
|
|
6
|
-
where: { databaseId: { equalTo: databaseId } },
|
|
7
|
-
})
|
|
8
|
-
.execute();
|
|
9
|
-
if (!tablesResult.ok) {
|
|
10
|
-
const message = tablesResult.errors.map((e) => e.message).join('; ');
|
|
11
|
-
throw new Error(`Failed to read tables: ${message}`);
|
|
12
|
-
}
|
|
13
|
-
const tableNodes = tablesResult.data.tables?.nodes ?? [];
|
|
14
|
-
const tableIds = tableNodes.map((t) => t.id);
|
|
15
|
-
const fieldsByTable = new Map();
|
|
16
|
-
const constraintsByTable = new Map();
|
|
17
|
-
if (tableIds.length > 0) {
|
|
18
|
-
const fieldsResult = await api.field
|
|
19
|
-
.findMany({
|
|
20
|
-
select: { id: true, name: true, tableId: true },
|
|
21
|
-
where: { tableId: { in: tableIds } },
|
|
22
|
-
})
|
|
23
|
-
.execute();
|
|
24
|
-
if (!fieldsResult.ok) {
|
|
25
|
-
const message = fieldsResult.errors.map((e) => e.message).join('; ');
|
|
26
|
-
throw new Error(`Failed to read fields: ${message}`);
|
|
27
|
-
}
|
|
28
|
-
for (const field of fieldsResult.data.fields?.nodes ?? []) {
|
|
29
|
-
const list = fieldsByTable.get(field.tableId) ?? [];
|
|
30
|
-
list.push({ id: field.id, name: field.name, tableId: field.tableId });
|
|
31
|
-
fieldsByTable.set(field.tableId, list);
|
|
32
|
-
}
|
|
33
|
-
const constraintsResult = await api.uniqueConstraint
|
|
34
|
-
.findMany({
|
|
35
|
-
select: { id: true, tableId: true, fieldIds: true },
|
|
36
|
-
where: { tableId: { in: tableIds } },
|
|
37
|
-
})
|
|
38
|
-
.execute();
|
|
39
|
-
if (constraintsResult.ok) {
|
|
40
|
-
for (const c of constraintsResult.data.uniqueConstraints?.nodes ?? []) {
|
|
41
|
-
const list = constraintsByTable.get(c.tableId) ?? [];
|
|
42
|
-
list.push({ id: c.id, fieldIds: Array.isArray(c.fieldIds) ? c.fieldIds : [] });
|
|
43
|
-
constraintsByTable.set(c.tableId, list);
|
|
44
|
-
}
|
|
45
|
-
}
|
|
46
|
-
}
|
|
47
|
-
const tables = tableNodes.map((table) => ({
|
|
48
|
-
id: table.id,
|
|
49
|
-
name: table.name,
|
|
50
|
-
fields: fieldsByTable.get(table.id) ?? [],
|
|
51
|
-
uniqueConstraints: constraintsByTable.get(table.id) ?? [],
|
|
52
|
-
}));
|
|
53
|
-
return { tables };
|
|
54
|
-
}
|
|
55
|
-
export function resolveTable(schema, tableName) {
|
|
56
|
-
const table = schema.tables.find((t) => t.name === tableName);
|
|
57
|
-
if (!table)
|
|
58
|
-
throw new Error(`Table "${tableName}" not found in current schema`);
|
|
59
|
-
return table;
|
|
60
|
-
}
|
|
61
|
-
export function resolveField(table, fieldName) {
|
|
62
|
-
const field = table.fields.find((f) => f.name === fieldName);
|
|
63
|
-
if (!field)
|
|
64
|
-
throw new Error(`Field "${fieldName}" not found in table "${table.name}"`);
|
|
65
|
-
return field;
|
|
66
|
-
}
|
|
67
|
-
export function findUniqueConstraintId(table, fieldId) {
|
|
68
|
-
return table.uniqueConstraints.find((c) => c.fieldIds.includes(fieldId))?.id;
|
|
69
|
-
}
|
package/esm/tool-schema.d.ts
DELETED
package/esm/tool-schema.js
DELETED
|
@@ -1,10 +0,0 @@
|
|
|
1
|
-
import { z } from 'zod';
|
|
2
|
-
// Tool parameter schemas are authored in zod; pi's ToolDefinition wants a
|
|
3
|
-
// typebox TSchema. Structurally a TSchema is just a JSON Schema object, so the
|
|
4
|
-
// draft-7 output of z.toJSONSchema (minus the $schema marker, matching what
|
|
5
|
-
// typebox emits) is cast across the boundary. typebox itself is a type-only
|
|
6
|
-
// import — it never appears in the runtime bundle.
|
|
7
|
-
export function toolSchema(schema) {
|
|
8
|
-
const { $schema: _$schema, ...rest } = z.toJSONSchema(schema, { target: 'draft-7' });
|
|
9
|
-
return rest;
|
|
10
|
-
}
|
|
@@ -1,8 +0,0 @@
|
|
|
1
|
-
import type { ToolDefinition } from '@earendil-works/pi-coding-agent';
|
|
2
|
-
declare const AddPoliciesSchema: import("typebox/type").TSchema;
|
|
3
|
-
export type AddPoliciesDetails = {
|
|
4
|
-
success: boolean;
|
|
5
|
-
message: string;
|
|
6
|
-
};
|
|
7
|
-
export declare const addPoliciesTool: ToolDefinition<typeof AddPoliciesSchema, AddPoliciesDetails>;
|
|
8
|
-
export {};
|
|
@@ -1,96 +0,0 @@
|
|
|
1
|
-
import { buildNodeData, getPolicyFieldDefaults, getPolicyProvisioningConfig } from '@agentic-kit/harness';
|
|
2
|
-
import { z } from 'zod';
|
|
3
|
-
import { resolveProjectContext } from '../context';
|
|
4
|
-
import { addPoliciesToExistingTable } from '../policy/add-policies-to-table';
|
|
5
|
-
import { resolveSchema, resolveTable } from '../schema-resolve';
|
|
6
|
-
import { toolSchema } from '../tool-schema';
|
|
7
|
-
const DEFAULT_ROLE = 'authenticated';
|
|
8
|
-
const CrudOperationSchema = z.enum(['create', 'read', 'update', 'delete']);
|
|
9
|
-
const PolicyEntrySchema = z.object({
|
|
10
|
-
policy_type: z
|
|
11
|
-
.string()
|
|
12
|
-
.describe('Policy type id. Supported: AuthzAllowAll, AuthzDenyAll, AuthzAppMembership, AuthzDirectOwner, AuthzEntityMembership, AuthzOrgHierarchy, AuthzPublishable (these auto-create columns via their Data* node), AuthzRelatedMemberList, AuthzRelatedEntityMembership. Not supported (use the policies UI): AuthzDirectOwnerAny, AuthzMemberList, AuthzTemporal, AuthzComposite.'),
|
|
13
|
-
operations: z
|
|
14
|
-
.array(CrudOperationSchema)
|
|
15
|
-
.min(1)
|
|
16
|
-
.describe('CRUD operations the policy applies to: any subset of ["create","read","update","delete"].'),
|
|
17
|
-
role_name: z
|
|
18
|
-
.string()
|
|
19
|
-
.describe('PostgreSQL role the policy applies to. Defaults to "authenticated".')
|
|
20
|
-
.optional(),
|
|
21
|
-
is_permissive: z
|
|
22
|
-
.boolean()
|
|
23
|
-
.describe('PERMISSIVE (default true) vs RESTRICTIVE — most policies should be permissive.')
|
|
24
|
-
.optional(),
|
|
25
|
-
data: z
|
|
26
|
-
.record(z.string(), z.unknown())
|
|
27
|
-
.describe('Type-specific shared data. AuthzDirectOwner: { entity_field: "owner_id" }. AuthzAppMembership: { permission?, is_admin?, is_owner? }. Empty object {} for AuthzAllowAll / AuthzDenyAll.')
|
|
28
|
-
.optional(),
|
|
29
|
-
node_data: z
|
|
30
|
-
.record(z.string(), z.unknown())
|
|
31
|
-
.describe('Optional data for the underlying Data* node (has-module policies only).')
|
|
32
|
-
.optional(),
|
|
33
|
-
});
|
|
34
|
-
const AddPoliciesZod = z.object({
|
|
35
|
-
table_name: z
|
|
36
|
-
.string()
|
|
37
|
-
.describe('Name of the existing table to attach the policies to. Use describe_schema first to verify it exists.'),
|
|
38
|
-
policies: z
|
|
39
|
-
.array(PolicyEntrySchema)
|
|
40
|
-
.min(1)
|
|
41
|
-
.describe('One or more policies to add. Each entry becomes one secure_table_provision call.'),
|
|
42
|
-
});
|
|
43
|
-
const AddPoliciesSchema = toolSchema(AddPoliciesZod);
|
|
44
|
-
function buildOperations(roleName, isPermissive) {
|
|
45
|
-
const config = { roleName, isPermissive, policyData: {}, isCustomized: false };
|
|
46
|
-
return { create: config, read: config, update: config, delete: config };
|
|
47
|
-
}
|
|
48
|
-
export const addPoliciesTool = {
|
|
49
|
-
name: 'add_policies',
|
|
50
|
-
label: 'Add policies',
|
|
51
|
-
description: 'Add one or more RLS policies to an existing table. Has-module policies (AuthzDirectOwner, AuthzEntityMembership, AuthzOrgHierarchy, AuthzPublishable) auto-create the columns they need — call directly, do not add columns first.',
|
|
52
|
-
promptSnippet: 'add_policies: attach RLS policies to an existing table (one call can add many). Gated.',
|
|
53
|
-
parameters: AddPoliciesSchema,
|
|
54
|
-
async execute(_id, params, _signal, _onUpdate, ctx) {
|
|
55
|
-
const resolved = await resolveProjectContext(ctx.cwd);
|
|
56
|
-
if (!resolved.context) {
|
|
57
|
-
return {
|
|
58
|
-
content: [{ type: 'text', text: resolved.reason }],
|
|
59
|
-
details: { success: false, message: resolved.reason },
|
|
60
|
-
};
|
|
61
|
-
}
|
|
62
|
-
const { modules, databaseId, schemaId } = resolved.context;
|
|
63
|
-
try {
|
|
64
|
-
const schema = await resolveSchema(resolved.context);
|
|
65
|
-
const table = resolveTable(schema, params.table_name);
|
|
66
|
-
const policies = params.policies.map((entry) => {
|
|
67
|
-
const config = getPolicyProvisioningConfig(entry.policy_type);
|
|
68
|
-
const defaults = getPolicyFieldDefaults(entry.policy_type);
|
|
69
|
-
const mergedData = { ...defaults, ...(entry.data ?? {}) };
|
|
70
|
-
const nodeData = entry.node_data ?? buildNodeData(entry.policy_type, mergedData);
|
|
71
|
-
return {
|
|
72
|
-
policyType: entry.policy_type,
|
|
73
|
-
dataNodeType: config?.dataNodeType,
|
|
74
|
-
nodeData,
|
|
75
|
-
sharedPolicyData: mergedData,
|
|
76
|
-
operations: buildOperations(entry.role_name ?? DEFAULT_ROLE, entry.is_permissive ?? true),
|
|
77
|
-
enabledOperations: entry.operations,
|
|
78
|
-
};
|
|
79
|
-
});
|
|
80
|
-
await addPoliciesToExistingTable({
|
|
81
|
-
client: modules,
|
|
82
|
-
databaseId,
|
|
83
|
-
schemaId,
|
|
84
|
-
tableId: table.id,
|
|
85
|
-
policies,
|
|
86
|
-
});
|
|
87
|
-
const count = params.policies.length;
|
|
88
|
-
const message = `Added ${count} ${count === 1 ? 'policy' : 'policies'} to ${params.table_name}`;
|
|
89
|
-
return { content: [{ type: 'text', text: message }], details: { success: true, message } };
|
|
90
|
-
}
|
|
91
|
-
catch (err) {
|
|
92
|
-
const message = err instanceof Error ? err.message : 'Failed to add policies';
|
|
93
|
-
return { content: [{ type: 'text', text: message }], details: { success: false, message } };
|
|
94
|
-
}
|
|
95
|
-
},
|
|
96
|
-
};
|
|
@@ -1,14 +0,0 @@
|
|
|
1
|
-
import type { ToolDefinition } from '@earendil-works/pi-coding-agent';
|
|
2
|
-
export type AddRecordsDetails = {
|
|
3
|
-
success: boolean;
|
|
4
|
-
message: string;
|
|
5
|
-
tableName?: string;
|
|
6
|
-
columns?: string[];
|
|
7
|
-
rows?: Record<string, unknown>[];
|
|
8
|
-
createdCount?: number;
|
|
9
|
-
asOf?: string;
|
|
10
|
-
needsAuth?: boolean;
|
|
11
|
-
};
|
|
12
|
-
declare const AddRecordsSchema: import("typebox/type").TSchema;
|
|
13
|
-
export declare const addRecordsTool: ToolDefinition<typeof AddRecordsSchema, AddRecordsDetails>;
|
|
14
|
-
export {};
|
package/esm/tools/add-records.js
DELETED
|
@@ -1,124 +0,0 @@
|
|
|
1
|
-
import { buildPostGraphileCreate, toCamelCaseSingular, toCreateMutationName, } from '@constructive-io/graphql-query/generators';
|
|
2
|
-
import { objects } from '@constructive-io/sdk';
|
|
3
|
-
import { z } from 'zod';
|
|
4
|
-
import { resolveDataToken, resolveProjectContext } from '../context';
|
|
5
|
-
import { cleanTable, findMetaTable, META_QUERY } from '../records/meta';
|
|
6
|
-
import { toolSchema } from '../tool-schema';
|
|
7
|
-
function fail(message) {
|
|
8
|
-
return { content: [{ type: 'text', text: message }], details: { success: false, message } };
|
|
9
|
-
}
|
|
10
|
-
function needsAuth(message) {
|
|
11
|
-
return {
|
|
12
|
-
content: [{ type: 'text', text: message }],
|
|
13
|
-
details: { success: false, message, needsAuth: true },
|
|
14
|
-
};
|
|
15
|
-
}
|
|
16
|
-
// Mirror @constructive-io/data's prepareCreateInput (create semantics): drop
|
|
17
|
-
// undefined/null/empty-string so server defaults apply; keep false/0/[]/objects.
|
|
18
|
-
function stripForCreate(record) {
|
|
19
|
-
const out = {};
|
|
20
|
-
for (const [key, value] of Object.entries(record)) {
|
|
21
|
-
if (value === undefined || value === null || value === '')
|
|
22
|
-
continue;
|
|
23
|
-
out[key] = value;
|
|
24
|
-
}
|
|
25
|
-
return out;
|
|
26
|
-
}
|
|
27
|
-
const AddRecordsZod = z.object({
|
|
28
|
-
table_name: z
|
|
29
|
-
.string()
|
|
30
|
-
.describe('Name of the table to insert rows into (snake_case, singular or plural).'),
|
|
31
|
-
records: z
|
|
32
|
-
.array(z.record(z.string(), z.unknown()))
|
|
33
|
-
.describe('Rows to insert. Each is an object of column → value (camelCase or snake_case column names).'),
|
|
34
|
-
});
|
|
35
|
-
const AddRecordsSchema = toolSchema(AddRecordsZod);
|
|
36
|
-
export const addRecordsTool = {
|
|
37
|
-
name: 'add_records',
|
|
38
|
-
label: 'Add records',
|
|
39
|
-
description: "Insert one or more rows into a table in the project's app database.",
|
|
40
|
-
promptSnippet: 'add_records: insert rows into an existing table. Gated.',
|
|
41
|
-
parameters: AddRecordsSchema,
|
|
42
|
-
async execute(_id, params, _signal, _onUpdate, ctx) {
|
|
43
|
-
const resolved = await resolveProjectContext(ctx.cwd);
|
|
44
|
-
if (!resolved.context)
|
|
45
|
-
return fail(resolved.reason);
|
|
46
|
-
const { dataEndpoint } = resolved.context;
|
|
47
|
-
if (!dataEndpoint) {
|
|
48
|
-
return fail('Cannot resolve the app data endpoint (DATABASE_NAME missing from .env). Re-provision the database, then retry.');
|
|
49
|
-
}
|
|
50
|
-
if (params.records.length === 0)
|
|
51
|
-
return fail('No records provided.');
|
|
52
|
-
const token = await resolveDataToken(resolved.context);
|
|
53
|
-
if (!token.token)
|
|
54
|
-
return needsAuth(token.reason ?? 'Sign in to the database to insert records.');
|
|
55
|
-
const adapter = new objects.FetchAdapter(dataEndpoint, {
|
|
56
|
-
Authorization: `Bearer ${token.token}`,
|
|
57
|
-
});
|
|
58
|
-
let tables;
|
|
59
|
-
try {
|
|
60
|
-
const meta = await adapter.execute(META_QUERY);
|
|
61
|
-
if (!meta.ok) {
|
|
62
|
-
return fail(`Failed to read schema from the app database: ${meta.errors.map((e) => e.message).join('; ')}`);
|
|
63
|
-
}
|
|
64
|
-
tables = (meta.data._meta?.tables ?? []).filter((t) => Boolean(t));
|
|
65
|
-
}
|
|
66
|
-
catch (err) {
|
|
67
|
-
return fail(err instanceof Error ? err.message : 'Failed to query the app database schema.');
|
|
68
|
-
}
|
|
69
|
-
const rawTable = findMetaTable(tables, params.table_name);
|
|
70
|
-
if (!rawTable) {
|
|
71
|
-
return fail(`Table "${params.table_name}" was not found in the app database.`);
|
|
72
|
-
}
|
|
73
|
-
const table = cleanTable(rawTable);
|
|
74
|
-
const allTables = tables.map(cleanTable);
|
|
75
|
-
const mutation = buildPostGraphileCreate(table, allTables).toString();
|
|
76
|
-
const mutationName = toCreateMutationName(table.name, table);
|
|
77
|
-
const singularName = toCamelCaseSingular(table.name, table);
|
|
78
|
-
// Constructive app tables scope rows by entityId (the owning user's id). The
|
|
79
|
-
// create input requires it, but callers won't know it — backfill it with the
|
|
80
|
-
// signed-in user's id from the Preview session when the table has the column
|
|
81
|
-
// and the record omits it.
|
|
82
|
-
const hasEntityId = table.fields.some((f) => f.name === 'entityId');
|
|
83
|
-
const created = [];
|
|
84
|
-
const errors = [];
|
|
85
|
-
for (const record of params.records) {
|
|
86
|
-
const prepared = hasEntityId && token.userId && record.entityId == null && record.entity_id == null
|
|
87
|
-
? { ...record, entityId: token.userId }
|
|
88
|
-
: record;
|
|
89
|
-
const variables = { input: { [singularName]: stripForCreate(prepared) } };
|
|
90
|
-
try {
|
|
91
|
-
const result = await adapter.execute(mutation, variables);
|
|
92
|
-
if (!result.ok) {
|
|
93
|
-
errors.push(result.errors.map((e) => e.message).join('; '));
|
|
94
|
-
continue;
|
|
95
|
-
}
|
|
96
|
-
const payload = result.data[mutationName];
|
|
97
|
-
const row = payload?.[singularName] ?? {};
|
|
98
|
-
created.push(row);
|
|
99
|
-
}
|
|
100
|
-
catch (err) {
|
|
101
|
-
errors.push(err instanceof Error ? err.message : 'Unknown error');
|
|
102
|
-
}
|
|
103
|
-
}
|
|
104
|
-
if (created.length === 0) {
|
|
105
|
-
return fail(`Failed to insert into "${params.table_name}": ${errors.join('; ') || 'unknown error'}`);
|
|
106
|
-
}
|
|
107
|
-
const columns = table.fields.map((f) => f.name);
|
|
108
|
-
const message = errors.length > 0
|
|
109
|
-
? `Inserted ${created.length} of ${params.records.length} row(s) into ${params.table_name} (${errors.length} failed).`
|
|
110
|
-
: `Inserted ${created.length} row(s) into ${params.table_name}.`;
|
|
111
|
-
return {
|
|
112
|
-
content: [{ type: 'text', text: message }],
|
|
113
|
-
details: {
|
|
114
|
-
success: true,
|
|
115
|
-
message,
|
|
116
|
-
tableName: rawTable.name,
|
|
117
|
-
columns,
|
|
118
|
-
rows: created,
|
|
119
|
-
createdCount: created.length,
|
|
120
|
-
asOf: new Date().toISOString(),
|
|
121
|
-
},
|
|
122
|
-
};
|
|
123
|
-
},
|
|
124
|
-
};
|