meadow-connection-postgresql 1.0.0 → 1.0.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/README.md ADDED
@@ -0,0 +1,133 @@
1
+ # meadow-connection-postgresql
2
+
3
+ PostgreSQL connection service for the Meadow data access layer.
4
+
5
+ [![Coverage Status](https://coveralls.io/repos/github/stevenvelozo/meadow-connection-postgresql/badge.svg?branch=main)](https://coveralls.io/github/stevenvelozo/meadow-connection-postgresql?branch=main)
6
+ [![Build Status](https://github.com/stevenvelozo/meadow-connection-postgresql/workflows/Tests/badge.svg)](https://github.com/stevenvelozo/meadow-connection-postgresql/actions)
7
+ [![npm version](https://badge.fury.io/js/meadow-connection-postgresql.svg)](https://www.npmjs.com/package/meadow-connection-postgresql)
8
+ [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
9
+
10
+ ## Features
11
+
12
+ - **Fable Service Provider** -- integrates with the Fable dependency injection ecosystem
13
+ - **Connection Pooling** -- managed pool via the `pg` driver's `Pool` class
14
+ - **SQL DDL Generation** -- produces PostgreSQL-native `CREATE TABLE` and `DROP TABLE` statements
15
+ - **Meadow-Compatible Settings** -- accepts both Meadow-style (`Server`, `Port`) and native `pg` property names
16
+ - **Quoted Identifiers** -- double-quoted table and column names for safe handling of reserved words
17
+ - **Auto-Connect Mode** -- optionally connect during service construction
18
+ - **Idempotent Schema** -- `CREATE TABLE IF NOT EXISTS` and graceful handling of duplicate table errors
19
+
20
+ ## Installation
21
+
22
+ ```shell
23
+ npm install meadow-connection-postgresql
24
+ ```
25
+
26
+ ## Quick Start
27
+
28
+ ```javascript
29
+ const libFable = require('fable');
30
+ const libMeadowConnectionPostgreSQL = require('meadow-connection-postgresql');
31
+
32
+ let _Fable = new libFable(
33
+ {
34
+ "PostgreSQL":
35
+ {
36
+ "Server": "localhost",
37
+ "Port": 5432,
38
+ "User": "postgres",
39
+ "Password": "secret",
40
+ "Database": "myapp"
41
+ }
42
+ });
43
+
44
+ _Fable.serviceManager.addAndInstantiateServiceType(
45
+ 'MeadowPostgreSQLProvider', libMeadowConnectionPostgreSQL);
46
+
47
+ _Fable.MeadowPostgreSQLProvider.connectAsync(
48
+ (pError, pPool) =>
49
+ {
50
+ if (pError) { return console.error(pError); }
51
+
52
+ let tmpPool = _Fable.MeadowPostgreSQLProvider.pool;
53
+ tmpPool.query('SELECT NOW()', (pErr, pRes) =>
54
+ {
55
+ console.log('Server time:', pRes.rows[0].now);
56
+ });
57
+ });
58
+ ```
59
+
60
+ ## Configuration
61
+
62
+ Settings are read from `fable.settings.PostgreSQL`:
63
+
64
+ | Setting | Alias | Default | Description |
65
+ |---------|-------|---------|-------------|
66
+ | `Server` | `host` | -- | PostgreSQL host |
67
+ | `Port` | `port` | -- | PostgreSQL port |
68
+ | `User` | `user` | -- | Authentication username |
69
+ | `Password` | `password` | -- | Authentication password |
70
+ | `Database` | `database` | -- | Target database name |
71
+ | `ConnectionPoolLimit` | `max` | -- | Maximum connections in the pool |
72
+
73
+ ## API
74
+
75
+ | Method | Description |
76
+ |--------|-------------|
77
+ | `connect()` | Synchronous -- create `pg.Pool` instance |
78
+ | `connectAsync(fCallback)` | Callback-style connection (recommended) |
79
+ | `pool` | Getter -- returns the `pg.Pool` instance |
80
+ | `generateCreateTableStatement(schema)` | Generate a `CREATE TABLE` DDL string |
81
+ | `createTable(schema, fCallback)` | Execute `CREATE TABLE` via the pool |
82
+ | `createTables(schema, fCallback)` | Create multiple tables sequentially |
83
+ | `generateDropTableStatement(name)` | Generate a `DROP TABLE IF EXISTS` DDL string |
84
+
85
+ ## Column Type Mapping
86
+
87
+ | Meadow DataType | PostgreSQL Type | Constraints |
88
+ |-----------------|-----------------|-------------|
89
+ | `ID` | `SERIAL` | `PRIMARY KEY` |
90
+ | `GUID` | `VARCHAR(Size)` | `DEFAULT '0xDe'` |
91
+ | `ForeignKey` | `INTEGER` | `NOT NULL DEFAULT 0` |
92
+ | `Numeric` | `INTEGER` | `NOT NULL DEFAULT 0` |
93
+ | `Decimal` | `DECIMAL(Size)` | -- |
94
+ | `String` | `VARCHAR(Size)` | `NOT NULL DEFAULT ''` |
95
+ | `Text` | `TEXT` | -- |
96
+ | `DateTime` | `TIMESTAMP` | -- |
97
+ | `Boolean` | `BOOLEAN` | `NOT NULL DEFAULT false` |
98
+
99
+ ## Part of the Retold Framework
100
+
101
+ This module is a Meadow connector that plugs into the Retold application framework. It provides the PostgreSQL persistence layer for the Meadow data access abstraction.
102
+
103
+ ## Testing
104
+
105
+ ```shell
106
+ npm test
107
+ ```
108
+
109
+ Coverage:
110
+
111
+ ```shell
112
+ npm run coverage
113
+ ```
114
+
115
+ ## Related Packages
116
+
117
+ - [meadow](https://github.com/stevenvelozo/meadow) -- Data access layer and ORM
118
+ - [fable](https://github.com/stevenvelozo/fable) -- Application framework and service manager
119
+ - [foxhound](https://github.com/stevenvelozo/foxhound) -- Query generation DSL
120
+ - [stricture](https://github.com/stevenvelozo/stricture) -- Schema definition and DDL tools
121
+ - [meadow-endpoints](https://github.com/stevenvelozo/meadow-endpoints) -- RESTful endpoint generation
122
+ - [meadow-connection-mysql](https://github.com/stevenvelozo/meadow-connection-mysql) -- MySQL / MariaDB connector
123
+ - [meadow-connection-mssql](https://github.com/stevenvelozo/meadow-connection-mssql) -- Microsoft SQL Server connector
124
+ - [meadow-connection-sqlite](https://github.com/stevenvelozo/meadow-connection-sqlite) -- SQLite connector
125
+ - [meadow-connection-mongodb](https://github.com/stevenvelozo/meadow-connection-mongodb) -- MongoDB connector
126
+
127
+ ## License
128
+
129
+ MIT
130
+
131
+ ## Contributing
132
+
133
+ Pull requests are welcome. For major changes, please open an issue first to discuss what you would like to change.
@@ -0,0 +1,20 @@
1
+ version: '3.8'
2
+
3
+ services:
4
+ postgresql-test:
5
+ image: postgres:16
6
+ container_name: meadow-connection-postgresql-test
7
+ environment:
8
+ POSTGRES_USER: postgres
9
+ POSTGRES_PASSWORD: testpassword
10
+ POSTGRES_DB: testdb
11
+ ports:
12
+ - "25432:5432"
13
+ volumes:
14
+ - ./test/docker-init:/docker-entrypoint-initdb.d
15
+ healthcheck:
16
+ test: ["CMD-SHELL", "pg_isready -U postgres"]
17
+ interval: 5s
18
+ timeout: 5s
19
+ retries: 20
20
+ start_period: 10s
package/docs/.nojekyll ADDED
File without changes
package/docs/README.md ADDED
@@ -0,0 +1,96 @@
1
+ # meadow-connection-postgresql
2
+
3
+ PostgreSQL connection service for the Meadow data access layer. This module provides connection pool management, SQL DDL generation, and table creation for applications using PostgreSQL as their persistence store.
4
+
5
+ ## Quick Start
6
+
7
+ ```javascript
8
+ const libFable = require('fable');
9
+ const libMeadowConnectionPostgreSQL = require('meadow-connection-postgresql');
10
+
11
+ // 1. Create a Fable instance with PostgreSQL settings
12
+ let _Fable = new libFable(
13
+ {
14
+ "PostgreSQL":
15
+ {
16
+ "Server": "localhost",
17
+ "Port": 5432,
18
+ "User": "postgres",
19
+ "Password": "secret",
20
+ "Database": "myapp",
21
+ "ConnectionPoolLimit": 20
22
+ }
23
+ });
24
+
25
+ // 2. Register and instantiate the service
26
+ _Fable.serviceManager.addAndInstantiateServiceType(
27
+ 'MeadowPostgreSQLProvider', libMeadowConnectionPostgreSQL);
28
+
29
+ // 3. Connect
30
+ _Fable.MeadowPostgreSQLProvider.connectAsync(
31
+ (pError, pPool) =>
32
+ {
33
+ if (pError) { return console.error(pError); }
34
+
35
+ // 4. Use the pool
36
+ let tmpPool = _Fable.MeadowPostgreSQLProvider.pool;
37
+ tmpPool.query('SELECT NOW()', (pErr, pRes) =>
38
+ {
39
+ console.log('Server time:', pRes.rows[0].now);
40
+ });
41
+ });
42
+ ```
43
+
44
+ ## Configuration
45
+
46
+ Settings are read from `fable.settings.PostgreSQL`. Both Meadow-style names and native `pg` driver names are supported:
47
+
48
+ | Setting | Alias | Description |
49
+ |---------|-------|-------------|
50
+ | `Server` | `host` | PostgreSQL hostname or IP |
51
+ | `Port` | `port` | PostgreSQL port |
52
+ | `User` | `user` | Authentication username |
53
+ | `Password` | `password` | Authentication password |
54
+ | `Database` | `database` | Target database name |
55
+ | `ConnectionPoolLimit` | `max` | Maximum connections in the pool |
56
+
57
+ ## How It Fits
58
+
59
+ ```
60
+ Application
61
+ |
62
+ v
63
+ Meadow (ORM)
64
+ |
65
+ v
66
+ FoxHound (Query Dialect)
67
+ |
68
+ v
69
+ meadow-connection-postgresql <-- this module
70
+ |
71
+ v
72
+ pg (node-postgres)
73
+ |
74
+ v
75
+ PostgreSQL Server
76
+ ```
77
+
78
+ ## Learn More
79
+
80
+ - [Quickstart Guide](quickstart.md) -- step-by-step setup
81
+ - [Architecture](architecture.md) -- connection lifecycle and design diagrams
82
+ - [Schema & Column Types](schema.md) -- DDL generation and type mapping
83
+ - [API Reference](api/reference.md) -- complete method documentation
84
+
85
+ ## Companion Modules
86
+
87
+ | Module | Purpose |
88
+ |--------|---------|
89
+ | [meadow](https://github.com/stevenvelozo/meadow) | Data access layer and ORM |
90
+ | [foxhound](https://github.com/stevenvelozo/foxhound) | Query generation DSL |
91
+ | [stricture](https://github.com/stevenvelozo/stricture) | Schema definition and DDL tools |
92
+ | [meadow-connection-mysql](https://github.com/stevenvelozo/meadow-connection-mysql) | MySQL / MariaDB connector |
93
+ | [meadow-connection-mssql](https://github.com/stevenvelozo/meadow-connection-mssql) | Microsoft SQL Server connector |
94
+ | [meadow-connection-sqlite](https://github.com/stevenvelozo/meadow-connection-sqlite) | SQLite connector |
95
+ | [meadow-connection-mongodb](https://github.com/stevenvelozo/meadow-connection-mongodb) | MongoDB connector |
96
+ | [meadow-connection-rocksdb](https://github.com/stevenvelozo/meadow-connection-rocksdb) | RocksDB key-value connector |
package/docs/_cover.md ADDED
@@ -0,0 +1,17 @@
1
+ # meadow-connection-postgresql
2
+
3
+ <small>v1.0.0</small>
4
+
5
+ > PostgreSQL connection service for the Meadow data access layer
6
+
7
+ - **Fable Service Provider** -- seamless dependency injection integration
8
+ - **Connection Pooling** -- managed pool via the `pg` driver
9
+ - **SQL DDL Generation** -- PostgreSQL-native `CREATE TABLE` statements
10
+ - **Quoted Identifiers** -- safe handling of reserved words
11
+ - **Meadow-Compatible Settings** -- accepts both Meadow-style and native property names
12
+ - **Idempotent Schema** -- safe to call on every startup
13
+
14
+ [Overview](README.md)
15
+ [Quickstart](quickstart.md)
16
+ [API Reference](api/reference.md)
17
+ [GitHub](https://github.com/stevenvelozo/meadow-connection-postgresql)
@@ -0,0 +1,33 @@
1
+ - **Getting Started**
2
+ - [Overview](README.md)
3
+ - [Quickstart](quickstart.md)
4
+
5
+ - **Concepts**
6
+ - [Architecture](architecture.md)
7
+ - [Schema & Column Types](schema.md)
8
+
9
+ - **API Reference**
10
+ - [Full Reference](api/reference.md)
11
+ - Connection
12
+ - [connectAsync(fCallback)](api/connectAsync.md)
13
+ - [connect()](api/connect.md)
14
+ - Accessors
15
+ - [pool](api/pool.md)
16
+ - Schema Management
17
+ - [generateCreateTableStatement()](api/generateCreateTableStatement.md)
18
+ - [createTable()](api/createTable.md)
19
+ - [createTables()](api/createTables.md)
20
+ - [generateDropTableStatement()](api/generateDropTableStatement.md)
21
+
22
+ - **Ecosystem**
23
+ - [Meadow](https://github.com/stevenvelozo/meadow)
24
+ - [FoxHound](https://github.com/stevenvelozo/foxhound)
25
+ - [Stricture](https://github.com/stevenvelozo/stricture)
26
+ - [Fable](https://github.com/stevenvelozo/fable)
27
+ - Connectors
28
+ - [MySQL](https://github.com/stevenvelozo/meadow-connection-mysql)
29
+ - [MSSQL](https://github.com/stevenvelozo/meadow-connection-mssql)
30
+ - [SQLite](https://github.com/stevenvelozo/meadow-connection-sqlite)
31
+ - [MongoDB](https://github.com/stevenvelozo/meadow-connection-mongodb)
32
+ - [RocksDB](https://github.com/stevenvelozo/meadow-connection-rocksdb)
33
+ - [Dgraph](https://github.com/stevenvelozo/meadow-connection-dgraph)
@@ -0,0 +1,5 @@
1
+ - [Overview](README.md)
2
+ - [Quickstart](quickstart.md)
3
+ - [Architecture](architecture.md)
4
+ - [API Reference](api/reference.md)
5
+ - [GitHub](https://github.com/stevenvelozo/meadow-connection-postgresql)
@@ -0,0 +1,100 @@
1
+ # connect()
2
+
3
+ Synchronous method that creates the `pg.Pool` connection pool instance.
4
+
5
+ ## Signature
6
+
7
+ ```javascript
8
+ connect()
9
+ ```
10
+
11
+ ## Parameters
12
+
13
+ None.
14
+
15
+ ## Return Value
16
+
17
+ None.
18
+
19
+ ## Behavior
20
+
21
+ 1. Builds connection settings from `this.options.PostgreSQL` (host, port, user, password, database, max)
22
+ 2. If already connected (`this._ConnectionPool` exists), logs an error with masked password and returns
23
+ 3. Otherwise, logs the connection details and creates a new `pg.Pool`
24
+ 4. Sets `this.connected = true`
25
+
26
+ ## Usage
27
+
28
+ ```javascript
29
+ _Fable.MeadowPostgreSQLProvider.connect();
30
+
31
+ if (_Fable.MeadowPostgreSQLProvider.connected)
32
+ {
33
+ let tmpPool = _Fable.MeadowPostgreSQLProvider.pool;
34
+ // Use the pool
35
+ }
36
+ ```
37
+
38
+ ## Why Both connect() and connectAsync()?
39
+
40
+ The `pg.Pool` constructor is synchronous -- it does not open actual TCP connections until a query is issued. The `connect()` method works reliably for immediate use. However, `connectAsync()` is preferred because:
41
+
42
+ - It follows the Fable service provider convention
43
+ - It provides error handling via the callback
44
+ - It guards against missing callbacks with a warning about race conditions
45
+ - It is consistent with other Meadow connector APIs
46
+
47
+ ## Double-Connect Protection
48
+
49
+ If `connect()` is called when already connected, it logs an error with the settings (password masked) and returns without action:
50
+
51
+ ```javascript
52
+ _Fable.MeadowPostgreSQLProvider.connect();
53
+ _Fable.MeadowPostgreSQLProvider.connect();
54
+ // Logs: "Meadow-Connection-PostgreSQL trying to connect but is already
55
+ // connected - skipping the generation of extra connections."
56
+ // Settings logged with password: '*****************'
57
+ ```
58
+
59
+ ## Auto-Connect
60
+
61
+ The `connect()` method is called automatically during construction if `MeadowConnectionPostgreSQLAutoConnect` is `true`:
62
+
63
+ ```javascript
64
+ let _Fable = new libFable(
65
+ {
66
+ "PostgreSQL":
67
+ {
68
+ "Server": "localhost",
69
+ "Port": 5432,
70
+ "User": "postgres",
71
+ "Password": "secret",
72
+ "Database": "myapp"
73
+ },
74
+ "MeadowConnectionPostgreSQLAutoConnect": true
75
+ });
76
+
77
+ _Fable.serviceManager.addAndInstantiateServiceType(
78
+ 'MeadowPostgreSQLProvider', libMeadowConnectionPostgreSQL);
79
+
80
+ // Already connected -- pool is ready
81
+ let tmpPool = _Fable.MeadowPostgreSQLProvider.pool;
82
+ ```
83
+
84
+ ## Pool Settings
85
+
86
+ The `pg.Pool` is created with these settings from `options.PostgreSQL`:
87
+
88
+ | Setting | pg Option | Description |
89
+ |---------|-----------|-------------|
90
+ | `host` | `host` | Server hostname |
91
+ | `port` | `port` | Server port |
92
+ | `user` | `user` | Authentication user |
93
+ | `password` | `password` | Authentication password |
94
+ | `database` | `database` | Target database |
95
+ | `max` | `max` | Maximum pool connections |
96
+
97
+ ## Related
98
+
99
+ - [connectAsync](connectAsync.md) -- Callback-style connection (recommended)
100
+ - [pool](pool.md) -- Access the pool after connecting
@@ -0,0 +1,92 @@
1
+ # connectAsync(fCallback)
2
+
3
+ Callback-style connection method. Creates the `pg.Pool` instance, or returns the existing pool if already connected.
4
+
5
+ ## Signature
6
+
7
+ ```javascript
8
+ connectAsync(fCallback)
9
+ ```
10
+
11
+ ## Parameters
12
+
13
+ | Parameter | Type | Description |
14
+ |-----------|------|-------------|
15
+ | `fCallback` | `function` | Callback receiving `(error, pool)` |
16
+
17
+ ## Return Value
18
+
19
+ Returns the result of the callback invocation.
20
+
21
+ ## Behavior
22
+
23
+ 1. If no callback is provided, logs an error and substitutes a no-op function
24
+ 2. If already connected (`this._ConnectionPool` exists), calls `fCallback(null, this._ConnectionPool)` immediately
25
+ 3. Otherwise, calls `this.connect()` to create the pool
26
+ 4. On success: calls `fCallback(null, this._ConnectionPool)`
27
+ 5. On error: logs the error, calls `fCallback(pError)`
28
+
29
+ ## Basic Usage
30
+
31
+ ```javascript
32
+ _Fable.MeadowPostgreSQLProvider.connectAsync(
33
+ (pError, pPool) =>
34
+ {
35
+ if (pError)
36
+ {
37
+ console.error('Connection failed:', pError);
38
+ return;
39
+ }
40
+ console.log('Connected! Pool ready.');
41
+ });
42
+ ```
43
+
44
+ ## Idempotent Calls
45
+
46
+ Calling `connectAsync()` multiple times is safe. If already connected, the existing pool is returned without creating a new one:
47
+
48
+ ```javascript
49
+ // First call -- creates the pool
50
+ _Fable.MeadowPostgreSQLProvider.connectAsync(
51
+ (pError, pPool) =>
52
+ {
53
+ // pPool is the pg.Pool instance
54
+
55
+ // Second call -- reuses the existing pool
56
+ _Fable.MeadowPostgreSQLProvider.connectAsync(
57
+ (pError2, pPool2) =>
58
+ {
59
+ // pPool2 === pPool (same pool)
60
+ });
61
+ });
62
+ ```
63
+
64
+ ## Missing Callback
65
+
66
+ If called without a callback, a warning is logged and a no-op function is used:
67
+
68
+ ```javascript
69
+ // Logs: "Meadow PostgreSQL connectAsync() called without a callback;
70
+ // this could lead to connection race conditions."
71
+ _Fable.MeadowPostgreSQLProvider.connectAsync();
72
+ ```
73
+
74
+ ## Error Handling
75
+
76
+ If `connect()` throws, the error is caught and passed to the callback:
77
+
78
+ ```javascript
79
+ _Fable.MeadowPostgreSQLProvider.connectAsync(
80
+ (pError) =>
81
+ {
82
+ if (pError)
83
+ {
84
+ console.error('PostgreSQL connection error:', pError.message);
85
+ }
86
+ });
87
+ ```
88
+
89
+ ## Related
90
+
91
+ - [connect()](connect.md) -- Synchronous connection method
92
+ - [pool](pool.md) -- Access the pool after connecting
@@ -0,0 +1,116 @@
1
+ # createTable(pMeadowTableSchema, fCallback)
2
+
3
+ Generates and executes a PostgreSQL `CREATE TABLE IF NOT EXISTS` statement from a Meadow table schema. Handles existing tables gracefully.
4
+
5
+ ## Signature
6
+
7
+ ```javascript
8
+ createTable(pMeadowTableSchema, fCallback)
9
+ ```
10
+
11
+ ## Parameters
12
+
13
+ | Parameter | Type | Description |
14
+ |-----------|------|-------------|
15
+ | `pMeadowTableSchema` | `object` | Meadow table schema with `TableName` and `Columns` array |
16
+ | `fCallback` | `function` | Callback receiving `(error)` |
17
+
18
+ ## Return Value
19
+
20
+ Returns the result of the callback invocation.
21
+
22
+ ## Behavior
23
+
24
+ 1. Calls `generateCreateTableStatement(pMeadowTableSchema)` to produce the DDL string
25
+ 2. Executes the DDL via `this._ConnectionPool.query(ddl, callback)`
26
+ 3. On success: logs info, calls `fCallback()` with no error
27
+ 4. On error code `42P07` (duplicate_table): logs a warning, calls `fCallback()` with no error
28
+ 5. On other errors: logs the error, calls `fCallback(pError)`
29
+
30
+ ## Basic Usage
31
+
32
+ ```javascript
33
+ let tmpAnimalSchema =
34
+ {
35
+ TableName: 'Animal',
36
+ Columns:
37
+ [
38
+ { Column: 'IDAnimal', DataType: 'ID' },
39
+ { Column: 'GUIDAnimal', DataType: 'GUID', Size: 36 },
40
+ { Column: 'Name', DataType: 'String', Size: 128 },
41
+ { Column: 'Age', DataType: 'Numeric' },
42
+ { Column: 'Weight', DataType: 'Decimal', Size: '10,2' }
43
+ ]
44
+ };
45
+
46
+ _Fable.MeadowPostgreSQLProvider.createTable(tmpAnimalSchema,
47
+ (pError) =>
48
+ {
49
+ if (pError)
50
+ {
51
+ console.error('Table creation failed:', pError);
52
+ return;
53
+ }
54
+ console.log('Animal table ready!');
55
+ });
56
+ ```
57
+
58
+ ## Idempotent Execution
59
+
60
+ Table creation is idempotent through two layers of protection:
61
+
62
+ 1. **`CREATE TABLE IF NOT EXISTS`** in the generated SQL
63
+ 2. **Error code 42P07 handling** -- if PostgreSQL returns `duplicate_table`, it is logged as a warning and does not produce an error in the callback
64
+
65
+ This makes `createTable()` safe to call during application startup:
66
+
67
+ ```javascript
68
+ // Safe to call every time the app starts
69
+ _Fable.MeadowPostgreSQLProvider.createTable(tmpAnimalSchema,
70
+ (pError) =>
71
+ {
72
+ // First run: table created
73
+ // Subsequent runs: table already exists (warning logged)
74
+ });
75
+ ```
76
+
77
+ ## Prerequisites
78
+
79
+ The connection must be established before calling `createTable()`:
80
+
81
+ ```javascript
82
+ _Fable.MeadowPostgreSQLProvider.connectAsync(
83
+ (pError) =>
84
+ {
85
+ if (pError) { return; }
86
+
87
+ _Fable.MeadowPostgreSQLProvider.createTable(tmpAnimalSchema,
88
+ (pCreateError) =>
89
+ {
90
+ if (pCreateError) { console.error(pCreateError); }
91
+ });
92
+ });
93
+ ```
94
+
95
+ ## Error Handling
96
+
97
+ Non-duplicate errors (e.g., syntax errors, permission denied) are passed to the callback:
98
+
99
+ ```javascript
100
+ _Fable.MeadowPostgreSQLProvider.createTable(tmpBadSchema,
101
+ (pError) =>
102
+ {
103
+ if (pError)
104
+ {
105
+ // pError.code might be '42601' (syntax error) or '42501' (insufficient privilege)
106
+ console.error('DDL execution failed:', pError.message);
107
+ }
108
+ });
109
+ ```
110
+
111
+ ## Related
112
+
113
+ - [generateCreateTableStatement](generateCreateTableStatement.md) -- Generate DDL without executing
114
+ - [createTables](createTables.md) -- Create multiple tables sequentially
115
+ - [generateDropTableStatement](generateDropTableStatement.md) -- Generate DROP TABLE DDL
116
+ - [Schema & Column Types](../schema.md) -- Full type mapping reference