snice 3.6.0 → 3.8.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/README.md +2 -2
- package/bin/snice.js +4 -5
- package/bin/templates/CLAUDE.md +25 -3
- package/bin/templates/pwa/README.md +188 -0
- package/bin/templates/pwa/global.d.ts +10 -0
- package/bin/templates/pwa/index.html +16 -0
- package/bin/templates/pwa/package.json +32 -0
- package/bin/templates/pwa/public/icons/.gitkeep +6 -0
- package/bin/templates/pwa/src/daemons/notifications.ts +148 -0
- package/bin/templates/pwa/src/fetcher.ts +15 -0
- package/bin/templates/pwa/src/guards/auth.ts +12 -0
- package/bin/templates/pwa/src/main.ts +42 -0
- package/bin/templates/pwa/src/middleware/auth.ts +16 -0
- package/bin/templates/pwa/src/middleware/error.ts +36 -0
- package/bin/templates/pwa/src/middleware/retry.ts +31 -0
- package/bin/templates/pwa/src/pages/dashboard.ts +143 -0
- package/bin/templates/pwa/src/pages/login.ts +161 -0
- package/bin/templates/pwa/src/pages/notifications.ts +156 -0
- package/bin/templates/pwa/src/pages/profile.ts +164 -0
- package/bin/templates/pwa/src/router.ts +20 -0
- package/bin/templates/pwa/src/services/auth.ts +48 -0
- package/bin/templates/pwa/src/services/jwt.ts +35 -0
- package/bin/templates/pwa/src/services/storage.ts +24 -0
- package/bin/templates/pwa/src/styles/global.css +55 -0
- package/bin/templates/pwa/src/types/auth.ts +21 -0
- package/bin/templates/pwa/src/types/notifications.ts +9 -0
- package/bin/templates/pwa/tests/helpers/test-utils.ts +84 -0
- package/bin/templates/pwa/tests/middleware/auth.test.ts +67 -0
- package/bin/templates/pwa/tests/middleware/error.test.ts +105 -0
- package/bin/templates/pwa/tests/middleware/retry.test.ts +103 -0
- package/bin/templates/pwa/tests/services/auth.test.ts +89 -0
- package/bin/templates/pwa/tests/services/jwt.test.ts +76 -0
- package/bin/templates/pwa/tests/services/storage.test.ts +69 -0
- package/bin/templates/{social → pwa}/tsconfig.json +11 -10
- package/bin/templates/pwa/vite.config.ts +94 -0
- package/bin/templates/{social/vite.config.ts → pwa/vitest.config.ts} +12 -17
- package/dist/components/music-player/snice-music-player.d.ts +72 -0
- package/dist/components/music-player/snice-music-player.js +730 -0
- package/dist/components/music-player/snice-music-player.js.map +1 -0
- package/dist/components/music-player/snice-music-player.types.d.ts +43 -0
- package/dist/components/timer/snice-timer.d.ts +27 -0
- package/dist/components/timer/snice-timer.js +197 -0
- package/dist/components/timer/snice-timer.js.map +1 -0
- package/dist/components/timer/snice-timer.types.d.ts +10 -0
- package/dist/fetcher.d.ts +65 -0
- package/dist/index.cjs +92 -3
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.ts +2 -0
- package/dist/index.esm.js +92 -4
- package/dist/index.esm.js.map +1 -1
- package/dist/index.iife.js +92 -3
- package/dist/index.iife.js.map +1 -1
- package/dist/symbols.cjs +1 -1
- package/dist/symbols.esm.js +1 -1
- package/dist/transitions.cjs +1 -1
- package/dist/transitions.esm.js +1 -1
- package/dist/types/context.d.ts +7 -1
- package/dist/types/router-options.d.ts +6 -0
- package/docs/ai/api.md +33 -1
- package/docs/ai/components/music-player.md +134 -0
- package/docs/ai/components/timer.md +43 -0
- package/docs/ai/patterns.md +48 -1
- package/docs/components/music-player.md +314 -0
- package/docs/components/timer.md +143 -0
- package/docs/fetcher.md +447 -0
- package/docs/routing.md +11 -8
- package/package.json +2 -1
- package/bin/templates/social/README.md +0 -42
- package/bin/templates/social/global.d.ts +0 -14
- package/bin/templates/social/index.html +0 -13
- package/bin/templates/social/package.json +0 -21
- package/bin/templates/social/src/main.ts +0 -33
- package/bin/templates/social/src/pages/feed-page.ts +0 -111
- package/bin/templates/social/src/pages/messages-page.ts +0 -102
- package/bin/templates/social/src/pages/not-found-page.ts +0 -46
- package/bin/templates/social/src/pages/profile-page.ts +0 -99
- package/bin/templates/social/src/pages/settings-page.ts +0 -119
- package/bin/templates/social/src/router.ts +0 -9
- package/bin/templates/social/src/styles/global.css +0 -156
- /package/bin/templates/{social → pwa}/public/vite.svg +0 -0
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
import { describe, it, expect, beforeEach, vi } from 'vitest';
|
|
2
|
+
import { getToken, setToken, clearToken, getUser, setUser } from '../../src/services/storage';
|
|
3
|
+
|
|
4
|
+
describe('Storage Service', () => {
|
|
5
|
+
beforeEach(() => {
|
|
6
|
+
localStorage.clear();
|
|
7
|
+
vi.clearAllMocks();
|
|
8
|
+
});
|
|
9
|
+
|
|
10
|
+
describe('Token Management', () => {
|
|
11
|
+
it('should set and get token', () => {
|
|
12
|
+
const token = 'test-token-123';
|
|
13
|
+
setToken(token);
|
|
14
|
+
expect(getToken()).toBe(token);
|
|
15
|
+
});
|
|
16
|
+
|
|
17
|
+
it('should return null when no token exists', () => {
|
|
18
|
+
expect(getToken()).toBeNull();
|
|
19
|
+
});
|
|
20
|
+
|
|
21
|
+
it('should clear token and user', () => {
|
|
22
|
+
setToken('test-token');
|
|
23
|
+
setUser({ id: '1', name: 'Test' });
|
|
24
|
+
|
|
25
|
+
clearToken();
|
|
26
|
+
|
|
27
|
+
expect(getToken()).toBeNull();
|
|
28
|
+
expect(getUser()).toBeNull();
|
|
29
|
+
});
|
|
30
|
+
});
|
|
31
|
+
|
|
32
|
+
describe('User Management', () => {
|
|
33
|
+
it('should set and get user object', () => {
|
|
34
|
+
const user = { id: '1', name: 'Test User', email: 'test@example.com' };
|
|
35
|
+
setUser(user);
|
|
36
|
+
expect(getUser()).toEqual(user);
|
|
37
|
+
});
|
|
38
|
+
|
|
39
|
+
it('should return null when no user exists', () => {
|
|
40
|
+
expect(getUser()).toBeNull();
|
|
41
|
+
});
|
|
42
|
+
|
|
43
|
+
it('should handle complex user objects', () => {
|
|
44
|
+
const user = {
|
|
45
|
+
id: '1',
|
|
46
|
+
name: 'Test User',
|
|
47
|
+
email: 'test@example.com',
|
|
48
|
+
metadata: {
|
|
49
|
+
preferences: {
|
|
50
|
+
theme: 'dark',
|
|
51
|
+
notifications: true,
|
|
52
|
+
},
|
|
53
|
+
},
|
|
54
|
+
};
|
|
55
|
+
|
|
56
|
+
setUser(user);
|
|
57
|
+
expect(getUser()).toEqual(user);
|
|
58
|
+
});
|
|
59
|
+
|
|
60
|
+
it('should overwrite existing user', () => {
|
|
61
|
+
setUser({ id: '1', name: 'User 1' });
|
|
62
|
+
setUser({ id: '2', name: 'User 2' });
|
|
63
|
+
|
|
64
|
+
const user = getUser<{ id: string; name: string }>();
|
|
65
|
+
expect(user?.id).toBe('2');
|
|
66
|
+
expect(user?.name).toBe('User 2');
|
|
67
|
+
});
|
|
68
|
+
});
|
|
69
|
+
});
|
|
@@ -1,22 +1,23 @@
|
|
|
1
1
|
{
|
|
2
2
|
"compilerOptions": {
|
|
3
3
|
"target": "ES2022",
|
|
4
|
-
"module": "ESNext",
|
|
5
4
|
"lib": ["ES2022", "DOM", "DOM.Iterable"],
|
|
6
|
-
"
|
|
5
|
+
"module": "ESNext",
|
|
7
6
|
"moduleResolution": "bundler",
|
|
8
|
-
"allowImportingTsExtensions": true,
|
|
9
7
|
"resolveJsonModule": true,
|
|
10
|
-
"
|
|
11
|
-
"noEmit": true,
|
|
8
|
+
"allowImportingTsExtensions": true,
|
|
12
9
|
"strict": true,
|
|
13
10
|
"noUnusedLocals": true,
|
|
14
11
|
"noUnusedParameters": true,
|
|
15
12
|
"noFallthroughCasesInSwitch": true,
|
|
16
|
-
"
|
|
17
|
-
"
|
|
13
|
+
"esModuleInterop": true,
|
|
14
|
+
"skipLibCheck": true,
|
|
15
|
+
"forceConsistentCasingInFileNames": true,
|
|
16
|
+
"experimentalDecorators": true,
|
|
18
17
|
"useDefineForClassFields": false,
|
|
19
|
-
"
|
|
18
|
+
"noEmit": true,
|
|
19
|
+
"types": ["vite/client"]
|
|
20
20
|
},
|
|
21
|
-
"include": ["src"]
|
|
22
|
-
|
|
21
|
+
"include": ["src/**/*"],
|
|
22
|
+
"exclude": ["node_modules", "dist"]
|
|
23
|
+
}
|
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
import { defineConfig } from 'vite';
|
|
2
|
+
import swc from 'unplugin-swc';
|
|
3
|
+
import { VitePWA } from 'vite-plugin-pwa';
|
|
4
|
+
|
|
5
|
+
export default defineConfig({
|
|
6
|
+
plugins: [
|
|
7
|
+
swc.vite({
|
|
8
|
+
jsc: {
|
|
9
|
+
parser: {
|
|
10
|
+
syntax: 'typescript',
|
|
11
|
+
decorators: true,
|
|
12
|
+
},
|
|
13
|
+
target: 'es2022',
|
|
14
|
+
transform: {
|
|
15
|
+
decoratorMetadata: false,
|
|
16
|
+
decoratorVersion: '2022-03',
|
|
17
|
+
useDefineForClassFields: false,
|
|
18
|
+
},
|
|
19
|
+
},
|
|
20
|
+
}),
|
|
21
|
+
VitePWA({
|
|
22
|
+
registerType: 'autoUpdate',
|
|
23
|
+
includeAssets: ['vite.svg', 'icons/*.png'],
|
|
24
|
+
manifest: {
|
|
25
|
+
name: '{{projectName}}',
|
|
26
|
+
short_name: '{{projectName}}',
|
|
27
|
+
description: 'PWA built with Snice',
|
|
28
|
+
theme_color: '#6366f1',
|
|
29
|
+
background_color: '#ffffff',
|
|
30
|
+
display: 'standalone',
|
|
31
|
+
icons: [
|
|
32
|
+
{
|
|
33
|
+
src: '/icons/icon-192.png',
|
|
34
|
+
sizes: '192x192',
|
|
35
|
+
type: 'image/png',
|
|
36
|
+
},
|
|
37
|
+
{
|
|
38
|
+
src: '/icons/icon-512.png',
|
|
39
|
+
sizes: '512x512',
|
|
40
|
+
type: 'image/png',
|
|
41
|
+
},
|
|
42
|
+
],
|
|
43
|
+
},
|
|
44
|
+
workbox: {
|
|
45
|
+
globPatterns: ['**/*.{js,css,html,ico,png,svg,woff,woff2}'],
|
|
46
|
+
runtimeCaching: [
|
|
47
|
+
{
|
|
48
|
+
urlPattern: /^https:\/\/fonts\.googleapis\.com\/.*/i,
|
|
49
|
+
handler: 'CacheFirst',
|
|
50
|
+
options: {
|
|
51
|
+
cacheName: 'google-fonts-cache',
|
|
52
|
+
expiration: {
|
|
53
|
+
maxEntries: 10,
|
|
54
|
+
maxAgeSeconds: 60 * 60 * 24 * 365, // 1 year
|
|
55
|
+
},
|
|
56
|
+
cacheableResponse: {
|
|
57
|
+
statuses: [0, 200],
|
|
58
|
+
},
|
|
59
|
+
},
|
|
60
|
+
},
|
|
61
|
+
{
|
|
62
|
+
urlPattern: /^https:\/\/api\..*/i,
|
|
63
|
+
handler: 'NetworkFirst',
|
|
64
|
+
options: {
|
|
65
|
+
cacheName: 'api-cache',
|
|
66
|
+
networkTimeoutSeconds: 10,
|
|
67
|
+
expiration: {
|
|
68
|
+
maxEntries: 50,
|
|
69
|
+
maxAgeSeconds: 60 * 5, // 5 minutes
|
|
70
|
+
},
|
|
71
|
+
},
|
|
72
|
+
},
|
|
73
|
+
],
|
|
74
|
+
},
|
|
75
|
+
}),
|
|
76
|
+
],
|
|
77
|
+
build: {
|
|
78
|
+
target: 'es2015',
|
|
79
|
+
minify: 'terser',
|
|
80
|
+
cssMinify: true,
|
|
81
|
+
rollupOptions: {
|
|
82
|
+
output: {
|
|
83
|
+
manualChunks: {
|
|
84
|
+
vendor: ['snice'],
|
|
85
|
+
},
|
|
86
|
+
},
|
|
87
|
+
},
|
|
88
|
+
sourcemap: true,
|
|
89
|
+
chunkSizeWarningLimit: 500,
|
|
90
|
+
},
|
|
91
|
+
esbuild: {
|
|
92
|
+
drop: process.env.NODE_ENV === 'production' ? ['debugger'] : [],
|
|
93
|
+
},
|
|
94
|
+
});
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { defineConfig } from '
|
|
1
|
+
import { defineConfig } from 'vitest/config';
|
|
2
2
|
import swc from 'unplugin-swc';
|
|
3
3
|
|
|
4
4
|
export default defineConfig({
|
|
@@ -18,21 +18,16 @@ export default defineConfig({
|
|
|
18
18
|
},
|
|
19
19
|
}),
|
|
20
20
|
],
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
21
|
+
test: {
|
|
22
|
+
environment: 'happy-dom',
|
|
23
|
+
globals: true,
|
|
24
|
+
coverage: {
|
|
25
|
+
reporter: ['text', 'json', 'html'],
|
|
26
|
+
exclude: [
|
|
27
|
+
'node_modules/',
|
|
28
|
+
'dist/',
|
|
29
|
+
'tests/**',
|
|
30
|
+
],
|
|
31
31
|
},
|
|
32
|
-
sourcemap: true,
|
|
33
|
-
chunkSizeWarningLimit: 500
|
|
34
32
|
},
|
|
35
|
-
|
|
36
|
-
drop: process.env.NODE_ENV === 'production' ? ['debugger'] : []
|
|
37
|
-
}
|
|
38
|
-
});
|
|
33
|
+
});
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
import type { Track, RepeatMode, PlayerState, SniceMusicPlayerElement } from './snice-music-player.types';
|
|
2
|
+
export declare class SniceMusicPlayer extends HTMLElement implements SniceMusicPlayerElement {
|
|
3
|
+
tracks: Track[];
|
|
4
|
+
currentTrackIndex: number;
|
|
5
|
+
currentTrack: string;
|
|
6
|
+
currentTime: number;
|
|
7
|
+
duration: number;
|
|
8
|
+
volume: number;
|
|
9
|
+
muted: boolean;
|
|
10
|
+
shuffle: boolean;
|
|
11
|
+
repeat: RepeatMode;
|
|
12
|
+
state: PlayerState;
|
|
13
|
+
autoplay: boolean;
|
|
14
|
+
showPlaylist: boolean;
|
|
15
|
+
showControls: boolean;
|
|
16
|
+
showVolume: boolean;
|
|
17
|
+
showArtwork: boolean;
|
|
18
|
+
showTrackInfo: boolean;
|
|
19
|
+
compact: boolean;
|
|
20
|
+
private showVolumeSlider;
|
|
21
|
+
private audioElement;
|
|
22
|
+
private updateInterval;
|
|
23
|
+
private shuffleHistory;
|
|
24
|
+
private shuffleQueue;
|
|
25
|
+
private progressElement?;
|
|
26
|
+
private volumeSlider?;
|
|
27
|
+
componentStyles(): import("snice").CSSResult;
|
|
28
|
+
init(): void;
|
|
29
|
+
cleanup(): void;
|
|
30
|
+
handleTracksChange(): void;
|
|
31
|
+
handleCurrentTrackChange(oldVal: string, newVal: string): void;
|
|
32
|
+
handleVolumeChange(oldVal: number, newVal: number): void;
|
|
33
|
+
handleMutedChange(oldVal: boolean, newVal: boolean): void;
|
|
34
|
+
renderPlayer(): import("snice").TemplateResult;
|
|
35
|
+
play(): Promise<void>;
|
|
36
|
+
pause(): void;
|
|
37
|
+
stop(): void;
|
|
38
|
+
next(): void;
|
|
39
|
+
previous(): void;
|
|
40
|
+
seek(time: number): void;
|
|
41
|
+
setVolume(volume: number): void;
|
|
42
|
+
toggleShuffle(): void;
|
|
43
|
+
setRepeat(mode: RepeatMode): void;
|
|
44
|
+
loadTrack(index: number): Promise<void>;
|
|
45
|
+
getCurrentTrack(): Track | null;
|
|
46
|
+
private toggleMute;
|
|
47
|
+
private toggleVolumeSlider;
|
|
48
|
+
private cycleRepeat;
|
|
49
|
+
private handleSeek;
|
|
50
|
+
private handleVolumeSlider;
|
|
51
|
+
private handleTrackEnded;
|
|
52
|
+
private getNextShuffleIndex;
|
|
53
|
+
private initializeShuffleQueue;
|
|
54
|
+
private startUpdateInterval;
|
|
55
|
+
private stopUpdateInterval;
|
|
56
|
+
private formatTime;
|
|
57
|
+
private emitPlay;
|
|
58
|
+
private emitPause;
|
|
59
|
+
private emitStop;
|
|
60
|
+
private emitTrackChange;
|
|
61
|
+
private emitTrackEnded;
|
|
62
|
+
private emitSeek;
|
|
63
|
+
private emitVolumeChange;
|
|
64
|
+
private emitShuffleChange;
|
|
65
|
+
private emitRepeatChange;
|
|
66
|
+
private emitError;
|
|
67
|
+
}
|
|
68
|
+
declare global {
|
|
69
|
+
interface HTMLElementTagNameMap {
|
|
70
|
+
'snice-music-player': SniceMusicPlayer;
|
|
71
|
+
}
|
|
72
|
+
}
|