@powersync/nuxt 0.0.0-dev-20260128023420 → 0.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.
Files changed (38) hide show
  1. package/{README → README.md} +46 -30
  2. package/dist/module.d.mts +2 -2
  3. package/dist/module.json +2 -2
  4. package/dist/module.mjs +22 -24
  5. package/dist/runtime/components/BucketsInspectorTab.d.vue.ts +1 -1
  6. package/dist/runtime/components/BucketsInspectorTab.vue +47 -149
  7. package/dist/runtime/components/BucketsInspectorTab.vue.d.ts +1 -1
  8. package/dist/runtime/components/ConfigInspectorTab.d.vue.ts +1 -1
  9. package/dist/runtime/components/ConfigInspectorTab.vue +11 -48
  10. package/dist/runtime/components/ConfigInspectorTab.vue.d.ts +1 -1
  11. package/dist/runtime/components/DataInspectorTab.d.vue.ts +1 -1
  12. package/dist/runtime/components/DataInspectorTab.vue +35 -149
  13. package/dist/runtime/components/DataInspectorTab.vue.d.ts +1 -1
  14. package/dist/runtime/components/LoadingSpinner.d.vue.ts +1 -1
  15. package/dist/runtime/components/LoadingSpinner.vue.d.ts +1 -1
  16. package/dist/runtime/components/LogsTab.d.vue.ts +1 -1
  17. package/dist/runtime/components/LogsTab.vue +42 -94
  18. package/dist/runtime/components/LogsTab.vue.d.ts +1 -1
  19. package/dist/runtime/components/PowerSyncInstanceTab.d.vue.ts +1 -1
  20. package/dist/runtime/components/PowerSyncInstanceTab.vue +1 -3
  21. package/dist/runtime/components/PowerSyncInstanceTab.vue.d.ts +1 -1
  22. package/dist/runtime/components/SyncStatusTab.d.vue.ts +1 -1
  23. package/dist/runtime/components/SyncStatusTab.vue +57 -168
  24. package/dist/runtime/components/SyncStatusTab.vue.d.ts +1 -1
  25. package/dist/runtime/composables/useDiagnosticsLogger.d.ts +1 -1
  26. package/dist/runtime/composables/useDiagnosticsLogger.js +16 -24
  27. package/dist/runtime/composables/usePowerSyncInspectorDiagnostics.js +13 -53
  28. package/dist/runtime/index.d.ts +3 -3
  29. package/dist/runtime/layouts/powersync-inspector-layout.d.vue.ts +1 -1
  30. package/dist/runtime/layouts/powersync-inspector-layout.vue +9 -36
  31. package/dist/runtime/layouts/powersync-inspector-layout.vue.d.ts +1 -1
  32. package/dist/runtime/pages/__powersync-inspector.d.vue.ts +1 -1
  33. package/dist/runtime/pages/__powersync-inspector.vue +8 -42
  34. package/dist/runtime/pages/__powersync-inspector.vue.d.ts +1 -1
  35. package/dist/runtime/utils/DynamicSchemaManager.js +3 -10
  36. package/dist/runtime/utils/RecordingStorageAdapter.js +4 -22
  37. package/dist/runtime/utils/TokenConnector.js +2 -7
  38. package/package.json +12 -10
@@ -1,17 +1,7 @@
1
1
  <template>
2
- <div
3
- border="t"
4
- border-color="gray-100"
5
- relative
6
- n-bg="base"
7
- flex="~ col"
8
- h="screen"
9
- overflow="hidden"
10
- >
2
+ <div border="t" border-color="gray-100" relative n-bg="base" flex="~ col" h="screen" overflow="hidden">
11
3
  <!-- Toolbar -->
12
- <div
13
- class="flex items-center justify-between gap-3 px-3 py-2 border-b border-gray-200 dark:border-neutral-700"
14
- >
4
+ <div class="flex items-center justify-between gap-3 px-3 py-2 border-b border-gray-200 dark:border-neutral-700">
15
5
  <div class="flex items-center gap-2 flex-1">
