@furystack/sequelize-store 6.0.49 → 7.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/CHANGELOG.md +26 -0
- package/README.md +23 -10
- package/esm/define-sequelize-store.d.ts +37 -0
- package/esm/define-sequelize-store.d.ts.map +1 -0
- package/esm/define-sequelize-store.js +39 -0
- package/esm/define-sequelize-store.js.map +1 -0
- package/esm/define-sequelize-store.spec.d.ts +2 -0
- package/esm/define-sequelize-store.spec.d.ts.map +1 -0
- package/esm/define-sequelize-store.spec.js +40 -0
- package/esm/define-sequelize-store.spec.js.map +1 -0
- package/esm/index.d.ts +2 -1
- package/esm/index.d.ts.map +1 -1
- package/esm/index.js +2 -1
- package/esm/index.js.map +1 -1
- package/esm/sequelize-client-factory.d.ts +9 -4
- package/esm/sequelize-client-factory.d.ts.map +1 -1
- package/esm/sequelize-client-factory.js +26 -29
- package/esm/sequelize-client-factory.js.map +1 -1
- package/esm/sequelize-store.d.ts +12 -18
- package/esm/sequelize-store.d.ts.map +1 -1
- package/esm/sequelize-store.js +11 -2
- package/esm/sequelize-store.js.map +1 -1
- package/esm/sequelize-store.spec.js +31 -76
- package/esm/sequelize-store.spec.js.map +1 -1
- package/package.json +6 -6
- package/src/define-sequelize-store.spec.ts +47 -0
- package/src/define-sequelize-store.ts +58 -0
- package/src/index.ts +2 -1
- package/src/sequelize-client-factory.ts +33 -21
- package/src/sequelize-store.spec.ts +36 -82
- package/src/sequelize-store.ts +15 -19
- package/esm/store-manager-helpers.d.ts +0 -26
- package/esm/store-manager-helpers.d.ts.map +0 -1
- package/esm/store-manager-helpers.js +0 -15
- package/esm/store-manager-helpers.js.map +0 -1
- package/src/store-manager-helpers.ts +0 -49
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,31 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## [7.0.1] - 2026-05-21
|
|
4
|
+
|
|
5
|
+
### ♻️ Refactoring
|
|
6
|
+
|
|
7
|
+
### `update` throws `NotFoundError` for missing entities
|
|
8
|
+
|
|
9
|
+
`SequelizeStore.update` now throws `NotFoundError` from `@furystack/core` (instead of a plain `Error('Entity not found')`) when zero rows match the primary key. The new message also includes the offending id (`Entity not found with id 'X', cannot update`) so logs are actionable. Callers can branch on `instanceof NotFoundError` without parsing messages — string matches on the bare `Entity not found` keep working as a substring.
|
|
10
|
+
|
|
11
|
+
### ⬆️ Dependencies
|
|
12
|
+
|
|
13
|
+
- Bump dev `vitest` to `^4.1.5`.
|
|
14
|
+
- Bumped `@types/node` to `^25.9.1` and `vitest` to `^4.1.7`. No source changes — dev-tooling bump only.
|
|
15
|
+
|
|
16
|
+
### 📚 Documentation
|
|
17
|
+
|
|
18
|
+
- Rewrote JSDoc on `SequelizeStore`, `SequelizeStoreSettings`, and `defineSequelizeStore` to follow the new value-test guidance: dropped restate-the-type narration, called out the lazy-init + memoized `initModel` contract, and the fact that the store has no `[Symbol.asyncDispose]` because client lifetime belongs to `SequelizeClientFactory`.
|
|
19
|
+
|
|
20
|
+
## [7.0.0] - 2026-04-25
|
|
21
|
+
|
|
22
|
+
### 💥 Breaking Changes
|
|
23
|
+
|
|
24
|
+
Stores are now first-class DI tokens. See the [v7 migration guide](../../docs/migrations/v7-functional-di.md) for rationale, recipes, and pitfalls.
|
|
25
|
+
|
|
26
|
+
- Removed `useSequelize(...)`. Declare the store at module scope with `defineSequelizeStore<T, M, PK>({ name, model, sequelizeModel, primaryKey, options, initModel? })`.
|
|
27
|
+
- `SequelizeClientFactory` is now an exported interface + `defineService({ lifetime: 'singleton' })` token. Clients are pooled by `JSON.stringify(options)` and closed on injector teardown.
|
|
28
|
+
|
|
3
29
|
## [6.0.49] - 2026-04-17
|
|
4
30
|
|
|
5
31
|
### ⬆️ Dependencies
|
package/README.md
CHANGED
|
@@ -12,10 +12,15 @@ yarn add @furystack/sequelize-store
|
|
|
12
12
|
|
|
13
13
|
## Initialization
|
|
14
14
|
|
|
15
|
+
`defineSequelizeStore` mints a `StoreToken` backed by a Sequelize model. The
|
|
16
|
+
shared `SequelizeClientFactory` singleton pools `Sequelize` clients keyed by
|
|
17
|
+
`JSON.stringify(options)` and closes them when the owning injector is
|
|
18
|
+
disposed.
|
|
19
|
+
|
|
15
20
|
```ts
|
|
16
|
-
import {
|
|
17
|
-
import {
|
|
18
|
-
import {
|
|
21
|
+
import { createInjector } from '@furystack/inject'
|
|
22
|
+
import { defineSequelizeStore } from '@furystack/sequelize-store'
|
|
23
|
+
import { defineDataSet } from '@furystack/repository'
|
|
19
24
|
import { Model, type Options } from 'sequelize'
|
|
20
25
|
|
|
21
26
|
export class TestEntry extends Model {
|
|
@@ -23,20 +28,28 @@ export class TestEntry extends Model {
|
|
|
23
28
|
declare public value: string
|
|
24
29
|
}
|
|
25
30
|
|
|
26
|
-
const
|
|
27
|
-
|
|
28
|
-
injector: myInjector,
|
|
31
|
+
export const TestEntryStore = defineSequelizeStore<TestEntry, TestEntry, '_id'>({
|
|
32
|
+
name: 'my-app/TestEntryStore',
|
|
29
33
|
model: TestEntry,
|
|
30
|
-
sequelizeModel: TestEntry,
|
|
34
|
+
sequelizeModel: TestEntry,
|
|
31
35
|
primaryKey: '_id',
|
|
32
36
|
options: {
|
|
33
|
-
// Sequelize connection options
|
|
34
37
|
dialect: 'sqlite',
|
|
35
38
|
storage: ':memory:',
|
|
36
39
|
} as Options,
|
|
37
40
|
})
|
|
38
41
|
|
|
39
|
-
const
|
|
42
|
+
export const TestEntryDataSet = defineDataSet({
|
|
43
|
+
name: 'my-app/TestEntryDataSet',
|
|
44
|
+
store: TestEntryStore,
|
|
45
|
+
})
|
|
46
|
+
|
|
47
|
+
const myInjector = createInjector()
|
|
48
|
+
const dataSet = myInjector.get(TestEntryDataSet)
|
|
40
49
|
```
|
|
41
50
|
|
|
42
|
-
> **Tip:** For application-level data access,
|
|
51
|
+
> **Tip:** For application-level data access, always go through a
|
|
52
|
+
> `DataSetToken` rather than resolving the `StoreToken` directly. The
|
|
53
|
+
> DataSet layer runs authorization, modification hooks, and entity-sync
|
|
54
|
+
> events; a direct store access skips all of them. The
|
|
55
|
+
> `furystack/no-direct-store-token` lint rule guards against this.
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import type { Constructable, StoreToken } from '@furystack/core';
|
|
2
|
+
import type { Model, ModelStatic, Options, Sequelize } from 'sequelize';
|
|
3
|
+
/**
|
|
4
|
+
* Options accepted by {@link defineSequelizeStore}.
|
|
5
|
+
*/
|
|
6
|
+
export type DefineSequelizeStoreOptions<T extends object, M extends Model<T>, TPrimaryKey extends keyof T> = {
|
|
7
|
+
name: string;
|
|
8
|
+
model: Constructable<T>;
|
|
9
|
+
sequelizeModel: ModelStatic<M>;
|
|
10
|
+
primaryKey: TPrimaryKey;
|
|
11
|
+
/** Sequelize client options (dialect, storage, etc.) — also acts as the pool key. */
|
|
12
|
+
options: Options;
|
|
13
|
+
/** Runs once per store before the first DB call (e.g. `Model.init(...)` + `sequelize.sync()`). */
|
|
14
|
+
initModel?: (sequelize: Sequelize) => Promise<void>;
|
|
15
|
+
};
|
|
16
|
+
/**
|
|
17
|
+
* Mints a singleton {@link StoreToken} backed by a {@link SequelizeStore}.
|
|
18
|
+
*
|
|
19
|
+
* Internally resolves the singleton {@link SequelizeClientFactory} so every
|
|
20
|
+
* store declared against the same `options` shares one {@link Sequelize}
|
|
21
|
+
* client. Declare the token once at module scope — inline calls mint new
|
|
22
|
+
* identities and defeat singleton caching.
|
|
23
|
+
*
|
|
24
|
+
* @example
|
|
25
|
+
* ```ts
|
|
26
|
+
* export const UserStore = defineSequelizeStore({
|
|
27
|
+
* name: 'my-app/UserStore',
|
|
28
|
+
* model: User,
|
|
29
|
+
* sequelizeModel: UserSequelizeModel,
|
|
30
|
+
* primaryKey: 'username',
|
|
31
|
+
* options: { dialect: 'sqlite', storage: './data.sqlite' },
|
|
32
|
+
* initModel: async (sequelize) => { ... },
|
|
33
|
+
* })
|
|
34
|
+
* ```
|
|
35
|
+
*/
|
|
36
|
+
export declare const defineSequelizeStore: <T extends object, M extends Model<T>, const TPrimaryKey extends keyof T>(opts: DefineSequelizeStoreOptions<T, M, TPrimaryKey>) => StoreToken<T, TPrimaryKey>;
|
|
37
|
+
//# sourceMappingURL=define-sequelize-store.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"define-sequelize-store.d.ts","sourceRoot":"","sources":["../src/define-sequelize-store.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAA;AAEhE,OAAO,KAAK,EAAE,KAAK,EAAE,WAAW,EAAE,OAAO,EAAE,SAAS,EAAE,MAAM,WAAW,CAAA;AAIvE;;GAEG;AACH,MAAM,MAAM,2BAA2B,CAAC,CAAC,SAAS,MAAM,EAAE,CAAC,SAAS,KAAK,CAAC,CAAC,CAAC,EAAE,WAAW,SAAS,MAAM,CAAC,IAAI;IAC3G,IAAI,EAAE,MAAM,CAAA;IACZ,KAAK,EAAE,aAAa,CAAC,CAAC,CAAC,CAAA;IACvB,cAAc,EAAE,WAAW,CAAC,CAAC,CAAC,CAAA;IAC9B,UAAU,EAAE,WAAW,CAAA;IACvB,qFAAqF;IACrF,OAAO,EAAE,OAAO,CAAA;IAChB,kGAAkG;IAClG,SAAS,CAAC,EAAE,CAAC,SAAS,EAAE,SAAS,KAAK,OAAO,CAAC,IAAI,CAAC,CAAA;CACpD,CAAA;AAED;;;;;;;;;;;;;;;;;;;GAmBG;AACH,eAAO,MAAM,oBAAoB,GAAI,CAAC,SAAS,MAAM,EAAE,CAAC,SAAS,KAAK,CAAC,CAAC,CAAC,EAAE,KAAK,CAAC,WAAW,SAAS,MAAM,CAAC,EAC1G,MAAM,2BAA2B,CAAC,CAAC,EAAE,CAAC,EAAE,WAAW,CAAC,KACnD,UAAU,CAAC,CAAC,EAAE,WAAW,CAexB,CAAA"}
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import { defineStore } from '@furystack/core';
|
|
2
|
+
import { SequelizeClientFactory } from './sequelize-client-factory.js';
|
|
3
|
+
import { SequelizeStore } from './sequelize-store.js';
|
|
4
|
+
/**
|
|
5
|
+
* Mints a singleton {@link StoreToken} backed by a {@link SequelizeStore}.
|
|
6
|
+
*
|
|
7
|
+
* Internally resolves the singleton {@link SequelizeClientFactory} so every
|
|
8
|
+
* store declared against the same `options` shares one {@link Sequelize}
|
|
9
|
+
* client. Declare the token once at module scope — inline calls mint new
|
|
10
|
+
* identities and defeat singleton caching.
|
|
11
|
+
*
|
|
12
|
+
* @example
|
|
13
|
+
* ```ts
|
|
14
|
+
* export const UserStore = defineSequelizeStore({
|
|
15
|
+
* name: 'my-app/UserStore',
|
|
16
|
+
* model: User,
|
|
17
|
+
* sequelizeModel: UserSequelizeModel,
|
|
18
|
+
* primaryKey: 'username',
|
|
19
|
+
* options: { dialect: 'sqlite', storage: './data.sqlite' },
|
|
20
|
+
* initModel: async (sequelize) => { ... },
|
|
21
|
+
* })
|
|
22
|
+
* ```
|
|
23
|
+
*/
|
|
24
|
+
export const defineSequelizeStore = (opts) => defineStore({
|
|
25
|
+
name: opts.name,
|
|
26
|
+
model: opts.model,
|
|
27
|
+
primaryKey: opts.primaryKey,
|
|
28
|
+
factory: ({ inject }) => {
|
|
29
|
+
const factory = inject(SequelizeClientFactory);
|
|
30
|
+
return new SequelizeStore({
|
|
31
|
+
model: opts.model,
|
|
32
|
+
primaryKey: opts.primaryKey,
|
|
33
|
+
sequelizeModel: opts.sequelizeModel,
|
|
34
|
+
getSequelizeClient: () => factory.getSequelizeClient(opts.options),
|
|
35
|
+
initModel: opts.initModel,
|
|
36
|
+
});
|
|
37
|
+
},
|
|
38
|
+
});
|
|
39
|
+
//# sourceMappingURL=define-sequelize-store.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"define-sequelize-store.js","sourceRoot":"","sources":["../src/define-sequelize-store.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,WAAW,EAAE,MAAM,iBAAiB,CAAA;AAE7C,OAAO,EAAE,sBAAsB,EAAE,MAAM,+BAA+B,CAAA;AACtE,OAAO,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAA;AAgBrD;;;;;;;;;;;;;;;;;;;GAmBG;AACH,MAAM,CAAC,MAAM,oBAAoB,GAAG,CAClC,IAAoD,EACxB,EAAE,CAC9B,WAAW,CAAiB;IAC1B,IAAI,EAAE,IAAI,CAAC,IAAI;IACf,KAAK,EAAE,IAAI,CAAC,KAAK;IACjB,UAAU,EAAE,IAAI,CAAC,UAAU;IAC3B,OAAO,EAAE,CAAC,EAAE,MAAM,EAAE,EAAE,EAAE;QACtB,MAAM,OAAO,GAAG,MAAM,CAAC,sBAAsB,CAAC,CAAA;QAC9C,OAAO,IAAI,cAAc,CAAoB;YAC3C,KAAK,EAAE,IAAI,CAAC,KAAK;YACjB,UAAU,EAAE,IAAI,CAAC,UAAU;YAC3B,cAAc,EAAE,IAAI,CAAC,cAAc;YACnC,kBAAkB,EAAE,GAAG,EAAE,CAAC,OAAO,CAAC,kBAAkB,CAAC,IAAI,CAAC,OAAO,CAAC;YAClE,SAAS,EAAE,IAAI,CAAC,SAAS;SAC1B,CAAC,CAAA;IACJ,CAAC;CACF,CAAC,CAAA"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"define-sequelize-store.spec.d.ts","sourceRoot":"","sources":["../src/define-sequelize-store.spec.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import { Model } from 'sequelize';
|
|
2
|
+
import { describe, expect, it } from 'vitest';
|
|
3
|
+
import { defineSequelizeStore } from './define-sequelize-store.js';
|
|
4
|
+
class Item {
|
|
5
|
+
}
|
|
6
|
+
class ItemSequelizeClass extends Model {
|
|
7
|
+
}
|
|
8
|
+
describe('defineSequelizeStore (metadata)', () => {
|
|
9
|
+
it('propagates name, lifetime, model and primaryKey onto the returned token', () => {
|
|
10
|
+
const token = defineSequelizeStore({
|
|
11
|
+
name: 'test/SequelizeItems',
|
|
12
|
+
model: Item,
|
|
13
|
+
sequelizeModel: ItemSequelizeClass,
|
|
14
|
+
primaryKey: 'id',
|
|
15
|
+
options: { dialect: 'sqlite', storage: ':memory:', logging: false },
|
|
16
|
+
});
|
|
17
|
+
expect(token.name).toBe('test/SequelizeItems');
|
|
18
|
+
expect(token.lifetime).toBe('singleton');
|
|
19
|
+
expect(token.model).toBe(Item);
|
|
20
|
+
expect(token.primaryKey).toBe('id');
|
|
21
|
+
});
|
|
22
|
+
it('mints a distinct token identity per call even when options match -- declare once at module scope', () => {
|
|
23
|
+
const a = defineSequelizeStore({
|
|
24
|
+
name: 'test/SequelizeDupe',
|
|
25
|
+
model: Item,
|
|
26
|
+
sequelizeModel: ItemSequelizeClass,
|
|
27
|
+
primaryKey: 'id',
|
|
28
|
+
options: { dialect: 'sqlite', storage: ':memory:', logging: false },
|
|
29
|
+
});
|
|
30
|
+
const b = defineSequelizeStore({
|
|
31
|
+
name: 'test/SequelizeDupe',
|
|
32
|
+
model: Item,
|
|
33
|
+
sequelizeModel: ItemSequelizeClass,
|
|
34
|
+
primaryKey: 'id',
|
|
35
|
+
options: { dialect: 'sqlite', storage: ':memory:', logging: false },
|
|
36
|
+
});
|
|
37
|
+
expect(a.id).not.toBe(b.id);
|
|
38
|
+
});
|
|
39
|
+
});
|
|
40
|
+
//# sourceMappingURL=define-sequelize-store.spec.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"define-sequelize-store.spec.js","sourceRoot":"","sources":["../src/define-sequelize-store.spec.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,MAAM,WAAW,CAAA;AACjC,OAAO,EAAE,QAAQ,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,QAAQ,CAAA;AAC7C,OAAO,EAAE,oBAAoB,EAAE,MAAM,6BAA6B,CAAA;AAElE,MAAM,IAAI;CAGT;AAED,MAAM,kBAAmB,SAAQ,KAAiB;CAGjD;AAED,QAAQ,CAAC,iCAAiC,EAAE,GAAG,EAAE;IAC/C,EAAE,CAAC,yEAAyE,EAAE,GAAG,EAAE;QACjF,MAAM,KAAK,GAAG,oBAAoB,CAAiC;YACjE,IAAI,EAAE,qBAAqB;YAC3B,KAAK,EAAE,IAAI;YACX,cAAc,EAAE,kBAAkB;YAClC,UAAU,EAAE,IAAI;YAChB,OAAO,EAAE,EAAE,OAAO,EAAE,QAAQ,EAAE,OAAO,EAAE,UAAU,EAAE,OAAO,EAAE,KAAK,EAAE;SACpE,CAAC,CAAA;QACF,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,qBAAqB,CAAC,CAAA;QAC9C,MAAM,CAAC,KAAK,CAAC,QAAQ,CAAC,CAAC,IAAI,CAAC,WAAW,CAAC,CAAA;QACxC,MAAM,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAA;QAC9B,MAAM,CAAC,KAAK,CAAC,UAAU,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAA;IACrC,CAAC,CAAC,CAAA;IAEF,EAAE,CAAC,kGAAkG,EAAE,GAAG,EAAE;QAC1G,MAAM,CAAC,GAAG,oBAAoB,CAAiC;YAC7D,IAAI,EAAE,oBAAoB;YAC1B,KAAK,EAAE,IAAI;YACX,cAAc,EAAE,kBAAkB;YAClC,UAAU,EAAE,IAAI;YAChB,OAAO,EAAE,EAAE,OAAO,EAAE,QAAQ,EAAE,OAAO,EAAE,UAAU,EAAE,OAAO,EAAE,KAAK,EAAE;SACpE,CAAC,CAAA;QACF,MAAM,CAAC,GAAG,oBAAoB,CAAiC;YAC7D,IAAI,EAAE,oBAAoB;YAC1B,KAAK,EAAE,IAAI;YACX,cAAc,EAAE,kBAAkB;YAClC,UAAU,EAAE,IAAI;YAChB,OAAO,EAAE,EAAE,OAAO,EAAE,QAAQ,EAAE,OAAO,EAAE,UAAU,EAAE,OAAO,EAAE,KAAK,EAAE;SACpE,CAAC,CAAA;QACF,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,CAAA;IAC7B,CAAC,CAAC,CAAA;AACJ,CAAC,CAAC,CAAA"}
|
package/esm/index.d.ts
CHANGED
package/esm/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,6BAA6B,CAAA;AAC3C,cAAc,+BAA+B,CAAA;AAC7C,cAAc,sBAAsB,CAAA"}
|
package/esm/index.js
CHANGED
package/esm/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,6BAA6B,CAAA;AAC3C,cAAc,+BAA+B,CAAA;AAC7C,cAAc,sBAAsB,CAAA"}
|
|
@@ -1,11 +1,16 @@
|
|
|
1
|
+
import type { Token } from '@furystack/inject';
|
|
1
2
|
import type { Options } from 'sequelize';
|
|
2
3
|
import { Sequelize } from 'sequelize';
|
|
3
4
|
/**
|
|
4
|
-
*
|
|
5
|
+
* Pools {@link Sequelize} client instances keyed by the serialized options so
|
|
6
|
+
* multiple stores against the same connection string share one client.
|
|
5
7
|
*/
|
|
6
|
-
export
|
|
7
|
-
private connections;
|
|
8
|
-
[Symbol.asyncDispose](): Promise<void>;
|
|
8
|
+
export interface SequelizeClientFactory {
|
|
9
9
|
getSequelizeClient(options: Options): Sequelize;
|
|
10
10
|
}
|
|
11
|
+
/**
|
|
12
|
+
* Singleton token for the {@link SequelizeClientFactory}. Closes every pooled
|
|
13
|
+
* client when the owning injector is disposed.
|
|
14
|
+
*/
|
|
15
|
+
export declare const SequelizeClientFactory: Token<SequelizeClientFactory, 'singleton'>;
|
|
11
16
|
//# sourceMappingURL=sequelize-client-factory.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"sequelize-client-factory.d.ts","sourceRoot":"","sources":["../src/sequelize-client-factory.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"sequelize-client-factory.d.ts","sourceRoot":"","sources":["../src/sequelize-client-factory.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,mBAAmB,CAAA;AAE9C,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,WAAW,CAAA;AACxC,OAAO,EAAM,SAAS,EAAE,MAAM,WAAW,CAAA;AA2CzC;;;GAGG;AACH,MAAM,WAAW,sBAAsB;IACrC,kBAAkB,CAAC,OAAO,EAAE,OAAO,GAAG,SAAS,CAAA;CAChD;AAED;;;GAGG;AACH,eAAO,MAAM,sBAAsB,EAAE,KAAK,CAAC,sBAAsB,EAAE,WAAW,CAsB5E,CAAA"}
|
|
@@ -1,10 +1,4 @@
|
|
|
1
|
-
|
|
2
|
-
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
3
|
-
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
4
|
-
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
5
|
-
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
6
|
-
};
|
|
7
|
-
import { Injectable } from '@furystack/inject';
|
|
1
|
+
import { defineService } from '@furystack/inject';
|
|
8
2
|
import { Op, Sequelize } from 'sequelize';
|
|
9
3
|
const operatorsAliases = {
|
|
10
4
|
$eq: Op.eq,
|
|
@@ -47,27 +41,30 @@ const operatorsAliases = {
|
|
|
47
41
|
$col: Op.col,
|
|
48
42
|
};
|
|
49
43
|
/**
|
|
50
|
-
*
|
|
44
|
+
* Singleton token for the {@link SequelizeClientFactory}. Closes every pooled
|
|
45
|
+
* client when the owning injector is disposed.
|
|
51
46
|
*/
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
};
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
47
|
+
export const SequelizeClientFactory = defineService({
|
|
48
|
+
name: '@furystack/sequelize-store/SequelizeClientFactory',
|
|
49
|
+
lifetime: 'singleton',
|
|
50
|
+
factory: ({ onDispose }) => {
|
|
51
|
+
const connections = new Map();
|
|
52
|
+
onDispose(async () => {
|
|
53
|
+
await Promise.all([...connections.values()].map((c) => c.close()));
|
|
54
|
+
connections.clear();
|
|
55
|
+
});
|
|
56
|
+
return {
|
|
57
|
+
getSequelizeClient(options) {
|
|
58
|
+
const key = JSON.stringify(options);
|
|
59
|
+
const existing = connections.get(key);
|
|
60
|
+
if (existing) {
|
|
61
|
+
return existing;
|
|
62
|
+
}
|
|
63
|
+
const client = new Sequelize({ ...options, operatorsAliases });
|
|
64
|
+
connections.set(key, client);
|
|
65
|
+
return client;
|
|
66
|
+
},
|
|
67
|
+
};
|
|
68
|
+
},
|
|
69
|
+
});
|
|
73
70
|
//# sourceMappingURL=sequelize-client-factory.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"sequelize-client-factory.js","sourceRoot":"","sources":["../src/sequelize-client-factory.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"sequelize-client-factory.js","sourceRoot":"","sources":["../src/sequelize-client-factory.ts"],"names":[],"mappings":"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"}
|
package/esm/sequelize-store.d.ts
CHANGED
|
@@ -1,31 +1,25 @@
|
|
|
1
|
-
import type { CreateResult, FilterType, FindOptions, PartialResult, PhysicalStore, WithOptionalId } from '@furystack/core';
|
|
2
|
-
import type { Constructable } from '@furystack/inject';
|
|
1
|
+
import type { Constructable, CreateResult, FilterType, FindOptions, PartialResult, PhysicalStore, WithOptionalId } from '@furystack/core';
|
|
3
2
|
import { EventHub } from '@furystack/utils';
|
|
4
3
|
import type { Model, ModelStatic, Sequelize } from 'sequelize';
|
|
5
4
|
export interface SequelizeStoreSettings<T extends object, M extends Model<T>, TPrimaryKey extends keyof T> {
|
|
6
|
-
/**
|
|
7
|
-
* The Model to use
|
|
8
|
-
*/
|
|
9
5
|
model: Constructable<T>;
|
|
10
|
-
/**
|
|
11
|
-
* The Sequelize Model class
|
|
12
|
-
*/
|
|
13
6
|
sequelizeModel: ModelStatic<M>;
|
|
14
|
-
/**
|
|
15
|
-
* The Primary key field
|
|
16
|
-
*/
|
|
17
7
|
primaryKey: TPrimaryKey;
|
|
18
|
-
/**
|
|
19
|
-
* Callback that returns the Sequelize client (provided by the client factory)
|
|
20
|
-
*/
|
|
8
|
+
/** Resolves the pooled Sequelize client (typically delegated to {@link SequelizeClientFactory}). */
|
|
21
9
|
getSequelizeClient: () => Sequelize;
|
|
22
|
-
/**
|
|
23
|
-
* Optional callback that will initialize the Model for the Sequelize instance
|
|
24
|
-
*/
|
|
10
|
+
/** Runs once before the first DB call (e.g. `Model.init(...)` + `sequelize.sync()`). */
|
|
25
11
|
initModel?: (sequelize: Sequelize) => Promise<void>;
|
|
26
12
|
}
|
|
27
13
|
/**
|
|
28
|
-
*
|
|
14
|
+
* {@link PhysicalStore} backed by a Sequelize Model.
|
|
15
|
+
*
|
|
16
|
+
* The Sequelize client is resolved lazily on the first DB call via
|
|
17
|
+
* {@link getModel}. {@link SequelizeStoreSettings.initModel} runs once and is
|
|
18
|
+
* memoized; if it throws the cached promise is cleared so the next call retries.
|
|
19
|
+
*
|
|
20
|
+
* The store has no `[Symbol.asyncDispose]` — client lifetime belongs to
|
|
21
|
+
* {@link SequelizeClientFactory}, which closes pooled clients on injector
|
|
22
|
+
* teardown.
|
|
29
23
|
*/
|
|
30
24
|
export declare class SequelizeStore<T extends object, M extends Model<T>, TPrimaryKey extends keyof T, TWriteableData = WithOptionalId<T, TPrimaryKey>> extends EventHub<{
|
|
31
25
|
onEntityAdded: {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"sequelize-store.d.ts","sourceRoot":"","sources":["../src/sequelize-store.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,YAAY,EACZ,UAAU,EACV,WAAW,EACX,aAAa,EACb,aAAa,EACb,cAAc,EACf,MAAM,iBAAiB,CAAA;
|
|
1
|
+
{"version":3,"file":"sequelize-store.d.ts","sourceRoot":"","sources":["../src/sequelize-store.ts"],"names":[],"mappings":"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"}
|
package/esm/sequelize-store.js
CHANGED
|
@@ -1,6 +1,15 @@
|
|
|
1
|
+
import { NotFoundError } from '@furystack/core';
|
|
1
2
|
import { EventHub } from '@furystack/utils';
|
|
2
3
|
/**
|
|
3
|
-
*
|
|
4
|
+
* {@link PhysicalStore} backed by a Sequelize Model.
|
|
5
|
+
*
|
|
6
|
+
* The Sequelize client is resolved lazily on the first DB call via
|
|
7
|
+
* {@link getModel}. {@link SequelizeStoreSettings.initModel} runs once and is
|
|
8
|
+
* memoized; if it throws the cached promise is cleared so the next call retries.
|
|
9
|
+
*
|
|
10
|
+
* The store has no `[Symbol.asyncDispose]` — client lifetime belongs to
|
|
11
|
+
* {@link SequelizeClientFactory}, which closes pooled clients on injector
|
|
12
|
+
* teardown.
|
|
4
13
|
*/
|
|
5
14
|
export class SequelizeStore extends EventHub {
|
|
6
15
|
options;
|
|
@@ -56,7 +65,7 @@ export class SequelizeStore extends EventHub {
|
|
|
56
65
|
const model = await this.getModel();
|
|
57
66
|
const result = await model.update(data, { where: { [this.primaryKey]: id } });
|
|
58
67
|
if (result[0] < 1) {
|
|
59
|
-
throw
|
|
68
|
+
throw new NotFoundError(`Entity not found with id '${String(id)}', cannot update`);
|
|
60
69
|
}
|
|
61
70
|
this.emit('onEntityUpdated', { id, change: data });
|
|
62
71
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"sequelize-store.js","sourceRoot":"","sources":["../src/sequelize-store.ts"],"names":[],"mappings":"AASA,OAAO,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAA;
|
|
1
|
+
{"version":3,"file":"sequelize-store.js","sourceRoot":"","sources":["../src/sequelize-store.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,20 +1,30 @@
|
|
|
1
1
|
import { TestClass, createStoreTest } from '@furystack/core/create-physical-store-tests';
|
|
2
|
-
import {
|
|
3
|
-
import { useSequelize } from './store-manager-helpers.js';
|
|
4
|
-
import { DataTypes, Model } from 'sequelize';
|
|
2
|
+
import { createInjector } from '@furystack/inject';
|
|
5
3
|
import { sleepAsync, usingAsync } from '@furystack/utils';
|
|
6
|
-
import {
|
|
4
|
+
import { DataTypes, Model } from 'sequelize';
|
|
5
|
+
import { describe, expect, it } from 'vitest';
|
|
6
|
+
import { defineSequelizeStore } from './define-sequelize-store.js';
|
|
7
7
|
import { SequelizeClientFactory } from './sequelize-client-factory.js';
|
|
8
|
-
import { describe, it, expect } from 'vitest';
|
|
9
8
|
class TestSequelizeClass extends Model {
|
|
10
9
|
}
|
|
10
|
+
const initTestModel = async (sequelize) => {
|
|
11
|
+
TestSequelizeClass.init({
|
|
12
|
+
id: { type: DataTypes.INTEGER, autoIncrement: true, primaryKey: true },
|
|
13
|
+
stringValue1: { type: DataTypes.STRING },
|
|
14
|
+
stringValue2: { type: DataTypes.STRING },
|
|
15
|
+
numberValue1: { type: DataTypes.INTEGER },
|
|
16
|
+
numberValue2: { type: DataTypes.INTEGER },
|
|
17
|
+
booleanValue: { type: DataTypes.BOOLEAN },
|
|
18
|
+
dateValue: { type: DataTypes.DATE },
|
|
19
|
+
}, { sequelize, timestamps: false });
|
|
20
|
+
};
|
|
11
21
|
describe('Sequelize Store', () => {
|
|
12
22
|
createStoreTest({
|
|
13
23
|
typeName: 'sequelize-store',
|
|
14
24
|
skipRegexTests: true,
|
|
15
25
|
createStore: (i) => {
|
|
16
|
-
|
|
17
|
-
|
|
26
|
+
const token = defineSequelizeStore({
|
|
27
|
+
name: 'sequelize-store/TestClass',
|
|
18
28
|
model: TestClass,
|
|
19
29
|
sequelizeModel: TestSequelizeClass,
|
|
20
30
|
primaryKey: 'id',
|
|
@@ -23,41 +33,14 @@ describe('Sequelize Store', () => {
|
|
|
23
33
|
storage: ':memory:',
|
|
24
34
|
logging: false,
|
|
25
35
|
},
|
|
26
|
-
initModel:
|
|
27
|
-
TestSequelizeClass.init({
|
|
28
|
-
id: {
|
|
29
|
-
type: DataTypes.INTEGER,
|
|
30
|
-
autoIncrement: true,
|
|
31
|
-
primaryKey: true,
|
|
32
|
-
},
|
|
33
|
-
stringValue1: {
|
|
34
|
-
type: DataTypes.STRING,
|
|
35
|
-
},
|
|
36
|
-
stringValue2: {
|
|
37
|
-
type: DataTypes.STRING,
|
|
38
|
-
},
|
|
39
|
-
numberValue1: {
|
|
40
|
-
type: DataTypes.INTEGER,
|
|
41
|
-
},
|
|
42
|
-
numberValue2: {
|
|
43
|
-
type: DataTypes.INTEGER,
|
|
44
|
-
},
|
|
45
|
-
booleanValue: {
|
|
46
|
-
type: DataTypes.BOOLEAN,
|
|
47
|
-
},
|
|
48
|
-
dateValue: {
|
|
49
|
-
type: DataTypes.DATE,
|
|
50
|
-
},
|
|
51
|
-
}, { sequelize, timestamps: false });
|
|
52
|
-
},
|
|
36
|
+
initModel: initTestModel,
|
|
53
37
|
});
|
|
54
|
-
|
|
55
|
-
return store;
|
|
38
|
+
return i.get(token);
|
|
56
39
|
},
|
|
57
40
|
});
|
|
58
41
|
it('should return the cached sequelize client instance from the factory', async () => {
|
|
59
|
-
await usingAsync(
|
|
60
|
-
const factory = i.
|
|
42
|
+
await usingAsync(createInjector(), async (i) => {
|
|
43
|
+
const factory = i.get(SequelizeClientFactory);
|
|
61
44
|
const settings = {
|
|
62
45
|
dialect: 'sqlite',
|
|
63
46
|
storage: ':memory:',
|
|
@@ -69,9 +52,9 @@ describe('Sequelize Store', () => {
|
|
|
69
52
|
});
|
|
70
53
|
});
|
|
71
54
|
it('should return the cached model from the store class', async () => {
|
|
72
|
-
await usingAsync(
|
|
73
|
-
|
|
74
|
-
|
|
55
|
+
await usingAsync(createInjector(), async (i) => {
|
|
56
|
+
const token = defineSequelizeStore({
|
|
57
|
+
name: 'sequelize-store/TestClass/cached-model',
|
|
75
58
|
model: TestClass,
|
|
76
59
|
sequelizeModel: TestSequelizeClass,
|
|
77
60
|
primaryKey: 'id',
|
|
@@ -82,36 +65,10 @@ describe('Sequelize Store', () => {
|
|
|
82
65
|
},
|
|
83
66
|
initModel: async (sequelize) => {
|
|
84
67
|
await sleepAsync(100);
|
|
85
|
-
|
|
86
|
-
id: {
|
|
87
|
-
type: DataTypes.INTEGER,
|
|
88
|
-
autoIncrement: true,
|
|
89
|
-
primaryKey: true,
|
|
90
|
-
},
|
|
91
|
-
stringValue1: {
|
|
92
|
-
type: DataTypes.STRING,
|
|
93
|
-
},
|
|
94
|
-
stringValue2: {
|
|
95
|
-
type: DataTypes.STRING,
|
|
96
|
-
},
|
|
97
|
-
numberValue1: {
|
|
98
|
-
type: DataTypes.INTEGER,
|
|
99
|
-
},
|
|
100
|
-
numberValue2: {
|
|
101
|
-
type: DataTypes.INTEGER,
|
|
102
|
-
},
|
|
103
|
-
booleanValue: {
|
|
104
|
-
type: DataTypes.BOOLEAN,
|
|
105
|
-
},
|
|
106
|
-
dateValue: {
|
|
107
|
-
type: DataTypes.DATE,
|
|
108
|
-
},
|
|
109
|
-
}, { sequelize, timestamps: false });
|
|
68
|
+
await initTestModel(sequelize);
|
|
110
69
|
},
|
|
111
70
|
});
|
|
112
|
-
const store = i
|
|
113
|
-
.getInstance(StoreManager)
|
|
114
|
-
.getStoreFor(TestClass, 'id');
|
|
71
|
+
const store = i.get(token);
|
|
115
72
|
const model1Promise = store.getModel();
|
|
116
73
|
const model2 = await store.getModel();
|
|
117
74
|
const model1 = await model1Promise;
|
|
@@ -121,9 +78,9 @@ describe('Sequelize Store', () => {
|
|
|
121
78
|
});
|
|
122
79
|
});
|
|
123
80
|
it('should throw if the sequelize model is not initialized', async () => {
|
|
124
|
-
await usingAsync(
|
|
125
|
-
|
|
126
|
-
|
|
81
|
+
await usingAsync(createInjector(), async (i) => {
|
|
82
|
+
const token = defineSequelizeStore({
|
|
83
|
+
name: 'sequelize-store/TestClass/no-init',
|
|
127
84
|
model: TestClass,
|
|
128
85
|
sequelizeModel: TestSequelizeClass,
|
|
129
86
|
primaryKey: 'id',
|
|
@@ -136,15 +93,13 @@ describe('Sequelize Store', () => {
|
|
|
136
93
|
// won't init the model here
|
|
137
94
|
},
|
|
138
95
|
});
|
|
139
|
-
const store = i
|
|
140
|
-
.getInstance(StoreManager)
|
|
141
|
-
.getStoreFor(TestClass, 'id');
|
|
96
|
+
const store = i.get(token);
|
|
142
97
|
expect.assertions(1);
|
|
143
98
|
try {
|
|
144
99
|
await store.getModel();
|
|
145
100
|
}
|
|
146
101
|
catch (error) {
|
|
147
|
-
expect(error.message).toBe('TestSequelizeClass has not been defined');
|
|
102
|
+
expect(error.message).toBe('TestSequelizeClass has not been defined');
|
|
148
103
|
}
|
|
149
104
|
});
|
|
150
105
|
});
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"sequelize-store.spec.js","sourceRoot":"","sources":["../src/sequelize-store.spec.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,eAAe,EAAE,MAAM,6CAA6C,CAAA;AACxF,OAAO,EAAE,
|
|
1
|
+
{"version":3,"file":"sequelize-store.spec.js","sourceRoot":"","sources":["../src/sequelize-store.spec.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@furystack/sequelize-store",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "7.0.1",
|
|
4
4
|
"description": "Sequelize-based Store implementation for FuryStack",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"scripts": {
|
|
@@ -38,16 +38,16 @@
|
|
|
38
38
|
},
|
|
39
39
|
"homepage": "https://github.com/furystack/furystack",
|
|
40
40
|
"dependencies": {
|
|
41
|
-
"@furystack/core": "^
|
|
42
|
-
"@furystack/inject": "^
|
|
43
|
-
"@furystack/utils": "^
|
|
41
|
+
"@furystack/core": "^17.1.0",
|
|
42
|
+
"@furystack/inject": "^13.0.1",
|
|
43
|
+
"@furystack/utils": "^9.0.1",
|
|
44
44
|
"sequelize": "^6.37.8"
|
|
45
45
|
},
|
|
46
46
|
"devDependencies": {
|
|
47
|
-
"@types/node": "^25.
|
|
47
|
+
"@types/node": "^25.9.1",
|
|
48
48
|
"sqlite3": "6.0.1",
|
|
49
49
|
"typescript": "^6.0.3",
|
|
50
|
-
"vitest": "^4.1.
|
|
50
|
+
"vitest": "^4.1.7"
|
|
51
51
|
},
|
|
52
52
|
"engines": {
|
|
53
53
|
"node": ">=22.0.0"
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import { Model } from 'sequelize'
|
|
2
|
+
import { describe, expect, it } from 'vitest'
|
|
3
|
+
import { defineSequelizeStore } from './define-sequelize-store.js'
|
|
4
|
+
|
|
5
|
+
class Item {
|
|
6
|
+
declare id: number
|
|
7
|
+
declare name: string
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
class ItemSequelizeClass extends Model<Item, Item> implements Item {
|
|
11
|
+
declare id: number
|
|
12
|
+
declare name: string
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
describe('defineSequelizeStore (metadata)', () => {
|
|
16
|
+
it('propagates name, lifetime, model and primaryKey onto the returned token', () => {
|
|
17
|
+
const token = defineSequelizeStore<Item, ItemSequelizeClass, 'id'>({
|
|
18
|
+
name: 'test/SequelizeItems',
|
|
19
|
+
model: Item,
|
|
20
|
+
sequelizeModel: ItemSequelizeClass,
|
|
21
|
+
primaryKey: 'id',
|
|
22
|
+
options: { dialect: 'sqlite', storage: ':memory:', logging: false },
|
|
23
|
+
})
|
|
24
|
+
expect(token.name).toBe('test/SequelizeItems')
|
|
25
|
+
expect(token.lifetime).toBe('singleton')
|
|
26
|
+
expect(token.model).toBe(Item)
|
|
27
|
+
expect(token.primaryKey).toBe('id')
|
|
28
|
+
})
|
|
29
|
+
|
|
30
|
+
it('mints a distinct token identity per call even when options match -- declare once at module scope', () => {
|
|
31
|
+
const a = defineSequelizeStore<Item, ItemSequelizeClass, 'id'>({
|
|
32
|
+
name: 'test/SequelizeDupe',
|
|
33
|
+
model: Item,
|
|
34
|
+
sequelizeModel: ItemSequelizeClass,
|
|
35
|
+
primaryKey: 'id',
|
|
36
|
+
options: { dialect: 'sqlite', storage: ':memory:', logging: false },
|
|
37
|
+
})
|
|
38
|
+
const b = defineSequelizeStore<Item, ItemSequelizeClass, 'id'>({
|
|
39
|
+
name: 'test/SequelizeDupe',
|
|
40
|
+
model: Item,
|
|
41
|
+
sequelizeModel: ItemSequelizeClass,
|
|
42
|
+
primaryKey: 'id',
|
|
43
|
+
options: { dialect: 'sqlite', storage: ':memory:', logging: false },
|
|
44
|
+
})
|
|
45
|
+
expect(a.id).not.toBe(b.id)
|
|
46
|
+
})
|
|
47
|
+
})
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
import type { Constructable, StoreToken } from '@furystack/core'
|
|
2
|
+
import { defineStore } from '@furystack/core'
|
|
3
|
+
import type { Model, ModelStatic, Options, Sequelize } from 'sequelize'
|
|
4
|
+
import { SequelizeClientFactory } from './sequelize-client-factory.js'
|
|
5
|
+
import { SequelizeStore } from './sequelize-store.js'
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* Options accepted by {@link defineSequelizeStore}.
|
|
9
|
+
*/
|
|
10
|
+
export type DefineSequelizeStoreOptions<T extends object, M extends Model<T>, TPrimaryKey extends keyof T> = {
|
|
11
|
+
name: string
|
|
12
|
+
model: Constructable<T>
|
|
13
|
+
sequelizeModel: ModelStatic<M>
|
|
14
|
+
primaryKey: TPrimaryKey
|
|
15
|
+
/** Sequelize client options (dialect, storage, etc.) — also acts as the pool key. */
|
|
16
|
+
options: Options
|
|
17
|
+
/** Runs once per store before the first DB call (e.g. `Model.init(...)` + `sequelize.sync()`). */
|
|
18
|
+
initModel?: (sequelize: Sequelize) => Promise<void>
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
* Mints a singleton {@link StoreToken} backed by a {@link SequelizeStore}.
|
|
23
|
+
*
|
|
24
|
+
* Internally resolves the singleton {@link SequelizeClientFactory} so every
|
|
25
|
+
* store declared against the same `options` shares one {@link Sequelize}
|
|
26
|
+
* client. Declare the token once at module scope — inline calls mint new
|
|
27
|
+
* identities and defeat singleton caching.
|
|
28
|
+
*
|
|
29
|
+
* @example
|
|
30
|
+
* ```ts
|
|
31
|
+
* export const UserStore = defineSequelizeStore({
|
|
32
|
+
* name: 'my-app/UserStore',
|
|
33
|
+
* model: User,
|
|
34
|
+
* sequelizeModel: UserSequelizeModel,
|
|
35
|
+
* primaryKey: 'username',
|
|
36
|
+
* options: { dialect: 'sqlite', storage: './data.sqlite' },
|
|
37
|
+
* initModel: async (sequelize) => { ... },
|
|
38
|
+
* })
|
|
39
|
+
* ```
|
|
40
|
+
*/
|
|
41
|
+
export const defineSequelizeStore = <T extends object, M extends Model<T>, const TPrimaryKey extends keyof T>(
|
|
42
|
+
opts: DefineSequelizeStoreOptions<T, M, TPrimaryKey>,
|
|
43
|
+
): StoreToken<T, TPrimaryKey> =>
|
|
44
|
+
defineStore<T, TPrimaryKey>({
|
|
45
|
+
name: opts.name,
|
|
46
|
+
model: opts.model,
|
|
47
|
+
primaryKey: opts.primaryKey,
|
|
48
|
+
factory: ({ inject }) => {
|
|
49
|
+
const factory = inject(SequelizeClientFactory)
|
|
50
|
+
return new SequelizeStore<T, M, TPrimaryKey>({
|
|
51
|
+
model: opts.model,
|
|
52
|
+
primaryKey: opts.primaryKey,
|
|
53
|
+
sequelizeModel: opts.sequelizeModel,
|
|
54
|
+
getSequelizeClient: () => factory.getSequelizeClient(opts.options),
|
|
55
|
+
initModel: opts.initModel,
|
|
56
|
+
})
|
|
57
|
+
},
|
|
58
|
+
})
|
package/src/index.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import type { Token } from '@furystack/inject'
|
|
2
|
+
import { defineService } from '@furystack/inject'
|
|
2
3
|
import type { Options } from 'sequelize'
|
|
3
4
|
import { Op, Sequelize } from 'sequelize'
|
|
4
5
|
|
|
@@ -44,26 +45,37 @@ const operatorsAliases = {
|
|
|
44
45
|
}
|
|
45
46
|
|
|
46
47
|
/**
|
|
47
|
-
*
|
|
48
|
+
* Pools {@link Sequelize} client instances keyed by the serialized options so
|
|
49
|
+
* multiple stores against the same connection string share one client.
|
|
48
50
|
*/
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
public async [Symbol.asyncDispose]() {
|
|
54
|
-
await Promise.all([...this.connections.values()].map((c) => c.close()))
|
|
55
|
-
this.connections.clear()
|
|
56
|
-
}
|
|
51
|
+
export interface SequelizeClientFactory {
|
|
52
|
+
getSequelizeClient(options: Options): Sequelize
|
|
53
|
+
}
|
|
57
54
|
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
55
|
+
/**
|
|
56
|
+
* Singleton token for the {@link SequelizeClientFactory}. Closes every pooled
|
|
57
|
+
* client when the owning injector is disposed.
|
|
58
|
+
*/
|
|
59
|
+
export const SequelizeClientFactory: Token<SequelizeClientFactory, 'singleton'> = defineService({
|
|
60
|
+
name: '@furystack/sequelize-store/SequelizeClientFactory',
|
|
61
|
+
lifetime: 'singleton',
|
|
62
|
+
factory: ({ onDispose }) => {
|
|
63
|
+
const connections = new Map<string, Sequelize>()
|
|
64
|
+
onDispose(async () => {
|
|
65
|
+
await Promise.all([...connections.values()].map((c) => c.close()))
|
|
66
|
+
connections.clear()
|
|
67
|
+
})
|
|
68
|
+
return {
|
|
69
|
+
getSequelizeClient(options: Options): Sequelize {
|
|
70
|
+
const key = JSON.stringify(options)
|
|
71
|
+
const existing = connections.get(key)
|
|
72
|
+
if (existing) {
|
|
73
|
+
return existing
|
|
74
|
+
}
|
|
75
|
+
const client = new Sequelize({ ...options, operatorsAliases })
|
|
76
|
+
connections.set(key, client)
|
|
77
|
+
return client
|
|
78
|
+
},
|
|
63
79
|
}
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
this.connections.set(key, client)
|
|
67
|
-
return client
|
|
68
|
-
}
|
|
69
|
-
}
|
|
80
|
+
},
|
|
81
|
+
})
|
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
import { TestClass, createStoreTest } from '@furystack/core/create-physical-store-tests'
|
|
2
|
-
import {
|
|
3
|
-
import { useSequelize } from './store-manager-helpers.js'
|
|
4
|
-
import { DataTypes, Model } from 'sequelize'
|
|
2
|
+
import { createInjector } from '@furystack/inject'
|
|
5
3
|
import { sleepAsync, usingAsync } from '@furystack/utils'
|
|
6
|
-
import {
|
|
4
|
+
import type { Sequelize } from 'sequelize'
|
|
5
|
+
import { DataTypes, Model } from 'sequelize'
|
|
6
|
+
import { describe, expect, it } from 'vitest'
|
|
7
|
+
import { defineSequelizeStore } from './define-sequelize-store.js'
|
|
7
8
|
import { SequelizeClientFactory } from './sequelize-client-factory.js'
|
|
8
9
|
import type { SequelizeStore } from './sequelize-store.js'
|
|
9
|
-
import { describe, it, expect } from 'vitest'
|
|
10
10
|
|
|
11
11
|
class TestSequelizeClass extends Model<TestClass, TestClass> implements TestClass {
|
|
12
12
|
declare id: number
|
|
@@ -18,13 +18,28 @@ class TestSequelizeClass extends Model<TestClass, TestClass> implements TestClas
|
|
|
18
18
|
declare dateValue: Date
|
|
19
19
|
}
|
|
20
20
|
|
|
21
|
+
const initTestModel = async (sequelize: Sequelize) => {
|
|
22
|
+
TestSequelizeClass.init(
|
|
23
|
+
{
|
|
24
|
+
id: { type: DataTypes.INTEGER, autoIncrement: true, primaryKey: true },
|
|
25
|
+
stringValue1: { type: DataTypes.STRING },
|
|
26
|
+
stringValue2: { type: DataTypes.STRING },
|
|
27
|
+
numberValue1: { type: DataTypes.INTEGER },
|
|
28
|
+
numberValue2: { type: DataTypes.INTEGER },
|
|
29
|
+
booleanValue: { type: DataTypes.BOOLEAN },
|
|
30
|
+
dateValue: { type: DataTypes.DATE },
|
|
31
|
+
},
|
|
32
|
+
{ sequelize, timestamps: false },
|
|
33
|
+
)
|
|
34
|
+
}
|
|
35
|
+
|
|
21
36
|
describe('Sequelize Store', () => {
|
|
22
37
|
createStoreTest({
|
|
23
38
|
typeName: 'sequelize-store',
|
|
24
39
|
skipRegexTests: true,
|
|
25
40
|
createStore: (i) => {
|
|
26
|
-
|
|
27
|
-
|
|
41
|
+
const token = defineSequelizeStore<TestClass, TestSequelizeClass, 'id'>({
|
|
42
|
+
name: 'sequelize-store/TestClass',
|
|
28
43
|
model: TestClass,
|
|
29
44
|
sequelizeModel: TestSequelizeClass,
|
|
30
45
|
primaryKey: 'id',
|
|
@@ -33,45 +48,15 @@ describe('Sequelize Store', () => {
|
|
|
33
48
|
storage: ':memory:',
|
|
34
49
|
logging: false,
|
|
35
50
|
},
|
|
36
|
-
initModel:
|
|
37
|
-
TestSequelizeClass.init(
|
|
38
|
-
{
|
|
39
|
-
id: {
|
|
40
|
-
type: DataTypes.INTEGER,
|
|
41
|
-
autoIncrement: true,
|
|
42
|
-
primaryKey: true,
|
|
43
|
-
},
|
|
44
|
-
stringValue1: {
|
|
45
|
-
type: DataTypes.STRING,
|
|
46
|
-
},
|
|
47
|
-
stringValue2: {
|
|
48
|
-
type: DataTypes.STRING,
|
|
49
|
-
},
|
|
50
|
-
numberValue1: {
|
|
51
|
-
type: DataTypes.INTEGER,
|
|
52
|
-
},
|
|
53
|
-
numberValue2: {
|
|
54
|
-
type: DataTypes.INTEGER,
|
|
55
|
-
},
|
|
56
|
-
booleanValue: {
|
|
57
|
-
type: DataTypes.BOOLEAN,
|
|
58
|
-
},
|
|
59
|
-
dateValue: {
|
|
60
|
-
type: DataTypes.DATE,
|
|
61
|
-
},
|
|
62
|
-
},
|
|
63
|
-
{ sequelize, timestamps: false },
|
|
64
|
-
)
|
|
65
|
-
},
|
|
51
|
+
initModel: initTestModel,
|
|
66
52
|
})
|
|
67
|
-
|
|
68
|
-
return store
|
|
53
|
+
return i.get(token)
|
|
69
54
|
},
|
|
70
55
|
})
|
|
71
56
|
|
|
72
57
|
it('should return the cached sequelize client instance from the factory', async () => {
|
|
73
|
-
await usingAsync(
|
|
74
|
-
const factory = i.
|
|
58
|
+
await usingAsync(createInjector(), async (i) => {
|
|
59
|
+
const factory = i.get(SequelizeClientFactory)
|
|
75
60
|
const settings = {
|
|
76
61
|
dialect: 'sqlite',
|
|
77
62
|
storage: ':memory:',
|
|
@@ -84,9 +69,9 @@ describe('Sequelize Store', () => {
|
|
|
84
69
|
})
|
|
85
70
|
|
|
86
71
|
it('should return the cached model from the store class', async () => {
|
|
87
|
-
await usingAsync(
|
|
88
|
-
|
|
89
|
-
|
|
72
|
+
await usingAsync(createInjector(), async (i) => {
|
|
73
|
+
const token = defineSequelizeStore<TestClass, TestSequelizeClass, 'id'>({
|
|
74
|
+
name: 'sequelize-store/TestClass/cached-model',
|
|
90
75
|
model: TestClass,
|
|
91
76
|
sequelizeModel: TestSequelizeClass,
|
|
92
77
|
primaryKey: 'id',
|
|
@@ -97,39 +82,10 @@ describe('Sequelize Store', () => {
|
|
|
97
82
|
},
|
|
98
83
|
initModel: async (sequelize) => {
|
|
99
84
|
await sleepAsync(100)
|
|
100
|
-
|
|
101
|
-
{
|
|
102
|
-
id: {
|
|
103
|
-
type: DataTypes.INTEGER,
|
|
104
|
-
autoIncrement: true,
|
|
105
|
-
primaryKey: true,
|
|
106
|
-
},
|
|
107
|
-
stringValue1: {
|
|
108
|
-
type: DataTypes.STRING,
|
|
109
|
-
},
|
|
110
|
-
stringValue2: {
|
|
111
|
-
type: DataTypes.STRING,
|
|
112
|
-
},
|
|
113
|
-
numberValue1: {
|
|
114
|
-
type: DataTypes.INTEGER,
|
|
115
|
-
},
|
|
116
|
-
numberValue2: {
|
|
117
|
-
type: DataTypes.INTEGER,
|
|
118
|
-
},
|
|
119
|
-
booleanValue: {
|
|
120
|
-
type: DataTypes.BOOLEAN,
|
|
121
|
-
},
|
|
122
|
-
dateValue: {
|
|
123
|
-
type: DataTypes.DATE,
|
|
124
|
-
},
|
|
125
|
-
},
|
|
126
|
-
{ sequelize, timestamps: false },
|
|
127
|
-
)
|
|
85
|
+
await initTestModel(sequelize)
|
|
128
86
|
},
|
|
129
87
|
})
|
|
130
|
-
const store
|
|
131
|
-
.getInstance(StoreManager)
|
|
132
|
-
.getStoreFor(TestClass, 'id')
|
|
88
|
+
const store = i.get(token) as SequelizeStore<TestClass, TestSequelizeClass, 'id'>
|
|
133
89
|
|
|
134
90
|
const model1Promise = store.getModel()
|
|
135
91
|
const model2 = await store.getModel()
|
|
@@ -143,9 +99,9 @@ describe('Sequelize Store', () => {
|
|
|
143
99
|
})
|
|
144
100
|
|
|
145
101
|
it('should throw if the sequelize model is not initialized', async () => {
|
|
146
|
-
await usingAsync(
|
|
147
|
-
|
|
148
|
-
|
|
102
|
+
await usingAsync(createInjector(), async (i) => {
|
|
103
|
+
const token = defineSequelizeStore<TestClass, TestSequelizeClass, 'id'>({
|
|
104
|
+
name: 'sequelize-store/TestClass/no-init',
|
|
149
105
|
model: TestClass,
|
|
150
106
|
sequelizeModel: TestSequelizeClass,
|
|
151
107
|
primaryKey: 'id',
|
|
@@ -158,15 +114,13 @@ describe('Sequelize Store', () => {
|
|
|
158
114
|
// won't init the model here
|
|
159
115
|
},
|
|
160
116
|
})
|
|
161
|
-
const store
|
|
162
|
-
.getInstance(StoreManager)
|
|
163
|
-
.getStoreFor(TestClass, 'id')
|
|
117
|
+
const store = i.get(token) as SequelizeStore<TestClass, TestSequelizeClass, 'id'>
|
|
164
118
|
|
|
165
119
|
expect.assertions(1)
|
|
166
120
|
try {
|
|
167
121
|
await store.getModel()
|
|
168
122
|
} catch (error) {
|
|
169
|
-
expect((error as Error).message).toBe('TestSequelizeClass has not been defined')
|
|
123
|
+
expect((error as Error).message).toBe('TestSequelizeClass has not been defined')
|
|
170
124
|
}
|
|
171
125
|
})
|
|
172
126
|
})
|
package/src/sequelize-store.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import type {
|
|
2
|
+
Constructable,
|
|
2
3
|
CreateResult,
|
|
3
4
|
FilterType,
|
|
4
5
|
FindOptions,
|
|
@@ -6,36 +7,31 @@ import type {
|
|
|
6
7
|
PhysicalStore,
|
|
7
8
|
WithOptionalId,
|
|
8
9
|
} from '@furystack/core'
|
|
9
|
-
import
|
|
10
|
+
import { NotFoundError } from '@furystack/core'
|
|
10
11
|
import { EventHub } from '@furystack/utils'
|
|
11
12
|
import type { FindAttributeOptions, Identifier, Model, ModelStatic, Sequelize, WhereOptions } from 'sequelize'
|
|
13
|
+
import type { SequelizeClientFactory } from './sequelize-client-factory.js'
|
|
12
14
|
|
|
13
15
|
export interface SequelizeStoreSettings<T extends object, M extends Model<T>, TPrimaryKey extends keyof T> {
|
|
14
|
-
/**
|
|
15
|
-
* The Model to use
|
|
16
|
-
*/
|
|
17
16
|
model: Constructable<T>
|
|
18
|
-
|
|
19
|
-
/**
|
|
20
|
-
* The Sequelize Model class
|
|
21
|
-
*/
|
|
22
17
|
sequelizeModel: ModelStatic<M>
|
|
23
|
-
/**
|
|
24
|
-
* The Primary key field
|
|
25
|
-
*/
|
|
26
18
|
primaryKey: TPrimaryKey
|
|
27
|
-
/**
|
|
28
|
-
* Callback that returns the Sequelize client (provided by the client factory)
|
|
29
|
-
*/
|
|
19
|
+
/** Resolves the pooled Sequelize client (typically delegated to {@link SequelizeClientFactory}). */
|
|
30
20
|
getSequelizeClient: () => Sequelize
|
|
31
|
-
/**
|
|
32
|
-
* Optional callback that will initialize the Model for the Sequelize instance
|
|
33
|
-
*/
|
|
21
|
+
/** Runs once before the first DB call (e.g. `Model.init(...)` + `sequelize.sync()`). */
|
|
34
22
|
initModel?: (sequelize: Sequelize) => Promise<void>
|
|
35
23
|
}
|
|
36
24
|
|
|
37
25
|
/**
|
|
38
|
-
*
|
|
26
|
+
* {@link PhysicalStore} backed by a Sequelize Model.
|
|
27
|
+
*
|
|
28
|
+
* The Sequelize client is resolved lazily on the first DB call via
|
|
29
|
+
* {@link getModel}. {@link SequelizeStoreSettings.initModel} runs once and is
|
|
30
|
+
* memoized; if it throws the cached promise is cleared so the next call retries.
|
|
31
|
+
*
|
|
32
|
+
* The store has no `[Symbol.asyncDispose]` — client lifetime belongs to
|
|
33
|
+
* {@link SequelizeClientFactory}, which closes pooled clients on injector
|
|
34
|
+
* teardown.
|
|
39
35
|
*/
|
|
40
36
|
export class SequelizeStore<
|
|
41
37
|
T extends object,
|
|
@@ -113,7 +109,7 @@ export class SequelizeStore<
|
|
|
113
109
|
|
|
114
110
|
const result = await model.update(data, { where: { [this.primaryKey]: id } as WhereOptions<T> })
|
|
115
111
|
if (result[0] < 1) {
|
|
116
|
-
throw
|
|
112
|
+
throw new NotFoundError(`Entity not found with id '${String(id)}', cannot update`)
|
|
117
113
|
}
|
|
118
114
|
this.emit('onEntityUpdated', { id, change: data })
|
|
119
115
|
}
|
|
@@ -1,26 +0,0 @@
|
|
|
1
|
-
import type { Constructable, Injector } from '@furystack/inject';
|
|
2
|
-
import type { Options, Sequelize, ModelStatic, Model } from 'sequelize';
|
|
3
|
-
export declare const useSequelize: <T extends object, M extends ModelStatic<Model<T>>, Key extends keyof T>({ injector, model, sequelizeModel, primaryKey, options, initModel, }: {
|
|
4
|
-
injector: Injector;
|
|
5
|
-
/**
|
|
6
|
-
* The constructable model class
|
|
7
|
-
*/
|
|
8
|
-
model: Constructable<T>;
|
|
9
|
-
/**
|
|
10
|
-
* The Sequelize Model class
|
|
11
|
-
*/
|
|
12
|
-
sequelizeModel: M;
|
|
13
|
-
/**
|
|
14
|
-
* The name of the Primary Key property
|
|
15
|
-
*/
|
|
16
|
-
primaryKey: Key;
|
|
17
|
-
/**
|
|
18
|
-
* Optional options for the MongoDb Client
|
|
19
|
-
*/
|
|
20
|
-
options: Options;
|
|
21
|
-
/**
|
|
22
|
-
* A callback for model initialization
|
|
23
|
-
*/
|
|
24
|
-
initModel?: (sequelize: Sequelize) => Promise<void>;
|
|
25
|
-
}) => void;
|
|
26
|
-
//# sourceMappingURL=store-manager-helpers.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"store-manager-helpers.d.ts","sourceRoot":"","sources":["../src/store-manager-helpers.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,aAAa,EAAE,QAAQ,EAAE,MAAM,mBAAmB,CAAA;AAChE,OAAO,KAAK,EAAE,OAAO,EAAE,SAAS,EAAE,WAAW,EAAE,KAAK,EAAE,MAAM,WAAW,CAAA;AAIvE,eAAO,MAAM,YAAY,GAAa,CAAC,SAAS,MAAM,EAAE,CAAC,SAAS,WAAW,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,EAAE,GAAG,SAAS,MAAM,CAAC,EAAE,sEAO3G;IACD,QAAQ,EAAE,QAAQ,CAAA;IAClB;;OAEG;IACH,KAAK,EAAE,aAAa,CAAC,CAAC,CAAC,CAAA;IAEvB;;OAEG;IACH,cAAc,EAAE,CAAC,CAAA;IAEjB;;OAEG;IACH,UAAU,EAAE,GAAG,CAAA;IACf;;OAEG;IACH,OAAO,EAAE,OAAO,CAAA;IAChB;;OAEG;IAEH,SAAS,CAAC,EAAE,CAAC,SAAS,EAAE,SAAS,KAAK,OAAO,CAAC,IAAI,CAAC,CAAA;CACpD,SAUA,CAAA"}
|
|
@@ -1,15 +0,0 @@
|
|
|
1
|
-
import { addStore } from '@furystack/core';
|
|
2
|
-
import { SequelizeClientFactory } from './sequelize-client-factory.js';
|
|
3
|
-
import { SequelizeStore } from './sequelize-store.js';
|
|
4
|
-
export const useSequelize = function ({ injector, model, sequelizeModel, primaryKey, options, initModel, }) {
|
|
5
|
-
const clientFactory = injector.getInstance(SequelizeClientFactory);
|
|
6
|
-
const store = new SequelizeStore({
|
|
7
|
-
model,
|
|
8
|
-
primaryKey,
|
|
9
|
-
getSequelizeClient: () => clientFactory.getSequelizeClient(options),
|
|
10
|
-
initModel,
|
|
11
|
-
sequelizeModel,
|
|
12
|
-
});
|
|
13
|
-
addStore(injector, store);
|
|
14
|
-
};
|
|
15
|
-
//# sourceMappingURL=store-manager-helpers.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"store-manager-helpers.js","sourceRoot":"","sources":["../src/store-manager-helpers.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,iBAAiB,CAAA;AAG1C,OAAO,EAAE,sBAAsB,EAAE,MAAM,+BAA+B,CAAA;AACtE,OAAO,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAA;AAErD,MAAM,CAAC,MAAM,YAAY,GAAG,UAAkF,EAC5G,QAAQ,EACR,KAAK,EACL,cAAc,EACd,UAAU,EACV,OAAO,EACP,SAAS,GA0BV;IACC,MAAM,aAAa,GAAG,QAAQ,CAAC,WAAW,CAAC,sBAAsB,CAAC,CAAA;IAClE,MAAM,KAAK,GAAG,IAAI,cAAc,CAAC;QAC/B,KAAK;QACL,UAAU;QACV,kBAAkB,EAAE,GAAG,EAAE,CAAC,aAAa,CAAC,kBAAkB,CAAC,OAAO,CAAC;QACnE,SAAS;QACT,cAAc;KACf,CAAC,CAAA;IACF,QAAQ,CAAC,QAAQ,EAAE,KAAK,CAAC,CAAA;AAC3B,CAAC,CAAA"}
|
|
@@ -1,49 +0,0 @@
|
|
|
1
|
-
import { addStore } from '@furystack/core'
|
|
2
|
-
import type { Constructable, Injector } from '@furystack/inject'
|
|
3
|
-
import type { Options, Sequelize, ModelStatic, Model } from 'sequelize'
|
|
4
|
-
import { SequelizeClientFactory } from './sequelize-client-factory.js'
|
|
5
|
-
import { SequelizeStore } from './sequelize-store.js'
|
|
6
|
-
|
|
7
|
-
export const useSequelize = function <T extends object, M extends ModelStatic<Model<T>>, Key extends keyof T>({
|
|
8
|
-
injector,
|
|
9
|
-
model,
|
|
10
|
-
sequelizeModel,
|
|
11
|
-
primaryKey,
|
|
12
|
-
options,
|
|
13
|
-
initModel,
|
|
14
|
-
}: {
|
|
15
|
-
injector: Injector
|
|
16
|
-
/**
|
|
17
|
-
* The constructable model class
|
|
18
|
-
*/
|
|
19
|
-
model: Constructable<T>
|
|
20
|
-
|
|
21
|
-
/**
|
|
22
|
-
* The Sequelize Model class
|
|
23
|
-
*/
|
|
24
|
-
sequelizeModel: M
|
|
25
|
-
|
|
26
|
-
/**
|
|
27
|
-
* The name of the Primary Key property
|
|
28
|
-
*/
|
|
29
|
-
primaryKey: Key
|
|
30
|
-
/**
|
|
31
|
-
* Optional options for the MongoDb Client
|
|
32
|
-
*/
|
|
33
|
-
options: Options
|
|
34
|
-
/**
|
|
35
|
-
* A callback for model initialization
|
|
36
|
-
*/
|
|
37
|
-
|
|
38
|
-
initModel?: (sequelize: Sequelize) => Promise<void>
|
|
39
|
-
}) {
|
|
40
|
-
const clientFactory = injector.getInstance(SequelizeClientFactory)
|
|
41
|
-
const store = new SequelizeStore({
|
|
42
|
-
model,
|
|
43
|
-
primaryKey,
|
|
44
|
-
getSequelizeClient: () => clientFactory.getSequelizeClient(options),
|
|
45
|
-
initModel,
|
|
46
|
-
sequelizeModel,
|
|
47
|
-
})
|
|
48
|
-
addStore(injector, store)
|
|
49
|
-
}
|