@tanglemedia/svelte-starter-toolbelt 2.0.0-next.2 → 2.0.0-next.3
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 +43 -38
- package/dist/service/index.d.ts +1 -0
- package/dist/service/index.js +1 -0
- package/dist/service/provider/create-fixture-service.provider.d.ts +9 -0
- package/dist/service/provider/create-fixture-service.provider.js +18 -0
- package/package.json +4 -4
- package/src/lib/service/index.ts +1 -0
- package/src/lib/service/provider/create-fixture-service.provider.test.ts +94 -0
- package/src/lib/service/provider/create-fixture-service.provider.ts +37 -0
package/README.md
CHANGED
|
@@ -1,58 +1,63 @@
|
|
|
1
|
-
#
|
|
1
|
+
# @tanglemedia/svelte-starter-toolbelt
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
Shared service, query, mutation, proxy, and utility helpers used across the Svelte Starter.
|
|
4
4
|
|
|
5
|
-
|
|
5
|
+
## Service providers
|
|
6
6
|
|
|
7
|
-
|
|
7
|
+
`createServiceFactory` builds typed collection services on top of a provider:
|
|
8
8
|
|
|
9
|
-
|
|
9
|
+
- `createDirectusServiceProvider` for Directus-backed collections
|
|
10
|
+
- `createFetchServiceProvider` for generic REST APIs
|
|
11
|
+
- `createFixtureServiceProvider` for local JSON fixtures served through core's `fixture` adapter
|
|
10
12
|
|
|
11
|
-
|
|
12
|
-
# create a new project in the current directory
|
|
13
|
-
npx sv create
|
|
13
|
+
### Fixture provider example
|
|
14
14
|
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
15
|
+
```typescript
|
|
16
|
+
import {
|
|
17
|
+
createFixtureServiceProvider,
|
|
18
|
+
createServiceFactory
|
|
19
|
+
} from '@tanglemedia/svelte-starter-toolbelt';
|
|
20
|
+
import configuredApp from '$boot';
|
|
18
21
|
|
|
19
|
-
|
|
22
|
+
type User = {
|
|
23
|
+
id: number;
|
|
24
|
+
name: string;
|
|
25
|
+
};
|
|
20
26
|
|
|
21
|
-
|
|
27
|
+
type Schema = {
|
|
28
|
+
users: User;
|
|
29
|
+
};
|
|
22
30
|
|
|
23
|
-
|
|
24
|
-
|
|
31
|
+
export const createService = createServiceFactory<Schema, typeof createFixtureServiceProvider>(
|
|
32
|
+
configuredApp,
|
|
33
|
+
createFixtureServiceProvider
|
|
34
|
+
);
|
|
25
35
|
|
|
26
|
-
|
|
27
|
-
|
|
36
|
+
export const usersService = createService('users');
|
|
37
|
+
export const { findUsers, findUsersById } = usersService;
|
|
28
38
|
```
|
|
29
39
|
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
## Building
|
|
40
|
+
`createFixtureServiceProvider` defaults `adapterKey` to `'fixture'`, so it works with this
|
|
41
|
+
`api.yml` setup:
|
|
33
42
|
|
|
34
|
-
|
|
43
|
+
```yaml
|
|
44
|
+
default: 'fixture'
|
|
35
45
|
|
|
36
|
-
|
|
37
|
-
|
|
46
|
+
adapters:
|
|
47
|
+
fixture:
|
|
48
|
+
adapter: fixture
|
|
49
|
+
configuration: {}
|
|
38
50
|
```
|
|
39
51
|
|
|
40
|
-
|
|
52
|
+
If you need a different adapter key:
|
|
41
53
|
|
|
42
|
-
```
|
|
43
|
-
|
|
54
|
+
```typescript
|
|
55
|
+
export const tenantUsersService = createService('users', {
|
|
56
|
+
adapterKey: 'tenant-fixture'
|
|
57
|
+
});
|
|
44
58
|
```
|
|
45
59
|
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
> To deploy your app, you may need to install an [adapter](https://svelte.dev/docs/kit/adapters) for your target environment.
|
|
49
|
-
|
|
50
|
-
## Publishing
|
|
60
|
+
## More docs
|
|
51
61
|
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
To publish your library to [npm](https://www.npmjs.com):
|
|
55
|
-
|
|
56
|
-
```bash
|
|
57
|
-
npm publish
|
|
58
|
-
```
|
|
62
|
+
- Package docs: `docs/packages/toolbelt.md`
|
|
63
|
+
- Service-focused guide: `docs/packages/toolbelt-services.md`
|
package/dist/service/index.d.ts
CHANGED
package/dist/service/index.js
CHANGED
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { ServiceAbstract, type AnyObject, type ConfigurableServiceClass, type ConfiguredApplication, type ServiceAbstractOptions } from '@tanglemedia/svelte-starter-core';
|
|
2
|
+
export declare class BaseFixtureService<T extends AnyObject> extends ServiceAbstract<T> {
|
|
3
|
+
}
|
|
4
|
+
type FixtureServiceProviderOpt<T extends AnyObject> = {
|
|
5
|
+
serviceClass?: (base: ConfigurableServiceClass<T, BaseFixtureService<T>>) => ConfigurableServiceClass<T, BaseFixtureService<T>>;
|
|
6
|
+
adapterKey?: string;
|
|
7
|
+
};
|
|
8
|
+
export declare function createFixtureServiceProvider({ configureService }: ConfiguredApplication): <T extends AnyObject>(collection: string, opt?: Partial<ServiceAbstractOptions> & FixtureServiceProviderOpt<T>) => BaseFixtureService<T>;
|
|
9
|
+
export {};
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { ServiceAbstract } from '@tanglemedia/svelte-starter-core';
|
|
2
|
+
export class BaseFixtureService extends ServiceAbstract {
|
|
3
|
+
}
|
|
4
|
+
export function createFixtureServiceProvider({ configureService }) {
|
|
5
|
+
const services = {};
|
|
6
|
+
return (collection, opt) => {
|
|
7
|
+
const k = JSON.stringify([collection, opt]);
|
|
8
|
+
if (services[k]) {
|
|
9
|
+
return services[k];
|
|
10
|
+
}
|
|
11
|
+
const Service = opt?.serviceClass ? opt.serviceClass(BaseFixtureService) : BaseFixtureService;
|
|
12
|
+
return (services[k] = configureService(Service, {
|
|
13
|
+
path: collection,
|
|
14
|
+
adapterKey: opt?.adapterKey ?? 'fixture',
|
|
15
|
+
...(opt ?? {})
|
|
16
|
+
}));
|
|
17
|
+
};
|
|
18
|
+
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@tanglemedia/svelte-starter-toolbelt",
|
|
3
|
-
"version": "2.0.0-next.
|
|
3
|
+
"version": "2.0.0-next.3",
|
|
4
4
|
"files": [
|
|
5
5
|
"src",
|
|
6
6
|
"dist",
|
|
@@ -29,7 +29,7 @@
|
|
|
29
29
|
},
|
|
30
30
|
"peerDependencies": {
|
|
31
31
|
"@directus/sdk": ">=17.0.0",
|
|
32
|
-
"@tanglemedia/svelte-starter-core": ">=4.0.0-next.
|
|
32
|
+
"@tanglemedia/svelte-starter-core": ">=4.0.0-next.1",
|
|
33
33
|
"@tanstack/svelte-query": ">=6",
|
|
34
34
|
"svelte": "^5.0.0"
|
|
35
35
|
},
|
|
@@ -64,8 +64,8 @@
|
|
|
64
64
|
"vite": "^8.0.8",
|
|
65
65
|
"msw": "^2.12.7",
|
|
66
66
|
"vitest": "^4.1.4",
|
|
67
|
-
"@tanglemedia/svelte-starter-
|
|
68
|
-
"@tanglemedia/svelte-starter-
|
|
67
|
+
"@tanglemedia/svelte-starter-core": "4.0.0-next.1",
|
|
68
|
+
"@tanglemedia/svelte-starter-types": "3.0.0-next.0"
|
|
69
69
|
},
|
|
70
70
|
"keywords": [
|
|
71
71
|
"svelte"
|
package/src/lib/service/index.ts
CHANGED
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
import { describe, expect, test, vi } from 'vitest';
|
|
2
|
+
import type { ConfiguredApplication, ServiceAbstractOptions } from '@tanglemedia/svelte-starter-core';
|
|
3
|
+
|
|
4
|
+
import {
|
|
5
|
+
BaseFixtureService,
|
|
6
|
+
createFixtureServiceProvider
|
|
7
|
+
} from './create-fixture-service.provider';
|
|
8
|
+
|
|
9
|
+
describe('createFixtureServiceProvider', () => {
|
|
10
|
+
test('returns a factory function', () => {
|
|
11
|
+
const app = {
|
|
12
|
+
configureService: vi.fn()
|
|
13
|
+
} as unknown as ConfiguredApplication;
|
|
14
|
+
|
|
15
|
+
const createService = createFixtureServiceProvider(app);
|
|
16
|
+
|
|
17
|
+
expect(typeof createService).toBe('function');
|
|
18
|
+
});
|
|
19
|
+
|
|
20
|
+
test('caches service instances for the same collection and options', () => {
|
|
21
|
+
const instance = { service: 'fixture' };
|
|
22
|
+
const app = {
|
|
23
|
+
configureService: vi.fn(() => instance)
|
|
24
|
+
} as unknown as ConfiguredApplication;
|
|
25
|
+
const createService = createFixtureServiceProvider(app);
|
|
26
|
+
|
|
27
|
+
const first = createService('users');
|
|
28
|
+
const second = createService('users');
|
|
29
|
+
|
|
30
|
+
expect(first).toBe(second);
|
|
31
|
+
expect(app.configureService).toHaveBeenCalledOnce();
|
|
32
|
+
});
|
|
33
|
+
|
|
34
|
+
test('defaults adapterKey to fixture', () => {
|
|
35
|
+
const configureService = vi.fn();
|
|
36
|
+
const app = {
|
|
37
|
+
configureService
|
|
38
|
+
} as unknown as ConfiguredApplication;
|
|
39
|
+
const createService = createFixtureServiceProvider(app);
|
|
40
|
+
|
|
41
|
+
createService('users');
|
|
42
|
+
|
|
43
|
+
expect(configureService).toHaveBeenCalledWith(
|
|
44
|
+
BaseFixtureService,
|
|
45
|
+
expect.objectContaining({
|
|
46
|
+
path: 'users',
|
|
47
|
+
adapterKey: 'fixture'
|
|
48
|
+
})
|
|
49
|
+
);
|
|
50
|
+
});
|
|
51
|
+
|
|
52
|
+
test('passes through a custom adapterKey when provided', () => {
|
|
53
|
+
const configureService = vi.fn();
|
|
54
|
+
const app = {
|
|
55
|
+
configureService
|
|
56
|
+
} as unknown as ConfiguredApplication;
|
|
57
|
+
const createService = createFixtureServiceProvider(app);
|
|
58
|
+
|
|
59
|
+
createService('users', {
|
|
60
|
+
adapterKey: 'tenant-fixture'
|
|
61
|
+
});
|
|
62
|
+
|
|
63
|
+
expect(configureService).toHaveBeenCalledWith(
|
|
64
|
+
BaseFixtureService,
|
|
65
|
+
expect.objectContaining({
|
|
66
|
+
adapterKey: 'tenant-fixture'
|
|
67
|
+
})
|
|
68
|
+
);
|
|
69
|
+
});
|
|
70
|
+
|
|
71
|
+
test('uses a custom serviceClass when provided', () => {
|
|
72
|
+
const configureService = vi.fn();
|
|
73
|
+
const app = {
|
|
74
|
+
configureService
|
|
75
|
+
} as unknown as ConfiguredApplication;
|
|
76
|
+
const createService = createFixtureServiceProvider(app);
|
|
77
|
+
|
|
78
|
+
class CustomFixtureService<T extends Record<string, unknown>> extends BaseFixtureService<T> {}
|
|
79
|
+
|
|
80
|
+
createService('users', {
|
|
81
|
+
serviceClass: () => CustomFixtureService,
|
|
82
|
+
throwError: false
|
|
83
|
+
} as Partial<ServiceAbstractOptions>);
|
|
84
|
+
|
|
85
|
+
expect(configureService).toHaveBeenCalledWith(
|
|
86
|
+
CustomFixtureService,
|
|
87
|
+
expect.objectContaining({
|
|
88
|
+
path: 'users',
|
|
89
|
+
adapterKey: 'fixture',
|
|
90
|
+
throwError: false
|
|
91
|
+
})
|
|
92
|
+
);
|
|
93
|
+
});
|
|
94
|
+
});
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import {
|
|
2
|
+
ServiceAbstract,
|
|
3
|
+
type AnyObject,
|
|
4
|
+
type ConfigurableServiceClass,
|
|
5
|
+
type ConfiguredApplication,
|
|
6
|
+
type ServiceAbstractOptions
|
|
7
|
+
} from '@tanglemedia/svelte-starter-core';
|
|
8
|
+
|
|
9
|
+
export class BaseFixtureService<T extends AnyObject> extends ServiceAbstract<T> {}
|
|
10
|
+
|
|
11
|
+
type FixtureServiceProviderOpt<T extends AnyObject> = {
|
|
12
|
+
serviceClass?: (base: ConfigurableServiceClass<T, BaseFixtureService<T>>) => ConfigurableServiceClass<T, BaseFixtureService<T>>;
|
|
13
|
+
adapterKey?: string;
|
|
14
|
+
};
|
|
15
|
+
|
|
16
|
+
export function createFixtureServiceProvider({ configureService }: ConfiguredApplication) {
|
|
17
|
+
const services: Record<string, unknown> = {};
|
|
18
|
+
|
|
19
|
+
return <T extends AnyObject>(
|
|
20
|
+
collection: string,
|
|
21
|
+
opt?: Partial<ServiceAbstractOptions> & FixtureServiceProviderOpt<T>
|
|
22
|
+
): BaseFixtureService<T> => {
|
|
23
|
+
const k = JSON.stringify([collection, opt]);
|
|
24
|
+
|
|
25
|
+
if (services[k]) {
|
|
26
|
+
return services[k] as BaseFixtureService<T>;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
const Service = opt?.serviceClass ? opt.serviceClass(BaseFixtureService) : BaseFixtureService<T>;
|
|
30
|
+
|
|
31
|
+
return (services[k] = configureService<T, BaseFixtureService<T>>(Service, {
|
|
32
|
+
path: collection,
|
|
33
|
+
adapterKey: opt?.adapterKey ?? 'fixture',
|
|
34
|
+
...(opt ?? {})
|
|
35
|
+
})) as BaseFixtureService<T>;
|
|
36
|
+
};
|
|
37
|
+
}
|