16
6
  <NTextInput
17
7
  v-model="searchQuery"
@@ -25,21 +15,12 @@
25
15
  v-model="selectedLevel"
26
16
  class="px-2 py-1 text-xs border border-gray-300 dark:border-neutral-600 rounded bg-white dark:bg-neutral-800"
27
17
  >
28
- <option value="all">
29
- All Levels
30
- </option>
31
- <option value="error">
32
- Error
33
- </option>
34
- <option value="warn">
35
- Warning
36
- </option>
37
- <option value="info">
38
- Info
39
- </option>
40
- <option value="debug">
41
- Debug
42
- </option>
18
+ <option value="all">All Levels</option>
19
+ <option value="error">Error</option>
20
+ <option value="warn">Warning</option>
21
+ <option value="info">Info</option>
22
+ <option value="debug">Debug</option>
23
+ <option value="trace">Trace</option>
43
24
  </select>
44
25
  </div>
45
26
 
@@ -47,63 +28,37 @@
47
28
  <NBadge n="slate xs">
48
29
  {{ filteredLogs.length }}
49
30
  </NBadge>
50
- <NButton
51
- n="xs red"
52
- icon="carbon:trash-can"
53
- @click="clearLogs"
54
- >
55
- Clear
56
- </NButton>
31
+ <NButton n="xs red" icon="carbon:trash-can" @click="clearLogs"> Clear </NButton>
57
32
  </div>
58
33
  </div>
59
34
 
60
35
  <!-- Logs Table -->
61
36
  <div class="flex-1 overflow-auto">
62
- <div
63
- v-if="filteredLogs.length === 0"
64
- class="text-center py-12"
65
- >
66
- <div class="text-gray-500 dark:text-gray-400 text-sm">
67
- No logs found
68
- </div>
37
+ <div v-if="filteredLogs.length === 0" class="text-center py-12">
38
+ <div class="text-gray-500 dark:text-gray-400 text-sm">No logs found</div>
69
39
  </div>
70
40
 
71
- <table
72
- v-else
73
- class="w-full"
74
- >
75
- <thead class="sticky top-0 bg-gray-50 dark:bg-neutral-900 border-b border-gray-200 dark:border-neutral-700 z-10">
41
+ <table v-else class="w-full">
42
+ <thead
43
+ class="sticky top-0 bg-gray-50 dark:bg-neutral-900 border-b border-gray-200 dark:border-neutral-700 z-10"
44
+ >
76
45
  <tr>
77
46
  <th class="px-2 py-1.5 text-left text-xs font-medium text-gray-500 dark:text-gray-400 w-8" />
78
- <th class="px-2 py-1.5 text-left text-xs font-medium text-gray-500 dark:text-gray-400 w-32">
79
- Time
80
- </th>
81
- <th class="px-2 py-1.5 text-left text-xs font-medium text-gray-500 dark:text-gray-400 w-20">
82
- Source
83
- </th>
84
- <th class="px-2 py-1.5 text-left text-xs font-medium text-gray-500 dark:text-gray-400 w-20">
85
- Level
86
- </th>
87
- <th class="px-2 py-1.5 text-left text-xs font-medium text-gray-500 dark:text-gray-400">
88
- Message
89
- </th>
47
+ <th class="px-2 py-1.5 text-left text-xs font-medium text-gray-500 dark:text-gray-400 w-32">Time</th>
48
+ <th class="px-2 py-1.5 text-left text-xs font-medium text-gray-500 dark:text-gray-400 w-20">Source</th>
49
+ <th class="px-2 py-1.5 text-left text-xs font-medium text-gray-500 dark:text-gray-400 w-20">Level</th>
50
+ <th class="px-2 py-1.5 text-left text-xs font-medium text-gray-500 dark:text-gray-400">Message</th>
90
51
  <th class="px-2 py-1.5 text-left text-xs font-medium text-gray-500 dark:text-gray-400 w-16" />
