@gencow/core 0.1.16 → 0.1.17

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/crud.d.ts CHANGED
@@ -48,6 +48,13 @@ type CrudOptions<T extends PgTable> = {
48
48
  realtime?: boolean;
49
49
  /** 키 접두사 오버라이드 (기본: 테이블명) */
50
50
  prefix?: string;
51
+ /**
52
+ * 생성할 메서드 목록 (기본: 전체 5개)
53
+ * 지정하면 해당 메서드만 레지스트리에 등록되고 반환됨.
54
+ * api.ts codegen에도 지정된 메서드만 포함됨.
55
+ * @example crud(table, { methods: ['list', 'get', 'create'] })
56
+ */
57
+ methods?: ('list' | 'get' | 'create' | 'update' | 'remove')[];
51
58
  };
52
59
  /** 지원 연산자 목록 */
53
60
  declare const FILTER_OPS: readonly ["eq", "ne", "gt", "gte", "lt", "lte", "in", "nin", "like", "ilike"];
@@ -103,14 +110,14 @@ export declare function crud<T extends PgTable>(table: T, options?: CrudOptions<
103
110
  }, {
104
111
  data: any;
105
112
  total: number;
106
- }>;
113
+ }> | undefined;
107
114
  get: import("./reactive").QueryDef<{
108
115
  id: import("./v").Validator<string> | import("./v").Validator<number>;
109
- }, any>;
110
- create: import("./reactive").MutationDef<any, any>;
111
- update: import("./reactive").MutationDef<any, any>;
116
+ }, any> | undefined;
117
+ create: import("./reactive").MutationDef<any, any> | undefined;
118
+ update: import("./reactive").MutationDef<any, any> | undefined;
112
119
  remove: import("./reactive").MutationDef<any, {
113
120
  success: boolean;
114
- }>;
121
+ }> | undefined;
115
122
  };
116
123
  export {};
package/dist/crud.js CHANGED
@@ -215,8 +215,11 @@ export function crud(table, options) {
215
215
  const countResult = await db.select({ count: drizzleCount() }).from(anyTable).where(whereClause);
216
216
  return { data, total: Number(countResult[0]?.count ?? 0) };
217
217
  }
218
+ // ── methods 필터링: 지정된 메서드만 레지스트리 등록 ──
219
+ // methods 옵션 미지정 시 전체 5개 등록 (하위호환)
220
+ const enabledMethods = new Set(options?.methods ?? ['list', 'get', 'create', 'update', 'remove']);
218
221
  // ── list ──────────────────────────────────────
