@brandtg/flapjack 0.2.0 → 1.0.0

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/migrate.d.ts CHANGED
@@ -4,21 +4,16 @@
4
4
  export interface MigrationOptions {
5
5
  /** PostgreSQL connection URL (e.g., "postgresql://user:pass@localhost/dbname") */
6
6
  databaseUrl: string;
7
- /** Name of the migrations tracking table (default: 'pgmigrations') */
8
- migrationsTable?: string;
9
- /** Schema name to create tables in (optional) */
10
- schema?: string;
11
7
  }
12
8
  /**
13
9
  * Run Flapjack database migrations.
14
10
  *
15
11
  * This function applies all pending migrations to create or update the
16
- * flapjack_feature_flag table in your PostgreSQL database.
12
+ * flapjack.feature_flag table in your PostgreSQL database. All tables,
13
+ * including the migrations tracking table, are created in the flapjack schema.
17
14
  *
18
15
  * @param options - Migration configuration options
19
16
  * @param options.databaseUrl - PostgreSQL connection URL
20
- * @param options.migrationsTable - Name of the migrations tracking table (default: 'pgmigrations')
21
- * @param options.schema - Schema name to create tables in (optional)
22
17
  * @returns Promise that resolves when migrations are complete
23
18
  *
24
19
  * @throws Will throw an error if the database connection fails or migrations cannot be applied
@@ -27,22 +22,9 @@ export interface MigrationOptions {
27
22
  * ```typescript
28
23
  * import { runMigrations } from "@brandtg/flapjack";
29
24
  *
30
- * // Basic usage
31
25
  * await runMigrations({
32
26
  * databaseUrl: process.env.DATABASE_URL,
33
27
  * });
34
- *
35
- * // With custom migrations table
36
- * await runMigrations({
37
- * databaseUrl: process.env.DATABASE_URL,
38
- * migrationsTable: "my_migrations",
39
- * });
40
- *
41
- * // With custom schema
42
- * await runMigrations({
43
- * databaseUrl: process.env.DATABASE_URL,
44
- * schema: "feature_flags",
45
- * });
46
28
  * ```
47
29
  */
48
30
  export declare function runMigrations(options: MigrationOptions): Promise<void>;
@@ -1 +1 @@
1
- {"version":3,"file":"migrate.d.ts","sourceRoot":"","sources":["../src/migrate.ts"],"names":[],"mappings":"AAOA;;GAEG;AACH,MAAM,WAAW,gBAAgB;IAC/B,kFAAkF;IAClF,WAAW,EAAE,MAAM,CAAC;IACpB,sEAAsE;IACtE,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,iDAAiD;IACjD,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAmCG;AACH,wBAAsB,aAAa,CAAC,OAAO,EAAE,gBAAgB,GAAG,OAAO,CAAC,IAAI,CAAC,CAgB5E"}
1
+ {"version":3,"file":"migrate.d.ts","sourceRoot":"","sources":["../src/migrate.ts"],"names":[],"mappings":"AAOA;;GAEG;AACH,MAAM,WAAW,gBAAgB;IAC/B,kFAAkF;IAClF,WAAW,EAAE,MAAM,CAAC;CACrB;AAED;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH,wBAAsB,aAAa,CAAC,OAAO,EAAE,gBAAgB,GAAG,OAAO,CAAC,IAAI,CAAC,CAiB5E"}
package/dist/migrate.js CHANGED
@@ -7,12 +7,11 @@ const __dirname = path.dirname(__filename);
7
7
  * Run Flapjack database migrations.
8
8
  *
9
9
  * This function applies all pending migrations to create or update the
10
- * flapjack_feature_flag table in your PostgreSQL database.
10
+ * flapjack.feature_flag table in your PostgreSQL database. All tables,
11
+ * including the migrations tracking table, are created in the flapjack schema.
11
12
  *
12
13
  * @param options - Migration configuration options
13
14
  * @param options.databaseUrl - PostgreSQL connection URL
14
- * @param options.migrationsTable - Name of the migrations tracking table (default: 'pgmigrations')
15
- * @param options.schema - Schema name to create tables in (optional)
16
15
  * @returns Promise that resolves when migrations are complete
17
16
  *
18
17
  * @throws Will throw an error if the database connection fails or migrations cannot be applied