91
52
  </tr>
92
53
  </thead>
93
54
  <tbody>
94
- <template
95
- v-for="log in filteredLogs"
96
- :key="log.key"
97
- >
55
+ <template v-for="log in filteredLogs" :key="log.key">
98
56
  <tr
99
57
  class="log-entry hover:bg-gray-50 dark:hover:bg-gray-800/50 transition-colors cursor-pointer border-b border-b-gray-100 dark:border-b-neutral-800"
100
58
  @click="toggleExpand(log.key)"
101
59
  >
102
60
  <td class="px-2 py-1.5">
103
- <div
104
- class="w-1.5 h-1.5 rounded-full"
105
- :class="getLogDotClass(log)"
106
- />
61
+ <div class="w-1.5 h-1.5 rounded-full" :class="getLogDotClass(log)" />
107
62
  </td>
108
63
  <td class="px-2 py-1.5">
109
64
  <span class="text-xs font-mono text-gray-600 dark:text-gray-400">
@@ -116,9 +71,7 @@
116
71
  </div>
117
72
  </td>
118
73
  <td class="px-2 py-1.5">
119
- <NBadge
120
- :n="`${getLogBadgeColor(log)} xs`"
121
- >
74
+ <NBadge :n="`${getLogBadgeColor(log)} xs`">
122
75
  {{ getLogType(log) }}
123
76
  </NBadge>
124
77
  </td>
@@ -135,24 +88,17 @@
135
88
  />
136
89
  </td>
137
90
  </tr>
138
- <tr
139
- v-if="expandedLogs.has(log.key) && hasExtraData(log)"
140
- class="bg-gray-50 dark:bg-neutral-900/50"
141
- >
91
+ <tr v-if="expandedLogs.has(log.key) && hasExtraData(log)" class="bg-gray-50 dark:bg-neutral-900/50">
142
92
  <td colspan="12">
143
93
  <div class="px-10 py-2">
144
94
  <div class="inline-flex items-center gap-2 mb-2">
145
- <NIcon
146
- n="sm"
147
- icon="carbon:object"
148
- />
95
+ <NIcon n="sm" icon="carbon:object" />
149
96
  <span class="text-xs text-gray-600 dark:text-gray-400">JSON</span>
150
97
  </div>
151
- <div class="bg-white dark:bg-neutral-800 p-3 rounded border border-gray-200 dark:border-neutral-700 overflow-x-auto">
152
- <div
153
- class="json-code-block text-xs"
154
- v-html="highlightedJson.get(log.key)"
155
- />
98
+ <div
99
+ class="bg-white dark:bg-neutral-800 p-3 rounded border border-gray-200 dark:border-neutral-700 overflow-x-auto"
100
+ >
101
+ <div class="json-code-block text-xs" v-html="highlightedJson.get(log.key) ?? ''" />
156
102
  </div>
157
103
  </div>
158
104
  </td>
