@aws-blocks/bb-distributed-data 0.1.3 → 0.1.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/DESIGN.md CHANGED
@@ -75,6 +75,7 @@ The core insight: PGlite supports everything DSQL doesn't. Without validation, c
75
75
  | `SET TRANSACTION ISOLATION LEVEL` | Fixed Repeatable Read |
76
76
  | `COLLATE` | C collation only |
77
77
  | `CREATE INDEX ... ASC/DESC` | Sort direction on index keys (NULLS FIRST/LAST is allowed) |
78
+ | `ALTER TABLE ... DROP [COLUMN]` | Not in DSQL's supported ALTER TABLE subset (`DROP CONSTRAINT` and `ALTER COLUMN ... DROP DEFAULT/NOT NULL/EXPRESSION/IDENTITY` are supported) |
78
79
 
79
80
  ### Transaction Tracking
80
81
 
package/README.md CHANGED
@@ -109,6 +109,7 @@ DSQL is a subset of PostgreSQL. The local mock enforces these restrictions so co
109
109
  | Extensions | Not available |
110
110
  | ADD COLUMN with DEFAULT | Add column without default, handle nulls in app |
111
111
  | Index key sort direction (`ASC`/`DESC`) | Omit it; enforce ordering with `ORDER BY` in queries (`NULLS FIRST/LAST` is supported) |
112
+ | `ALTER TABLE DROP [COLUMN]` | Leave the column in place and stop referencing it; or rebuild the table (create new → `INSERT INTO ... SELECT` → `DROP` → `RENAME TO`, one migration file per step) |
112
113
 
113
114
  ### Transaction Constraints
114
115
 
