instant-cli 1.0.40-branch-python-sdk-v1.26483086955.1 → 1.0.40-branch-python-sdk-v1.26525895103.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 +126 -27
- package/dist/commands/genpy.js.map +1 -1
- package/package.json +4 -4
- package/src/commands/genpy.ts +134 -26
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.26525895103.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,+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;
|
|
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;AAgGF,wBAAgB,mBAAmB,CAAC,MAAM,EAAE,UAAU,GAAG,MAAM,CA+K9D;AAoGD,wBAAgB,cAAc,CAAC,MAAM,EAAE,UAAU,GAAG,MAAM,CAoIzD"}
|
package/dist/commands/genpy.js
CHANGED
|
@@ -50,6 +50,60 @@ export const genpyCommand = ({ outDir }) => Effect.gen(function* () {
|
|
|
50
50
|
.pipe(Effect.mapError((e) => GenpyWriteError.make({ message: `Failed to write ${pyiPath}: ${e}` })));
|
|
51
51
|
yield* Effect.log(`✅ Wrote ${pyPath} and ${pyiPath}`);
|
|
52
52
|
});
|
|
53
|
+
// In python-land we would do something like keyword.iskeyword(), to generate
|
|
54
|
+
// this list but because our gen-script is in ts-land we use an explicit set
|
|
55
|
+
// based on Python 3 keywords
|
|
56
|
+
// https://docs.python.org/3/reference/lexical_analysis.html#keywords
|
|
57
|
+
const PY_KEYWORDS = new Set([
|
|
58
|
+
'False',
|
|
59
|
+
'None',
|
|
60
|
+
'True',
|
|
61
|
+
'and',
|
|
62
|
+
'as',
|
|
63
|
+
'assert',
|
|
64
|
+
'async',
|
|
65
|
+
'await',
|
|
66
|
+
'break',
|
|
67
|
+
'class',
|
|
68
|
+
'continue',
|
|
69
|
+
'def',
|
|
70
|
+
'del',
|
|
71
|
+
'elif',
|
|
72
|
+
'else',
|
|
73
|
+
'except',
|
|
74
|
+
'finally',
|
|
75
|
+
'for',
|
|
76
|
+
'from',
|
|
77
|
+
'global',
|
|
78
|
+
'if',
|
|
79
|
+
'import',
|
|
80
|
+
'in',
|
|
81
|
+
'is',
|
|
82
|
+
'lambda',
|
|
83
|
+
'nonlocal',
|
|
84
|
+
'not',
|
|
85
|
+
'or',
|
|
86
|
+
'pass',
|
|
87
|
+
'raise',
|
|
88
|
+
'return',
|
|
89
|
+
'try',
|
|
90
|
+
'while',
|
|
91
|
+
'with',
|
|
92
|
+
'yield',
|
|
93
|
+
]);
|
|
94
|
+
function isPyIdent(name) {
|
|
95
|
+
return /^[A-Za-z_][A-Za-z0-9_]*$/.test(name) && !PY_KEYWORDS.has(name);
|
|
96
|
+
}
|
|
97
|
+
function safePyIdent(name) {
|
|
98
|
+
if (isPyIdent(name))
|
|
99
|
+
return name;
|
|
100
|
+
let safe = name.replace(/[^A-Za-z0-9_]+/g, '_').replace(/_+/g, '_');
|
|
101
|
+
if (safe === '' || /^[0-9]/.test(safe))
|
|
102
|
+
safe = '_' + safe;
|
|
103
|
+
if (PY_KEYWORDS.has(safe))
|
|
104
|
+
safe += '_';
|
|
105
|
+
return safe;
|
|
106
|
+
}
|
|
53
107
|
function className(entName) {
|
|
54
108
|
// Strip a leading `$` (system entities like `$users`, `$files`), then
|
|
55
109
|
// PascalCase across word separators (`-`, `_`, whitespace) so non-identifier
|
|
@@ -92,10 +146,12 @@ export function buildEntityModelsPy(schema) {
|
|
|
92
146
|
if (baseType === 'datetime')
|
|
93
147
|
usesDatetime = true;
|
|
94
148
|
const type = attrDef.required ? baseType : `${baseType} | None`;
|
|
149
|
+
const safeName = safePyIdent(attrName);
|
|
95
150
|
fieldsByEntity[entName].push({
|
|
96
|
-
name:
|
|
151
|
+
name: safeName,
|
|
97
152
|
type,
|
|
98
153
|
hasDefault: !attrDef.required,
|
|
154
|
+
rawKey: safeName === attrName ? undefined : attrName,
|
|
99
155
|
});
|
|
100
156
|
}
|
|
101
157
|
}
|
|
@@ -103,21 +159,25 @@ export function buildEntityModelsPy(schema) {
|
|
|
103
159
|
const fwd = link.forward;
|
|
104
160
|
const rev = link.reverse;
|
|
105
161
|
if (linkFieldsByEntity[fwd.on]) {
|
|
162
|
+
const safeName = safePyIdent(fwd.label);
|
|
106
163
|
linkFieldsByEntity[fwd.on].push({
|
|
107
|
-
name:
|
|
164
|
+
name: safeName,
|
|
108
165
|
type: fwd.has === 'one'
|
|
109
166
|
? `${className(rev.on)} | None`
|
|
110
167
|
: `list[${className(rev.on)}] | None`,
|
|
111
168
|
hasDefault: true,
|
|
169
|
+
rawKey: safeName === fwd.label ? undefined : fwd.label,
|
|
112
170
|
});
|
|
113
171
|
}
|
|
114
172
|
if (linkFieldsByEntity[rev.on]) {
|
|
173
|
+
const safeName = safePyIdent(rev.label);
|
|
115
174
|
linkFieldsByEntity[rev.on].push({
|
|
116
|
-
name:
|
|
175
|
+
name: safeName,
|
|
117
176
|
type: rev.has === 'one'
|
|
118
177
|
? `${className(fwd.on)} | None`
|
|
119
178
|
: `list[${className(fwd.on)}] | None`,
|
|
120
179
|
hasDefault: true,
|
|
180
|
+
rawKey: safeName === rev.label ? undefined : rev.label,
|
|
121
181
|
});
|
|
122
182
|
}
|
|
123
183
|
}
|
|
@@ -125,18 +185,35 @@ export function buildEntityModelsPy(schema) {
|
|
|
125
185
|
for (const entName of entityNames) {
|
|
126
186
|
linkFieldsByEntity[entName].sort((a, b) => a.name.localeCompare(b.name));
|
|
127
187
|
}
|
|
188
|
+
let usesField = false;
|
|
128
189
|
const classBlocks = entityNames.map((entName) => {
|
|
190
|
+
const allFields = [
|
|
191
|
+
...fieldsByEntity[entName],
|
|
192
|
+
...linkFieldsByEntity[entName],
|
|
193
|
+
];
|
|
194
|
+
const hasAlias = allFields.some((f) => f.rawKey !== undefined);
|
|
195
|
+
const config = hasAlias
|
|
196
|
+
? 'ConfigDict(extra="ignore", populate_by_name=True)'
|
|
197
|
+
: 'ConfigDict(extra="ignore")';
|
|
129
198
|
const lines = [
|
|
130
199
|
`class ${className(entName)}(BaseModel):`,
|
|
131
|
-
` model_config =
|
|
200
|
+
` model_config = ${config}`,
|
|
132
201
|
];
|
|
133
|
-
for (const f of
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
202
|
+
for (const f of allFields) {
|
|
203
|
+
let decl;
|
|
204
|
+
if (f.rawKey !== undefined) {
|
|
205
|
+
usesField = true;
|
|
206
|
+
const args = f.hasDefault
|
|
207
|
+
? `default=None, alias=${JSON.stringify(f.rawKey)}`
|
|
208
|
+
: `alias=${JSON.stringify(f.rawKey)}`;
|
|
209
|
+
decl = ` ${f.name}: ${f.type} = Field(${args})`;
|
|
210
|
+
}
|
|
211
|
+
else if (f.hasDefault) {
|
|
212
|
+
decl = ` ${f.name}: ${f.type} = None`;
|
|
213
|
+
}
|
|
214
|
+
else {
|
|
215
|
+
decl = ` ${f.name}: ${f.type}`;
|
|
216
|
+
}
|
|
140
217
|
lines.push(decl);
|
|
141
218
|
}
|
|
142
219
|
return lines.join('\n');
|
|
@@ -151,9 +228,12 @@ export function buildEntityModelsPy(schema) {
|
|
|
151
228
|
if (usesDatetime)
|
|
152
229
|
stdlibImports.push('from datetime import datetime');
|
|
153
230
|
stdlibImports.push(`from typing import ${typingImports.join(', ')}`);
|
|
231
|
+
const pydanticImports = usesField
|
|
232
|
+
? 'BaseModel, ConfigDict, Field'
|
|
233
|
+
: 'BaseModel, ConfigDict';
|
|
154
234
|
const importBlock = stdlibImports.join('\n') +
|
|
155
235
|
'\n\n' +
|
|
156
|
-
|
|
236
|
+
`from pydantic import ${pydanticImports}`;
|
|
157
237
|
// Add record-model rebuilds so forward-string annotations to entity
|
|
158
238
|
// types resolve under `from __future__ import annotations`.
|
|
159
239
|
const recordRebuilds = [];
|
|
@@ -315,26 +395,45 @@ export function buildTxStubPyi(schema) {
|
|
|
315
395
|
for (const entName of entityNames) {
|
|
316
396
|
linkFieldsByEntity[entName].sort((a, b) => a.label.localeCompare(b.label));
|
|
317
397
|
}
|
|
398
|
+
// Class-syntax TypedDict requires identifier keys; switch to the
|
|
399
|
+
// functional form when any key on a given dict is irregular.
|
|
400
|
+
const buildTypedDict = (name, fields) => {
|
|
401
|
+
const allIdent = fields.every((f) => isPyIdent(f.key));
|
|
402
|
+
if (allIdent) {
|
|
403
|
+
const lines = [`class ${name}(TypedDict, total=False):`];
|
|
404
|
+
for (const f of fields)
|
|
405
|
+
lines.push(` ${f.key}: ${f.type}`);
|
|
406
|
+
if (fields.length === 0)
|
|
407
|
+
lines.push(' pass');
|
|
408
|
+
return lines.join('\n');
|
|
409
|
+
}
|
|
410
|
+
const lines = [
|
|
411
|
+
`${name} = TypedDict(`,
|
|
412
|
+
` ${JSON.stringify(name)},`,
|
|
413
|
+
' {',
|
|
414
|
+
];
|
|
415
|
+
for (const f of fields) {
|
|
416
|
+
lines.push(` ${JSON.stringify(f.key)}: ${f.type},`);
|
|
417
|
+
}
|
|
418
|
+
lines.push(' },', ' total=False,', ')');
|
|
419
|
+
return lines.join('\n');
|
|
420
|
+
};
|
|
318
421
|
const perEntityBlocks = [];
|
|
319
422
|
for (const entName of entityNames) {
|
|
320
423
|
const cls = className(entName);
|
|
321
|
-
const
|
|
424
|
+
const argFields = [];
|
|
322
425
|
for (const [attrName, attrDef] of Object.entries(schema.entities[entName].attrs)) {
|
|
323
426
|
const t = mapValueType(attrDef.valueType);
|
|
324
427
|
if (t === 'datetime')
|
|
325
428
|
usesDatetime = true;
|
|
326
|
-
|
|
327
|
-
}
|
|
328
|
-
if (argsLines.length === 1)
|
|
329
|
-
argsLines.push(' pass');
|
|
330
|
-
perEntityBlocks.push(argsLines.join('\n'));
|
|
331
|
-
const linkLines = [`class ${cls}Links(TypedDict, total=False):`];
|
|
332
|
-
for (const link of linkFieldsByEntity[entName]) {
|
|
333
|
-
linkLines.push(` ${link.label}: ${link.type}`);
|
|
429
|
+
argFields.push({ key: attrName, type: t });
|
|
334
430
|
}
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
431
|
+
perEntityBlocks.push(buildTypedDict(`${cls}Args`, argFields));
|
|
432
|
+
const linkFields = linkFieldsByEntity[entName].map((l) => ({
|
|
433
|
+
key: l.label,
|
|
434
|
+
type: l.type,
|
|
435
|
+
}));
|
|
436
|
+
perEntityBlocks.push(buildTypedDict(`${cls}Links`, linkFields));
|
|
338
437
|
perEntityBlocks.push([
|
|
339
438
|
`class _${cls}Chunk:`,
|
|
340
439
|
` def update(self, args: ${cls}Args) -> _${cls}Chunk: ...`,
|
|
@@ -350,9 +449,9 @@ export function buildTxStubPyi(schema) {
|
|
|
350
449
|
' def __getitem__(self, eid: str) -> ChunkT: ...',
|
|
351
450
|
' def lookup(self, attr: str, value: Any) -> ChunkT: ...',
|
|
352
451
|
].join('\n');
|
|
353
|
-
//
|
|
354
|
-
//
|
|
355
|
-
const identifierEntities = entityNames.filter(
|
|
452
|
+
// Only valid Python identifiers can appear as `_TxBuilder` attrs (for
|
|
453
|
+
// `db.tx.<name>` autocomplete); irregular names use `db.tx["..."]`.
|
|
454
|
+
const identifierEntities = entityNames.filter(isPyIdent);
|
|
356
455
|
const txLines = ['class _TxBuilder:'];
|
|
357
456
|
if (identifierEntities.length === 0) {
|
|
358
457
|
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.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 = { 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\n// In python-land we would do something like keyword.iskeyword(), to generate\n// this list but because our gen-script is in ts-land we use an explicit set\n// based on Python 3 keywords\n// https://docs.python.org/3/reference/lexical_analysis.html#keywords\nconst PY_KEYWORDS = new Set([\n 'False',\n 'None',\n 'True',\n 'and',\n 'as',\n 'assert',\n 'async',\n 'await',\n 'break',\n 'class',\n 'continue',\n 'def',\n 'del',\n 'elif',\n 'else',\n 'except',\n 'finally',\n 'for',\n 'from',\n 'global',\n 'if',\n 'import',\n 'in',\n 'is',\n 'lambda',\n 'nonlocal',\n 'not',\n 'or',\n 'pass',\n 'raise',\n 'return',\n 'try',\n 'while',\n 'with',\n 'yield',\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 = [\n `${name} = TypedDict(`,\n ` ${JSON.stringify(name)},`,\n ' {',\n ];\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.26525895103.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.26525895103.1",
|
|
54
|
+
"@instantdb/platform": "1.0.40-branch-python-sdk-v1.26525895103.1",
|
|
55
|
+
"@instantdb/version": "1.0.40-branch-python-sdk-v1.26525895103.1"
|
|
56
56
|
},
|
|
57
57
|
"devDependencies": {
|
|
58
58
|
"@babel/core": "^7.17.9",
|
package/src/commands/genpy.ts
CHANGED
|
@@ -96,7 +96,68 @@ type LinkDefLike = {
|
|
|
96
96
|
reverse: { on: string; label: string; has: 'one' | 'many' };
|
|
97
97
|
};
|
|
98
98
|
|
|
99
|
-
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
|
+
// In python-land we would do something like keyword.iskeyword(), to generate
|
|
109
|
+
// this list but because our gen-script is in ts-land we use an explicit set
|
|
110
|
+
// based on Python 3 keywords
|
|
111
|
+
// https://docs.python.org/3/reference/lexical_analysis.html#keywords
|
|
112
|
+
const PY_KEYWORDS = new Set([
|
|
113
|
+
'False',
|
|
114
|
+
'None',
|
|
115
|
+
'True',
|
|
116
|
+
'and',
|
|
117
|
+
'as',
|
|
118
|
+
'assert',
|
|
119
|
+
'async',
|
|
120
|
+
'await',
|
|
121
|
+
'break',
|
|
122
|
+
'class',
|
|
123
|
+
'continue',
|
|
124
|
+
'def',
|
|
125
|
+
'del',
|
|
126
|
+
'elif',
|
|
127
|
+
'else',
|
|
128
|
+
'except',
|
|
129
|
+
'finally',
|
|
130
|
+
'for',
|
|
131
|
+
'from',
|
|
132
|
+
'global',
|
|
133
|
+
'if',
|
|
134
|
+
'import',
|
|
135
|
+
'in',
|
|
136
|
+
'is',
|
|
137
|
+
'lambda',
|
|
138
|
+
'nonlocal',
|
|
139
|
+
'not',
|
|
140
|
+
'or',
|
|
141
|
+
'pass',
|
|
142
|
+
'raise',
|
|
143
|
+
'return',
|
|
144
|
+
'try',
|
|
145
|
+
'while',
|
|
146
|
+
'with',
|
|
147
|
+
'yield',
|
|
148
|
+
]);
|
|
149
|
+
|
|
150
|
+
function isPyIdent(name: string): boolean {
|
|
151
|
+
return /^[A-Za-z_][A-Za-z0-9_]*$/.test(name) && !PY_KEYWORDS.has(name);
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
function safePyIdent(name: string): string {
|
|
155
|
+
if (isPyIdent(name)) return name;
|
|
156
|
+
let safe = name.replace(/[^A-Za-z0-9_]+/g, '_').replace(/_+/g, '_');
|
|
157
|
+
if (safe === '' || /^[0-9]/.test(safe)) safe = '_' + safe;
|
|
158
|
+
if (PY_KEYWORDS.has(safe)) safe += '_';
|
|
159
|
+
return safe;
|
|
160
|
+
}
|
|
100
161
|
|
|
101
162
|
function className(entName: string): string {
|
|
102
163
|
// Strip a leading `$` (system entities like `$users`, `$files`), then
|
|
@@ -144,10 +205,12 @@ export function buildEntityModelsPy(schema: SchemaLike): string {
|
|
|
144
205
|
const baseType = mapValueType(attrDef.valueType);
|
|
145
206
|
if (baseType === 'datetime') usesDatetime = true;
|
|
146
207
|
const type = attrDef.required ? baseType : `${baseType} | None`;
|
|
208
|
+
const safeName = safePyIdent(attrName);
|
|
147
209
|
fieldsByEntity[entName].push({
|
|
148
|
-
name:
|
|
210
|
+
name: safeName,
|
|
149
211
|
type,
|
|
150
212
|
hasDefault: !attrDef.required,
|
|
213
|
+
rawKey: safeName === attrName ? undefined : attrName,
|
|
151
214
|
});
|
|
152
215
|
}
|
|
153
216
|
}
|
|
@@ -156,23 +219,27 @@ export function buildEntityModelsPy(schema: SchemaLike): string {
|
|
|
156
219
|
const fwd = link.forward;
|
|
157
220
|
const rev = link.reverse;
|
|
158
221
|
if (linkFieldsByEntity[fwd.on]) {
|
|
222
|
+
const safeName = safePyIdent(fwd.label);
|
|
159
223
|
linkFieldsByEntity[fwd.on].push({
|
|
160
|
-
name:
|
|
224
|
+
name: safeName,
|
|
161
225
|
type:
|
|
162
226
|
fwd.has === 'one'
|
|
163
227
|
? `${className(rev.on)} | None`
|
|
164
228
|
: `list[${className(rev.on)}] | None`,
|
|
165
229
|
hasDefault: true,
|
|
230
|
+
rawKey: safeName === fwd.label ? undefined : fwd.label,
|
|
166
231
|
});
|
|
167
232
|
}
|
|
168
233
|
if (linkFieldsByEntity[rev.on]) {
|
|
234
|
+
const safeName = safePyIdent(rev.label);
|
|
169
235
|
linkFieldsByEntity[rev.on].push({
|
|
170
|
-
name:
|
|
236
|
+
name: safeName,
|
|
171
237
|
type:
|
|
172
238
|
rev.has === 'one'
|
|
173
239
|
? `${className(fwd.on)} | None`
|
|
174
240
|
: `list[${className(fwd.on)}] | None`,
|
|
175
241
|
hasDefault: true,
|
|
242
|
+
rawKey: safeName === rev.label ? undefined : rev.label,
|
|
176
243
|
});
|
|
177
244
|
}
|
|
178
245
|
}
|
|
@@ -182,18 +249,33 @@ export function buildEntityModelsPy(schema: SchemaLike): string {
|
|
|
182
249
|
linkFieldsByEntity[entName].sort((a, b) => a.name.localeCompare(b.name));
|
|
183
250
|
}
|
|
184
251
|
|
|
252
|
+
let usesField = false;
|
|
185
253
|
const classBlocks = entityNames.map((entName) => {
|
|
254
|
+
const allFields = [
|
|
255
|
+
...fieldsByEntity[entName],
|
|
256
|
+
...linkFieldsByEntity[entName],
|
|
257
|
+
];
|
|
258
|
+
const hasAlias = allFields.some((f) => f.rawKey !== undefined);
|
|
259
|
+
const config = hasAlias
|
|
260
|
+
? 'ConfigDict(extra="ignore", populate_by_name=True)'
|
|
261
|
+
: 'ConfigDict(extra="ignore")';
|
|
186
262
|
const lines = [
|
|
187
263
|
`class ${className(entName)}(BaseModel):`,
|
|
188
|
-
` model_config =
|
|
264
|
+
` model_config = ${config}`,
|
|
189
265
|
];
|
|
190
|
-
for (const f of
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
266
|
+
for (const f of allFields) {
|
|
267
|
+
let decl: string;
|
|
268
|
+
if (f.rawKey !== undefined) {
|
|
269
|
+
usesField = true;
|
|
270
|
+
const args = f.hasDefault
|
|
271
|
+
? `default=None, alias=${JSON.stringify(f.rawKey)}`
|
|
272
|
+
: `alias=${JSON.stringify(f.rawKey)}`;
|
|
273
|
+
decl = ` ${f.name}: ${f.type} = Field(${args})`;
|
|
274
|
+
} else if (f.hasDefault) {
|
|
275
|
+
decl = ` ${f.name}: ${f.type} = None`;
|
|
276
|
+
} else {
|
|
277
|
+
decl = ` ${f.name}: ${f.type}`;
|
|
278
|
+
}
|
|
197
279
|
lines.push(decl);
|
|
198
280
|
}
|
|
199
281
|
return lines.join('\n');
|
|
@@ -213,10 +295,13 @@ export function buildEntityModelsPy(schema: SchemaLike): string {
|
|
|
213
295
|
const stdlibImports: string[] = [];
|
|
214
296
|
if (usesDatetime) stdlibImports.push('from datetime import datetime');
|
|
215
297
|
stdlibImports.push(`from typing import ${typingImports.join(', ')}`);
|
|
298
|
+
const pydanticImports = usesField
|
|
299
|
+
? 'BaseModel, ConfigDict, Field'
|
|
300
|
+
: 'BaseModel, ConfigDict';
|
|
216
301
|
const importBlock =
|
|
217
302
|
stdlibImports.join('\n') +
|
|
218
303
|
'\n\n' +
|
|
219
|
-
|
|
304
|
+
`from pydantic import ${pydanticImports}`;
|
|
220
305
|
|
|
221
306
|
// Add record-model rebuilds so forward-string annotations to entity
|
|
222
307
|
// types resolve under `from __future__ import annotations`.
|
|
@@ -410,27 +495,50 @@ export function buildTxStubPyi(schema: SchemaLike): string {
|
|
|
410
495
|
linkFieldsByEntity[entName].sort((a, b) => a.label.localeCompare(b.label));
|
|
411
496
|
}
|
|
412
497
|
|
|
498
|
+
// Class-syntax TypedDict requires identifier keys; switch to the
|
|
499
|
+
// functional form when any key on a given dict is irregular.
|
|
500
|
+
const buildTypedDict = (
|
|
501
|
+
name: string,
|
|
502
|
+
fields: { key: string; type: string }[],
|
|
503
|
+
): string => {
|
|
504
|
+
const allIdent = fields.every((f) => isPyIdent(f.key));
|
|
505
|
+
if (allIdent) {
|
|
506
|
+
const lines = [`class ${name}(TypedDict, total=False):`];
|
|
507
|
+
for (const f of fields) lines.push(` ${f.key}: ${f.type}`);
|
|
508
|
+
if (fields.length === 0) lines.push(' pass');
|
|
509
|
+
return lines.join('\n');
|
|
510
|
+
}
|
|
511
|
+
const lines = [
|
|
512
|
+
`${name} = TypedDict(`,
|
|
513
|
+
` ${JSON.stringify(name)},`,
|
|
514
|
+
' {',
|
|
515
|
+
];
|
|
516
|
+
for (const f of fields) {
|
|
517
|
+
lines.push(` ${JSON.stringify(f.key)}: ${f.type},`);
|
|
518
|
+
}
|
|
519
|
+
lines.push(' },', ' total=False,', ')');
|
|
520
|
+
return lines.join('\n');
|
|
521
|
+
};
|
|
522
|
+
|
|
413
523
|
const perEntityBlocks: string[] = [];
|
|
414
524
|
for (const entName of entityNames) {
|
|
415
525
|
const cls = className(entName);
|
|
416
526
|
|
|
417
|
-
const
|
|
527
|
+
const argFields: { key: string; type: string }[] = [];
|
|
418
528
|
for (const [attrName, attrDef] of Object.entries(
|
|
419
529
|
schema.entities[entName].attrs,
|
|
420
530
|
)) {
|
|
421
531
|
const t = mapValueType(attrDef.valueType);
|
|
422
532
|
if (t === 'datetime') usesDatetime = true;
|
|
423
|
-
|
|
533
|
+
argFields.push({ key: attrName, type: t });
|
|
424
534
|
}
|
|
425
|
-
|
|
426
|
-
perEntityBlocks.push(argsLines.join('\n'));
|
|
535
|
+
perEntityBlocks.push(buildTypedDict(`${cls}Args`, argFields));
|
|
427
536
|
|
|
428
|
-
const
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
}
|
|
432
|
-
|
|
433
|
-
perEntityBlocks.push(linkLines.join('\n'));
|
|
537
|
+
const linkFields = linkFieldsByEntity[entName].map((l) => ({
|
|
538
|
+
key: l.label,
|
|
539
|
+
type: l.type,
|
|
540
|
+
}));
|
|
541
|
+
perEntityBlocks.push(buildTypedDict(`${cls}Links`, linkFields));
|
|
434
542
|
|
|
435
543
|
perEntityBlocks.push(
|
|
436
544
|
[
|
|
@@ -451,9 +559,9 @@ export function buildTxStubPyi(schema: SchemaLike): string {
|
|
|
451
559
|
' def lookup(self, attr: str, value: Any) -> ChunkT: ...',
|
|
452
560
|
].join('\n');
|
|
453
561
|
|
|
454
|
-
//
|
|
455
|
-
//
|
|
456
|
-
const identifierEntities = entityNames.filter(
|
|
562
|
+
// Only valid Python identifiers can appear as `_TxBuilder` attrs (for
|
|
563
|
+
// `db.tx.<name>` autocomplete); irregular names use `db.tx["..."]`.
|
|
564
|
+
const identifierEntities = entityNames.filter(isPyIdent);
|
|
457
565
|
const txLines = ['class _TxBuilder:'];
|
|
458
566
|
if (identifierEntities.length === 0) {
|
|
459
567
|
txLines.push(' pass');
|