@pdg/drizzle-mysql 1.0.3 → 1.0.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -333,6 +333,35 @@ await db.trans(async () => {
333
333
 
334
334
  `db.current()`는 현재 문맥의 Drizzle 데이터베이스 인스턴스를 반환합니다. 래퍼가 제공하지 않는 Drizzle 기능은 이 API로 직접 사용할 수 있습니다.
335
335
 
336
+ ### 테이블 수정·삭제 금지
337
+
338
+ 이 패키지의 `mysqlTable`에 `{ updateBlocked: true, deleteBlocked: true }`를 전달하면 등록과 조회는 유지하면서 테이블 전체의 수정·삭제를 금지합니다. 정책은 세 번째 인자에 전달하거나, 인덱스·제약조건 설정 콜백을 사용하는 경우 네 번째 인자에 전달합니다. 각 옵션을 생략하거나 `false`로 지정하면 해당 작업은 기존처럼 허용됩니다. 별도로 선언하는 정책 객체에는 `as const` 또는 `satisfies TablePolicy`를 사용해 `true` 리터럴 타입을 유지하면 타입 검사에서도 차단됩니다.
339
+
340
+ ```ts
341
+ import { mysqlTable, int, varchar, index } from '@pdg/drizzle-mysql';
342
+
343
+ const logs = mysqlTable(
344
+ 'logs',
345
+ {
346
+ id: int().autoincrement().primaryKey(),
347
+ message: varchar({ length: 100 }).notNull(),
348
+ },
349
+ { updateBlocked: true, deleteBlocked: true },
350
+ );
351
+
352
+ const indexedLogs = mysqlTable(
353
+ 'indexed_logs',
354
+ {
355
+ id: int().autoincrement().primaryKey(),
356
+ message: varchar({ length: 100 }).notNull(),
357
+ },
358
+ (t) => [index('indexed_logs_message_idx').on(t.message)],
359
+ { updateBlocked: true, deleteBlocked: true },
360
+ );
361
+ ```
362
+
363
+ `updateBlocked`는 `MySqlQuery.edit`와 `editByPrimaryKey`, `deleteBlocked`는 `remove`와 `removeByPrimaryKey` 호출을 TypeScript에서 차단합니다. 타입 정보가 사라지거나 JavaScript에서 호출하더라도 조건 콜백과 DB 접근 전에 명시적인 오류가 발생합니다. 테이블 수정 금지는 컬럼의 `updateAllowed()`보다 우선합니다. 정책은 `db.query(table)`과 직접 생성한 `MySqlQuery` 모두에 적용되지만, 원본 Drizzle 쿼리나 직접 실행한 SQL에는 적용되지 않습니다. DB 수준의 제한이 필요하면 별도로 `UPDATE`·`DELETE` 권한을 제한해야 합니다.
364
+
336
365
  ### 생성·수정 시각
337
366
 
338
367
  컬럼 정책은 이 패키지에서 가져온 `mysqlTable`에 선언합니다. 자동 증가 컬럼은 기본적으로 등록과 수정이 금지되며, 각각 `insertAllowed()`와 `updateAllowed()`로 허용할 수 있습니다. `primaryKey()`로 지정한 컬럼도 기본적으로 수정이 금지되며, `updateAllowed()`를 명시해야 수정할 수 있습니다. 다른 컬럼은 `insertBlocked()`와 `updateBlocked()`로 금지하거나 `updateRequired()`로 수정 시 필수로 지정합니다. 금지된 값을 전달하거나 필수 수정 값을 누락하면 런타임에도 오류가 발생합니다.
@@ -3,6 +3,7 @@ import { MySqlTable, MySqlColumn, type MySqlAsyncSelectBase } from 'drizzle-orm/
3
3
  import type { SelectedFields } from 'drizzle-orm/operations';
4
4
  import type { GetSelectTableName } from 'drizzle-orm/query-builders/select.types';
5
5
  import type { MySqlColumnSelectionName, MySqlSelectedNamedColumnUnion, MySqlSelectedNamedColumns, MySqlSelectedTableColumns, MySqlAliasTable } from './columns.cjs';
6
+ import { type TableMutationPolicy } from './mysqlTable.cjs';
6
7
  import type { MySqlInsertValues, MySqlUpdateValues, MySqlCompareValues, MySqlColumnName, MySqlArrayCompareValues, MySqlRangeCompareValues, MySqlPatternCompareValues, MySqlNullConditionInput, MySqlConditions } from './@types/index.cjs';
7
8
  import type { MySql2Database } from 'drizzle-orm/mysql2';
8
9
  /********************************************************************************************************************
@@ -114,19 +115,28 @@ export declare class MySqlQuery<TTable extends MySqlTable, IV extends MySqlInser
114
115
  /********************************************************************************************************************
115
116
  * edit
116
117
  * ******************************************************************************************************************/
117
- edit(set: UV, where: BaseWhere<this>): Omit<import("drizzle-orm/mysql-core").MySqlAsyncUpdateBase<import("drizzle-orm").Assume<import("drizzle-orm").Assume<TTable, MySqlTable<import("drizzle-orm/mysql-core").TableConfig>>, MySqlTable<import("drizzle-orm/mysql-core").TableConfig>>, import("drizzle-orm/mysql2").MySql2QueryResultHKT, false, "where">, "where">;
118
+ edit(this: this & (TableMutationPolicy<TTable> extends {
119
+ updateBlocked: true;
120
+ } ? never : unknown), set: UV, where: BaseWhere<this>): Omit<import("drizzle-orm/mysql-core").MySqlAsyncUpdateBase<import("drizzle-orm").Assume<import("drizzle-orm").Assume<TTable, MySqlTable<import("drizzle-orm/mysql-core").TableConfig>>, MySqlTable<import("drizzle-orm/mysql-core").TableConfig>>, import("drizzle-orm/mysql2").MySql2QueryResultHKT, false, "where">, "where">;
118
121
  /********************************************************************************************************************
119
122
  * editByPrimaryKey
120
123
  * ******************************************************************************************************************/
121
- editByPrimaryKey(set: UV, key: PrimaryKeyInput<TTable>): Omit<import("drizzle-orm/mysql-core").MySqlAsyncUpdateBase<import("drizzle-orm").Assume<import("drizzle-orm").Assume<TTable, MySqlTable<import("drizzle-orm/mysql-core").TableConfig>>, MySqlTable<import("drizzle-orm/mysql-core").TableConfig>>, import("drizzle-orm/mysql2").MySql2QueryResultHKT, false, "where">, "where">;
124
+ editByPrimaryKey(this: this & (TableMutationPolicy<TTable> extends {
125
+ updateBlocked: true;
126
+ } ? never : unknown), set: UV, key: PrimaryKeyInput<TTable>): Omit<import("drizzle-orm/mysql-core").MySqlAsyncUpdateBase<import("drizzle-orm").Assume<import("drizzle-orm").Assume<TTable, MySqlTable<import("drizzle-orm/mysql-core").TableConfig>>, MySqlTable<import("drizzle-orm/mysql-core").TableConfig>>, import("drizzle-orm/mysql2").MySql2QueryResultHKT, false, "where">, "where">;
122
127
  /********************************************************************************************************************
123
128
  * remove
124
129
  * ******************************************************************************************************************/
125
- remove(where: BaseWhere<this>): Omit<import("drizzle-orm/mysql-core").MySqlAsyncDeleteBase<import("drizzle-orm").Assume<TTable, MySqlTable<import("drizzle-orm/mysql-core").TableConfig>>, import("drizzle-orm/mysql2").MySql2QueryResultHKT, false, "where">, "where">;
130
+ remove(this: this & (TableMutationPolicy<TTable> extends {
131
+ deleteBlocked: true;
132
+ } ? never : unknown), where: BaseWhere<this>): Omit<import("drizzle-orm/mysql-core").MySqlAsyncDeleteBase<import("drizzle-orm").Assume<TTable, MySqlTable<import("drizzle-orm/mysql-core").TableConfig>>, import("drizzle-orm/mysql2").MySql2QueryResultHKT, false, "where">, "where">;
126
133
  /********************************************************************************************************************
127
134
  * removeByPrimaryKey
128
135
  * ******************************************************************************************************************/
129
- removeByPrimaryKey(key: PrimaryKeyInput<TTable>): Omit<import("drizzle-orm/mysql-core").MySqlAsyncDeleteBase<import("drizzle-orm").Assume<TTable, MySqlTable<import("drizzle-orm/mysql-core").TableConfig>>, import("drizzle-orm/mysql2").MySql2QueryResultHKT, false, "where">, "where">;
136
+ removeByPrimaryKey(this: this & (TableMutationPolicy<TTable> extends {
137
+ deleteBlocked: true;
138
+ } ? never : unknown), key: PrimaryKeyInput<TTable>): Omit<import("drizzle-orm/mysql-core").MySqlAsyncDeleteBase<import("drizzle-orm").Assume<TTable, MySqlTable<import("drizzle-orm/mysql-core").TableConfig>>, import("drizzle-orm/mysql2").MySql2QueryResultHKT, false, "where">, "where">;
139
+ private assertMutationAllowed;
130
140
  /********************************************************************************************************************
131
141
  * eq
132
142
  * ******************************************************************************************************************/
@@ -3,6 +3,7 @@ import { MySqlTable, MySqlColumn, type MySqlAsyncSelectBase } from 'drizzle-orm/
3
3
  import type { SelectedFields } from 'drizzle-orm/operations';
4
4
  import type { GetSelectTableName } from 'drizzle-orm/query-builders/select.types';
5
5
  import type { MySqlColumnSelectionName, MySqlSelectedNamedColumnUnion, MySqlSelectedNamedColumns, MySqlSelectedTableColumns, MySqlAliasTable } from './columns.js';
6
+ import { type TableMutationPolicy } from './mysqlTable.js';
6
7
  import type { MySqlInsertValues, MySqlUpdateValues, MySqlCompareValues, MySqlColumnName, MySqlArrayCompareValues, MySqlRangeCompareValues, MySqlPatternCompareValues, MySqlNullConditionInput, MySqlConditions } from './@types/index.js';
7
8
  import type { MySql2Database } from 'drizzle-orm/mysql2';
8
9
  /********************************************************************************************************************
@@ -114,19 +115,28 @@ export declare class MySqlQuery<TTable extends MySqlTable, IV extends MySqlInser
114
115
  /********************************************************************************************************************
115
116
  * edit
116
117
  * ******************************************************************************************************************/
117
- edit(set: UV, where: BaseWhere<this>): Omit<import("drizzle-orm/mysql-core").MySqlAsyncUpdateBase<import("drizzle-orm").Assume<import("drizzle-orm").Assume<TTable, MySqlTable<import("drizzle-orm/mysql-core").TableConfig>>, MySqlTable<import("drizzle-orm/mysql-core").TableConfig>>, import("drizzle-orm/mysql2").MySql2QueryResultHKT, false, "where">, "where">;
118
+ edit(this: this & (TableMutationPolicy<TTable> extends {
119
+ updateBlocked: true;
120
+ } ? never : unknown), set: UV, where: BaseWhere<this>): Omit<import("drizzle-orm/mysql-core").MySqlAsyncUpdateBase<import("drizzle-orm").Assume<import("drizzle-orm").Assume<TTable, MySqlTable<import("drizzle-orm/mysql-core").TableConfig>>, MySqlTable<import("drizzle-orm/mysql-core").TableConfig>>, import("drizzle-orm/mysql2").MySql2QueryResultHKT, false, "where">, "where">;
118
121
  /********************************************************************************************************************
119
122
  * editByPrimaryKey
120
123
  * ******************************************************************************************************************/
121
- editByPrimaryKey(set: UV, key: PrimaryKeyInput<TTable>): Omit<import("drizzle-orm/mysql-core").MySqlAsyncUpdateBase<import("drizzle-orm").Assume<import("drizzle-orm").Assume<TTable, MySqlTable<import("drizzle-orm/mysql-core").TableConfig>>, MySqlTable<import("drizzle-orm/mysql-core").TableConfig>>, import("drizzle-orm/mysql2").MySql2QueryResultHKT, false, "where">, "where">;
124
+ editByPrimaryKey(this: this & (TableMutationPolicy<TTable> extends {
125
+ updateBlocked: true;
126
+ } ? never : unknown), set: UV, key: PrimaryKeyInput<TTable>): Omit<import("drizzle-orm/mysql-core").MySqlAsyncUpdateBase<import("drizzle-orm").Assume<import("drizzle-orm").Assume<TTable, MySqlTable<import("drizzle-orm/mysql-core").TableConfig>>, MySqlTable<import("drizzle-orm/mysql-core").TableConfig>>, import("drizzle-orm/mysql2").MySql2QueryResultHKT, false, "where">, "where">;
122
127
  /********************************************************************************************************************
123
128
  * remove
124
129
  * ******************************************************************************************************************/
125
- remove(where: BaseWhere<this>): Omit<import("drizzle-orm/mysql-core").MySqlAsyncDeleteBase<import("drizzle-orm").Assume<TTable, MySqlTable<import("drizzle-orm/mysql-core").TableConfig>>, import("drizzle-orm/mysql2").MySql2QueryResultHKT, false, "where">, "where">;
130
+ remove(this: this & (TableMutationPolicy<TTable> extends {
131
+ deleteBlocked: true;
132
+ } ? never : unknown), where: BaseWhere<this>): Omit<import("drizzle-orm/mysql-core").MySqlAsyncDeleteBase<import("drizzle-orm").Assume<TTable, MySqlTable<import("drizzle-orm/mysql-core").TableConfig>>, import("drizzle-orm/mysql2").MySql2QueryResultHKT, false, "where">, "where">;
126
133
  /********************************************************************************************************************
127
134
  * removeByPrimaryKey
128
135
  * ******************************************************************************************************************/
129
- removeByPrimaryKey(key: PrimaryKeyInput<TTable>): Omit<import("drizzle-orm/mysql-core").MySqlAsyncDeleteBase<import("drizzle-orm").Assume<TTable, MySqlTable<import("drizzle-orm/mysql-core").TableConfig>>, import("drizzle-orm/mysql2").MySql2QueryResultHKT, false, "where">, "where">;
136
+ removeByPrimaryKey(this: this & (TableMutationPolicy<TTable> extends {
137
+ deleteBlocked: true;
138
+ } ? never : unknown), key: PrimaryKeyInput<TTable>): Omit<import("drizzle-orm/mysql-core").MySqlAsyncDeleteBase<import("drizzle-orm").Assume<TTable, MySqlTable<import("drizzle-orm/mysql-core").TableConfig>>, import("drizzle-orm/mysql2").MySql2QueryResultHKT, false, "where">, "where">;
139
+ private assertMutationAllowed;
130
140
  /********************************************************************************************************************
131
141
  * eq
132
142
  * ******************************************************************************************************************/
package/dist/index.cjs CHANGED
@@ -1,4 +1,4 @@
1
- 'use strict';Object.defineProperty(exports,'__esModule',{value:true});var mysql=require('mysql2/promise'),mysql2=require('drizzle-orm/mysql2'),native=require('drizzle-orm'),node_async_hooks=require('node:async_hooks'),alias=require('drizzle-orm/mysql-core/alias'),mysqlCore=require('drizzle-orm/mysql-core'),columnBuilder=require('drizzle-orm/column-builder');function _interopNamespaceDefault(e){var n=Object.create(null);if(e){Object.keys(e).forEach(function(k){if(k!=='default'){var d=Object.getOwnPropertyDescriptor(e,k);Object.defineProperty(n,k,d.get?d:{enumerable:true,get:function(){return e[k]}});}})}n.default=e;return Object.freeze(n)}var native__namespace=/*#__PURE__*/_interopNamespaceDefault(native);function createAlias(schema) {
1
+ 'use strict';Object.defineProperty(exports,'__esModule',{value:true});var mysql=require('mysql2/promise'),mysql2=require('drizzle-orm/mysql2'),native=require('drizzle-orm'),node_async_hooks=require('node:async_hooks'),alias=require('drizzle-orm/mysql-core/alias'),mysqlCore=require('drizzle-orm/mysql-core'),common=require('drizzle-orm/mysql-core/columns/common');function _interopNamespaceDefault(e){var n=Object.create(null);if(e){Object.keys(e).forEach(function(k){if(k!=='default'){var d=Object.getOwnPropertyDescriptor(e,k);Object.defineProperty(n,k,d.get?d:{enumerable:true,get:function(){return e[k]}});}})}n.default=e;return Object.freeze(n)}var native__namespace=/*#__PURE__*/_interopNamespaceDefault(native);function createAlias(schema) {
2
2
  /********************************************************************************************************************
3
3
  * getDefaultAlias
4
4
  * ******************************************************************************************************************/
@@ -202,7 +202,7 @@ for (const [method, policy] of Object.entries({
202
202
  createdAt: { timestamp: 'created' },
203
203
  updatedAt: { timestamp: 'updated' },
204
204
  })) {
205
- Object.defineProperty(columnBuilder.ColumnBuilder.prototype, method, {
205
+ Object.defineProperty(common.MySqlColumnBuilder.prototype, method, {
206
206
  configurable: true,
207
207
  value: function () {
208
208
  policies.set(this, { ...policies.get(this), ...policy });
@@ -211,15 +211,28 @@ for (const [method, policy] of Object.entries({
211
211
  });
212
212
  }
213
213
  const tablePolicies = new WeakMap();
214
+ const tableMutationPolicies = new WeakMap();
214
215
  function getColumnPolicies(table) {
215
216
  return tablePolicies.get(table) ?? {};
216
217
  }
217
- function mysqlTable(name, columns, extraConfig) {
218
+ function getTablePolicy(table) {
219
+ return tableMutationPolicies.get(table) ?? {};
220
+ }
221
+ function mysqlTable(name, columns, extraConfigOrPolicy, policy) {
222
+ const extraConfig = typeof extraConfigOrPolicy === 'function' ? extraConfigOrPolicy : undefined;
223
+ const mutationPolicy = typeof extraConfigOrPolicy === 'object' ? extraConfigOrPolicy : policy;
224
+ const nativeExtraConfig = extraConfig
225
+ ? (self) => {
226
+ const config = extraConfig(self);
227
+ return Array.isArray(config) ? config : Object.values(config);
228
+ }
229
+ : undefined;
218
230
  let builders = {};
219
231
  const table = typeof columns === 'function'
220
- ? mysqlCore.mysqlTable(name, (types) => (builders = columns(types)), extraConfig)
221
- : mysqlCore.mysqlTable(name, (builders = columns), extraConfig);
232
+ ? mysqlCore.mysqlTable(name, (types) => (builders = columns(types)), nativeExtraConfig)
233
+ : mysqlCore.mysqlTable(name, (builders = columns), nativeExtraConfig);
222
234
  tablePolicies.set(table, Object.fromEntries(Object.entries(builders).map(([key, builder]) => [key, policies.get(builder) ?? {}])));
235
+ tableMutationPolicies.set(table, { ...mutationPolicy });
223
236
  return table;
224
237
  }/********************************************************************************************************************
225
238
  * MySqlQuery
@@ -419,9 +432,7 @@ class MySqlQuery {
419
432
  values[key] === undefined) {
420
433
  throw new Error(`update: column "${key}" is required.`);
421
434
  }
422
- if (policy.timestamp &&
423
- values[key] === undefined &&
424
- (operation === 'insert' || policy.timestamp === 'updated')) {
435
+ if (policy.timestamp && values[key] === undefined && (operation === 'insert' || policy.timestamp === 'updated')) {
425
436
  if (!generated) {
426
437
  const getTimestamp = this.getTimestamp ?? this.current.getTimestamp;
427
438
  if (!getTimestamp)
@@ -482,6 +493,7 @@ class MySqlQuery {
482
493
  * edit
483
494
  * ******************************************************************************************************************/
484
495
  edit(set, where) {
496
+ this.assertMutationAllowed('update', 'edit');
485
497
  const condition = typeof where === 'function' ? where(this) : where;
486
498
  if (!native.is(condition, native.SQL)) {
487
499
  throw new Error('edit: a SQL where condition is required.');
@@ -496,12 +508,14 @@ class MySqlQuery {
496
508
  * editByPrimaryKey
497
509
  * ******************************************************************************************************************/
498
510
  editByPrimaryKey(set, key) {
511
+ this.assertMutationAllowed('update', 'editByPrimaryKey');
499
512
  return this.edit(set, this.primaryKeyCondition(key, 'editByPrimaryKey'));
500
513
  }
501
514
  /********************************************************************************************************************
502
515
  * remove
503
516
  * ******************************************************************************************************************/
504
517
  remove(where) {
518
+ this.assertMutationAllowed('delete', 'remove');
505
519
  const condition = typeof where === 'function' ? where(this) : where;
506
520
  if (!native.is(condition, native.SQL)) {
507
521
  throw new Error('remove: a SQL where condition is required.');
@@ -513,8 +527,15 @@ class MySqlQuery {
513
527
  * removeByPrimaryKey
514
528
  * ******************************************************************************************************************/
515
529
  removeByPrimaryKey(key) {
530
+ this.assertMutationAllowed('delete', 'removeByPrimaryKey');
516
531
  return this.remove(this.primaryKeyCondition(key, 'removeByPrimaryKey'));
517
532
  }
533
+ assertMutationAllowed(operation, method) {
534
+ const policy = getTablePolicy(this.t);
535
+ if (operation === 'update' ? policy.updateBlocked : policy.deleteBlocked) {
536
+ throw new Error(`${method}: ${operation} is blocked for table "${mysqlCore.getTableConfig(this.t).name}".`);
537
+ }
538
+ }
518
539
  /********************************************************************************************************************
519
540
  * eq
520
541
  * ******************************************************************************************************************/
package/dist/index.d.cts CHANGED
@@ -2,7 +2,7 @@ import { drizzleMySql } from './drizzleMySql.cjs';
2
2
  export default drizzleMySql;
3
3
  export * from './@types/index.cjs';
4
4
  export * from './columns.cjs';
5
- export { mysqlTable } from './mysqlTable.cjs';
5
+ export { mysqlTable, type TablePolicy } from './mysqlTable.cjs';
6
6
  export * from './conditions.cjs';
7
7
  export * from './drizzleMySql.cjs';
8
8
  export * from './MySqlQuery.cjs';
package/dist/index.d.ts CHANGED
@@ -2,7 +2,7 @@ import { drizzleMySql } from './drizzleMySql.js';
2
2
  export default drizzleMySql;
3
3
  export * from './@types/index.js';
4
4
  export * from './columns.js';
5
- export { mysqlTable } from './mysqlTable.js';
5
+ export { mysqlTable, type TablePolicy } from './mysqlTable.js';
6
6
  export * from './conditions.js';
7
7
  export * from './drizzleMySql.js';
8
8
  export * from './MySqlQuery.js';
package/dist/index.esm.js CHANGED
@@ -1,4 +1,4 @@
1
- import mysql from'mysql2/promise';import {drizzle}from'drizzle-orm/mysql2';import*as native from'drizzle-orm';import {isTable,getTableColumns,sql,is,SQL,eq,and,count,defineRelations}from'drizzle-orm';export{asc,avg,avgDistinct,count,countDistinct,desc,exists,max,min,not,notExists,sum,sumDistinct}from'drizzle-orm';import {AsyncLocalStorage}from'node:async_hooks';import {alias}from'drizzle-orm/mysql-core/alias';import {MySqlTable,mysqlTable as mysqlTable$1,getTableConfig,MySqlColumn}from'drizzle-orm/mysql-core';export{bigint,binary,blob,boolean,char,check,customType,date,datetime,decimal,double,float,foreignKey,index,int,json,longblob,longtext,mediumblob,mediumint,mediumtext,mysqlDatabase,mysqlEnum,mysqlSchema,mysqlTableCreator,mysqlView,primaryKey,real,serial,smallint,text,time,timestamp,tinyblob,tinyint,tinytext,unique,uniqueIndex,varbinary,varchar,year}from'drizzle-orm/mysql-core';import {ColumnBuilder}from'drizzle-orm/column-builder';function createAlias(schema) {
1
+ import mysql from'mysql2/promise';import {drizzle}from'drizzle-orm/mysql2';import*as native from'drizzle-orm';import {isTable,getTableColumns,sql,is,SQL,eq,and,count,defineRelations}from'drizzle-orm';export{asc,avg,avgDistinct,count,countDistinct,desc,exists,max,min,not,notExists,sum,sumDistinct}from'drizzle-orm';import {AsyncLocalStorage}from'node:async_hooks';import {alias}from'drizzle-orm/mysql-core/alias';import {MySqlTable,mysqlTable as mysqlTable$1,getTableConfig,MySqlColumn}from'drizzle-orm/mysql-core';export{bigint,binary,blob,boolean,char,check,customType,date,datetime,decimal,double,float,foreignKey,index,int,json,longblob,longtext,mediumblob,mediumint,mediumtext,mysqlDatabase,mysqlEnum,mysqlSchema,mysqlTableCreator,mysqlView,primaryKey,real,serial,smallint,text,time,timestamp,tinyblob,tinyint,tinytext,unique,uniqueIndex,varbinary,varchar,year}from'drizzle-orm/mysql-core';import {MySqlColumnBuilder}from'drizzle-orm/mysql-core/columns/common';function createAlias(schema) {
2
2
  /********************************************************************************************************************
3
3
  * getDefaultAlias
4
4
  * ******************************************************************************************************************/
@@ -202,7 +202,7 @@ for (const [method, policy] of Object.entries({
202
202
  createdAt: { timestamp: 'created' },
203
203
  updatedAt: { timestamp: 'updated' },
204
204
  })) {
205
- Object.defineProperty(ColumnBuilder.prototype, method, {
205
+ Object.defineProperty(MySqlColumnBuilder.prototype, method, {
206
206
  configurable: true,
207
207
  value: function () {
208
208
  policies.set(this, { ...policies.get(this), ...policy });
@@ -211,15 +211,28 @@ for (const [method, policy] of Object.entries({
211
211
  });
212
212
  }
213
213
  const tablePolicies = new WeakMap();
214
+ const tableMutationPolicies = new WeakMap();
214
215
  function getColumnPolicies(table) {
215
216
  return tablePolicies.get(table) ?? {};
216
217
  }
217
- function mysqlTable(name, columns, extraConfig) {
218
+ function getTablePolicy(table) {
219
+ return tableMutationPolicies.get(table) ?? {};
220
+ }
221
+ function mysqlTable(name, columns, extraConfigOrPolicy, policy) {
222
+ const extraConfig = typeof extraConfigOrPolicy === 'function' ? extraConfigOrPolicy : undefined;
223
+ const mutationPolicy = typeof extraConfigOrPolicy === 'object' ? extraConfigOrPolicy : policy;
224
+ const nativeExtraConfig = extraConfig
225
+ ? (self) => {
226
+ const config = extraConfig(self);
227
+ return Array.isArray(config) ? config : Object.values(config);
228
+ }
229
+ : undefined;
218
230
  let builders = {};
219
231
  const table = typeof columns === 'function'
220
- ? mysqlTable$1(name, (types) => (builders = columns(types)), extraConfig)
221
- : mysqlTable$1(name, (builders = columns), extraConfig);
232
+ ? mysqlTable$1(name, (types) => (builders = columns(types)), nativeExtraConfig)
233
+ : mysqlTable$1(name, (builders = columns), nativeExtraConfig);
222
234
  tablePolicies.set(table, Object.fromEntries(Object.entries(builders).map(([key, builder]) => [key, policies.get(builder) ?? {}])));
235
+ tableMutationPolicies.set(table, { ...mutationPolicy });
223
236
  return table;
224
237
  }/********************************************************************************************************************
225
238
  * MySqlQuery
@@ -419,9 +432,7 @@ class MySqlQuery {
419
432
  values[key] === undefined) {
420
433
  throw new Error(`update: column "${key}" is required.`);
421
434
  }
422
- if (policy.timestamp &&
423
- values[key] === undefined &&
424
- (operation === 'insert' || policy.timestamp === 'updated')) {
435
+ if (policy.timestamp && values[key] === undefined && (operation === 'insert' || policy.timestamp === 'updated')) {
425
436
  if (!generated) {
426
437
  const getTimestamp = this.getTimestamp ?? this.current.getTimestamp;
427
438
  if (!getTimestamp)
@@ -482,6 +493,7 @@ class MySqlQuery {
482
493
  * edit
483
494
  * ******************************************************************************************************************/
484
495
  edit(set, where) {
496
+ this.assertMutationAllowed('update', 'edit');
485
497
  const condition = typeof where === 'function' ? where(this) : where;
486
498
  if (!is(condition, SQL)) {
487
499
  throw new Error('edit: a SQL where condition is required.');
@@ -496,12 +508,14 @@ class MySqlQuery {
496
508
  * editByPrimaryKey
497
509
  * ******************************************************************************************************************/
498
510
  editByPrimaryKey(set, key) {
511
+ this.assertMutationAllowed('update', 'editByPrimaryKey');
499
512
  return this.edit(set, this.primaryKeyCondition(key, 'editByPrimaryKey'));
500
513
  }
501
514
  /********************************************************************************************************************
502
515
  * remove
503
516
  * ******************************************************************************************************************/
504
517
  remove(where) {
518
+ this.assertMutationAllowed('delete', 'remove');
505
519
  const condition = typeof where === 'function' ? where(this) : where;
506
520
  if (!is(condition, SQL)) {
507
521
  throw new Error('remove: a SQL where condition is required.');
@@ -513,8 +527,15 @@ class MySqlQuery {
513
527
  * removeByPrimaryKey
514
528
  * ******************************************************************************************************************/
515
529
  removeByPrimaryKey(key) {
530
+ this.assertMutationAllowed('delete', 'removeByPrimaryKey');
516
531
  return this.remove(this.primaryKeyCondition(key, 'removeByPrimaryKey'));
517
532
  }
533
+ assertMutationAllowed(operation, method) {
534
+ const policy = getTablePolicy(this.t);
535
+ if (operation === 'update' ? policy.updateBlocked : policy.deleteBlocked) {
536
+ throw new Error(`${method}: ${operation} is blocked for table "${getTableConfig(this.t).name}".`);
537
+ }
538
+ }
518
539
  /********************************************************************************************************************
519
540
  * eq
520
541
  * ******************************************************************************************************************/
@@ -1,4 +1,4 @@
1
- import { type ColumnBuilderBase } from 'drizzle-orm/column-builder';
1
+ import type { ColumnBuilderBase, ColumnBuilderBaseConfig, ColumnBuilderExtraConfig, ColumnType } from 'drizzle-orm/column-builder';
2
2
  import { type MySqlTable, type MySqlTableWithColumns } from 'drizzle-orm/mysql-core';
3
3
  import type { BuildColumns } from 'drizzle-orm/column-builder';
4
4
  import type { MySqlColumnBuilders } from 'drizzle-orm/mysql-core/columns/all';
@@ -8,13 +8,18 @@ export type ColumnPolicy = {
8
8
  update?: 'blocked' | 'allowed' | 'required';
9
9
  timestamp?: 'created' | 'updated';
10
10
  };
11
+ export type TablePolicy = {
12
+ updateBlocked?: boolean;
13
+ deleteBlocked?: boolean;
14
+ };
11
15
  declare const policyType: unique symbol;
12
16
  declare const tablePolicyType: unique symbol;
17
+ declare const tableMutationPolicyType: unique symbol;
13
18
  type Mark<T, P extends ColumnPolicy> = T & {
14
19
  readonly [policyType]: P;
15
20
  };
16
- declare module 'drizzle-orm/column-builder' {
17
- interface ColumnBuilder<T, TRuntimeConfig, TExtraConfig> {
21
+ declare module 'drizzle-orm/mysql-core/columns/common' {
22
+ interface MySqlColumnBuilder<T extends ColumnBuilderBaseConfig<ColumnType>, TRuntimeConfig extends object, TExtraConfig extends ColumnBuilderExtraConfig> {
18
23
  insertBlocked(): Mark<this, {
19
24
  insert: 'blocked';
20
25
  }>;
@@ -46,7 +51,10 @@ type Policies<C> = {
46
51
  export type TablePolicies<T> = T extends {
47
52
  readonly [tablePolicyType]: infer P;
48
53
  } ? P : {};
49
- type TableResult<N extends string, C extends Record<string, ColumnBuilderBase>> = MySqlTableWithColumns<{
54
+ export type TableMutationPolicy<T> = T extends {
55
+ readonly [tableMutationPolicyType]: infer P;
56
+ } ? P : {};
57
+ type TableResult<N extends string, C extends Record<string, ColumnBuilderBase>, P extends TablePolicy> = MySqlTableWithColumns<{
50
58
  name: N;
51
59
  schema: undefined;
52
60
  columns: BuildColumns<N, C, 'mysql'>;
@@ -54,7 +62,10 @@ type TableResult<N extends string, C extends Record<string, ColumnBuilderBase>>
54
62
  isAlias: false;
55
63
  }> & {
56
64
  readonly [tablePolicyType]: Policies<C>;
65
+ readonly [tableMutationPolicyType]: P;
57
66
  };
58
67
  export declare function getColumnPolicies(table: MySqlTable): Record<string, ColumnPolicy>;
59
- export declare function mysqlTable<N extends string, C extends Record<string, ColumnBuilderBase>>(name: N, columns: C | ((types: MySqlColumnBuilders) => C), extraConfig?: (self: BuildColumns<N, C, 'mysql'>) => MySqlTableExtraConfig | (MySqlTableExtraConfigValue | MySqlTableExtraConfigValue[])[]): TableResult<N, C>;
68
+ export declare function getTablePolicy(table: MySqlTable): TablePolicy;
69
+ type ExtraConfig<N extends string, C extends Record<string, ColumnBuilderBase>> = (self: BuildColumns<N, C, 'mysql'>) => MySqlTableExtraConfig | (MySqlTableExtraConfigValue | MySqlTableExtraConfigValue[])[];
70
+ export declare function mysqlTable<N extends string, C extends Record<string, ColumnBuilderBase>, const P extends TablePolicy = {}, const Q extends TablePolicy = {}>(name: N, columns: C | ((types: MySqlColumnBuilders) => C), extraConfigOrPolicy?: ExtraConfig<N, C> | (P & TablePolicy), policy?: Q & TablePolicy): TableResult<N, C, P & Q>;
60
71
  export {};
@@ -1,4 +1,4 @@
1
- import { type ColumnBuilderBase } from 'drizzle-orm/column-builder';
1
+ import type { ColumnBuilderBase, ColumnBuilderBaseConfig, ColumnBuilderExtraConfig, ColumnType } from 'drizzle-orm/column-builder';
2
2
  import { type MySqlTable, type MySqlTableWithColumns } from 'drizzle-orm/mysql-core';
3
3
  import type { BuildColumns } from 'drizzle-orm/column-builder';
4
4
  import type { MySqlColumnBuilders } from 'drizzle-orm/mysql-core/columns/all';
@@ -8,13 +8,18 @@ export type ColumnPolicy = {
8
8
  update?: 'blocked' | 'allowed' | 'required';
9
9
  timestamp?: 'created' | 'updated';
10
10
  };
11
+ export type TablePolicy = {
12
+ updateBlocked?: boolean;
13
+ deleteBlocked?: boolean;
14
+ };
11
15
  declare const policyType: unique symbol;
12
16
  declare const tablePolicyType: unique symbol;
17
+ declare const tableMutationPolicyType: unique symbol;
13
18
  type Mark<T, P extends ColumnPolicy> = T & {
14
19
  readonly [policyType]: P;
15
20
  };
16
- declare module 'drizzle-orm/column-builder' {
17
- interface ColumnBuilder<T, TRuntimeConfig, TExtraConfig> {
21
+ declare module 'drizzle-orm/mysql-core/columns/common' {
22
+ interface MySqlColumnBuilder<T extends ColumnBuilderBaseConfig<ColumnType>, TRuntimeConfig extends object, TExtraConfig extends ColumnBuilderExtraConfig> {
18
23
  insertBlocked(): Mark<this, {
19
24
  insert: 'blocked';
20
25
  }>;
@@ -46,7 +51,10 @@ type Policies<C> = {
46
51
  export type TablePolicies<T> = T extends {
47
52
  readonly [tablePolicyType]: infer P;
48
53
  } ? P : {};
49
- type TableResult<N extends string, C extends Record<string, ColumnBuilderBase>> = MySqlTableWithColumns<{
54
+ export type TableMutationPolicy<T> = T extends {
55
+ readonly [tableMutationPolicyType]: infer P;
56
+ } ? P : {};
57
+ type TableResult<N extends string, C extends Record<string, ColumnBuilderBase>, P extends TablePolicy> = MySqlTableWithColumns<{
50
58
  name: N;
51
59
  schema: undefined;
52
60
  columns: BuildColumns<N, C, 'mysql'>;
@@ -54,7 +62,10 @@ type TableResult<N extends string, C extends Record<string, ColumnBuilderBase>>
54
62
  isAlias: false;
55
63
  }> & {
56
64
  readonly [tablePolicyType]: Policies<C>;
65
+ readonly [tableMutationPolicyType]: P;
57
66
  };
58
67
  export declare function getColumnPolicies(table: MySqlTable): Record<string, ColumnPolicy>;
59
- export declare function mysqlTable<N extends string, C extends Record<string, ColumnBuilderBase>>(name: N, columns: C | ((types: MySqlColumnBuilders) => C), extraConfig?: (self: BuildColumns<N, C, 'mysql'>) => MySqlTableExtraConfig | (MySqlTableExtraConfigValue | MySqlTableExtraConfigValue[])[]): TableResult<N, C>;
68
+ export declare function getTablePolicy(table: MySqlTable): TablePolicy;
69
+ type ExtraConfig<N extends string, C extends Record<string, ColumnBuilderBase>> = (self: BuildColumns<N, C, 'mysql'>) => MySqlTableExtraConfig | (MySqlTableExtraConfigValue | MySqlTableExtraConfigValue[])[];
70
+ export declare function mysqlTable<N extends string, C extends Record<string, ColumnBuilderBase>, const P extends TablePolicy = {}, const Q extends TablePolicy = {}>(name: N, columns: C | ((types: MySqlColumnBuilders) => C), extraConfigOrPolicy?: ExtraConfig<N, C> | (P & TablePolicy), policy?: Q & TablePolicy): TableResult<N, C, P & Q>;
60
71
  export {};
package/package.json CHANGED
@@ -2,7 +2,7 @@
2
2
  "name": "@pdg/drizzle-mysql",
3
3
  "title": "Drizzle for MySql",
4
4
  "description": "Drizzle for MySql",
5
- "version": "1.0.3",
5
+ "version": "1.0.5",
6
6
  "type": "module",
7
7
  "main": "./dist/index.cjs",
8
8
  "module": "./dist/index.esm.js",