@@ -21,34 +20,22 @@ const __dirname = path.dirname(__filename);
21
20
  * ```typescript
22
21
  * import { runMigrations } from "@brandtg/flapjack";
23
22
  *
24
- * // Basic usage
25
23
  * await runMigrations({
26
24
  * databaseUrl: process.env.DATABASE_URL,
27
25
  * });
28
- *
29
- * // With custom migrations table
30
- * await runMigrations({
31
- * databaseUrl: process.env.DATABASE_URL,
32
- * migrationsTable: "my_migrations",
33
- * });
34
- *
35
- * // With custom schema
36
- * await runMigrations({
37
- * databaseUrl: process.env.DATABASE_URL,
38
- * schema: "feature_flags",
39
- * });
40
26
  * ```
41
27
  */
42
28
  export async function runMigrations(options) {
43
- const { databaseUrl, migrationsTable = "pgmigrations", schema } = options;
29
+ const { databaseUrl } = options;
44
30
  // Path to migrations directory (relative to dist in production)
45
31
  const migrationsDir = path.resolve(__dirname, "../migrations");
46
32
  const migrationConfig = {
47
33
  databaseUrl,
48
34
  dir: migrationsDir,
49
35
  direction: "up",
50
- migrationsTable,
51
- ...(schema && { schema }),
36
+ schema: "flapjack",
37
+ migrationsTable: "pgmigrations",
38
+ createSchema: true,
52
39
  verbose: false,
53
40
  };
54
41
  await runner(migrationConfig);
package/dist/model.js CHANGED
@@ -1,5 +1,5 @@
1
1
  import MurmurHash3 from "imurmurhash";
2
- const TABLE = "flapjack_feature_flag";
2
+ const TABLE = "flapjack.feature_flag";
3
3
  const COLUMNS = [
4
4
  "id",
5
5
  "name",
@@ -406,8 +406,8 @@ export class FeatureFlagModel {
406
406
  return false;
407
407
  }
408
408
  }
409
- const GROUP_TABLE = "flapjack_feature_flag_group";
410
- const GROUP_MEMBER_TABLE = "flapjack_feature_flag_group_member";
409
+ const GROUP_TABLE = "flapjack.feature_flag_group";
410
+ const GROUP_MEMBER_TABLE = "flapjack.feature_flag_group_member";
411
411
  const GROUP_COLUMNS = ["id", "name", "note", "created", "modified"];
412
412
  function mapGroupRow(row) {
413
413
  return {
@@ -9,30 +9,37 @@ export const shorthands = undefined;
9
9
  * @returns {Promise<void> | void}
10
10
  */
11
11
  export const up = (pgm) => {
12
- // Create the flapjack_feature_flag table
13
- pgm.createTable("flapjack_feature_flag", {
14
- id: "id",
15
- name: { type: "text", notNull: true, unique: true },
16
- everyone: { type: "boolean" },
17
- percent: {
18
- type: "numeric(3,1)",
19
- check: "percent >= 0 AND percent <= 99.9",
12
+ // Create the feature_flag table (schema created by node-pg-migrate)
13
+ pgm.createTable(
14
+ { schema: "flapjack", name: "feature_flag" },
15
+ {
16
+ id: "id",
17
+ name: { type: "text", notNull: true, unique: true },
18
+ everyone: { type: "boolean" },
19
+ percent: {
20
+ type: "numeric(3,1)",
21
+ check: "percent >= 0 AND percent <= 99.9",
22
+ },
23
+ roles: { type: "text[]", default: pgm.func("'{}'::text[]") },
24
+ groups: { type: "text[]", default: pgm.func("'{}'::text[]") },
25
+ users: { type: "text[]", default: pgm.func("'{}'::text[]") },
26
+ note: { type: "text" },
27
+ created: {
28
+ type: "timestamptz",
29
+ notNull: true,
30
+ default: pgm.func("now()"),
31
+ },
32
+ modified: {
33
+ type: "timestamptz",
34
+ notNull: true,
35
+ default: pgm.func("now()"),
36
+ },
20
37
  },
21
- roles: { type: "text[]", default: pgm.func("'{}'::text[]") },
22
- groups: { type: "text[]", default: pgm.func("'{}'::text[]") },
23
- users: { type: "text[]", default: pgm.func("'{}'::text[]") },
24
- note: { type: "text" },
25
- created: { type: "timestamptz", notNull: true, default: pgm.func("now()") },
26
- modified: {
27
- type: "timestamptz",
28
- notNull: true,
29
- default: pgm.func("now()"),
30
- },
31
- });
38
+ );
32
39
 
33
40
  // Create a trigger to update the modified timestamp on row update
34
41
  pgm.sql(`
35
- CREATE OR REPLACE FUNCTION flapjack_set_modified_timestamp()
42
+ CREATE OR REPLACE FUNCTION flapjack.set_modified_timestamp()
36
43
  RETURNS trigger AS $$
37
44
  BEGIN
38
45
  NEW.modified = now();
@@ -41,12 +48,12 @@ export const up = (pgm) => {
41
48
  $$ LANGUAGE plpgsql;
42
49
  `);
43
50
 
44
- // Attach the trigger to the flapjack_feature_flag table
51
+ // Attach the trigger to the feature_flag table
45
52
  pgm.sql(`
46
- CREATE TRIGGER flapjack_feature_flag_set_modified
47
- BEFORE UPDATE ON flapjack_feature_flag
53
+ CREATE TRIGGER feature_flag_set_modified
54
+ BEFORE UPDATE ON flapjack.feature_flag
48
55
  FOR EACH ROW
49
- EXECUTE FUNCTION flapjack_set_modified_timestamp();
56
+ EXECUTE FUNCTION flapjack.set_modified_timestamp();
50
57
  `);
51
58
  };
52
59
 
@@ -57,9 +64,9 @@ export const up = (pgm) => {
57
64
  */
58
65
  export const down = (pgm) => {
59
66
  pgm.sql(`
60
- DROP TRIGGER IF EXISTS flapjack_feature_flag_set_modified
61
- ON flapjack_feature_flag;
67
+ DROP TRIGGER IF EXISTS feature_flag_set_modified
68
+ ON flapjack.feature_flag;
62
69
  `);
63
- pgm.sql(`DROP FUNCTION IF EXISTS flapjack_set_modified_timestamp;`);
64
- pgm.dropTable("flapjack_feature_flag");
70
+ pgm.sql(`DROP FUNCTION IF EXISTS flapjack.set_modified_timestamp;`);
71
+ pgm.dropTable({ schema: "flapjack", name: "feature_flag" });
65
72
  };
@@ -9,9 +9,12 @@ export const shorthands = undefined;
9
9
  * @returns {Promise<void> | void}
10
10
  */
11
11
  export const up = (pgm) => {
12
- pgm.addColumn("flapjack_feature_flag", {
13
- expires: { type: "timestamptz" },
14
- });
12
+ pgm.addColumn(
13
+ { schema: "flapjack", name: "feature_flag" },
14
+ {
15
+ expires: { type: "timestamptz" },
16
+ },
17
+ );
15
18
  };
16
19
 
17
20
  /**
@@ -20,5 +23,5 @@ export const up = (pgm) => {
20
23
  * @returns {Promise<void> | void}
21
24
  */
22
25
  export const down = (pgm) => {
23
- pgm.dropColumn("flapjack_feature_flag", "expires");
26
+ pgm.dropColumn({ schema: "flapjack", name: "feature_flag" }, "expires");
24
27
  };
@@ -9,40 +9,54 @@ export const shorthands = undefined;
9
9
  * @returns {Promise<void> | void}
10
10
  */
11
11
  export const up = (pgm) => {
12
- // Create the flapjack_feature_flag_group table
13
- pgm.createTable("flapjack_feature_flag_group", {
14
- id: "id",
15
- name: { type: "text", notNull: true, unique: true },
16
- note: { type: "text" },
17
- created: { type: "timestamptz", notNull: true, default: pgm.func("now()") },
18
- modified: {
19
- type: "timestamptz",
20
- notNull: true,
21
- default: pgm.func("now()"),
12
+ // Create the feature_flag_group table
13
+ pgm.createTable(
14
+ { schema: "flapjack", name: "feature_flag_group" },
15
+ {
16
+ id: "id",
17
+ name: { type: "text", notNull: true, unique: true },
18
+ note: { type: "text" },
19
+ created: {
20
+ type: "timestamptz",
21
+ notNull: true,
22
+ default: pgm.func("now()"),
23
+ },
24
+ modified: {
25
+ type: "timestamptz",
26
+ notNull: true,
27
+ default: pgm.func("now()"),
28
+ },
22
29
  },
23
- });
30
+ );
24
31
 
25
- // Create the flapjack_feature_flag_group_member relation table
26
- pgm.createTable("flapjack_feature_flag_group_member", {
27
- id: "id",
28
- group_id: {
29
- type: "integer",
30
- notNull: true,
31
- references: "flapjack_feature_flag_group",
32
- onDelete: "CASCADE",
33
- },
34
- feature_flag_id: {
35
- type: "integer",
36
- notNull: true,
37
- references: "flapjack_feature_flag",
38
- onDelete: "CASCADE",
32
+ // Create the feature_flag_group_member relation table
33
+ pgm.createTable(
34
+ { schema: "flapjack", name: "feature_flag_group_member" },
35
+ {
36
+ id: "id",
37
+ group_id: {
38
+ type: "integer",
39
+ notNull: true,
40
+ references: { schema: "flapjack", name: "feature_flag_group" },
41
+ onDelete: "CASCADE",
42
+ },
43
+ feature_flag_id: {
44
+ type: "integer",
45
+ notNull: true,
46
+ references: { schema: "flapjack", name: "feature_flag" },
47
+ onDelete: "CASCADE",
48
+ },
49
+ created: {
50
+ type: "timestamptz",
51
+ notNull: true,
52
+ default: pgm.func("now()"),
53
+ },
39
54
  },
40
- created: { type: "timestamptz", notNull: true, default: pgm.func("now()") },
41
- });
55
+ );
42
56
 
43
57
  // Add unique constraint on group_id and feature_flag_id
44
58
  pgm.addConstraint(
45
- "flapjack_feature_flag_group_member",
59
+ { schema: "flapjack", name: "feature_flag_group_member" },
46
60
  "unique_group_feature_flag",
47
61
  {
48
62
  unique: ["group_id", "feature_flag_id"],
@@ -50,15 +64,21 @@ export const up = (pgm) => {
50
64
  );
51
65
 
52
66
  // Create indexes for efficient lookups
53
- pgm.createIndex("flapjack_feature_flag_group_member", "group_id");
54
- pgm.createIndex("flapjack_feature_flag_group_member", "feature_flag_id");
67
+ pgm.createIndex(
68
+ { schema: "flapjack", name: "feature_flag_group_member" },
69
+ "group_id",
70
+ );
71
+ pgm.createIndex(
72
+ { schema: "flapjack", name: "feature_flag_group_member" },
73
+ "feature_flag_id",
74
+ );
55
75
 
56
76
  // Attach the modified timestamp trigger to the group table
57
77
  pgm.sql(`
58
- CREATE TRIGGER flapjack_feature_flag_group_set_modified
59
- BEFORE UPDATE ON flapjack_feature_flag_group
78
+ CREATE TRIGGER feature_flag_group_set_modified
79
+ BEFORE UPDATE ON flapjack.feature_flag_group
60
80
  FOR EACH ROW
61
- EXECUTE FUNCTION flapjack_set_modified_timestamp();
81
+ EXECUTE FUNCTION flapjack.set_modified_timestamp();
62
82
  `);
63
83
  };
64
84
 
@@ -69,9 +89,9 @@ export const up = (pgm) => {
69
89
  */
70
90
  export const down = (pgm) => {
71
91
  pgm.sql(`
72
- DROP TRIGGER IF EXISTS flapjack_feature_flag_group_set_modified
73
- ON flapjack_feature_flag_group;
92
+ DROP TRIGGER IF EXISTS feature_flag_group_set_modified
93
+ ON flapjack.feature_flag_group;
74
94
  `);
75
- pgm.dropTable("flapjack_feature_flag_group_member");
76
- pgm.dropTable("flapjack_feature_flag_group");
95
+ pgm.dropTable({ schema: "flapjack", name: "feature_flag_group_member" });
96
+ pgm.dropTable({ schema: "flapjack", name: "feature_flag_group" });
77
97
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@brandtg/flapjack",
3
- "version": "0.2.0",
3
+ "version": "1.0.0",
4
4
  "description": "A simple feature flags library with PostgreSQL integration",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",