219
- const listDef = query(`${prefix}.list`, {
222
+ const listDef = !enabledMethods.has('list') ? undefined : query(`${prefix}.list`, {
220
223
  public: isPublic,
221
224
  args: {
222
225
  page: v.optional(v.number()),
@@ -243,8 +246,6 @@ export function crud(table, options) {
243
246
  orderByClause = desc(defaultOrderCol);
244
247
  }
245
248
  // SELECT + COUNT 순차 실행 — 소규모 커넥션 풀 환경에서 동시 점유 방지
246
- // Note: data←→count 사이 INSERT/DELETE 시 total 불일치 가능 (BaaS 단일사용자/저부하에서 무시 가능)
247
- // TODO(P2): 대규모 시 db.transaction() 래핑 검토
248
249
  const results = await ctx.db.select()
249
250
  .from(anyTable)
250
251
  .where(whereClause)
@@ -261,7 +262,7 @@ export function crud(table, options) {
261
262
  }
262
263
  });
263
264
  // ── get ───────────────────────────────────────
264
- const getDef = query(`${prefix}.get`, {
265
+ const getDef = !enabledMethods.has('get') ? undefined : query(`${prefix}.get`, {
265
266
  public: isPublic,
266
267
  args: { id: idValidator },
267
268
  handler: async (ctx, args) => {
@@ -277,7 +278,7 @@ export function crud(table, options) {
277
278
  }
278
279
  });
279
280
  // ── create ────────────────────────────────────
280
- const createDef = mutation(`${prefix}.create`, {
281
+ const createDef = !enabledMethods.has('create') ? undefined : mutation(`${prefix}.create`, {
281
282
  public: isPublic,
282
283
  invalidates: [],
283
284
  handler: async (ctx, args) => {
@@ -293,7 +294,7 @@ export function crud(table, options) {
293
294
  }
294
295
  const [result] = await ctx.db.insert(anyTable).values(insertData).returning();
295
296
  // Realtime push — { data, total } 형태로 emit
296
- if (useRealtime) {
297
+ if (useRealtime && enabledMethods.has('list')) {
297
298
  const listResult = await fetchListWithTotal(ctx.db);
298
299
  ctx.realtime.emit(`${prefix}.list`, listResult);
299
300
  }
@@ -301,7 +302,7 @@ export function crud(table, options) {
301
302
  }
302
303
  });
303
304
  // ── update ────────────────────────────────────
304
- const updateDef = mutation(`${prefix}.update`, {
305
+ const updateDef = !enabledMethods.has('update') ? undefined : mutation(`${prefix}.update`, {
305
306
  public: isPublic,
306
307
  invalidates: [],
307
308
  handler: async (ctx, args) => {
@@ -323,15 +324,19 @@ export function crud(table, options) {
323
324
  .returning();
324
325
  // Realtime push (list + get 양쪽) — { data, total } 형태
325
326
  if (useRealtime) {
326
- const listResult = await fetchListWithTotal(ctx.db);
327
- ctx.realtime.emit(`${prefix}.list`, listResult);
328
- ctx.realtime.emit(`${prefix}.get`, result);
327
+ if (enabledMethods.has('list')) {
328
+ const listResult = await fetchListWithTotal(ctx.db);
329
+ ctx.realtime.emit(`${prefix}.list`, listResult);
330
+ }
331
+ if (enabledMethods.has('get')) {
332
+ ctx.realtime.emit(`${prefix}.get`, result);
333
+ }
329
334
  }
330
335
  return result;
331
336
  }
332
337
  });
333
338
  // ── remove ────────────────────────────────────
334
- const removeDef = mutation(`${prefix}.remove`, {
339
+ const removeDef = !enabledMethods.has('remove') ? undefined : mutation(`${prefix}.remove`, {
335
340
  public: isPublic,
336
341
  invalidates: [],
337
342
  handler: async (ctx, args) => {
@@ -347,13 +352,16 @@ export function crud(table, options) {
347
352
  await ctx.db.delete(anyTable).where(eq(pk, args.id));
348
353
  }
349
354
  // Realtime push — { data, total } 형태
350
- if (useRealtime) {
355
+ if (useRealtime && enabledMethods.has('list')) {
351
356
  const listResult = await fetchListWithTotal(ctx.db);
352
357
  ctx.realtime.emit(`${prefix}.list`, listResult);
353
358
  }
354
359
  return { success: true };
355
360
  }
356
361
  });
362
+ // 반환 객체는 항상 5개 키를 가지지만, 비활성 메서드는 undefined.
363
+ // 사용자가 destructure 시 undefined를 받으면 export하지 않으므로
364
+ // codegen의 레지스트리에 등록되지 않아 api.ts 불일치가 해소됨.
357
365
  return {
358
366
  list: listDef,
359
367
  get: getDef,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@gencow/core",
3
- "version": "0.1.16",
3
+ "version": "0.1.17",
4
4
  "description": "Gencow core library — defineQuery, defineMutation, reactive subscriptions",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",
package/src/crud.ts CHANGED
@@ -52,6 +52,13 @@ type CrudOptions<T extends PgTable> = {
52
52
  realtime?: boolean;
53
53
  /** 키 접두사 오버라이드 (기본: 테이블명) */
54
54
  prefix?: string;
55
+ /**
56
+ * 생성할 메서드 목록 (기본: 전체 5개)
57
+ * 지정하면 해당 메서드만 레지스트리에 등록되고 반환됨.
58
+ * api.ts codegen에도 지정된 메서드만 포함됨.
59
+ * @example crud(table, { methods: ['list', 'get', 'create'] })
60
+ */
61
+ methods?: ('list' | 'get' | 'create' | 'update' | 'remove')[];
55
62
  };
56
63
 
57
64
  // ─── Helpers ────────────────────────────────────────────
@@ -271,9 +278,13 @@ export function crud<T extends PgTable>(table: T, options?: CrudOptions<T>) {
271
278
  return { data, total: Number(countResult[0]?.count ?? 0) };
272
279
  }
273
280
 
281
+ // ── methods 필터링: 지정된 메서드만 레지스트리 등록 ──
282
+ // methods 옵션 미지정 시 전체 5개 등록 (하위호환)
283
+ const enabledMethods = new Set(options?.methods ?? ['list', 'get', 'create', 'update', 'remove']);
284
+
274
285
  // ── list ──────────────────────────────────────
275
286
 
276
- const listDef = query(`${prefix}.list`, {
287
+ const listDef = !enabledMethods.has('list') ? undefined : query(`${prefix}.list`, {
277
288
  public: isPublic,
278
289
  args: {
279
290
  page: v.optional(v.number()),
@@ -302,8 +313,6 @@ export function crud<T extends PgTable>(table: T, options?: CrudOptions<T>) {
302
313
  }
303
314
 
304
315
  // SELECT + COUNT 순차 실행 — 소규모 커넥션 풀 환경에서 동시 점유 방지
305
- // Note: data←→count 사이 INSERT/DELETE 시 total 불일치 가능 (BaaS 단일사용자/저부하에서 무시 가능)
306
- // TODO(P2): 대규모 시 db.transaction() 래핑 검토
307
316
  const results = await ctx.db.select()
308
317
  .from(anyTable)
309
318
  .where(whereClause)
@@ -323,7 +332,7 @@ export function crud<T extends PgTable>(table: T, options?: CrudOptions<T>) {
323
332
 
324
333
  // ── get ───────────────────────────────────────
325
334
 
326
- const getDef = query(`${prefix}.get`, {
335
+ const getDef = !enabledMethods.has('get') ? undefined : query(`${prefix}.get`, {
327
336
  public: isPublic,
328
337
  args: { id: idValidator },
329
338
  handler: async (ctx: any, args: any) => {
@@ -343,7 +352,7 @@ export function crud<T extends PgTable>(table: T, options?: CrudOptions<T>) {
343
352
 
344
353
  // ── create ────────────────────────────────────
345
354
 
346
- const createDef = mutation(`${prefix}.create`, {
355
+ const createDef = !enabledMethods.has('create') ? undefined : mutation(`${prefix}.create`, {
347
356
  public: isPublic,
348
357
  invalidates: [],
349
358
  handler: async (ctx: any, args: any) => {
@@ -364,7 +373,7 @@ export function crud<T extends PgTable>(table: T, options?: CrudOptions<T>) {
364
373
  const [result] = await ctx.db.insert(anyTable).values(insertData).returning();
365
374
 
366
375
  // Realtime push — { data, total } 형태로 emit
367
- if (useRealtime) {
376
+ if (useRealtime && enabledMethods.has('list')) {
368
377
  const listResult = await fetchListWithTotal(ctx.db);
369
378
  ctx.realtime.emit(`${prefix}.list`, listResult);
370
379
  }
@@ -375,7 +384,7 @@ export function crud<T extends PgTable>(table: T, options?: CrudOptions<T>) {
375
384
 
376
385
  // ── update ────────────────────────────────────
377
386
 
378
- const updateDef = mutation(`${prefix}.update`, {
387
+ const updateDef = !enabledMethods.has('update') ? undefined : mutation(`${prefix}.update`, {
379
388
  public: isPublic,
380
389
  invalidates: [],
381
390
  handler: async (ctx: any, args: any) => {
@@ -402,9 +411,13 @@ export function crud<T extends PgTable>(table: T, options?: CrudOptions<T>) {
402
411
 
403
412
  // Realtime push (list + get 양쪽) — { data, total } 형태
404
413
  if (useRealtime) {
405
- const listResult = await fetchListWithTotal(ctx.db);
406
- ctx.realtime.emit(`${prefix}.list`, listResult);
407
- ctx.realtime.emit(`${prefix}.get`, result);
414
+ if (enabledMethods.has('list')) {
415
+ const listResult = await fetchListWithTotal(ctx.db);
416
+ ctx.realtime.emit(`${prefix}.list`, listResult);
417
+ }
418
+ if (enabledMethods.has('get')) {
419
+ ctx.realtime.emit(`${prefix}.get`, result);
420
+ }
408
421
  }
409
422
 
410
423
  return result;
@@ -413,7 +426,7 @@ export function crud<T extends PgTable>(table: T, options?: CrudOptions<T>) {
413
426
 
414
427
  // ── remove ────────────────────────────────────
415
428
 
416
- const removeDef = mutation(`${prefix}.remove`, {
429
+ const removeDef = !enabledMethods.has('remove') ? undefined : mutation(`${prefix}.remove`, {
417
430
  public: isPublic,
418
431
  invalidates: [],
419
432
  handler: async (ctx: any, args: any) => {
@@ -429,7 +442,7 @@ export function crud<T extends PgTable>(table: T, options?: CrudOptions<T>) {
429
442
  }
430
443
 
431
444
  // Realtime push — { data, total } 형태
432
- if (useRealtime) {
445
+ if (useRealtime && enabledMethods.has('list')) {
433
446
  const listResult = await fetchListWithTotal(ctx.db);
434
447
  ctx.realtime.emit(`${prefix}.list`, listResult);
435
448
  }
@@ -438,6 +451,9 @@ export function crud<T extends PgTable>(table: T, options?: CrudOptions<T>) {
438
451
  }
439
452
  });
440
453
 
454
+ // 반환 객체는 항상 5개 키를 가지지만, 비활성 메서드는 undefined.
455
+ // 사용자가 destructure 시 undefined를 받으면 export하지 않으므로
456
+ // codegen의 레지스트리에 등록되지 않아 api.ts 불일치가 해소됨.
441
457
  return {
442
458
  list: listDef,
443
459
  get: getDef,