@@ -157,6 +157,10 @@ describe('DsqlMockEngine — CREATE INDEX ASYNC parity', () => {
157
157
  it('rejects CREATE INDEX ASYNC with a DESC sort order on a key', async () => {
158
158
  await assert.rejects(() => engine.withDdl(() => db.execute(sql `CREATE INDEX ASYNC idx_users_email_desc ON users (email DESC)`)), /sort order/i);
159
159
  });
160
+ it('rejects ALTER TABLE DROP COLUMN', async () => {
161
+ await engine.withDdl(() => db.execute(sql `CREATE TABLE legacy (id TEXT PRIMARY KEY, obsolete TEXT)`));
162
+ await assert.rejects(() => engine.withDdl(() => db.execute(sql `ALTER TABLE legacy DROP COLUMN obsolete`)), /DROP COLUMN/i);
163
+ });
160
164
  it('does not strip ASYNC outside of CREATE INDEX (column named "async")', async () => {
161
165
  await engine.withDdl(() => db.execute(sql `CREATE TABLE jobs (id TEXT PRIMARY KEY, async BOOLEAN)`));
162
166
  await db.execute(sql `INSERT INTO jobs (id, async) VALUES (${'j1'}, ${true})`);
@@ -1 +1 @@
1
- {"version":3,"file":"index.aws.d.ts","sourceRoot":"","sources":["../src/index.aws.ts"],"names":[],"mappings":"AAGA;;;GAGG;AAEH,OAAO,EAAE,KAAK,EAA0B,MAAM,kBAAkB,CAAC;AACjE,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAC;AACpD,OAAO,EAAgB,KAAK,QAAQ,EAAE,KAAK,WAAW,EAAE,MAAM,yBAAyB,CAAC;AAIxF,OAAO,KAAK,EAAE,0BAA0B,EAAE,kBAAkB,EAAE,MAAM,YAAY,CAAC;AAGjF,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,uBAAuB,CAAC;AAEzD,qBAAa,mBAAoB,SAAQ,KAAK;IAC5C,OAAO,CAAC,KAAK,CAA6B;IAE1C,2FAA2F;IAC3F,SAAS,CAAC,GAAG,EAAE,WAAW,CAAC;gBAEf,KAAK,EAAE,WAAW,EAAE,EAAE,EAAE,MAAM,EAAE,QAAQ,CAAC,EAAE,0BAA0B;IAQjF,OAAO,KAAK,IAAI,GAiBf;IAED,KAAK,CAAC,CAAC,EAAE,KAAK,EAAE,QAAQ,GAAG,OAAO,CAAC,CAAC,EAAE,CAAC;IACvC,QAAQ,CAAC,CAAC,EAAE,KAAK,EAAE,QAAQ,GAAG,OAAO,CAAC,CAAC,GAAG,IAAI,CAAC;IAC/C,OAAO,CAAC,KAAK,EAAE,QAAQ,GAAG,OAAO,CAAC;QAAE,QAAQ,EAAE,MAAM,CAAA;KAAE,CAAC;IAEvD;;;;;OAKG;IACG,WAAW,CAAC,CAAC,EAAE,EAAE,EAAE,CAAC,EAAE,EAAE,WAAW,KAAK,OAAO,CAAC,CAAC,CAAC,EAAE,OAAO,CAAC,EAAE,kBAAkB,GAAG,OAAO,CAAC,CAAC,CAAC;IAInG,gBAAgB;IAChB,SAAS;CACV;AAED,OAAO,EAAE,GAAG,EAAE,mBAAmB,EAAE,MAAM,yBAAyB,CAAC;AACnE,YAAY,EAAE,QAAQ,EAAE,WAAW,EAAE,MAAM,yBAAyB,CAAC;AACrE,OAAO,EAAE,yBAAyB,EAAE,MAAM,aAAa,CAAC;AACxD,YAAY,EAAE,0BAA0B,EAAE,kBAAkB,EAAE,MAAM,YAAY,CAAC"}
1
+ {"version":3,"file":"index.aws.d.ts","sourceRoot":"","sources":["../src/index.aws.ts"],"names":[],"mappings":"AAGA;;;GAGG;AAEH,OAAO,EAAE,KAAK,EAA0B,MAAM,kBAAkB,CAAC;AACjE,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAC;AACpD,OAAO,EAAgB,KAAK,QAAQ,EAAE,KAAK,WAAW,EAAE,MAAM,yBAAyB,CAAC;AAIxF,OAAO,KAAK,EAAE,0BAA0B,EAAE,kBAAkB,EAAE,MAAM,YAAY,CAAC;AAGjF,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,uBAAuB,CAAC;AAGzD,qBAAa,mBAAoB,SAAQ,KAAK;IAC5C,OAAO,CAAC,KAAK,CAA6B;IAE1C,2FAA2F;IAC3F,SAAS,CAAC,GAAG,EAAE,WAAW,CAAC;gBAEf,KAAK,EAAE,WAAW,EAAE,EAAE,EAAE,MAAM,EAAE,QAAQ,CAAC,EAAE,0BAA0B;IAQjF,OAAO,KAAK,IAAI,GAiBf;IAED,KAAK,CAAC,CAAC,EAAE,KAAK,EAAE,QAAQ,GAAG,OAAO,CAAC,CAAC,EAAE,CAAC;IACvC,QAAQ,CAAC,CAAC,EAAE,KAAK,EAAE,QAAQ,GAAG,OAAO,CAAC,CAAC,GAAG,IAAI,CAAC;IAC/C,OAAO,CAAC,KAAK,EAAE,QAAQ,GAAG,OAAO,CAAC;QAAE,QAAQ,EAAE,MAAM,CAAA;KAAE,CAAC;IAEvD;;;;;OAKG;IACG,WAAW,CAAC,CAAC,EAAE,EAAE,EAAE,CAAC,EAAE,EAAE,WAAW,KAAK,OAAO,CAAC,CAAC,CAAC,EAAE,OAAO,CAAC,EAAE,kBAAkB,GAAG,OAAO,CAAC,CAAC,CAAC;IAInG,gBAAgB;IAChB,SAAS;CACV;AAED,OAAO,EAAE,GAAG,EAAE,mBAAmB,EAAE,MAAM,yBAAyB,CAAC;AACnE,YAAY,EAAE,QAAQ,EAAE,WAAW,EAAE,MAAM,yBAAyB,CAAC;AACrE,OAAO,EAAE,yBAAyB,EAAE,MAAM,aAAa,CAAC;AACxD,YAAY,EAAE,0BAA0B,EAAE,kBAAkB,EAAE,MAAM,YAAY,CAAC"}
package/dist/index.aws.js CHANGED
@@ -11,12 +11,13 @@ import { DsqlEngine } from './engines/dsql-engine.js';
11
11
  import { transactionWithRetry } from './transaction.js';
12
12
  import { ENV_SANITIZE, sanitizeDbRoleName } from './constants.js';
13
13
  import { Logger } from '@aws-blocks/bb-logger';
14
+ import { BB_NAME, BB_VERSION } from './version.js';
14
15
  export class DistributedDatabase extends Scope {
15
16
  _base = null;
16
17
  /** @internal Logger for internal operations. Defaults to error-level when not provided. */
17
18
  log;
18
19
  constructor(scope, id, _options) {
19
- super(id, { parent: scope });
20
+ super(id, { parent: scope, bbName: BB_NAME, bbVersion: BB_VERSION });
20
21
  this.log = _options?.logger ?? new Logger(this, 'logger', { level: 'error' });
21
22
  const envName = this.fullId.replace(ENV_SANITIZE, '_');
22
23
  const clusterEndpoint = process.env[`BLOCKS_${envName}_ENDPOINT`] ?? '';
@@ -8,6 +8,13 @@ import type { ScopeParent } from '@aws-blocks/core';
8
8
  import type { DistributedDatabaseOptions } from './types.js';
9
9
  export declare class DistributedDatabase extends Scope {
10
10
  constructor(scope: ScopeParent, id: string, options?: DistributedDatabaseOptions);
11
+ /**
12
+ * Runtime-only. This is the CDK (synth) build: it defines infrastructure and
13
+ * has no engine — queries run in the app Lambda against the deployed cluster.
14
+ * `createKyselyAdapter()` no longer calls this eagerly, so reaching it means a
15
+ * query ran at synth time (e.g. at module scope).
16
+ */
17
+ getEngine(): never;
11
18
  }
12
19
  export { sql, createKyselyAdapter } from '@aws-blocks/data-common';
13
20
  export type { SqlQuery, Transaction } from '@aws-blocks/data-common';
@@ -1 +1 @@
1
- {"version":3,"file":"index.cdk.d.ts","sourceRoot":"","sources":["../src/index.cdk.ts"],"names":[],"mappings":"AAGA;;;;GAIG;AAEH,OAAO,EAAE,KAAK,EAAwB,MAAM,sBAAsB,CAAC;AACnE,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAC;AAQpD,OAAO,KAAK,EAAE,0BAA0B,EAAE,MAAM,YAAY,CAAC;AAG7D,qBAAa,mBAAoB,SAAQ,KAAK;gBAChC,KAAK,EAAE,WAAW,EAAE,EAAE,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,0BAA0B;CAwFjF;AAaD,OAAO,EAAE,GAAG,EAAE,mBAAmB,EAAE,MAAM,yBAAyB,CAAC;AACnE,YAAY,EAAE,QAAQ,EAAE,WAAW,EAAE,MAAM,yBAAyB,CAAC;AACrE,OAAO,EAAE,yBAAyB,EAAE,MAAM,aAAa,CAAC;AACxD,YAAY,EAAE,0BAA0B,EAAE,MAAM,YAAY,CAAC"}
1
+ {"version":3,"file":"index.cdk.d.ts","sourceRoot":"","sources":["../src/index.cdk.ts"],"names":[],"mappings":"AAGA;;;;GAIG;AAEH,OAAO,EAAE,KAAK,EAAoC,MAAM,sBAAsB,CAAC;AAC/E,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAC;AAQpD,OAAO,KAAK,EAAE,0BAA0B,EAAE,MAAM,YAAY,CAAC;AAG7D,qBAAa,mBAAoB,SAAQ,KAAK;gBAChC,KAAK,EAAE,WAAW,EAAE,EAAE,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,0BAA0B;IAyFhF;;;;;OAKG;IACH,SAAS,IAAI,KAAK;CAGnB;AAaD,OAAO,EAAE,GAAG,EAAE,mBAAmB,EAAE,MAAM,yBAAyB,CAAC;AACnE,YAAY,EAAE,QAAQ,EAAE,WAAW,EAAE,MAAM,yBAAyB,CAAC;AACrE,OAAO,EAAE,yBAAyB,EAAE,MAAM,aAAa,CAAC;AACxD,YAAY,EAAE,0BAA0B,EAAE,MAAM,YAAY,CAAC"}
package/dist/index.cdk.js CHANGED
@@ -5,7 +5,7 @@
5
5
  * Provisions Aurora DSQL cluster via CloudFormation.
6
6
  * Optionally runs migrations via a CustomResource Lambda.
7
7
  */
8
- import { Scope, DEFAULT_NODE_RUNTIME } from '@aws-blocks/core/cdk';
8
+ import { Scope, DEFAULT_NODE_RUNTIME, synthGuard } from '@aws-blocks/core/cdk';
9
9
  import * as cdk from 'aws-cdk-lib';
10
10
  import * as iam from 'aws-cdk-lib/aws-iam';
11
11
  import * as lambda from 'aws-cdk-lib/aws-lambda-nodejs';
@@ -88,6 +88,15 @@ export class DistributedDatabase extends Scope {
88
88
  // Ensure migrations run after cluster is created
89
89
  migrationCR.node.addDependency(cluster);
90
90
  }
91
+ /**
92
+ * Runtime-only. This is the CDK (synth) build: it defines infrastructure and
93
+ * has no engine — queries run in the app Lambda against the deployed cluster.
94
+ * `createKyselyAdapter()` no longer calls this eagerly, so reaching it means a
95
+ * query ran at synth time (e.g. at module scope).
96
+ */
97
+ getEngine() {
98
+ return synthGuard('DistributedDatabase', 'getEngine');
99
+ }
91
100
  }
92
101
  /** Hash all .sql files in a directory to detect changes. */
93
102
  function hashMigrationsDir(dir) {
@@ -1 +1 @@
1
- {"version":3,"file":"index.mock.d.ts","sourceRoot":"","sources":["../src/index.mock.ts"],"names":[],"mappings":"AAGA;;;GAGG;AAEH,OAAO,EAAE,KAAK,EAA0B,MAAM,kBAAkB,CAAC;AACjE,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAC;AACpD,OAAO,EAAgB,KAAK,QAAQ,EAAE,KAAK,WAAW,EAAE,MAAM,yBAAyB,CAAC;AAIxF,OAAO,KAAK,EAAE,0BAA0B,EAAE,kBAAkB,EAAE,MAAM,YAAY,CAAC;AAEjF,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,uBAAuB,CAAC;AAEzD,qBAAa,mBAAoB,SAAQ,KAAK;IAC5C,OAAO,CAAC,IAAI,CAAe;IAC3B,OAAO,CAAC,UAAU,CAAiB;IACnC,OAAO,CAAC,aAAa,CAA8B;IAEnD,2FAA2F;IAC3F,SAAS,CAAC,GAAG,EAAE,WAAW,CAAC;gBAEf,KAAK,EAAE,WAAW,EAAE,EAAE,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,0BAA0B;YAelE,KAAK;IAEnB,KAAK,CAAC,CAAC,EAAE,KAAK,EAAE,QAAQ,GAAG,OAAO,CAAC,CAAC,EAAE,CAAC;IACvC,QAAQ,CAAC,CAAC,EAAE,KAAK,EAAE,QAAQ,GAAG,OAAO,CAAC,CAAC,GAAG,IAAI,CAAC;IAC/C,OAAO,CAAC,KAAK,EAAE,QAAQ,GAAG,OAAO,CAAC;QAAE,QAAQ,EAAE,MAAM,CAAA;KAAE,CAAC;IAEvD;;;;;OAKG;IACG,WAAW,CAAC,CAAC,EAAE,EAAE,EAAE,CAAC,EAAE,EAAE,WAAW,KAAK,OAAO,CAAC,CAAC,CAAC,EAAE,OAAO,CAAC,EAAE,kBAAkB,GAAG,OAAO,CAAC,CAAC,CAAC;IAKnG,yDAAyD;IACzD,gBAAgB,IAAI,IAAI;IAExB,gBAAgB;IAChB,SAAS;CACV;AAED,OAAO,EAAE,GAAG,EAAE,mBAAmB,EAAE,MAAM,yBAAyB,CAAC;AACnE,YAAY,EAAE,QAAQ,EAAE,WAAW,EAAE,MAAM,yBAAyB,CAAC;AACrE,OAAO,EAAE,yBAAyB,EAAE,MAAM,aAAa,CAAC;AACxD,YAAY,EAAE,0BAA0B,EAAE,kBAAkB,EAAE,MAAM,YAAY,CAAC"}
1
+ {"version":3,"file":"index.mock.d.ts","sourceRoot":"","sources":["../src/index.mock.ts"],"names":[],"mappings":"AAGA;;;GAGG;AAEH,OAAO,EAAE,KAAK,EAA0B,MAAM,kBAAkB,CAAC;AACjE,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAC;AACpD,OAAO,EAAgB,KAAK,QAAQ,EAAE,KAAK,WAAW,EAAE,MAAM,yBAAyB,CAAC;AAIxF,OAAO,KAAK,EAAE,0BAA0B,EAAE,kBAAkB,EAAE,MAAM,YAAY,CAAC;AAEjF,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,uBAAuB,CAAC;AAGzD,qBAAa,mBAAoB,SAAQ,KAAK;IAC5C,OAAO,CAAC,IAAI,CAAe;IAC3B,OAAO,CAAC,UAAU,CAAiB;IACnC,OAAO,CAAC,aAAa,CAA8B;IAEnD,2FAA2F;IAC3F,SAAS,CAAC,GAAG,EAAE,WAAW,CAAC;gBAEf,KAAK,EAAE,WAAW,EAAE,EAAE,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,0BAA0B;YAelE,KAAK;IAEnB,KAAK,CAAC,CAAC,EAAE,KAAK,EAAE,QAAQ,GAAG,OAAO,CAAC,CAAC,EAAE,CAAC;IACvC,QAAQ,CAAC,CAAC,EAAE,KAAK,EAAE,QAAQ,GAAG,OAAO,CAAC,CAAC,GAAG,IAAI,CAAC;IAC/C,OAAO,CAAC,KAAK,EAAE,QAAQ,GAAG,OAAO,CAAC;QAAE,QAAQ,EAAE,MAAM,CAAA;KAAE,CAAC;IAEvD;;;;;OAKG;IACG,WAAW,CAAC,CAAC,EAAE,EAAE,EAAE,CAAC,EAAE,EAAE,WAAW,KAAK,OAAO,CAAC,CAAC,CAAC,EAAE,OAAO,CAAC,EAAE,kBAAkB,GAAG,OAAO,CAAC,CAAC,CAAC;IAKnG,yDAAyD;IACzD,gBAAgB,IAAI,IAAI;IAExB,gBAAgB;IAChB,SAAS;CACV;AAED,OAAO,EAAE,GAAG,EAAE,mBAAmB,EAAE,MAAM,yBAAyB,CAAC;AACnE,YAAY,EAAE,QAAQ,EAAE,WAAW,EAAE,MAAM,yBAAyB,CAAC;AACrE,OAAO,EAAE,yBAAyB,EAAE,MAAM,aAAa,CAAC;AACxD,YAAY,EAAE,0BAA0B,EAAE,kBAAkB,EAAE,MAAM,YAAY,CAAC"}
@@ -10,6 +10,7 @@ import { DsqlMockEngine } from './engines/dsql-mock-engine.js';
10
10
  import { runMigrations, loadMigrationsFromDir } from './migrations.js';
11
11
  import { transactionWithRetry } from './transaction.js';
12
12
  import { Logger } from '@aws-blocks/bb-logger';
13
+ import { BB_NAME, BB_VERSION } from './version.js';
13
14
  export class DistributedDatabase extends Scope {
14
15
  base;
15
16
  mockEngine;
@@ -17,7 +18,7 @@ export class DistributedDatabase extends Scope {
17
18
  /** @internal Logger for internal operations. Defaults to error-level when not provided. */
18
19
  log;
19
20
  constructor(scope, id, options) {
20
- super(id, { parent: scope });
21
+ super(id, { parent: scope, bbName: BB_NAME, bbVersion: BB_VERSION });
21
22
  this.log = options?.logger ?? new Logger(this, 'logger', { level: 'error' });
22
23
  this.mockEngine = new DsqlMockEngine(`.bb-data/${this.fullId}`);
23
24
  this.base = new DatabaseBase(this.mockEngine);
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=index.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.test.d.ts","sourceRoot":"","sources":["../src/index.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,56 @@
1
+ // Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
2
+ // SPDX-License-Identifier: Apache-2.0
3
+ /**
4
+ * Telemetry-registration tests for DistributedDatabase.
5
+ *
6
+ * `Scope.getRegisteredBlocks()` only names a block whose `bbName` is in
7
+ * OFFICIAL_BB_NAMES, and that set is generated from the umbrella's
8
+ * `aws-blocks.vendorize` map. These tests pin the three coupled artifacts to
9
+ * each other: the block's generated BB_NAME, its vendorize entry, and the
10
+ * generated name set. A block that omits `bbMeta` still constructs fine and
11
+ * every other test still passes, so that gap is only visible here.
12
+ *
13
+ * The package ships a distinct mock implementation (the default entry does not
14
+ * re-export the AWS class), so both `index.aws.ts` and `index.mock.ts` carry
15
+ * the `super()` change. Registration happens in `super()`, identical for both;
16
+ * these tests exercise the AWS class because its constructor is side-effect
17
+ * free (the mock eagerly spins up PGlite on disk), keeping the suite fast and
18
+ * deterministic.
19
+ */
20
+ import { test, describe, beforeEach } from 'node:test';
21
+ import assert from 'node:assert';
22
+ import { readFileSync } from 'node:fs';
23
+ import { dirname, join } from 'node:path';
24
+ import { fileURLToPath } from 'node:url';
25
+ import { Scope } from '@aws-blocks/core';
26
+ import { DistributedDatabase } from './index.aws.js';
27
+ import { BB_NAME, BB_VERSION } from './version.js';
28
+ const __dirname = dirname(fileURLToPath(import.meta.url));
29
+ let counter = 0;
30
+ function makeDb() {
31
+ const scope = new Scope(`distdata-telemetry-${++counter}`);
32
+ return new DistributedDatabase(scope, 'db');
33
+ }
34
+ describe('DistributedDatabase telemetry registration', () => {
35
+ beforeEach(() => {
36
+ Scope._resetRegistry();
37
+ });
38
+ test('BB_NAME is the name the vendorize map and OFFICIAL_BB_NAMES carry', () => {
39
+ assert.strictEqual(BB_NAME, 'DistributedDatabase');
40
+ });
41
+ test('BB_VERSION tracks the package version', () => {
42
+ const pkg = JSON.parse(readFileSync(join(__dirname, '..', 'package.json'), 'utf-8'));
43
+ assert.strictEqual(BB_VERSION, pkg.version);
44
+ });
45
+ test('an instance carries bbName and bbVersion', () => {
46
+ const db = makeDb();
47
+ assert.strictEqual(db.bbName, BB_NAME);
48
+ assert.strictEqual(db.bbVersion, BB_VERSION);
49
+ });
50
+ test('registers as an official block, so telemetry is allowed to name it', () => {
51
+ makeDb();
52
+ const { blocks, customBlocksCount } = Scope.getRegisteredBlocks();
53
+ assert.deepStrictEqual(blocks.filter(b => b.name === BB_NAME), [{ name: BB_NAME, version: BB_VERSION }]);
54
+ assert.strictEqual(customBlocksCount, 0, 'must not be filtered out as an unnamed custom block');
55
+ });
56
+ });
@@ -1 +1 @@
1
- {"version":3,"file":"validation.d.ts","sourceRoot":"","sources":["../src/validation.ts"],"names":[],"mappings":"AAWA,OAAO,EAAE,eAAe,EAAuB,MAAM,yBAAyB,CAAC;AAU/E,mEAAmE;AACnE,wBAAgB,wBAAwB,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CA6C5D;AA6BD,uFAAuF;AACvF,wBAAgB,iBAAiB,CAAC,GAAG,EAAE,MAAM,GAAG,IAAI,CAenD;AAED,kDAAkD;AAClD,wBAAgB,iBAAiB,CAAC,GAAG,EAAE,MAAM,GAAG,KAAK,GAAG,KAAK,GAAG,OAAO,CAKtE;AAID,qBAAa,kBAAkB;IAC7B,OAAO,CAAC,QAAQ,CAAK;IACrB,OAAO,CAAC,MAAM,CAAS;IACvB,OAAO,CAAC,QAAQ,CAAK;IAErB,eAAe,CAAC,GAAG,EAAE,MAAM,GAAG,IAAI;IAalC,cAAc,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI;IAUnC,KAAK,IAAI,IAAI;CACd;AAID,wBAAgB,kBAAkB,CAAC,UAAU,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GAAG,IAAI,CAiB3E;AAED,OAAO,EAAE,eAAe,EAAE,CAAC"}
1
+ {"version":3,"file":"validation.d.ts","sourceRoot":"","sources":["../src/validation.ts"],"names":[],"mappings":"AAWA,OAAO,EAAE,eAAe,EAAuB,MAAM,yBAAyB,CAAC;AAU/E,mEAAmE;AACnE,wBAAgB,wBAAwB,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CA6C5D;AA8BD,uFAAuF;AACvF,wBAAgB,iBAAiB,CAAC,GAAG,EAAE,MAAM,GAAG,IAAI,CAenD;AAED,kDAAkD;AAClD,wBAAgB,iBAAiB,CAAC,GAAG,EAAE,MAAM,GAAG,KAAK,GAAG,KAAK,GAAG,OAAO,CAKtE;AAID,qBAAa,kBAAkB;IAC7B,OAAO,CAAC,QAAQ,CAAK;IACrB,OAAO,CAAC,MAAM,CAAS;IACvB,OAAO,CAAC,QAAQ,CAAK;IAErB,eAAe,CAAC,GAAG,EAAE,MAAM,GAAG,IAAI;IAalC,cAAc,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI;IAUnC,KAAK,IAAI,IAAI;CACd;AAID,wBAAgB,kBAAkB,CAAC,UAAU,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GAAG,IAAI,CAiB3E;AAED,OAAO,EAAE,eAAe,EAAE,CAAC"}
@@ -73,6 +73,7 @@ const RULES = [
73
73
  { pattern: /\b(LISTEN|NOTIFY)\b/i, message: 'DSQL does not support LISTEN/NOTIFY.', severity: 'error' },
74
74
  { pattern: /\bCREATE\s+EXTENSION\b/i, message: 'DSQL does not support extensions.', severity: 'error' },
75
75
  { pattern: /\bALTER\s+TABLE\b[\s\S]*\bADD\s+COLUMN\b[\s\S]*\bDEFAULT\b/i, message: 'DSQL does not support ADD COLUMN with DEFAULT.', severity: 'error' },
76
+ { pattern: /\bALTER\s+TABLE\b[^;]*\bDROP\s+(?:COLUMN\b|IF\s+EXISTS\b|(?!(?:DEFAULT|NOT|EXPRESSION|IDENTITY|CONSTRAINT)\b)[\w"])/i, message: 'DSQL does not support ALTER TABLE DROP COLUMN. Leave the column in place and stop referencing it, or rebuild the table (create a new table → INSERT INTO ... SELECT → DROP → RENAME TO). (DSQL: "unsupported ALTER TABLE DROP COLUMN statement")', severity: 'error' },
76
77
  { pattern: /\bALTER\s+DEFAULT\s+PRIVILEGES\b/i, message: 'DSQL does not support ALTER DEFAULT PRIVILEGES.', severity: 'error' },
77
78
  { pattern: /\b(CREATE\s+POLICY|ENABLE\s+ROW\s+LEVEL\s+SECURITY)\b/i, message: 'DSQL does not support Row Level Security.', severity: 'error' },
78
79
  { pattern: /\bCREATE\s+(TEMP|TEMPORARY)\s+TABLE\b/i, message: 'DSQL does not support temporary tables.', severity: 'error' },
@@ -45,12 +45,38 @@ describe('validateStatement', () => {
45
45
  ['ISOLATION LEVEL', 'SET TRANSACTION ISOLATION LEVEL SERIALIZABLE'],
46
46
  // DSQL only supports C collation — locale-aware sorting is not available
47
47
  ['COLLATE', 'SELECT * FROM t ORDER BY name COLLATE "en_US"'],
48
+ // DROP COLUMN is not in DSQL's supported ALTER TABLE subset — rebuild the table instead
49
+ ['DROP COLUMN', 'ALTER TABLE t DROP COLUMN x'],
50
+ // Postgres allows omitting the COLUMN keyword — same DROP COLUMN action, same rejection
51
+ ['DROP COLUMN shorthand', 'ALTER TABLE t DROP x'],
52
+ ['DROP COLUMN IF EXISTS shorthand', 'ALTER TABLE t DROP IF EXISTS x'],
53
+ ['DROP COLUMN quoted shorthand', 'ALTER TABLE t DROP "identity"'],
48
54
  ];
49
55
  for (const [label, sql] of rejects) {
50
56
  it(`rejects ${label}`, () => {
51
57
  assert.throws(() => validateStatement(sql), { name: 'DsqlValidationError' });
52
58
  });
53
59
  }
60
+ it('allows supported ALTER TABLE forms that contain DROP', () => {
61
+ // Per the DSQL ALTER TABLE grammar, the ALTER COLUMN ... DROP actions and
62
+ // DROP CONSTRAINT are supported — must not be confused with the
63
+ // unsupported DROP [COLUMN].
64
+ // https://docs.aws.amazon.com/aurora-dsql/latest/userguide/alter-table-syntax-support.html
65
+ assert.doesNotThrow(() => validateStatement('ALTER TABLE t ALTER COLUMN c DROP IDENTITY'));
66
+ assert.doesNotThrow(() => validateStatement('ALTER TABLE t ALTER COLUMN c DROP DEFAULT'));
67
+ assert.doesNotThrow(() => validateStatement('ALTER TABLE t ALTER COLUMN c DROP NOT NULL'));
68
+ assert.doesNotThrow(() => validateStatement('ALTER TABLE t ALTER COLUMN c DROP EXPRESSION'));
69
+ assert.doesNotThrow(() => validateStatement('ALTER TABLE t DROP CONSTRAINT c'));
70
+ assert.doesNotThrow(() => validateStatement('ALTER TABLE t DROP CONSTRAINT IF EXISTS c CASCADE'));
71
+ assert.doesNotThrow(() => validateStatement('ALTER TABLE t RENAME TO t2'));
72
+ assert.doesNotThrow(() => validateStatement('DROP TABLE t'));
73
+ });
74
+ it('allows a supported ALTER TABLE followed by an unrelated statement in one batch', () => {
75
+ // The DROP COLUMN rule must not match across a statement boundary: the
76
+ // ALTER TABLE here is a supported DROP DEFAULT, and the DROP TABLE that
77
+ // follows the semicolon belongs to a different statement.
78
+ assert.doesNotThrow(() => validateStatement('ALTER TABLE t ALTER COLUMN c DROP DEFAULT; DROP TABLE archived'));
79
+ });
54
80
  });
55
81
  describe('classifyStatement', () => {
56
82
  it('classifies DDL/DML/other', () => {
@@ -0,0 +1,3 @@
1
+ export declare const BB_NAME = "DistributedDatabase";
2
+ export declare const BB_VERSION = "0.1.5";
3
+ //# sourceMappingURL=version.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"version.d.ts","sourceRoot":"","sources":["../src/version.ts"],"names":[],"mappings":"AACA,eAAO,MAAM,OAAO,wBAAwB,CAAC;AAC7C,eAAO,MAAM,UAAU,UAAU,CAAC"}
@@ -0,0 +1,3 @@
1
+ // Auto-generated by scripts/generate-version.mjs — do not edit manually
2
+ export const BB_NAME = 'DistributedDatabase';
3
+ export const BB_VERSION = '0.1.5';
package/package.json CHANGED
@@ -1,6 +1,15 @@
1
1
  {
2
2
  "name": "@aws-blocks/bb-distributed-data",
3
- "version": "0.1.3",
3
+ "version": "0.1.5",
4
+ "repository": {
5
+ "type": "git",
6
+ "url": "git+https://github.com/aws-devtools-labs/aws-blocks.git",
7
+ "directory": "packages/bb-distributed-data"
8
+ },
9
+ "homepage": "https://github.com/aws-devtools-labs/aws-blocks/tree/main/packages/bb-distributed-data#readme",
10
+ "bugs": {
11
+ "url": "https://github.com/aws-devtools-labs/aws-blocks/issues"
12
+ },
4
13
  "author": "Amazon Web Services",
5
14
  "license": "Apache-2.0",
6
15
  "type": "module",
@@ -23,13 +32,14 @@
23
32
  }
24
33
  },
25
34
  "scripts": {
35
+ "prebuild": "node ../../scripts/generate-version.mjs DistributedDatabase",
26
36
  "build": "tsc --build",
27
37
  "test": "node --test 'dist/**/*.test.js'"
28
38
  },
29
39
  "dependencies": {
30
- "@aws-blocks/core": "^0.1.1",
31
- "@aws-blocks/data-common": "^0.1.1",
32
- "@aws-blocks/bb-logger": "^0.1.2",
40
+ "@aws-blocks/core": "^0.1.17",
41
+ "@aws-blocks/data-common": "^0.1.3",
42
+ "@aws-blocks/bb-logger": "^0.1.3",
33
43
  "@aws-sdk/dsql-signer": "^3.700.0",
34
44
  "@electric-sql/pglite": "^0.2.0",
35
45
  "pg": "^8.13.0"