instant-cli 1.0.40-branch-python-sdk-v1.26482908819.1 → 1.0.40-branch-python-sdk-v1.26525151443.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/.turbo/turbo-build.log +1 -1
- package/dist/commands/genpy.d.ts.map +1 -1
- package/dist/commands/genpy.js +89 -30
- package/dist/commands/genpy.js.map +1 -1
- package/package.json +4 -4
- package/src/commands/genpy.ts +103 -35
package/.turbo/turbo-build.log
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
1
|
|
|
2
|
-
> instant-cli@1.0.40-branch-python-sdk-v1.
|
|
2
|
+
> instant-cli@1.0.40-branch-python-sdk-v1.26525151443.1 build /home/runner/work/instant/instant/client/packages/cli
|
|
3
3
|
> rm -rf dist; tsc -p tsconfig.build.json
|
|
4
4
|
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"genpy.d.ts","sourceRoot":"","sources":["../../src/commands/genpy.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,IAAI,EAAE,MAAM,kBAAkB,CAAC;AAEpD,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAC;AAExC,OAAO,EACL,mBAAmB,EACnB,qBAAqB,EACtB,MAAM,sBAAsB,CAAC;;;;;;AAE9B,qBAAa,eAAgB,SAAQ,oBAInC;CAAG;AAML,eAAO,MAAM,YAAY,GAAI,YAAY;IAAE,MAAM,CAAC,EAAE,MAAM,CAAA;CAAE,+
|
|
1
|
+
{"version":3,"file":"genpy.d.ts","sourceRoot":"","sources":["../../src/commands/genpy.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,IAAI,EAAE,MAAM,kBAAkB,CAAC;AAEpD,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAC;AAExC,OAAO,EACL,mBAAmB,EACnB,qBAAqB,EACtB,MAAM,sBAAsB,CAAC;;;;;;AAE9B,qBAAa,eAAgB,SAAQ,oBAInC;CAAG;AAML,eAAO,MAAM,YAAY,GAAI,YAAY;IAAE,MAAM,CAAC,EAAE,MAAM,CAAA;CAAE,+HAwDxD,CAAC;AAIL,KAAK,UAAU,GAAG;IAChB,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,aAAa,CAAC,CAAC;IACxC,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,WAAW,CAAC,CAAC;CACpC,CAAC;AAEF,KAAK,aAAa,GAAG;IACnB,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,eAAe,CAAC,CAAC;CACxC,CAAC;AAEF,KAAK,eAAe,GAAG;IACrB,SAAS,EAAE,QAAQ,GAAG,QAAQ,GAAG,SAAS,GAAG,MAAM,GAAG,MAAM,CAAC;IAC7D,QAAQ,EAAE,OAAO,CAAC;CACnB,CAAC;AAEF,KAAK,WAAW,GAAG;IACjB,OAAO,EAAE;QAAE,EAAE,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAC;QAAC,GAAG,EAAE,KAAK,GAAG,MAAM,CAAA;KAAE,CAAC;IAC5D,OAAO,EAAE;QAAE,EAAE,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAC;QAAC,GAAG,EAAE,KAAK,GAAG,MAAM,CAAA;KAAE,CAAC;CAC7D,CAAC;AA8DF,wBAAgB,mBAAmB,CAAC,MAAM,EAAE,UAAU,GAAG,MAAM,CA+K9D;AAoGD,wBAAgB,cAAc,CAAC,MAAM,EAAE,UAAU,GAAG,MAAM,CAgIzD"}
|
package/dist/commands/genpy.js
CHANGED
|
@@ -35,9 +35,7 @@ export const genpyCommand = ({ outDir }) => Effect.gen(function* () {
|
|
|
35
35
|
const targetDir = outDir
|
|
36
36
|
? path.resolve(outDir)
|
|
37
37
|
: path.dirname(localSchemaFile.path);
|
|
38
|
-
yield* fs
|
|
39
|
-
.makeDirectory(targetDir, { recursive: true })
|
|
40
|
-
.pipe(Effect.mapError((e) => GenpyWriteError.make({
|
|
38
|
+
yield* fs.makeDirectory(targetDir, { recursive: true }).pipe(Effect.mapError((e) => GenpyWriteError.make({
|
|
41
39
|
message: `Failed to create ${targetDir}: ${e}`,
|
|
42
40
|
})));
|
|
43
41
|
const pyPath = path.join(targetDir, 'instant_types.py');
|
|
@@ -52,6 +50,26 @@ export const genpyCommand = ({ outDir }) => Effect.gen(function* () {
|
|
|
52
50
|
.pipe(Effect.mapError((e) => GenpyWriteError.make({ message: `Failed to write ${pyiPath}: ${e}` })));
|
|
53
51
|
yield* Effect.log(`✅ Wrote ${pyPath} and ${pyiPath}`);
|
|
54
52
|
});
|
|
53
|
+
const PY_KEYWORDS = new Set([
|
|
54
|
+
'False', 'None', 'True', 'and', 'as', 'assert', 'async', 'await',
|
|
55
|
+
'break', 'class', 'continue', 'def', 'del', 'elif', 'else', 'except',
|
|
56
|
+
'finally', 'for', 'from', 'global', 'if', 'import', 'in', 'is',
|
|
57
|
+
'lambda', 'nonlocal', 'not', 'or', 'pass', 'raise', 'return', 'try',
|
|
58
|
+
'while', 'with', 'yield', 'match', 'case',
|
|
59
|
+
]);
|
|
60
|
+
function isPyIdent(name) {
|
|
61
|
+
return /^[A-Za-z_][A-Za-z0-9_]*$/.test(name) && !PY_KEYWORDS.has(name);
|
|
62
|
+
}
|
|
63
|
+
function safePyIdent(name) {
|
|
64
|
+
if (isPyIdent(name))
|
|
65
|
+
return name;
|
|
66
|
+
let safe = name.replace(/[^A-Za-z0-9_]+/g, '_').replace(/_+/g, '_');
|
|
67
|
+
if (safe === '' || /^[0-9]/.test(safe))
|
|
68
|
+
safe = '_' + safe;
|
|
69
|
+
if (PY_KEYWORDS.has(safe))
|
|
70
|
+
safe += '_';
|
|
71
|
+
return safe;
|
|
72
|
+
}
|
|
55
73
|
function className(entName) {
|
|
56
74
|
// Strip a leading `$` (system entities like `$users`, `$files`), then
|
|
57
75
|
// PascalCase across word separators (`-`, `_`, whitespace) so non-identifier
|
|
@@ -94,10 +112,12 @@ export function buildEntityModelsPy(schema) {
|
|
|
94
112
|
if (baseType === 'datetime')
|
|
95
113
|
usesDatetime = true;
|
|
96
114
|
const type = attrDef.required ? baseType : `${baseType} | None`;
|
|
115
|
+
const safeName = safePyIdent(attrName);
|
|
97
116
|
fieldsByEntity[entName].push({
|
|
98
|
-
name:
|
|
117
|
+
name: safeName,
|
|
99
118
|
type,
|
|
100
119
|
hasDefault: !attrDef.required,
|
|
120
|
+
rawKey: safeName === attrName ? undefined : attrName,
|
|
101
121
|
});
|
|
102
122
|
}
|
|
103
123
|
}
|
|
@@ -105,21 +125,25 @@ export function buildEntityModelsPy(schema) {
|
|
|
105
125
|
const fwd = link.forward;
|
|
106
126
|
const rev = link.reverse;
|
|
107
127
|
if (linkFieldsByEntity[fwd.on]) {
|
|
128
|
+
const safeName = safePyIdent(fwd.label);
|
|
108
129
|
linkFieldsByEntity[fwd.on].push({
|
|
109
|
-
name:
|
|
130
|
+
name: safeName,
|
|
110
131
|
type: fwd.has === 'one'
|
|
111
132
|
? `${className(rev.on)} | None`
|
|
112
133
|
: `list[${className(rev.on)}] | None`,
|
|
113
134
|
hasDefault: true,
|
|
135
|
+
rawKey: safeName === fwd.label ? undefined : fwd.label,
|
|
114
136
|
});
|
|
115
137
|
}
|
|
116
138
|
if (linkFieldsByEntity[rev.on]) {
|
|
139
|
+
const safeName = safePyIdent(rev.label);
|
|
117
140
|
linkFieldsByEntity[rev.on].push({
|
|
118
|
-
name:
|
|
141
|
+
name: safeName,
|
|
119
142
|
type: rev.has === 'one'
|
|
120
143
|
? `${className(fwd.on)} | None`
|
|
121
144
|
: `list[${className(fwd.on)}] | None`,
|
|
122
145
|
hasDefault: true,
|
|
146
|
+
rawKey: safeName === rev.label ? undefined : rev.label,
|
|
123
147
|
});
|
|
124
148
|
}
|
|
125
149
|
}
|
|
@@ -127,18 +151,35 @@ export function buildEntityModelsPy(schema) {
|
|
|
127
151
|
for (const entName of entityNames) {
|
|
128
152
|
linkFieldsByEntity[entName].sort((a, b) => a.name.localeCompare(b.name));
|
|
129
153
|
}
|
|
154
|
+
let usesField = false;
|
|
130
155
|
const classBlocks = entityNames.map((entName) => {
|
|
156
|
+
const allFields = [
|
|
157
|
+
...fieldsByEntity[entName],
|
|
158
|
+
...linkFieldsByEntity[entName],
|
|
159
|
+
];
|
|
160
|
+
const hasAlias = allFields.some((f) => f.rawKey !== undefined);
|
|
161
|
+
const config = hasAlias
|
|
162
|
+
? 'ConfigDict(extra="ignore", populate_by_name=True)'
|
|
163
|
+
: 'ConfigDict(extra="ignore")';
|
|
131
164
|
const lines = [
|
|
132
165
|
`class ${className(entName)}(BaseModel):`,
|
|
133
|
-
` model_config =
|
|
166
|
+
` model_config = ${config}`,
|
|
134
167
|
];
|
|
135
|
-
for (const f of
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
168
|
+
for (const f of allFields) {
|
|
169
|
+
let decl;
|
|
170
|
+
if (f.rawKey !== undefined) {
|
|
171
|
+
usesField = true;
|
|
172
|
+
const args = f.hasDefault
|
|
173
|
+
? `default=None, alias=${JSON.stringify(f.rawKey)}`
|
|
174
|
+
: `alias=${JSON.stringify(f.rawKey)}`;
|
|
175
|
+
decl = ` ${f.name}: ${f.type} = Field(${args})`;
|
|
176
|
+
}
|
|
177
|
+
else if (f.hasDefault) {
|
|
178
|
+
decl = ` ${f.name}: ${f.type} = None`;
|
|
179
|
+
}
|
|
180
|
+
else {
|
|
181
|
+
decl = ` ${f.name}: ${f.type}`;
|
|
182
|
+
}
|
|
142
183
|
lines.push(decl);
|
|
143
184
|
}
|
|
144
185
|
return lines.join('\n');
|
|
@@ -153,9 +194,12 @@ export function buildEntityModelsPy(schema) {
|
|
|
153
194
|
if (usesDatetime)
|
|
154
195
|
stdlibImports.push('from datetime import datetime');
|
|
155
196
|
stdlibImports.push(`from typing import ${typingImports.join(', ')}`);
|
|
197
|
+
const pydanticImports = usesField
|
|
198
|
+
? 'BaseModel, ConfigDict, Field'
|
|
199
|
+
: 'BaseModel, ConfigDict';
|
|
156
200
|
const importBlock = stdlibImports.join('\n') +
|
|
157
201
|
'\n\n' +
|
|
158
|
-
|
|
202
|
+
`from pydantic import ${pydanticImports}`;
|
|
159
203
|
// Add record-model rebuilds so forward-string annotations to entity
|
|
160
204
|
// types resolve under `from __future__ import annotations`.
|
|
161
205
|
const recordRebuilds = [];
|
|
@@ -317,26 +361,41 @@ export function buildTxStubPyi(schema) {
|
|
|
317
361
|
for (const entName of entityNames) {
|
|
318
362
|
linkFieldsByEntity[entName].sort((a, b) => a.label.localeCompare(b.label));
|
|
319
363
|
}
|
|
364
|
+
// Class-syntax TypedDict requires identifier keys; switch to the
|
|
365
|
+
// functional form when any key on a given dict is irregular.
|
|
366
|
+
const buildTypedDict = (name, fields) => {
|
|
367
|
+
const allIdent = fields.every((f) => isPyIdent(f.key));
|
|
368
|
+
if (allIdent) {
|
|
369
|
+
const lines = [`class ${name}(TypedDict, total=False):`];
|
|
370
|
+
for (const f of fields)
|
|
371
|
+
lines.push(` ${f.key}: ${f.type}`);
|
|
372
|
+
if (fields.length === 0)
|
|
373
|
+
lines.push(' pass');
|
|
374
|
+
return lines.join('\n');
|
|
375
|
+
}
|
|
376
|
+
const lines = [`${name} = TypedDict(`, ` ${JSON.stringify(name)},`, ' {'];
|
|
377
|
+
for (const f of fields) {
|
|
378
|
+
lines.push(` ${JSON.stringify(f.key)}: ${f.type},`);
|
|
379
|
+
}
|
|
380
|
+
lines.push(' },', ' total=False,', ')');
|
|
381
|
+
return lines.join('\n');
|
|
382
|
+
};
|
|
320
383
|
const perEntityBlocks = [];
|
|
321
384
|
for (const entName of entityNames) {
|
|
322
385
|
const cls = className(entName);
|
|
323
|
-
const
|
|
386
|
+
const argFields = [];
|
|
324
387
|
for (const [attrName, attrDef] of Object.entries(schema.entities[entName].attrs)) {
|
|
325
388
|
const t = mapValueType(attrDef.valueType);
|
|
326
389
|
if (t === 'datetime')
|
|
327
390
|
usesDatetime = true;
|
|
328
|
-
|
|
329
|
-
}
|
|
330
|
-
if (argsLines.length === 1)
|
|
331
|
-
argsLines.push(' pass');
|
|
332
|
-
perEntityBlocks.push(argsLines.join('\n'));
|
|
333
|
-
const linkLines = [`class ${cls}Links(TypedDict, total=False):`];
|
|
334
|
-
for (const link of linkFieldsByEntity[entName]) {
|
|
335
|
-
linkLines.push(` ${link.label}: ${link.type}`);
|
|
391
|
+
argFields.push({ key: attrName, type: t });
|
|
336
392
|
}
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
393
|
+
perEntityBlocks.push(buildTypedDict(`${cls}Args`, argFields));
|
|
394
|
+
const linkFields = linkFieldsByEntity[entName].map((l) => ({
|
|
395
|
+
key: l.label,
|
|
396
|
+
type: l.type,
|
|
397
|
+
}));
|
|
398
|
+
perEntityBlocks.push(buildTypedDict(`${cls}Links`, linkFields));
|
|
340
399
|
perEntityBlocks.push([
|
|
341
400
|
`class _${cls}Chunk:`,
|
|
342
401
|
` def update(self, args: ${cls}Args) -> _${cls}Chunk: ...`,
|
|
@@ -352,9 +411,9 @@ export function buildTxStubPyi(schema) {
|
|
|
352
411
|
' def __getitem__(self, eid: str) -> ChunkT: ...',
|
|
353
412
|
' def lookup(self, attr: str, value: Any) -> ChunkT: ...',
|
|
354
413
|
].join('\n');
|
|
355
|
-
//
|
|
356
|
-
//
|
|
357
|
-
const identifierEntities = entityNames.filter(
|
|
414
|
+
// Only valid Python identifiers can appear as `_TxBuilder` attrs (for
|
|
415
|
+
// `db.tx.<name>` autocomplete); irregular names use `db.tx["..."]`.
|
|
416
|
+
const identifierEntities = entityNames.filter(isPyIdent);
|
|
358
417
|
const txLines = ['class _TxBuilder:'];
|
|
359
418
|
if (identifierEntities.length === 0) {
|
|
360
419
|
txLines.push(' pass');
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"genpy.js","sourceRoot":"","sources":["../../src/commands/genpy.ts"],"names":[],"mappings":"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","sourcesContent":["import { FileSystem, Path } from '@effect/platform';\nimport chalk from 'chalk';\nimport { Effect, Schema } from 'effect';\nimport { readLocalSchemaFile } from '../old.js';\nimport {\n ReadSchemaFileError,\n SchemaValidationError,\n} from '../lib/pushSchema.ts';\n\nexport class GenpyWriteError extends Schema.TaggedError<GenpyWriteError>(\n 'GenpyWriteError',\n)('GenpyWriteError', {\n message: Schema.String,\n}) {}\n\nconst PY_HEADER = `# AUTOGENERATED by \\`instant-cli genpy\\`. DO NOT EDIT THIS FILE BY HAND.\n# Re-run \\`npx instant-cli genpy\\` after schema changes.\n`;\n\nexport const genpyCommand = ({ outDir }: { outDir?: string }) =>\n Effect.gen(function* () {\n const localSchemaFile = yield* Effect.tryPromise({\n try: readLocalSchemaFile,\n catch: (e) =>\n e instanceof Error\n ? ReadSchemaFileError.make({ message: e.message })\n : ReadSchemaFileError.make({ message: String(e) }),\n });\n if (!localSchemaFile || !localSchemaFile.schema) {\n return yield* ReadSchemaFileError.make({\n message: `We couldn't find your ${chalk.yellow('`instant.schema.ts`')} file. Make sure it's in the project root or under \\`src/\\`. (Hint: set INSTANT_SCHEMA_FILE_PATH to override.)`,\n });\n }\n if (localSchemaFile.schema.constructor?.name !== 'InstantSchemaDef') {\n return yield* SchemaValidationError.make({\n message: `We couldn't find your schema export.\\nIn your ${chalk.yellow('`instant.schema.ts`')} file, make sure you ${chalk.green('`export default schema`')}`,\n });\n }\n\n const path = yield* Path.Path;\n const fs = yield* FileSystem.FileSystem;\n // Default: write alongside the schema file. `--out-dir` overrides for\n // monorepos where Python lives elsewhere, or for our own sandbox where\n // the schema is shared with the JS CLI tests.\n const targetDir = outDir\n ? path.resolve(outDir)\n : path.dirname(localSchemaFile.path);\n yield* fs\n .makeDirectory(targetDir, { recursive: true })\n .pipe(\n Effect.mapError((e) =>\n GenpyWriteError.make({\n message: `Failed to create ${targetDir}: ${e}`,\n }),\n ),\n );\n const pyPath = path.join(targetDir, 'instant_types.py');\n const pyiPath = path.join(targetDir, 'instant_types.pyi');\n\n const pyContent = buildEntityModelsPy(localSchemaFile.schema);\n const pyiContent = buildTxStubPyi(localSchemaFile.schema);\n yield* fs\n .writeFileString(pyPath, pyContent)\n .pipe(\n Effect.mapError((e) =>\n GenpyWriteError.make({ message: `Failed to write ${pyPath}: ${e}` }),\n ),\n );\n yield* fs\n .writeFileString(pyiPath, pyiContent)\n .pipe(\n Effect.mapError((e) =>\n GenpyWriteError.make({ message: `Failed to write ${pyiPath}: ${e}` }),\n ),\n );\n\n yield* Effect.log(`✅ Wrote ${pyPath} and ${pyiPath}`);\n });\n\n// ---------- entity model codegen ----------\n\ntype SchemaLike = {\n entities: Record<string, EntityDefLike>;\n links: Record<string, LinkDefLike>;\n};\n\ntype EntityDefLike = {\n attrs: Record<string, DataAttrDefLike>;\n};\n\ntype DataAttrDefLike = {\n valueType: 'string' | 'number' | 'boolean' | 'date' | 'json';\n required: boolean;\n};\n\ntype LinkDefLike = {\n forward: { on: string; label: string; has: 'one' | 'many' };\n reverse: { on: string; label: string; has: 'one' | 'many' };\n};\n\ntype Field = { name: string; type: string; hasDefault: boolean };\n\nfunction className(entName: string): string {\n // Strip a leading `$` (system entities like `$users`, `$files`), then\n // PascalCase across word separators (`-`, `_`, whitespace) so non-identifier\n // characters in entity names don't produce invalid Python class names.\n const stripped = entName.startsWith('$') ? entName.slice(1) : entName;\n return stripped\n .split(/[-_\\s]+/)\n .filter(Boolean)\n .map((part) => part.charAt(0).toUpperCase() + part.slice(1))\n .join('');\n}\n\nfunction mapValueType(vt: DataAttrDefLike['valueType']): string {\n switch (vt) {\n case 'string':\n return 'str';\n case 'number':\n return 'float';\n case 'boolean':\n return 'bool';\n case 'date':\n return 'datetime';\n case 'json':\n return 'Any';\n default:\n // Defensive: if a new valueType ever lands in the schema without a\n // genpy update, fall back to Any so generated code stays valid Python.\n return 'Any';\n }\n}\n\nexport function buildEntityModelsPy(schema: SchemaLike): string {\n const entityNames = Object.keys(schema.entities).sort();\n const fieldsByEntity: Record<string, Field[]> = {};\n const linkFieldsByEntity: Record<string, Field[]> = {};\n let usesDatetime = false;\n\n for (const entName of entityNames) {\n fieldsByEntity[entName] = [{ name: 'id', type: 'str', hasDefault: false }];\n linkFieldsByEntity[entName] = [];\n for (const [attrName, attrDef] of Object.entries(\n schema.entities[entName].attrs,\n )) {\n const baseType = mapValueType(attrDef.valueType);\n if (baseType === 'datetime') usesDatetime = true;\n const type = attrDef.required ? baseType : `${baseType} | None`;\n fieldsByEntity[entName].push({\n name: attrName,\n type,\n hasDefault: !attrDef.required,\n });\n }\n }\n\n for (const link of Object.values(schema.links)) {\n const fwd = link.forward;\n const rev = link.reverse;\n if (linkFieldsByEntity[fwd.on]) {\n linkFieldsByEntity[fwd.on].push({\n name: fwd.label,\n type:\n fwd.has === 'one'\n ? `${className(rev.on)} | None`\n : `list[${className(rev.on)}] | None`,\n hasDefault: true,\n });\n }\n if (linkFieldsByEntity[rev.on]) {\n linkFieldsByEntity[rev.on].push({\n name: rev.label,\n type:\n rev.has === 'one'\n ? `${className(fwd.on)} | None`\n : `list[${className(fwd.on)}] | None`,\n hasDefault: true,\n });\n }\n }\n\n // Sort link fields alphabetically for stable output across schema rewrites.\n for (const entName of entityNames) {\n linkFieldsByEntity[entName].sort((a, b) => a.name.localeCompare(b.name));\n }\n\n const classBlocks = entityNames.map((entName) => {\n const lines = [\n `class ${className(entName)}(BaseModel):`,\n ` model_config = ConfigDict(extra=\"ignore\")`,\n ];\n for (const f of [\n ...fieldsByEntity[entName],\n ...linkFieldsByEntity[entName],\n ]) {\n const decl = f.hasDefault\n ? ` ${f.name}: ${f.type} = None`\n : ` ${f.name}: ${f.type}`;\n lines.push(decl);\n }\n return lines.join('\\n');\n });\n\n const rebuilds = entityNames.map(\n (entName) => `${className(entName)}.model_rebuild()`,\n );\n\n // Webhook record / handler types live in the same .py so users get one\n // import point (`from instant_types import ...`) for both query results\n // and webhook handler type-checking.\n const webhookSection = buildWebhookSection(schema, entityNames);\n\n const typingImports = ['Any', 'Callable', 'Literal', 'TypedDict'];\n\n const stdlibImports: string[] = [];\n if (usesDatetime) stdlibImports.push('from datetime import datetime');\n stdlibImports.push(`from typing import ${typingImports.join(', ')}`);\n const importBlock =\n stdlibImports.join('\\n') +\n '\\n\\n' +\n 'from pydantic import BaseModel, ConfigDict';\n\n // Add record-model rebuilds so forward-string annotations to entity\n // types resolve under `from __future__ import annotations`.\n const recordRebuilds: string[] = [];\n for (const entName of entityNames) {\n const cls = className(entName);\n for (const action of ['Create', 'Update', 'Delete']) {\n recordRebuilds.push(`${cls}${action}Record.model_rebuild()`);\n }\n }\n\n // Registry consumed by `Instant(schema=schema)`.\n const entityMapLines = [' \"entities\": {'];\n for (const entName of entityNames) {\n entityMapLines.push(\n ` ${JSON.stringify(entName)}: ${className(entName)},`,\n );\n }\n entityMapLines.push(' },');\n const recordMapLines = [' \"records\": {'];\n for (const entName of entityNames) {\n const cls = className(entName);\n for (const action of ['create', 'update', 'delete']) {\n const capAction = action.charAt(0).toUpperCase() + action.slice(1);\n recordMapLines.push(\n ` (${JSON.stringify(entName)}, ${JSON.stringify(action)}): ${cls}${capAction}Record,`,\n );\n }\n }\n recordMapLines.push(' },');\n const schemaLiteral = [\n 'schema = {',\n ...entityMapLines,\n ...recordMapLines,\n '}',\n ].join('\\n');\n\n return [\n PY_HEADER + '\"\"\"Generated Pydantic models for Instant schema.\"\"\"',\n '',\n 'from __future__ import annotations',\n '',\n importBlock,\n '',\n '',\n classBlocks.join('\\n\\n\\n'),\n '',\n '',\n '# Resolve forward references introduced by `from __future__ import annotations`.',\n rebuilds.join('\\n'),\n '',\n '',\n webhookSection,\n '',\n '',\n '# Rebuild webhook records so `before` / `after` annotations resolve to entity classes.',\n recordRebuilds.join('\\n'),\n '',\n '',\n '# Registry consumed by `Instant(schema=schema)` for query-result + webhook validation.',\n schemaLiteral,\n '',\n ].join('\\n');\n}\n\n// ---------- webhook record / handler codegen ----------\n\nfunction buildWebhookSection(\n schema: SchemaLike,\n entityNames: string[],\n): string {\n // Schemas with zero entities would produce `WebhookRecord = ` (no RHS).\n if (entityNames.length === 0) return '';\n\n const recordClasses: string[] = [];\n const namespaceUnions: string[] = [];\n const namespaceHandlerDicts: string[] = [];\n\n // `before`/`after` shape varies by action.\n const RECORD_VARIANTS = [\n { action: 'create', before: 'None = None', afterTpl: (c: string) => c },\n { action: 'update', before: 'CLS', afterTpl: (c: string) => c },\n { action: 'delete', before: 'CLS', afterTpl: () => 'None = None' },\n ] as const;\n\n for (const entName of entityNames) {\n const cls = className(entName);\n for (const { action, before, afterTpl } of RECORD_VARIANTS) {\n const cap = action.charAt(0).toUpperCase() + action.slice(1);\n recordClasses.push(\n [\n `class ${cls}${cap}Record(BaseModel):`,\n ` model_config = ConfigDict(extra=\"ignore\")`,\n ` namespace: Literal[${JSON.stringify(entName)}] = ${JSON.stringify(entName)}`,\n ` id: str`,\n ` action: Literal[${JSON.stringify(action)}] = ${JSON.stringify(action)}`,\n ` before: ${before === 'CLS' ? cls : before}`,\n ` after: ${afterTpl(cls)}`,\n ` idempotencyKey: str`,\n ].join('\\n'),\n );\n }\n\n namespaceUnions.push(\n `${cls}Record = ${cls}CreateRecord | ${cls}UpdateRecord | ${cls}DeleteRecord`,\n );\n\n // Per-namespace handler TypedDict. Functional syntax so the `$default`\n // key is expressible.\n namespaceHandlerDicts.push(\n [\n `_${cls}Handlers = TypedDict(`,\n ` \"_${cls}Handlers\",`,\n ' {',\n ` \"create\": Callable[[${cls}CreateRecord], Any],`,\n ` \"update\": Callable[[${cls}UpdateRecord], Any],`,\n ` \"delete\": Callable[[${cls}DeleteRecord], Any],`,\n ` \"$default\": Callable[[${cls}Record], Any],`,\n ' },',\n ' total=False,',\n ')',\n ].join('\\n'),\n );\n }\n\n const rootUnionTerms = entityNames.map((n) => `${className(n)}Record`);\n const rootUnion = `WebhookRecord = ${rootUnionTerms.join(' | ')}`;\n\n const handlerDictLines = [\n 'WebhookHandlers = TypedDict(',\n ' \"WebhookHandlers\",',\n ' {',\n ];\n for (const entName of entityNames) {\n handlerDictLines.push(\n ` ${JSON.stringify(entName)}: _${className(entName)}Handlers,`,\n );\n }\n handlerDictLines.push(` \"$default\": Callable[[WebhookRecord], Any],`);\n handlerDictLines.push(' },', ' total=False,', ')');\n\n return [\n '# ---------- webhook record models ----------',\n '',\n recordClasses.join('\\n\\n\\n'),\n '',\n '',\n '# ---------- webhook handler types ----------',\n '',\n namespaceUnions.join('\\n'),\n '',\n rootUnion,\n '',\n '',\n namespaceHandlerDicts.join('\\n\\n\\n'),\n '',\n '',\n handlerDictLines.join('\\n'),\n ].join('\\n');\n}\n\n// ---------- tx builder .pyi stub ----------\n\nexport function buildTxStubPyi(schema: SchemaLike): string {\n const entityNames = Object.keys(schema.entities).sort();\n let usesDatetime = false;\n\n // Per-entity link fields (label + arg type for link/unlink TypedDict).\n const linkFieldsByEntity: Record<string, { label: string; type: string }[]> =\n {};\n for (const entName of entityNames) {\n linkFieldsByEntity[entName] = [];\n }\n for (const link of Object.values(schema.links)) {\n const fwdArgType = link.forward.has === 'one' ? 'str' : 'str | list[str]';\n const revArgType = link.reverse.has === 'one' ? 'str' : 'str | list[str]';\n if (linkFieldsByEntity[link.forward.on]) {\n linkFieldsByEntity[link.forward.on].push({\n label: link.forward.label,\n type: fwdArgType,\n });\n }\n if (linkFieldsByEntity[link.reverse.on]) {\n linkFieldsByEntity[link.reverse.on].push({\n label: link.reverse.label,\n type: revArgType,\n });\n }\n }\n for (const entName of entityNames) {\n linkFieldsByEntity[entName].sort((a, b) => a.label.localeCompare(b.label));\n }\n\n const perEntityBlocks: string[] = [];\n for (const entName of entityNames) {\n const cls = className(entName);\n\n const argsLines = [`class ${cls}Args(TypedDict, total=False):`];\n for (const [attrName, attrDef] of Object.entries(\n schema.entities[entName].attrs,\n )) {\n const t = mapValueType(attrDef.valueType);\n if (t === 'datetime') usesDatetime = true;\n argsLines.push(` ${attrName}: ${t}`);\n }\n if (argsLines.length === 1) argsLines.push(' pass');\n perEntityBlocks.push(argsLines.join('\\n'));\n\n const linkLines = [`class ${cls}Links(TypedDict, total=False):`];\n for (const link of linkFieldsByEntity[entName]) {\n linkLines.push(` ${link.label}: ${link.type}`);\n }\n if (linkLines.length === 1) linkLines.push(' pass');\n perEntityBlocks.push(linkLines.join('\\n'));\n\n perEntityBlocks.push(\n [\n `class _${cls}Chunk:`,\n ` def update(self, args: ${cls}Args) -> _${cls}Chunk: ...`,\n ` def create(self, args: ${cls}Args) -> _${cls}Chunk: ...`,\n ` def link(self, args: ${cls}Links) -> _${cls}Chunk: ...`,\n ` def unlink(self, args: ${cls}Links) -> _${cls}Chunk: ...`,\n ` def delete(self) -> _${cls}Chunk: ...`,\n ` def merge(self, args: ${cls}Args) -> _${cls}Chunk: ...`,\n ].join('\\n'),\n );\n }\n\n const builderBlock = [\n 'class _NamespaceBuilder(Generic[ChunkT]):',\n ' def __getitem__(self, eid: str) -> ChunkT: ...',\n ' def lookup(self, attr: str, value: Any) -> ChunkT: ...',\n ].join('\\n');\n\n // `$`-prefixed entities can't be reached via attribute syntax, so omit\n // them from `_TxBuilder` attrs. Subscript form (`db.tx[\"$users\"]`) still works.\n const identifierEntities = entityNames.filter((n) => !n.startsWith('$'));\n const txLines = ['class _TxBuilder:'];\n if (identifierEntities.length === 0) {\n txLines.push(' pass');\n } else {\n for (const entName of identifierEntities) {\n txLines.push(\n ` ${entName}: _NamespaceBuilder[_${className(entName)}Chunk]`,\n );\n }\n }\n\n const stdlibImports = ['from typing import Any, Generic, TypedDict, TypeVar'];\n if (usesDatetime) stdlibImports.unshift('from datetime import datetime');\n\n return [\n PY_HEADER +\n '\"\"\"Tx builder typing stub. Applied via `Instant(schema=...)`.\"\"\"',\n '',\n 'from __future__ import annotations',\n '',\n stdlibImports.join('\\n'),\n '',\n '',\n 'ChunkT = TypeVar(\"ChunkT\")',\n '',\n '',\n perEntityBlocks.join('\\n\\n\\n'),\n '',\n '',\n builderBlock,\n '',\n '',\n txLines.join('\\n'),\n '',\n ].join('\\n');\n}\n"]}
|
|
1
|
+
{"version":3,"file":"genpy.js","sourceRoot":"","sources":["../../src/commands/genpy.ts"],"names":[],"mappings":"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","sourcesContent":["import { FileSystem, Path } from '@effect/platform';\nimport chalk from 'chalk';\nimport { Effect, Schema } from 'effect';\nimport { readLocalSchemaFile } from '../old.js';\nimport {\n ReadSchemaFileError,\n SchemaValidationError,\n} from '../lib/pushSchema.ts';\n\nexport class GenpyWriteError extends Schema.TaggedError<GenpyWriteError>(\n 'GenpyWriteError',\n)('GenpyWriteError', {\n message: Schema.String,\n}) {}\n\nconst PY_HEADER = `# AUTOGENERATED by \\`instant-cli genpy\\`. DO NOT EDIT THIS FILE BY HAND.\n# Re-run \\`npx instant-cli genpy\\` after schema changes.\n`;\n\nexport const genpyCommand = ({ outDir }: { outDir?: string }) =>\n Effect.gen(function* () {\n const localSchemaFile = yield* Effect.tryPromise({\n try: readLocalSchemaFile,\n catch: (e) =>\n e instanceof Error\n ? ReadSchemaFileError.make({ message: e.message })\n : ReadSchemaFileError.make({ message: String(e) }),\n });\n if (!localSchemaFile || !localSchemaFile.schema) {\n return yield* ReadSchemaFileError.make({\n message: `We couldn't find your ${chalk.yellow('`instant.schema.ts`')} file. Make sure it's in the project root or under \\`src/\\`. (Hint: set INSTANT_SCHEMA_FILE_PATH to override.)`,\n });\n }\n if (localSchemaFile.schema.constructor?.name !== 'InstantSchemaDef') {\n return yield* SchemaValidationError.make({\n message: `We couldn't find your schema export.\\nIn your ${chalk.yellow('`instant.schema.ts`')} file, make sure you ${chalk.green('`export default schema`')}`,\n });\n }\n\n const path = yield* Path.Path;\n const fs = yield* FileSystem.FileSystem;\n // Default: write alongside the schema file. `--out-dir` overrides for\n // monorepos where Python lives elsewhere, or for our own sandbox where\n // the schema is shared with the JS CLI tests.\n const targetDir = outDir\n ? path.resolve(outDir)\n : path.dirname(localSchemaFile.path);\n yield* fs.makeDirectory(targetDir, { recursive: true }).pipe(\n Effect.mapError((e) =>\n GenpyWriteError.make({\n message: `Failed to create ${targetDir}: ${e}`,\n }),\n ),\n );\n const pyPath = path.join(targetDir, 'instant_types.py');\n const pyiPath = path.join(targetDir, 'instant_types.pyi');\n\n const pyContent = buildEntityModelsPy(localSchemaFile.schema);\n const pyiContent = buildTxStubPyi(localSchemaFile.schema);\n yield* fs\n .writeFileString(pyPath, pyContent)\n .pipe(\n Effect.mapError((e) =>\n GenpyWriteError.make({ message: `Failed to write ${pyPath}: ${e}` }),\n ),\n );\n yield* fs\n .writeFileString(pyiPath, pyiContent)\n .pipe(\n Effect.mapError((e) =>\n GenpyWriteError.make({ message: `Failed to write ${pyiPath}: ${e}` }),\n ),\n );\n\n yield* Effect.log(`✅ Wrote ${pyPath} and ${pyiPath}`);\n });\n\n// ---------- entity model codegen ----------\n\ntype SchemaLike = {\n entities: Record<string, EntityDefLike>;\n links: Record<string, LinkDefLike>;\n};\n\ntype EntityDefLike = {\n attrs: Record<string, DataAttrDefLike>;\n};\n\ntype DataAttrDefLike = {\n valueType: 'string' | 'number' | 'boolean' | 'date' | 'json';\n required: boolean;\n};\n\ntype LinkDefLike = {\n forward: { on: string; label: string; has: 'one' | 'many' };\n reverse: { on: string; label: string; has: 'one' | 'many' };\n};\n\ntype Field = {\n name: string;\n type: string;\n hasDefault: boolean;\n // Original schema key when `name` had to be sanitized; drives the\n // emitted `Field(alias=rawKey)` so runtime validation still matches.\n rawKey?: string;\n};\n\nconst PY_KEYWORDS = new Set([\n 'False', 'None', 'True', 'and', 'as', 'assert', 'async', 'await',\n 'break', 'class', 'continue', 'def', 'del', 'elif', 'else', 'except',\n 'finally', 'for', 'from', 'global', 'if', 'import', 'in', 'is',\n 'lambda', 'nonlocal', 'not', 'or', 'pass', 'raise', 'return', 'try',\n 'while', 'with', 'yield', 'match', 'case',\n]);\n\nfunction isPyIdent(name: string): boolean {\n return /^[A-Za-z_][A-Za-z0-9_]*$/.test(name) && !PY_KEYWORDS.has(name);\n}\n\nfunction safePyIdent(name: string): string {\n if (isPyIdent(name)) return name;\n let safe = name.replace(/[^A-Za-z0-9_]+/g, '_').replace(/_+/g, '_');\n if (safe === '' || /^[0-9]/.test(safe)) safe = '_' + safe;\n if (PY_KEYWORDS.has(safe)) safe += '_';\n return safe;\n}\n\nfunction className(entName: string): string {\n // Strip a leading `$` (system entities like `$users`, `$files`), then\n // PascalCase across word separators (`-`, `_`, whitespace) so non-identifier\n // characters in entity names don't produce invalid Python class names.\n const stripped = entName.startsWith('$') ? entName.slice(1) : entName;\n return stripped\n .split(/[-_\\s]+/)\n .filter(Boolean)\n .map((part) => part.charAt(0).toUpperCase() + part.slice(1))\n .join('');\n}\n\nfunction mapValueType(vt: DataAttrDefLike['valueType']): string {\n switch (vt) {\n case 'string':\n return 'str';\n case 'number':\n return 'float';\n case 'boolean':\n return 'bool';\n case 'date':\n return 'datetime';\n case 'json':\n return 'Any';\n default:\n // Defensive: if a new valueType ever lands in the schema without a\n // genpy update, fall back to Any so generated code stays valid Python.\n return 'Any';\n }\n}\n\nexport function buildEntityModelsPy(schema: SchemaLike): string {\n const entityNames = Object.keys(schema.entities).sort();\n const fieldsByEntity: Record<string, Field[]> = {};\n const linkFieldsByEntity: Record<string, Field[]> = {};\n let usesDatetime = false;\n\n for (const entName of entityNames) {\n fieldsByEntity[entName] = [{ name: 'id', type: 'str', hasDefault: false }];\n linkFieldsByEntity[entName] = [];\n for (const [attrName, attrDef] of Object.entries(\n schema.entities[entName].attrs,\n )) {\n const baseType = mapValueType(attrDef.valueType);\n if (baseType === 'datetime') usesDatetime = true;\n const type = attrDef.required ? baseType : `${baseType} | None`;\n const safeName = safePyIdent(attrName);\n fieldsByEntity[entName].push({\n name: safeName,\n type,\n hasDefault: !attrDef.required,\n rawKey: safeName === attrName ? undefined : attrName,\n });\n }\n }\n\n for (const link of Object.values(schema.links)) {\n const fwd = link.forward;\n const rev = link.reverse;\n if (linkFieldsByEntity[fwd.on]) {\n const safeName = safePyIdent(fwd.label);\n linkFieldsByEntity[fwd.on].push({\n name: safeName,\n type:\n fwd.has === 'one'\n ? `${className(rev.on)} | None`\n : `list[${className(rev.on)}] | None`,\n hasDefault: true,\n rawKey: safeName === fwd.label ? undefined : fwd.label,\n });\n }\n if (linkFieldsByEntity[rev.on]) {\n const safeName = safePyIdent(rev.label);\n linkFieldsByEntity[rev.on].push({\n name: safeName,\n type:\n rev.has === 'one'\n ? `${className(fwd.on)} | None`\n : `list[${className(fwd.on)}] | None`,\n hasDefault: true,\n rawKey: safeName === rev.label ? undefined : rev.label,\n });\n }\n }\n\n // Sort link fields alphabetically for stable output across schema rewrites.\n for (const entName of entityNames) {\n linkFieldsByEntity[entName].sort((a, b) => a.name.localeCompare(b.name));\n }\n\n let usesField = false;\n const classBlocks = entityNames.map((entName) => {\n const allFields = [\n ...fieldsByEntity[entName],\n ...linkFieldsByEntity[entName],\n ];\n const hasAlias = allFields.some((f) => f.rawKey !== undefined);\n const config = hasAlias\n ? 'ConfigDict(extra=\"ignore\", populate_by_name=True)'\n : 'ConfigDict(extra=\"ignore\")';\n const lines = [\n `class ${className(entName)}(BaseModel):`,\n ` model_config = ${config}`,\n ];\n for (const f of allFields) {\n let decl: string;\n if (f.rawKey !== undefined) {\n usesField = true;\n const args = f.hasDefault\n ? `default=None, alias=${JSON.stringify(f.rawKey)}`\n : `alias=${JSON.stringify(f.rawKey)}`;\n decl = ` ${f.name}: ${f.type} = Field(${args})`;\n } else if (f.hasDefault) {\n decl = ` ${f.name}: ${f.type} = None`;\n } else {\n decl = ` ${f.name}: ${f.type}`;\n }\n lines.push(decl);\n }\n return lines.join('\\n');\n });\n\n const rebuilds = entityNames.map(\n (entName) => `${className(entName)}.model_rebuild()`,\n );\n\n // Webhook record / handler types live in the same .py so users get one\n // import point (`from instant_types import ...`) for both query results\n // and webhook handler type-checking.\n const webhookSection = buildWebhookSection(schema, entityNames);\n\n const typingImports = ['Any', 'Callable', 'Literal', 'TypedDict'];\n\n const stdlibImports: string[] = [];\n if (usesDatetime) stdlibImports.push('from datetime import datetime');\n stdlibImports.push(`from typing import ${typingImports.join(', ')}`);\n const pydanticImports = usesField\n ? 'BaseModel, ConfigDict, Field'\n : 'BaseModel, ConfigDict';\n const importBlock =\n stdlibImports.join('\\n') +\n '\\n\\n' +\n `from pydantic import ${pydanticImports}`;\n\n // Add record-model rebuilds so forward-string annotations to entity\n // types resolve under `from __future__ import annotations`.\n const recordRebuilds: string[] = [];\n for (const entName of entityNames) {\n const cls = className(entName);\n for (const action of ['Create', 'Update', 'Delete']) {\n recordRebuilds.push(`${cls}${action}Record.model_rebuild()`);\n }\n }\n\n // Registry consumed by `Instant(schema=schema)`.\n const entityMapLines = [' \"entities\": {'];\n for (const entName of entityNames) {\n entityMapLines.push(\n ` ${JSON.stringify(entName)}: ${className(entName)},`,\n );\n }\n entityMapLines.push(' },');\n const recordMapLines = [' \"records\": {'];\n for (const entName of entityNames) {\n const cls = className(entName);\n for (const action of ['create', 'update', 'delete']) {\n const capAction = action.charAt(0).toUpperCase() + action.slice(1);\n recordMapLines.push(\n ` (${JSON.stringify(entName)}, ${JSON.stringify(action)}): ${cls}${capAction}Record,`,\n );\n }\n }\n recordMapLines.push(' },');\n const schemaLiteral = [\n 'schema = {',\n ...entityMapLines,\n ...recordMapLines,\n '}',\n ].join('\\n');\n\n return [\n PY_HEADER + '\"\"\"Generated Pydantic models for Instant schema.\"\"\"',\n '',\n 'from __future__ import annotations',\n '',\n importBlock,\n '',\n '',\n classBlocks.join('\\n\\n\\n'),\n '',\n '',\n '# Resolve forward references introduced by `from __future__ import annotations`.',\n rebuilds.join('\\n'),\n '',\n '',\n webhookSection,\n '',\n '',\n '# Rebuild webhook records so `before` / `after` annotations resolve to entity classes.',\n recordRebuilds.join('\\n'),\n '',\n '',\n '# Registry consumed by `Instant(schema=schema)` for query-result + webhook validation.',\n schemaLiteral,\n '',\n ].join('\\n');\n}\n\n// ---------- webhook record / handler codegen ----------\n\nfunction buildWebhookSection(\n schema: SchemaLike,\n entityNames: string[],\n): string {\n // Schemas with zero entities would produce `WebhookRecord = ` (no RHS).\n if (entityNames.length === 0) return '';\n\n const recordClasses: string[] = [];\n const namespaceUnions: string[] = [];\n const namespaceHandlerDicts: string[] = [];\n\n // `before`/`after` shape varies by action.\n const RECORD_VARIANTS = [\n { action: 'create', before: 'None = None', afterTpl: (c: string) => c },\n { action: 'update', before: 'CLS', afterTpl: (c: string) => c },\n { action: 'delete', before: 'CLS', afterTpl: () => 'None = None' },\n ] as const;\n\n for (const entName of entityNames) {\n const cls = className(entName);\n for (const { action, before, afterTpl } of RECORD_VARIANTS) {\n const cap = action.charAt(0).toUpperCase() + action.slice(1);\n recordClasses.push(\n [\n `class ${cls}${cap}Record(BaseModel):`,\n ` model_config = ConfigDict(extra=\"ignore\")`,\n ` namespace: Literal[${JSON.stringify(entName)}] = ${JSON.stringify(entName)}`,\n ` id: str`,\n ` action: Literal[${JSON.stringify(action)}] = ${JSON.stringify(action)}`,\n ` before: ${before === 'CLS' ? cls : before}`,\n ` after: ${afterTpl(cls)}`,\n ` idempotencyKey: str`,\n ].join('\\n'),\n );\n }\n\n namespaceUnions.push(\n `${cls}Record = ${cls}CreateRecord | ${cls}UpdateRecord | ${cls}DeleteRecord`,\n );\n\n // Per-namespace handler TypedDict. Functional syntax so the `$default`\n // key is expressible.\n namespaceHandlerDicts.push(\n [\n `_${cls}Handlers = TypedDict(`,\n ` \"_${cls}Handlers\",`,\n ' {',\n ` \"create\": Callable[[${cls}CreateRecord], Any],`,\n ` \"update\": Callable[[${cls}UpdateRecord], Any],`,\n ` \"delete\": Callable[[${cls}DeleteRecord], Any],`,\n ` \"$default\": Callable[[${cls}Record], Any],`,\n ' },',\n ' total=False,',\n ')',\n ].join('\\n'),\n );\n }\n\n const rootUnionTerms = entityNames.map((n) => `${className(n)}Record`);\n const rootUnion = `WebhookRecord = ${rootUnionTerms.join(' | ')}`;\n\n const handlerDictLines = [\n 'WebhookHandlers = TypedDict(',\n ' \"WebhookHandlers\",',\n ' {',\n ];\n for (const entName of entityNames) {\n handlerDictLines.push(\n ` ${JSON.stringify(entName)}: _${className(entName)}Handlers,`,\n );\n }\n handlerDictLines.push(` \"$default\": Callable[[WebhookRecord], Any],`);\n handlerDictLines.push(' },', ' total=False,', ')');\n\n return [\n '# ---------- webhook record models ----------',\n '',\n recordClasses.join('\\n\\n\\n'),\n '',\n '',\n '# ---------- webhook handler types ----------',\n '',\n namespaceUnions.join('\\n'),\n '',\n rootUnion,\n '',\n '',\n namespaceHandlerDicts.join('\\n\\n\\n'),\n '',\n '',\n handlerDictLines.join('\\n'),\n ].join('\\n');\n}\n\n// ---------- tx builder .pyi stub ----------\n\nexport function buildTxStubPyi(schema: SchemaLike): string {\n const entityNames = Object.keys(schema.entities).sort();\n let usesDatetime = false;\n\n // Per-entity link fields (label + arg type for link/unlink TypedDict).\n const linkFieldsByEntity: Record<string, { label: string; type: string }[]> =\n {};\n for (const entName of entityNames) {\n linkFieldsByEntity[entName] = [];\n }\n for (const link of Object.values(schema.links)) {\n const fwdArgType = link.forward.has === 'one' ? 'str' : 'str | list[str]';\n const revArgType = link.reverse.has === 'one' ? 'str' : 'str | list[str]';\n if (linkFieldsByEntity[link.forward.on]) {\n linkFieldsByEntity[link.forward.on].push({\n label: link.forward.label,\n type: fwdArgType,\n });\n }\n if (linkFieldsByEntity[link.reverse.on]) {\n linkFieldsByEntity[link.reverse.on].push({\n label: link.reverse.label,\n type: revArgType,\n });\n }\n }\n for (const entName of entityNames) {\n linkFieldsByEntity[entName].sort((a, b) => a.label.localeCompare(b.label));\n }\n\n // Class-syntax TypedDict requires identifier keys; switch to the\n // functional form when any key on a given dict is irregular.\n const buildTypedDict = (\n name: string,\n fields: { key: string; type: string }[],\n ): string => {\n const allIdent = fields.every((f) => isPyIdent(f.key));\n if (allIdent) {\n const lines = [`class ${name}(TypedDict, total=False):`];\n for (const f of fields) lines.push(` ${f.key}: ${f.type}`);\n if (fields.length === 0) lines.push(' pass');\n return lines.join('\\n');\n }\n const lines = [`${name} = TypedDict(`, ` ${JSON.stringify(name)},`, ' {'];\n for (const f of fields) {\n lines.push(` ${JSON.stringify(f.key)}: ${f.type},`);\n }\n lines.push(' },', ' total=False,', ')');\n return lines.join('\\n');\n };\n\n const perEntityBlocks: string[] = [];\n for (const entName of entityNames) {\n const cls = className(entName);\n\n const argFields: { key: string; type: string }[] = [];\n for (const [attrName, attrDef] of Object.entries(\n schema.entities[entName].attrs,\n )) {\n const t = mapValueType(attrDef.valueType);\n if (t === 'datetime') usesDatetime = true;\n argFields.push({ key: attrName, type: t });\n }\n perEntityBlocks.push(buildTypedDict(`${cls}Args`, argFields));\n\n const linkFields = linkFieldsByEntity[entName].map((l) => ({\n key: l.label,\n type: l.type,\n }));\n perEntityBlocks.push(buildTypedDict(`${cls}Links`, linkFields));\n\n perEntityBlocks.push(\n [\n `class _${cls}Chunk:`,\n ` def update(self, args: ${cls}Args) -> _${cls}Chunk: ...`,\n ` def create(self, args: ${cls}Args) -> _${cls}Chunk: ...`,\n ` def link(self, args: ${cls}Links) -> _${cls}Chunk: ...`,\n ` def unlink(self, args: ${cls}Links) -> _${cls}Chunk: ...`,\n ` def delete(self) -> _${cls}Chunk: ...`,\n ` def merge(self, args: ${cls}Args) -> _${cls}Chunk: ...`,\n ].join('\\n'),\n );\n }\n\n const builderBlock = [\n 'class _NamespaceBuilder(Generic[ChunkT]):',\n ' def __getitem__(self, eid: str) -> ChunkT: ...',\n ' def lookup(self, attr: str, value: Any) -> ChunkT: ...',\n ].join('\\n');\n\n // Only valid Python identifiers can appear as `_TxBuilder` attrs (for\n // `db.tx.<name>` autocomplete); irregular names use `db.tx[\"...\"]`.\n const identifierEntities = entityNames.filter(isPyIdent);\n const txLines = ['class _TxBuilder:'];\n if (identifierEntities.length === 0) {\n txLines.push(' pass');\n } else {\n for (const entName of identifierEntities) {\n txLines.push(\n ` ${entName}: _NamespaceBuilder[_${className(entName)}Chunk]`,\n );\n }\n }\n\n const stdlibImports = ['from typing import Any, Generic, TypedDict, TypeVar'];\n if (usesDatetime) stdlibImports.unshift('from datetime import datetime');\n\n return [\n PY_HEADER +\n '\"\"\"Tx builder typing stub. Applied via `Instant(schema=...)`.\"\"\"',\n '',\n 'from __future__ import annotations',\n '',\n stdlibImports.join('\\n'),\n '',\n '',\n 'ChunkT = TypeVar(\"ChunkT\")',\n '',\n '',\n perEntityBlocks.join('\\n\\n\\n'),\n '',\n '',\n builderBlock,\n '',\n '',\n txLines.join('\\n'),\n '',\n ].join('\\n');\n}\n"]}
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "instant-cli",
|
|
3
3
|
"type": "module",
|
|
4
|
-
"version": "1.0.40-branch-python-sdk-v1.
|
|
4
|
+
"version": "1.0.40-branch-python-sdk-v1.26525151443.1",
|
|
5
5
|
"description": "Instant's CLI",
|
|
6
6
|
"license": "Apache-2.0",
|
|
7
7
|
"homepage": "https://github.com/instantdb/instant/tree/main/client/packages/cli",
|
|
@@ -50,9 +50,9 @@
|
|
|
50
50
|
"strip-ansi": "^7.1.2",
|
|
51
51
|
"supports-hyperlinks": "^4.4.0",
|
|
52
52
|
"unconfig": "^7.5.0",
|
|
53
|
-
"@instantdb/core": "1.0.40-branch-python-sdk-v1.
|
|
54
|
-
"@instantdb/platform": "1.0.40-branch-python-sdk-v1.
|
|
55
|
-
"@instantdb/version": "1.0.40-branch-python-sdk-v1.
|
|
53
|
+
"@instantdb/core": "1.0.40-branch-python-sdk-v1.26525151443.1",
|
|
54
|
+
"@instantdb/platform": "1.0.40-branch-python-sdk-v1.26525151443.1",
|
|
55
|
+
"@instantdb/version": "1.0.40-branch-python-sdk-v1.26525151443.1"
|
|
56
56
|
},
|
|
57
57
|
"devDependencies": {
|
|
58
58
|
"@babel/core": "^7.17.9",
|
package/src/commands/genpy.ts
CHANGED
|
@@ -45,15 +45,13 @@ export const genpyCommand = ({ outDir }: { outDir?: string }) =>
|
|
|
45
45
|
const targetDir = outDir
|
|
46
46
|
? path.resolve(outDir)
|
|
47
47
|
: path.dirname(localSchemaFile.path);
|
|
48
|
-
yield* fs
|
|
49
|
-
.
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
),
|
|
56
|
-
);
|
|
48
|
+
yield* fs.makeDirectory(targetDir, { recursive: true }).pipe(
|
|
49
|
+
Effect.mapError((e) =>
|
|
50
|
+
GenpyWriteError.make({
|
|
51
|
+
message: `Failed to create ${targetDir}: ${e}`,
|
|
52
|
+
}),
|
|
53
|
+
),
|
|
54
|
+
);
|
|
57
55
|
const pyPath = path.join(targetDir, 'instant_types.py');
|
|
58
56
|
const pyiPath = path.join(targetDir, 'instant_types.pyi');
|
|
59
57
|
|
|
@@ -98,7 +96,34 @@ type LinkDefLike = {
|
|
|
98
96
|
reverse: { on: string; label: string; has: 'one' | 'many' };
|
|
99
97
|
};
|
|
100
98
|
|
|
101
|
-
type Field = {
|
|
99
|
+
type Field = {
|
|
100
|
+
name: string;
|
|
101
|
+
type: string;
|
|
102
|
+
hasDefault: boolean;
|
|
103
|
+
// Original schema key when `name` had to be sanitized; drives the
|
|
104
|
+
// emitted `Field(alias=rawKey)` so runtime validation still matches.
|
|
105
|
+
rawKey?: string;
|
|
106
|
+
};
|
|
107
|
+
|
|
108
|
+
const PY_KEYWORDS = new Set([
|
|
109
|
+
'False', 'None', 'True', 'and', 'as', 'assert', 'async', 'await',
|
|
110
|
+
'break', 'class', 'continue', 'def', 'del', 'elif', 'else', 'except',
|
|
111
|
+
'finally', 'for', 'from', 'global', 'if', 'import', 'in', 'is',
|
|
112
|
+
'lambda', 'nonlocal', 'not', 'or', 'pass', 'raise', 'return', 'try',
|
|
113
|
+
'while', 'with', 'yield', 'match', 'case',
|
|
114
|
+
]);
|
|
115
|
+
|
|
116
|
+
function isPyIdent(name: string): boolean {
|
|
117
|
+
return /^[A-Za-z_][A-Za-z0-9_]*$/.test(name) && !PY_KEYWORDS.has(name);
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
function safePyIdent(name: string): string {
|
|
121
|
+
if (isPyIdent(name)) return name;
|
|
122
|
+
let safe = name.replace(/[^A-Za-z0-9_]+/g, '_').replace(/_+/g, '_');
|
|
123
|
+
if (safe === '' || /^[0-9]/.test(safe)) safe = '_' + safe;
|
|
124
|
+
if (PY_KEYWORDS.has(safe)) safe += '_';
|
|
125
|
+
return safe;
|
|
126
|
+
}
|
|
102
127
|
|
|
103
128
|
function className(entName: string): string {
|
|
104
129
|
// Strip a leading `$` (system entities like `$users`, `$files`), then
|
|
@@ -146,10 +171,12 @@ export function buildEntityModelsPy(schema: SchemaLike): string {
|
|
|
146
171
|
const baseType = mapValueType(attrDef.valueType);
|
|
147
172
|
if (baseType === 'datetime') usesDatetime = true;
|
|
148
173
|
const type = attrDef.required ? baseType : `${baseType} | None`;
|
|
174
|
+
const safeName = safePyIdent(attrName);
|
|
149
175
|
fieldsByEntity[entName].push({
|
|
150
|
-
name:
|
|
176
|
+
name: safeName,
|
|
151
177
|
type,
|
|
152
178
|
hasDefault: !attrDef.required,
|
|
179
|
+
rawKey: safeName === attrName ? undefined : attrName,
|
|
153
180
|
});
|
|
154
181
|
}
|
|
155
182
|
}
|
|
@@ -158,23 +185,27 @@ export function buildEntityModelsPy(schema: SchemaLike): string {
|
|
|
158
185
|
const fwd = link.forward;
|
|
159
186
|
const rev = link.reverse;
|
|
160
187
|
if (linkFieldsByEntity[fwd.on]) {
|
|
188
|
+
const safeName = safePyIdent(fwd.label);
|
|
161
189
|
linkFieldsByEntity[fwd.on].push({
|
|
162
|
-
name:
|
|
190
|
+
name: safeName,
|
|
163
191
|
type:
|
|
164
192
|
fwd.has === 'one'
|
|
165
193
|
? `${className(rev.on)} | None`
|
|
166
194
|
: `list[${className(rev.on)}] | None`,
|
|
167
195
|
hasDefault: true,
|
|
196
|
+
rawKey: safeName === fwd.label ? undefined : fwd.label,
|
|
168
197
|
});
|
|
169
198
|
}
|
|
170
199
|
if (linkFieldsByEntity[rev.on]) {
|
|
200
|
+
const safeName = safePyIdent(rev.label);
|
|
171
201
|
linkFieldsByEntity[rev.on].push({
|
|
172
|
-
name:
|
|
202
|
+
name: safeName,
|
|
173
203
|
type:
|
|
174
204
|
rev.has === 'one'
|
|
175
205
|
? `${className(fwd.on)} | None`
|
|
176
206
|
: `list[${className(fwd.on)}] | None`,
|
|
177
207
|
hasDefault: true,
|
|
208
|
+
rawKey: safeName === rev.label ? undefined : rev.label,
|
|
178
209
|
});
|
|
179
210
|
}
|
|
180
211
|
}
|
|
@@ -184,18 +215,33 @@ export function buildEntityModelsPy(schema: SchemaLike): string {
|
|
|
184
215
|
linkFieldsByEntity[entName].sort((a, b) => a.name.localeCompare(b.name));
|
|
185
216
|
}
|
|
186
217
|
|
|
218
|
+
let usesField = false;
|
|
187
219
|
const classBlocks = entityNames.map((entName) => {
|
|
220
|
+
const allFields = [
|
|
221
|
+
...fieldsByEntity[entName],
|
|
222
|
+
...linkFieldsByEntity[entName],
|
|
223
|
+
];
|
|
224
|
+
const hasAlias = allFields.some((f) => f.rawKey !== undefined);
|
|
225
|
+
const config = hasAlias
|
|
226
|
+
? 'ConfigDict(extra="ignore", populate_by_name=True)'
|
|
227
|
+
: 'ConfigDict(extra="ignore")';
|
|
188
228
|
const lines = [
|
|
189
229
|
`class ${className(entName)}(BaseModel):`,
|
|
190
|
-
` model_config =
|
|
230
|
+
` model_config = ${config}`,
|
|
191
231
|
];
|
|
192
|
-
for (const f of
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
232
|
+
for (const f of allFields) {
|
|
233
|
+
let decl: string;
|
|
234
|
+
if (f.rawKey !== undefined) {
|
|
235
|
+
usesField = true;
|
|
236
|
+
const args = f.hasDefault
|
|
237
|
+
? `default=None, alias=${JSON.stringify(f.rawKey)}`
|
|
238
|
+
: `alias=${JSON.stringify(f.rawKey)}`;
|
|
239
|
+
decl = ` ${f.name}: ${f.type} = Field(${args})`;
|
|
240
|
+
} else if (f.hasDefault) {
|
|
241
|
+
decl = ` ${f.name}: ${f.type} = None`;
|
|
242
|
+
} else {
|
|
243
|
+
decl = ` ${f.name}: ${f.type}`;
|
|
244
|
+
}
|
|
199
245
|
lines.push(decl);
|
|
200
246
|
}
|
|
201
247
|
return lines.join('\n');
|
|
@@ -215,10 +261,13 @@ export function buildEntityModelsPy(schema: SchemaLike): string {
|
|
|
215
261
|
const stdlibImports: string[] = [];
|
|
216
262
|
if (usesDatetime) stdlibImports.push('from datetime import datetime');
|
|
217
263
|
stdlibImports.push(`from typing import ${typingImports.join(', ')}`);
|
|
264
|
+
const pydanticImports = usesField
|
|
265
|
+
? 'BaseModel, ConfigDict, Field'
|
|
266
|
+
: 'BaseModel, ConfigDict';
|
|
218
267
|
const importBlock =
|
|
219
268
|
stdlibImports.join('\n') +
|
|
220
269
|
'\n\n' +
|
|
221
|
-
|
|
270
|
+
`from pydantic import ${pydanticImports}`;
|
|
222
271
|
|
|
223
272
|
// Add record-model rebuilds so forward-string annotations to entity
|
|
224
273
|
// types resolve under `from __future__ import annotations`.
|
|
@@ -412,27 +461,46 @@ export function buildTxStubPyi(schema: SchemaLike): string {
|
|
|
412
461
|
linkFieldsByEntity[entName].sort((a, b) => a.label.localeCompare(b.label));
|
|
413
462
|
}
|
|
414
463
|
|
|
464
|
+
// Class-syntax TypedDict requires identifier keys; switch to the
|
|
465
|
+
// functional form when any key on a given dict is irregular.
|
|
466
|
+
const buildTypedDict = (
|
|
467
|
+
name: string,
|
|
468
|
+
fields: { key: string; type: string }[],
|
|
469
|
+
): string => {
|
|
470
|
+
const allIdent = fields.every((f) => isPyIdent(f.key));
|
|
471
|
+
if (allIdent) {
|
|
472
|
+
const lines = [`class ${name}(TypedDict, total=False):`];
|
|
473
|
+
for (const f of fields) lines.push(` ${f.key}: ${f.type}`);
|
|
474
|
+
if (fields.length === 0) lines.push(' pass');
|
|
475
|
+
return lines.join('\n');
|
|
476
|
+
}
|
|
477
|
+
const lines = [`${name} = TypedDict(`, ` ${JSON.stringify(name)},`, ' {'];
|
|
478
|
+
for (const f of fields) {
|
|
479
|
+
lines.push(` ${JSON.stringify(f.key)}: ${f.type},`);
|
|
480
|
+
}
|
|
481
|
+
lines.push(' },', ' total=False,', ')');
|
|
482
|
+
return lines.join('\n');
|
|
483
|
+
};
|
|
484
|
+
|
|
415
485
|
const perEntityBlocks: string[] = [];
|
|
416
486
|
for (const entName of entityNames) {
|
|
417
487
|
const cls = className(entName);
|
|
418
488
|
|
|
419
|
-
const
|
|
489
|
+
const argFields: { key: string; type: string }[] = [];
|
|
420
490
|
for (const [attrName, attrDef] of Object.entries(
|
|
421
491
|
schema.entities[entName].attrs,
|
|
422
492
|
)) {
|
|
423
493
|
const t = mapValueType(attrDef.valueType);
|
|
424
494
|
if (t === 'datetime') usesDatetime = true;
|
|
425
|
-
|
|
495
|
+
argFields.push({ key: attrName, type: t });
|
|
426
496
|
}
|
|
427
|
-
|
|
428
|
-
perEntityBlocks.push(argsLines.join('\n'));
|
|
497
|
+
perEntityBlocks.push(buildTypedDict(`${cls}Args`, argFields));
|
|
429
498
|
|
|
430
|
-
const
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
}
|
|
434
|
-
|
|
435
|
-
perEntityBlocks.push(linkLines.join('\n'));
|
|
499
|
+
const linkFields = linkFieldsByEntity[entName].map((l) => ({
|
|
500
|
+
key: l.label,
|
|
501
|
+
type: l.type,
|
|
502
|
+
}));
|
|
503
|
+
perEntityBlocks.push(buildTypedDict(`${cls}Links`, linkFields));
|
|
436
504
|
|
|
437
505
|
perEntityBlocks.push(
|
|
438
506
|
[
|
|
@@ -453,9 +521,9 @@ export function buildTxStubPyi(schema: SchemaLike): string {
|
|
|
453
521
|
' def lookup(self, attr: str, value: Any) -> ChunkT: ...',
|
|
454
522
|
].join('\n');
|
|
455
523
|
|
|
456
|
-
//
|
|
457
|
-
//
|
|
458
|
-
const identifierEntities = entityNames.filter(
|
|
524
|
+
// Only valid Python identifiers can appear as `_TxBuilder` attrs (for
|
|
525
|
+
// `db.tx.<name>` autocomplete); irregular names use `db.tx["..."]`.
|
|
526
|
+
const identifierEntities = entityNames.filter(isPyIdent);
|
|
459
527
|
const txLines = ['class _TxBuilder:'];
|
|
460
528
|
if (identifierEntities.length === 0) {
|
|
461
529
|
txLines.push(' pass');
|