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.
Files changed (80) hide show
  1. package/README.md +2 -2
  2. package/bin/snice.js +4 -5
  3. package/bin/templates/CLAUDE.md +25 -3
  4. package/bin/templates/pwa/README.md +188 -0
  5. package/bin/templates/pwa/global.d.ts +10 -0
  6. package/bin/templates/pwa/index.html +16 -0
  7. package/bin/templates/pwa/package.json +32 -0
  8. package/bin/templates/pwa/public/icons/.gitkeep +6 -0
  9. package/bin/templates/pwa/src/daemons/notifications.ts +148 -0
  10. package/bin/templates/pwa/src/fetcher.ts +15 -0
  11. package/bin/templates/pwa/src/guards/auth.ts +12 -0
  12. package/bin/templates/pwa/src/main.ts +42 -0
  13. package/bin/templates/pwa/src/middleware/auth.ts +16 -0
  14. package/bin/templates/pwa/src/middleware/error.ts +36 -0
  15. package/bin/templates/pwa/src/middleware/retry.ts +31 -0
  16. package/bin/templates/pwa/src/pages/dashboard.ts +143 -0
  17. package/bin/templates/pwa/src/pages/login.ts +161 -0
  18. package/bin/templates/pwa/src/pages/notifications.ts +156 -0
  19. package/bin/templates/pwa/src/pages/profile.ts +164 -0
  20. package/bin/templates/pwa/src/router.ts +20 -0
  21. package/bin/templates/pwa/src/services/auth.ts +48 -0
  22. package/bin/templates/pwa/src/services/jwt.ts +35 -0
  23. package/bin/templates/pwa/src/services/storage.ts +24 -0
  24. package/bin/templates/pwa/src/styles/global.css +55 -0
  25. package/bin/templates/pwa/src/types/auth.ts +21 -0
  26. package/bin/templates/pwa/src/types/notifications.ts +9 -0
  27. package/bin/templates/pwa/tests/helpers/test-utils.ts +84 -0
  28. package/bin/templates/pwa/tests/middleware/auth.test.ts +67 -0
  29. package/bin/templates/pwa/tests/middleware/error.test.ts +105 -0
  30. package/bin/templates/pwa/tests/middleware/retry.test.ts +103 -0
  31. package/bin/templates/pwa/tests/services/auth.test.ts +89 -0
  32. package/bin/templates/pwa/tests/services/jwt.test.ts +76 -0
  33. package/bin/templates/pwa/tests/services/storage.test.ts +69 -0
  34. package/bin/templates/{social → pwa}/tsconfig.json +11 -10
  35. package/bin/templates/pwa/vite.config.ts +94 -0
  36. package/bin/templates/{social/vite.config.ts → pwa/vitest.config.ts} +12 -17
  37. package/dist/components/music-player/snice-music-player.d.ts +72 -0
  38. package/dist/components/music-player/snice-music-player.js +730 -0
  39. package/dist/components/music-player/snice-music-player.js.map +1 -0
  40. package/dist/components/music-player/snice-music-player.types.d.ts +43 -0
  41. package/dist/components/timer/snice-timer.d.ts +27 -0
  42. package/dist/components/timer/snice-timer.js +197 -0
  43. package/dist/components/timer/snice-timer.js.map +1 -0
  44. package/dist/components/timer/snice-timer.types.d.ts +10 -0
  45. package/dist/fetcher.d.ts +65 -0
  46. package/dist/index.cjs +92 -3
  47. package/dist/index.cjs.map +1 -1
  48. package/dist/index.d.ts +2 -0
  49. package/dist/index.esm.js +92 -4
  50. package/dist/index.esm.js.map +1 -1
  51. package/dist/index.iife.js +92 -3
  52. package/dist/index.iife.js.map +1 -1
  53. package/dist/symbols.cjs +1 -1
  54. package/dist/symbols.esm.js +1 -1
  55. package/dist/transitions.cjs +1 -1
  56. package/dist/transitions.esm.js +1 -1
  57. package/dist/types/context.d.ts +7 -1
  58. package/dist/types/router-options.d.ts +6 -0
  59. package/docs/ai/api.md +33 -1
  60. package/docs/ai/components/music-player.md +134 -0
  61. package/docs/ai/components/timer.md +43 -0
  62. package/docs/ai/patterns.md +48 -1
  63. package/docs/components/music-player.md +314 -0
  64. package/docs/components/timer.md +143 -0
  65. package/docs/fetcher.md +447 -0
  66. package/docs/routing.md +11 -8
  67. package/package.json +2 -1
  68. package/bin/templates/social/README.md +0 -42
  69. package/bin/templates/social/global.d.ts +0 -14
  70. package/bin/templates/social/index.html +0 -13
  71. package/bin/templates/social/package.json +0 -21
  72. package/bin/templates/social/src/main.ts +0 -33
  73. package/bin/templates/social/src/pages/feed-page.ts +0 -111
  74. package/bin/templates/social/src/pages/messages-page.ts +0 -102
  75. package/bin/templates/social/src/pages/not-found-page.ts +0 -46
  76. package/bin/templates/social/src/pages/profile-page.ts +0 -99
  77. package/bin/templates/social/src/pages/settings-page.ts +0 -119
  78. package/bin/templates/social/src/router.ts +0 -9
  79. package/bin/templates/social/src/styles/global.css +0 -156
  80. /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
- "skipLibCheck": true,
5
+ "module": "ESNext",
7
6
  "moduleResolution": "bundler",
8
- "allowImportingTsExtensions": true,
9
7
  "resolveJsonModule": true,
10
- "isolatedModules": true,
11
- "noEmit": true,
8
+ "allowImportingTsExtensions": true,
12
9
  "strict": true,
13
10
  "noUnusedLocals": true,
14
11
  "noUnusedParameters": true,
15
12
  "noFallthroughCasesInSwitch": true,
16
- "experimentalDecorators": false,
17
- "emitDecoratorMetadata": false,
13
+ "esModuleInterop": true,
14
+ "skipLibCheck": true,
15
+ "forceConsistentCasingInFileNames": true,
16
+ "experimentalDecorators": true,
18
17
  "useDefineForClassFields": false,
19
- "types": ["vite/client", "node"]
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 'vite';
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
- build: {
22
- target: 'es2015',
23
- minify: 'terser',
24
- cssMinify: true,
25
- rollupOptions: {
26
- output: {
27
- manualChunks: {
28
- vendor: ['snice']
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
- esbuild: {
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
+ }