@@ -211,17 +157,13 @@ const fuse = computed(() => {
211
157
  const filteredLogs = computed(() => {
212
158
  let filtered = logs.value || [];
213
159
  if (selectedLevel.value !== "all") {
214
- filtered = filtered.filter(
215
- (log) => log.value?.type === selectedLevel.value
216
- );
160
+ filtered = filtered.filter((log) => log.value?.type === selectedLevel.value);
217
161
  }
218
162
  if (searchQuery.value && fuse.value) {
219
163
  const searchResults = fuse.value.search(searchQuery.value);
220
164
  const searchedItems = searchResults.map((result) => result.item);
221
165
  if (selectedLevel.value !== "all") {
222
- filtered = filtered.filter(
223
- (log) => searchedItems.some((item) => item.key === log.key)
224
- );
166
+ filtered = filtered.filter((log) => searchedItems.some((item) => item.key === log.key));
225
167
  } else {
226
168
  filtered = searchedItems;
227
169
  }
@@ -237,14 +179,14 @@ async function toggleExpand(key) {
237
179
  const log = logs.value.find((l) => l.key === key);
238
180
  if (log) {
239
181
  const jsonStr = formatExtraData(log);
240
- const html = await codeToHtml(jsonStr, {
182
+ const html = await codeToHtml(jsonStr || '""', {
241
183
  lang: "json",
242
184
  themes: {
243
185
  light: "catppuccin-latte",
244
186
  dark: "catppuccin-frappe"
245
187
  }
246
188
  });
247
- highlightedJson.value.set(key, html);
189
+ highlightedJson.value.set(key, typeof html === "string" ? html : "");
248
190
  }
249
191
  }
250
192
  }
@@ -254,14 +196,18 @@ function getLogMessage(log) {
254
196
  return String(log.value.args[0] || "Empty log message");
255
197
  }
256
198
  function getLogSource(log) {
257
- return log.value?.args[2]?.name || "";
199
+ const context = log.value?.args[2];
200
+ return context?.name ?? "";
258
201
  }
259
202
  function hasExtraData(log) {
260
203
  return !!(log.value?.args && log.value.args.length > 2 && log.value.args[1] && !(typeof log.value.args[1] === "object" && log.value.args[1] !== null && Object.keys(log.value.args[1]).length === 0));
261
204
  }
262
205
  function formatExtraData(log) {
263
206
  if (!log.value?.args || log.value.args.length <= 1) return "";
264
- return JSON.stringify(log.value.args[1], null, 2);
207
+ const data = log.value.args[1];
208
+ if (data === void 0 || data === null) return "";
209
+ const str = JSON.stringify(data, null, 2);
210
+ return typeof str === "string" ? str : "";
265
211
  }
266
212
  function getSearchableExtraData(log) {
267
213
  if (!log.value?.args || log.value.args.length <= 1) return "";
@@ -293,7 +239,8 @@ function getLogDotClass(log) {
293
239
  error: "bg-red-500",
294
240
  warn: "bg-yellow-500",
295
241
  info: "bg-blue-500",
296
- debug: "bg-gray-400"
242
+ debug: "bg-gray-400",
243
+ trace: "bg-gray-300 dark:bg-gray-500"
297
244
  };
298
245
  return classes[type] || classes.info;
299
246
  }
@@ -303,7 +250,8 @@ function getLogBadgeColor(log) {
303
250
  error: "red",
304
251
  warn: "yellow",
305
252
  info: "blue",
306
- debug: "gray"
253
+ debug: "gray",
254
+ trace: "slate"
307
255
  };
308
256
  return colors[type] || colors.info;
309
257
  }
@@ -1,3 +1,3 @@
1
- declare const __VLS_export: import("vue").DefineComponent<{}, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").PublicProps, Readonly<{}> & Readonly<{}>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, true, {}, any>;
1
+ declare const __VLS_export: import("vue").DefineComponent<{}, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").PublicProps, Readonly<import("vue").ExtractPropTypes<{}>>, {}, {}>;
2
2
  declare const _default: typeof __VLS_export;
3
3
  export default _default;
@@ -1,3 +1,3 @@
1
- declare const __VLS_export: import("vue").DefineComponent<{}, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").PublicProps, Readonly<{}> & Readonly<{}>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, true, {}, any>;
1
+ declare const __VLS_export: import("vue").DefineComponent<{}, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").PublicProps, Readonly<import("vue").ExtractPropTypes<{}>>, {}, {}>;
2
2
  declare const _default: typeof __VLS_export;
3
3
  export default _default;
@@ -4,6 +4,4 @@
4
4
  </div>
5
5
  </template>
6
6
 
7
- <script setup lang="ts">
8
-
9
- </script>
7
+ <script setup lang="ts"></script>
@@ -1,3 +1,3 @@
1
- declare const __VLS_export: import("vue").DefineComponent<{}, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").PublicProps, Readonly<{}> & Readonly<{}>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, true, {}, any>;
1
+ declare const __VLS_export: import("vue").DefineComponent<{}, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").PublicProps, Readonly<import("vue").ExtractPropTypes<{}>>, {}, {}>;
2
2
  declare const _default: typeof __VLS_export;
3
3
  export default _default;
@@ -1,3 +1,3 @@
1
- declare const __VLS_export: import("vue").DefineComponent<{}, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").PublicProps, Readonly<{}> & Readonly<{}>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, true, {}, any>;
1
+ declare const __VLS_export: import("vue").DefineComponent<{}, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").PublicProps, Readonly<import("vue").ExtractPropTypes<{}>>, {}, {}>;
2
2
  declare const _default: typeof __VLS_export;
3
3
  export default _default;
@@ -1,32 +1,14 @@
1
1
  <template>
2
- <div
3
- border="t"
4
- border-color="gray-100"
5
- relative
6
- n-bg="base"
7
- flex="~ col"
8
- h="screen"
9
- >
2
+ <div border="t" border-color="gray-100" relative n-bg="base" flex="~ col" h="screen">
10
3
  <div flex="~ col gap-2">
11
- <NSectionBlock
12
- icon="carbon:data-share"
13
- text="Data Flow"
14
- >
15
- <div
16
- grid="~ cols-6 gap-4"
17
- mb="4"
18
- >
4
+ <NSectionBlock icon="carbon:data-share" text="Data Flow">
5
+ <div grid="~ cols-6 gap-4" mb="4">
19
6
  <!-- Download Progress -->
20
7
  <div flex="~ col gap-2">
21
8
  <span text="sm gray-500">Download Progress</span>
22
9
  <div flex="~ items-center gap-2">
23
10
  <template v-if="downloadProgressDetails !== null">
24
- <div
25
- flex="1"
26
- bg="gray-200"
27
- rounded="full"
28
- h="2"
29
- >
11
+ <div flex="1" bg="gray-200" rounded="full" h="2">
30
12
  <div
31
13
  bg="blue-600"
32
14
  h="2"
@@ -38,10 +20,7 @@
38
20
  }"
39
21
  />
40
22
  </div>
41
- <span
42
- text="sm"
43
- font="medium"
44
- >{{ totalDownloadProgress }}%</span>
23
+ <span text="sm" font="medium">{{ totalDownloadProgress }}%</span>
45
24
  </template>
46
25
  <template v-else>
47
26
  <span text="sm gray-400">No active download</span>
@@ -54,50 +33,29 @@
54
33
  <span text="sm gray-500">Status</span>
55
34
  <NBadge
56
35
  :n="downloadError ? 'red' : 'green'"
57
- :icon="
58
- downloadError ? 'carbon:warning-filled' : 'carbon:checkmark-filled'
59
- "
36
+ :icon="downloadError ? 'carbon:warning-filled' : 'carbon:checkmark-filled'"
60
37
  >
61
38
  {{ downloadError ? "Error" : "Healthy" }}
62
39
  </NBadge>
63
40
  </div>
64
41
 
65
42
  <!-- Error Details -->
66
- <div
67
- flex="~ col gap-2"
68
- col="span-4"
69
- >
43
+ <div flex="~ col gap-2" col="span-4">
70
44
  <span text="sm gray-500">Error Message</span>
71
- <NBadge
72
- v-if="downloadError"
73
- n="red sm"
74
- icon="carbon:warning-filled"
75
- >
45
+ <NBadge v-if="downloadError" n="red sm" icon="carbon:warning-filled">
76
46
  {{ downloadError.message }}
77
47
  </NBadge>
78
- <NBadge
79
- v-else
80
- n="slate sm"
81
- icon="carbon:checkmark-filled"
82
- >
83
- N/A
84
- </NBadge>
48
+ <NBadge v-else n="slate sm" icon="carbon:checkmark-filled"> N/A </NBadge>
85
49
  </div>
86
50
  </div>
87
51
 
88
- <div
89
- grid="~ cols-6 gap-4"
90
- mb="4"
91
- >
52
+ <div grid="~ cols-6 gap-4" mb="4">
92
53
  <!-- Upload Progress -->
93
54
  <div flex="~ col gap-2">
94
55
  <span text="sm gray-500">Upload Progress</span>
95
56
  <div flex="~ items-center gap-2">
96
57
  <span v-if="syncStatus?.dataFlowStatus.uploading">upload in progress...</span>
97
- <span
98
- v-else
99
- text="sm gray-400"
100
- >No active upload</span>
58
+ <span v-else text="sm gray-400">No active upload</span>
101
59
  </div>
102
60
  </div>
103
61
 
@@ -106,9 +64,7 @@
106
64
  <span text="sm gray-500">Status</span>
107
65
  <NBadge
108
66
  :n="uploadError ? 'red' : 'green'"
109
- :icon="
110
- uploadError ? 'carbon:warning-filled' : 'carbon:checkmark-filled'
111
- "
67
+ :icon="uploadError ? 'carbon:warning-filled' : 'carbon:checkmark-filled'"
112
68
  >
113
69
  {{ uploadError ? "Error" : "Healthy" }}
114
70
  </NBadge>
@@ -127,133 +83,43 @@
127
83
  </div>
128
84
 
129
85
  <!-- Error Details -->
130
- <div
131
- flex="~ col gap-2"
132
- col="span-2"
133
- >
86
+ <div flex="~ col gap-2" col="span-2">
134
87
  <span text="sm gray-500">Error Message</span>
135
- <NBadge
136
- v-if="uploadError"
137
- n="red sm"
138
- icon="carbon:warning-filled"
139
- >
88
+ <NBadge v-if="uploadError" n="red sm" icon="carbon:warning-filled">
140
89
  {{ uploadError.message }}
141
90
  </NBadge>
142
- <NBadge
143
- v-else
144
- n="slate sm"
145
- icon="carbon:checkmark-filled"
146
- >
147
- N/A
148
- </NBadge>
91
+ <NBadge v-else n="slate sm" icon="carbon:checkmark-filled"> N/A </NBadge>
149
92
  </div>
150
93
  </div>
151
94
  </NSectionBlock>
152
95
 
153
- <span
154
- border="b"
155
- border-color="gray-100"
156
- />
157
-
158
- <NSectionBlock
159
- icon="carbon:data-volume"
160
- text="Data Size"
161
- >
162
- <NTip
163
- v-if="!isDiagnosticSchemaSetup"
164
- n="red6 dark:red5"
165
- icon="carbon:warning-alt"
166
- >
167
- Make sure to extend your schema with the diagnostics schema using the
168
- `diagnosticsSchema` from the `usePowerSyncInspector` composable.
169
- </NTip>
170
- <div
171
- v-else
172
- grid="~ cols-5 gap-4"
173
- mb="4"
174
- >
175
- <div flex="~ col gap-2">
176
- <span text="sm gray-500">Buckets Synced</span>
177
- <span text="sm"> {{ totals?.buckets }} </span>
178
- </div>
179
-
180
- <div flex="~ col gap-2">
181
- <span text="sm gray-500">Rows Synced</span>
182
- <span text="sm"> {{ totals?.row_count }} </span>
183
- </div>
184
-
185
- <div flex="~ col gap-2">
186
- <span text="sm gray-500">Data size</span>
187
- <span text="sm">
188
- {{ totals?.data_size }}
189
- </span>
190
- </div>
191
-
192
- <div flex="~ col gap-2">
193
- <span text="sm gray-500">Metadata size</span>
194
- <span text="sm">
195
- {{ totals?.metadata_size }}
196
- </span>
197
- </div>
198
-
199
- <div flex="~ col gap-2">
200
- <span text="sm gray-500">Download size</span>
201
- <span text="sm">
202
- {{ totals?.download_size }}
203
- </span>
204
- </div>
205
- </div>
206
- </NSectionBlock>
207
-
208
- <span
209
- border="b"
210
- border-color="gray-100"
211
- />
212
-
213
- <NSectionBlock
214
- icon="carbon:data-share"
215
- text="Operations"
216
- >
217
- <NTip
218
- v-if="!isDiagnosticSchemaSetup"
219
- n="red6 dark:red5"
220
- icon="carbon:warning-alt"
221
- >
222
- Make sure to extend your schema with the diagnostics schema using the
223
- `diagnosticsSchema` from the `usePowerSyncInspector` composable.
224
- </NTip>
225
- <div
226
- v-else
227
- grid="~ cols-2 gap-4"
228
- mb="4"
229
- >
230
- <div flex="~ col gap-2">
231
- <span text="sm gray-500">Total operations</span>
232
- <span text="sm">
233
- {{ totals?.total_operations }}
234
- </span>
96
+ <span border="b" border-color="gray-100" />
97
+
98
+ <template v-for="(section, index) in metricSections" :key="section.text">
99
+ <NSectionBlock :icon="section.icon" :text="section.text">
100
+ <NTip v-if="!isDiagnosticSchemaSetup" n="red6 dark:red5" icon="carbon:warning-alt">
101
+ Make sure to extend your schema with the diagnostics schema using the `diagnosticsSchema` from the
102
+ `usePowerSyncInspector` composable.
103
+ </NTip>
104
+ <div v-else :grid="`~ cols-${section.cols} gap-4`" mb="4">
105
+ <div v-for="metric in section.metrics" :key="metric.label" flex="~ col gap-2">
106
+ <span text="sm gray-500">{{ metric.label }}</span>
107
+ <span text="sm">{{ metric.value }}</span>
108
+ </div>
235
109
  </div>
110
+ </NSectionBlock>
236
111
 
237
- <div flex="~ col gap-2">
238
- <span text="sm gray-500">Downloaded operations</span>
239
- <span text="sm">
240
- {{ totals?.downloaded_operations }}
241
- </span>
242
- </div>
243
- </div>
244
- </NSectionBlock>
112
+ <span v-if="index < metricSections.length - 1" border="b" border-color="gray-100" />
113
+ </template>
245
114
 
246
- <span
247
- border="b"
248
- border-color="gray-100"
249
- />
115
+ <span border="b" border-color="gray-100" />
250
116
  </div>
251
117
  </div>
252
118
  </template>
253
119
 
254
120
  <script setup>
255
121
  import { usePowerSyncInspectorDiagnostics } from "#imports";
256
- import { onMounted } from "vue";
122
+ import { computed, onMounted } from "vue";
257
123
  const {
258
124
  db,
259
125
  isDiagnosticSchemaSetup,
@@ -266,7 +132,30 @@ const {
266
132
  uploadQueueSize,
267
133
  totals
268
134
  } = usePowerSyncInspectorDiagnostics();
135
+ const metricSections = computed(() => [
136
+ {
137
+ icon: "carbon:data-volume",
138
+ text: "Data Size",
139
+ cols: 5,
140
+ metrics: [
141
+ { label: "Buckets Synced", value: totals.value?.buckets },
142
+ { label: "Rows Synced", value: totals.value?.row_count },
143
+ { label: "Data size", value: totals.value?.data_size },
144
+ { label: "Metadata size", value: totals.value?.metadata_size },
145
+ { label: "Download size", value: totals.value?.download_size }
146
+ ]
147
+ },
148
+ {
149
+ icon: "carbon:data-share",
150
+ text: "Operations",
151
+ cols: 2,
152
+ metrics: [
153
+ { label: "Total operations", value: totals.value?.total_operations },
154
+ { label: "Downloaded operations", value: totals.value?.downloaded_operations }
155
+ ]
156
+ }
157
+ ]);
269
158
  onMounted(async () => {
270
- await db.value?.waitForFirstSync();
159
+ await db?.value?.waitForFirstSync();
271
160
  });
272
161
  </script>
@@ -1,3 +1,3 @@
1
- declare const __VLS_export: import("vue").DefineComponent<{}, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").PublicProps, Readonly<{}> & Readonly<{}>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, true, {}, any>;
1
+ declare const __VLS_export: import("vue").DefineComponent<{}, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").PublicProps, Readonly<import("vue").ExtractPropTypes<{}>>, {}, {}>;
2
2
  declare const _default: typeof __VLS_export;
3
3
  export default _default;
@@ -21,7 +21,7 @@ import { type ILogHandler } from '@powersync/web';
21
21
  * ```
22
22
  */
23
23
  export declare const useDiagnosticsLogger: (customHandler?: ILogHandler) => {
24
- logger: import("js-logger").GlobalLogger;
24
+ logger: import("@powersync/common").GlobalLogger;
25
25
  logsStorage: import("unstorage").Storage<import("unstorage").StorageValue>;
26
26
  emitter: import("mitt").Emitter<Record<import("mitt").EventType, unknown>>;
27
27
  };
@@ -1,5 +1,4 @@
1
1
  import { createBaseLogger, LogLevel } from "@powersync/web";
2
- import { createConsola } from "consola";
3
2
  import { createStorage } from "unstorage";
4
3
  import localStorageDriver from "unstorage/drivers/session-storage";
5
4
  import mitt from "mitt";
@@ -7,34 +6,27 @@ const emitter = mitt();
7
6
  const logsStorage = createStorage({
8
7
  driver: localStorageDriver({ base: "powersync:" })
9
8
  });
10
- const consola = createConsola({
11
- level: 5,
12
- // trace
13
- fancy: true,
14
- formatOptions: {
15
- columns: 80,
16
- colors: true,
17
- compact: false,
18
- date: true
19
- }
20
- });
21
- consola.addReporter({
22
- log: async (logObject) => {
23
- const key = `log:${logObject.date.toISOString()}`;
24
- await logsStorage.set(key, logObject);
25
- emitter.emit("log", { key, value: logObject });
26
- }
27
- });
28
9
  export const useDiagnosticsLogger = (customHandler) => {
29
10
  const logger = createBaseLogger();
30
- logger.useDefaults();
11
+ const consoleHandler = logger.createDefaultHandler({
12
+ formatter: (messages, context) => {
13
+ messages.unshift(`[PowerSync]${context.name ? ` [${context.name}]` : ""}`);
14
+ }
15
+ });
31
16
  logger.setLevel(LogLevel.DEBUG);
32
17
  logger.setHandler(async (messages, context) => {
33
- const level = context.level.name;
18
+ consoleHandler(messages, context);
34
19
  const messageArray = Array.from(messages);
35
- const mainMessage = String(messageArray[0] || "Empty log message");
36
- const extraData = messageArray.slice(1).map((item) => item.toString()).join(" ");
37
- consola[level.toLowerCase()](`[PowerSync] ${context.name ? `[${context.name}]` : ""} ${mainMessage}`, extraData, context);
20
+ const mainMessage = String(messageArray[0] ?? "Empty log message");
21
+ const extra = messageArray.length > 1 ? messageArray.length === 2 ? messageArray[1] : messageArray.slice(1) : void 0;
22
+ const logObject = {
23
+ date: /* @__PURE__ */ new Date(),
24
+ type: context.level.name.toLowerCase(),
25
+ args: [mainMessage, extra, context]
26
+ };
27
+ const key = `log:${logObject.date.toISOString()}`;
28
+ await logsStorage.set(key, logObject);
29
+ emitter.emit("log", { key, value: logObject });
38
30
  await customHandler?.(messages, context);
39
31
  });
40
32
  return { logger, logsStorage, emitter };