sonamu 0.9.13 → 0.9.14
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/dist/database/puri.d.ts +13 -1
- package/dist/database/puri.d.ts.map +1 -1
- package/dist/database/puri.js +47 -5
- package/dist/entity/entity-manager.d.ts +1 -0
- package/dist/entity/entity-manager.d.ts.map +1 -1
- package/dist/migration/code-generation.d.ts.map +1 -1
- package/dist/migration/code-generation.js +74 -8
- package/dist/migration/postgresql-schema-reader.d.ts +1 -0
- package/dist/migration/postgresql-schema-reader.d.ts.map +1 -1
- package/dist/migration/postgresql-schema-reader.js +4 -2
- package/dist/template/implementations/sd.template.d.ts.map +1 -1
- package/dist/template/implementations/sd.template.js +70 -14
- package/dist/types/types.d.ts +6 -0
- package/dist/types/types.d.ts.map +1 -1
- package/dist/types/types.js +2 -1
- package/package.json +3 -3
- package/src/database/puri.ts +92 -7
- package/src/database/puri.types.test-d.ts +70 -0
- package/src/migration/__tests__/code-generation.search-text.test.ts +146 -1
- package/src/migration/code-generation.ts +85 -6
- package/src/migration/postgresql-schema-reader.ts +4 -1
- package/src/skills/sonamu/i18n.md +9 -1
- package/src/template/implementations/sd.template.ts +69 -13
- package/src/types/__tests__/entity-json-schema-search-text.test.ts +39 -0
- package/src/types/types.ts +5 -0
- package/src/ui/entity.instructions.md +7 -3
|
@@ -60,6 +60,45 @@ describe("EntityJsonSchema searchText/opclass validation", () => {
|
|
|
60
60
|
expect(legacyResult.success).toBe(true);
|
|
61
61
|
});
|
|
62
62
|
|
|
63
|
+
test("index where predicate는 raw SQL 문자열로 허용하되 빈 문자열은 거부해야 한다", () => {
|
|
64
|
+
const baseEntity = createBaseEntity();
|
|
65
|
+
const partialIndex = {
|
|
66
|
+
...baseEntity,
|
|
67
|
+
indexes: [
|
|
68
|
+
{
|
|
69
|
+
...baseEntity.indexes[0],
|
|
70
|
+
where: "deleted_at IS NULL",
|
|
71
|
+
},
|
|
72
|
+
],
|
|
73
|
+
};
|
|
74
|
+
const partialResult = EntityJsonSchema.safeParse(partialIndex);
|
|
75
|
+
expect(partialResult.success).toBe(true);
|
|
76
|
+
|
|
77
|
+
const emptyPredicate = {
|
|
78
|
+
...baseEntity,
|
|
79
|
+
indexes: [
|
|
80
|
+
{
|
|
81
|
+
...baseEntity.indexes[0],
|
|
82
|
+
where: "",
|
|
83
|
+
},
|
|
84
|
+
],
|
|
85
|
+
};
|
|
86
|
+
const emptyResult = EntityJsonSchema.safeParse(emptyPredicate);
|
|
87
|
+
expect(emptyResult.success).toBe(false);
|
|
88
|
+
|
|
89
|
+
const blankPredicate = {
|
|
90
|
+
...baseEntity,
|
|
91
|
+
indexes: [
|
|
92
|
+
{
|
|
93
|
+
...baseEntity.indexes[0],
|
|
94
|
+
where: " ",
|
|
95
|
+
},
|
|
96
|
+
],
|
|
97
|
+
};
|
|
98
|
+
const blankResult = EntityJsonSchema.safeParse(blankPredicate);
|
|
99
|
+
expect(blankResult.success).toBe(false);
|
|
100
|
+
});
|
|
101
|
+
|
|
63
102
|
test("searchText source column 존재/타입 검증이 동작해야 한다", () => {
|
|
64
103
|
const unknownSource = createBaseEntity();
|
|
65
104
|
unknownSource.props[4] = {
|
package/src/types/types.ts
CHANGED
|
@@ -410,6 +410,8 @@ export type EntityIndex = {
|
|
|
410
410
|
name: string;
|
|
411
411
|
using?: "btree" | "hash" | "gin" | "gist" | "pgroonga";
|
|
412
412
|
nullsNotDistinct?: boolean; // unique index only
|
|
413
|
+
/** PostgreSQL partial index predicate. Raw SQL WHERE expression without the WHERE keyword. */
|
|
414
|
+
where?: string;
|
|
413
415
|
/**
|
|
414
416
|
* HNSW (Hierarchical Navigable Small World) 인덱스: 각 노드의 최대 연결 수
|
|
415
417
|
*
|
|
@@ -832,6 +834,8 @@ export type MigrationIndex = {
|
|
|
832
834
|
name: string;
|
|
833
835
|
using?: "btree" | "hash" | "gin" | "gist" | "pgroonga";
|
|
834
836
|
nullsNotDistinct?: boolean;
|
|
837
|
+
/** PostgreSQL partial index predicate. Raw SQL WHERE expression without the WHERE keyword. */
|
|
838
|
+
where?: string;
|
|
835
839
|
/** HNSW (Hierarchical Navigable Small World): 각 노드의 최대 연결 수 */
|
|
836
840
|
m?: number;
|
|
837
841
|
/** HNSW (Hierarchical Navigable Small World): 구성 시 탐색 범위 */
|
|
@@ -1495,6 +1499,7 @@ const EntityIndexSchema = z
|
|
|
1495
1499
|
name: z.string().min(1).max(63),
|
|
1496
1500
|
using: z.enum(["btree", "hash", "gin", "gist", "pgroonga"]).optional(),
|
|
1497
1501
|
nullsNotDistinct: z.boolean().optional(),
|
|
1502
|
+
where: z.string().trim().min(1).optional(),
|
|
1498
1503
|
m: z.number().optional(),
|
|
1499
1504
|
efConstruction: z.number().optional(),
|
|
1500
1505
|
lists: z.number().optional(),
|
|
@@ -336,8 +336,11 @@
|
|
|
336
336
|
2. 모든 엔티티는 `EntityNameOrderBy`, `EntityNameSearchField` Enum을 필수로 포함해야 합니다.
|
|
337
337
|
3. 엔티티 내에서 사용하는 Enum ID는 엔티티 이름을 접두어로 사용합니다. (예: UserStatus, ProductType)
|
|
338
338
|
4. indexes가 지정되지 않으면 빈 배열로 반환합니다.
|
|
339
|
-
5.
|
|
340
|
-
|
|
339
|
+
5. partial index가 필요하면 index에 `where`를 raw SQL predicate로 지정합니다. (예:
|
|
340
|
+
`"where": "deleted_at IS NULL"`)
|
|
341
|
+
6. `where`는 PostgreSQL partial index predicate로 그대로 사용되므로 사용자 입력을 조합하지 않습니다.
|
|
342
|
+
7. subsets이 지정되지 않으면 `{ "A": ["id"] }`로 반환합니다.
|
|
343
|
+
8. relation 필드명은 `_id` 접미어 대신 관련 엔티티를 나타내는 이름을 사용합니다. (예: "user", "author", "category")
|
|
341
344
|
|
|
342
345
|
### Property Rules
|
|
343
346
|
|
|
@@ -511,7 +514,8 @@
|
|
|
511
514
|
{
|
|
512
515
|
"name": "products_status_index",
|
|
513
516
|
"type": "index",
|
|
514
|
-
"columns": [{ "name": "status" }]
|
|
517
|
+
"columns": [{ "name": "status" }],
|
|
518
|
+
"where": "status = 'active'"
|
|
515
519
|
}
|
|
516
520
|
],
|
|
517
521
|
"subsets": {
|